12#include <config-kwin.h>
40#if KWIN_BUILD_SCREENLOCKER
48#include <KLocalizedString>
50#include <QCommandLineParser>
51#include <QQuickWindow>
52#include <private/qtx11extras_p.h>
53#include <qplatformdefs.h>
57#if __has_include(<malloc.h>)
63#include <xcb/damage.h>
65#define XCB_GE_GENERIC 35
78 : QApplication(argc, argv)
81 , m_config(KSharedConfig::openConfig(QStringLiteral(
"kwinrc")))
83 , m_operationMode(mode)
85 qRegisterMetaType<Options::WindowOperation>(
"Options::WindowOperation");
86 qRegisterMetaType<KWin::EffectWindow *>();
87 qRegisterMetaType<KWin::SurfaceInterface *>(
"KWin::SurfaceInterface *");
88 qRegisterMetaType<KSharedConfigPtr>();
89 qRegisterMetaType<std::chrono::nanoseconds>();
99 return m_operationMode;
104 m_operationMode = mode;
118 setProperty(
"org.kde.KActivities.core.disableAutostart",
true);
120 setQuitOnLastWindowClosed(
false);
121 setQuitLockEnabled(
false);
123 if (!m_config->isImmutable() && m_configLock) {
126 m_config->reparseConfiguration();
129 m_kxkbConfig = KSharedConfig::openConfig(QStringLiteral(
"kxkbrc"), KConfig::NoGlobals);
131 if (!m_inputConfig) {
132 m_inputConfig = KSharedConfig::openConfig(QStringLiteral(
"kcminputrc"), KConfig::NoGlobals);
159 m_outputBackend.reset();
179 KAboutData aboutData(QStringLiteral(
"kwin"),
182 i18n(
"KDE window manager"),
184 i18n(
"(c) 1999-2019, The KDE Developers"));
186 aboutData.addAuthor(i18n(
"Matthias Ettrich"), QString(), QStringLiteral(
"ettrich@kde.org"));
187 aboutData.addAuthor(i18n(
"Cristian Tibirna"), QString(), QStringLiteral(
"tibirna@kde.org"));
188 aboutData.addAuthor(i18n(
"Daniel M. Duley"), QString(), QStringLiteral(
"mosfet@kde.org"));
189 aboutData.addAuthor(i18n(
"Luboš Luňák"), QString(), QStringLiteral(
"l.lunak@kde.org"));
190 aboutData.addAuthor(i18n(
"Martin Flöser"), QString(), QStringLiteral(
"mgraesslin@kde.org"));
191 aboutData.addAuthor(i18n(
"David Edmundson"), QStringLiteral(
"Maintainer"), QStringLiteral(
"davidedmundson@kde.org"));
192 aboutData.addAuthor(i18n(
"Roman Gilg"), QStringLiteral(
"Maintainer"), QStringLiteral(
"subdiff@gmail.com"));
193 aboutData.addAuthor(i18n(
"Vlad Zahorodnii"), QStringLiteral(
"Maintainer"), QStringLiteral(
"vlad.zahorodnii@kde.org"));
194 aboutData.addAuthor(i18n(
"Xaver Hugl"), QStringLiteral(
"Maintainer"), QStringLiteral(
"xaver.hugl@gmail.com"));
195 KAboutData::setApplicationData(aboutData);
198static const QString s_lockOption = QStringLiteral(
"lock");
199static const QString s_crashesOption = QStringLiteral(
"crashes");
203 QCommandLineOption lockOption(s_lockOption, i18n(
"Disable configuration options"));
204 QCommandLineOption crashesOption(s_crashesOption, i18n(
"Indicate that KWin has recently crashed n times"), QStringLiteral(
"n"));
206 parser->setApplicationDescription(i18n(
"KDE window manager"));
207 parser->addOption(lockOption);
208 parser->addOption(crashesOption);
209 KAboutData::applicationData().setupCommandLine(parser);
214 KAboutData aboutData = KAboutData::applicationData();
215 aboutData.processCommandLine(parser);
222#ifdef M_TRIM_THRESHOLD
229 const int pagesize = sysconf(_SC_PAGESIZE);
230 mallopt(M_TRIM_THRESHOLD, 5 * pagesize);
236 KLocalizedString::setApplicationDomain(QByteArrayLiteral(
"kwin"));
242 QQuickWindow::setDefaultAlphaBuffer(
true);
255#if KWIN_BUILD_SCREENLOCKER
256 m_screenLockerWatcher = std::make_unique<ScreenLockerWatcher>();
258 auto input = InputRedirection::create(
this);
275 m_pluginManager = std::make_unique<PluginManager>();
280 m_colorManager = std::make_unique<ColorManager>();
285 m_inputMethod = std::make_unique<InputMethod>();
290 m_tabletModeManager = std::make_unique<TabletModeManager>();
295 return m_tabletModeManager.get();
300 installNativeEventFilter(m_eventFilter.get());
305 removeNativeEventFilter(m_eventFilter.get());
310 delete InputRedirection::self();
325 m_pluginManager.reset();
330 m_colorManager.reset();
335 m_inputMethod.reset();
340 return std::make_unique<Edge>(edges);
345 return std::make_unique<InputRedirectionCursor>();
351 return std::make_unique<CompositedOutlineVisual>(outline);
371 QList<QPointer<X11EventFilterContainer>> &list)
373 for (
int i = 0; i < list.count(); ++i) {
375 if (container->
filter() == eventFilter) {
376 return list.takeAt(i);
384 Q_ASSERT(scale != 0);
385 if (scale != m_xwaylandScale) {
386 m_xwaylandScale = scale;
394 const bool xwaylandClientsScale = KConfig(QStringLiteral(
"kdeglobals"))
395 .group(QStringLiteral(
"KScreen"))
396 .readEntry(
"XwaylandClientsScale",
true);
398 KConfigGroup xwaylandGroup = kwinApp()->config()->group(QStringLiteral(
"Xwayland"));
399 if (xwaylandClientsScale) {
400 xwaylandGroup.writeEntry(
"Scale", m_xwaylandScale, KConfig::Notify);
402 xwaylandGroup.deleteEntry(
"Scale", KConfig::Notify);
404 xwaylandGroup.sync();
408 QProcess::startDetached(
"kcminit", {
"kcm_fonts_init",
"kcm_style_init"});
416 container = takeEventFilter(filter, m_genericEventFilters);
418 container = takeEventFilter(filter, m_eventFilters);
425 static const QList<QByteArray> s_xcbEerrors({QByteArrayLiteral(
"Success"),
426 QByteArrayLiteral(
"BadRequest"),
427 QByteArrayLiteral(
"BadValue"),
428 QByteArrayLiteral(
"BadWindow"),
429 QByteArrayLiteral(
"BadPixmap"),
430 QByteArrayLiteral(
"BadAtom"),
431 QByteArrayLiteral(
"BadCursor"),
432 QByteArrayLiteral(
"BadFont"),
433 QByteArrayLiteral(
"BadMatch"),
434 QByteArrayLiteral(
"BadDrawable"),
435 QByteArrayLiteral(
"BadAccess"),
436 QByteArrayLiteral(
"BadAlloc"),
437 QByteArrayLiteral(
"BadColor"),
438 QByteArrayLiteral(
"BadGC"),
439 QByteArrayLiteral(
"BadIDChoice"),
440 QByteArrayLiteral(
"BadName"),
441 QByteArrayLiteral(
"BadLength"),
442 QByteArrayLiteral(
"BadImplementation"),
443 QByteArrayLiteral(
"Unknown")});
445 kwinApp()->updateX11Time(event);
447 const uint8_t x11EventType =
event->response_type & ~0x80;
450 xcb_generic_error_t *error =
reinterpret_cast<xcb_generic_error_t *
>(event);
452 for (
const auto &extension : extensions) {
453 if (error->major_code == extension.majorOpcode) {
454 QByteArray errorName;
455 if (error->error_code < s_xcbEerrors.size()) {
456 errorName = s_xcbEerrors.at(error->error_code);
457 }
else if (error->error_code >= extension.errorBase) {
458 const int index = error->error_code - extension.errorBase;
459 if (index >= 0 && index < extension.errorCodes.size()) {
460 errorName = extension.errorCodes.at(index);
463 if (errorName.isEmpty()) {
464 errorName = QByteArrayLiteral(
"Unknown");
466 qCWarning(KWIN_CORE,
"XCB error: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d (%s)",
467 int(error->error_code), errorName.constData(),
468 int(error->sequence),
int(error->resource_id),
469 int(error->major_code), extension.name.constData(),
470 int(error->minor_code),
471 extension.opCodes.size() > error->minor_code ? extension.opCodes.at(error->minor_code).constData() :
"Unknown");
483 const auto eventFilters = m_genericEventFilters;
497 const auto eventFilters = m_eventFilters;
504 if (filter->
eventTypes().contains(x11EventType) && filter->
event(event)) {
517static quint32 monotonicTime()
521 const int result = clock_gettime(CLOCK_MONOTONIC, &ts);
523 qCWarning(KWIN_CORE,
"Failed to query monotonic time: %s", strerror(errno));
526 return ts.tv_sec * 1000 + ts.tv_nsec / 1000000L;
548 xcb_timestamp_t time = XCB_TIME_CURRENT_TIME;
549 const uint8_t eventType =
event->response_type & ~0x80;
552 case XCB_KEY_RELEASE:
553 time =
reinterpret_cast<xcb_key_press_event_t *
>(event)->time;
555 case XCB_BUTTON_PRESS:
556 case XCB_BUTTON_RELEASE:
557 time =
reinterpret_cast<xcb_button_press_event_t *
>(event)->time;
559 case XCB_MOTION_NOTIFY:
560 time =
reinterpret_cast<xcb_motion_notify_event_t *
>(event)->time;
562 case XCB_ENTER_NOTIFY:
563 case XCB_LEAVE_NOTIFY:
564 time =
reinterpret_cast<xcb_enter_notify_event_t *
>(event)->time;
568 case XCB_KEYMAP_NOTIFY:
570 case XCB_GRAPHICS_EXPOSURE:
571 case XCB_NO_EXPOSURE:
572 case XCB_VISIBILITY_NOTIFY:
573 case XCB_CREATE_NOTIFY:
574 case XCB_DESTROY_NOTIFY:
575 case XCB_UNMAP_NOTIFY:
577 case XCB_MAP_REQUEST:
578 case XCB_REPARENT_NOTIFY:
579 case XCB_CONFIGURE_NOTIFY:
580 case XCB_CONFIGURE_REQUEST:
581 case XCB_GRAVITY_NOTIFY:
582 case XCB_RESIZE_REQUEST:
583 case XCB_CIRCULATE_NOTIFY:
584 case XCB_CIRCULATE_REQUEST:
587 case XCB_PROPERTY_NOTIFY:
588 time =
reinterpret_cast<xcb_property_notify_event_t *
>(event)->time;
590 case XCB_SELECTION_CLEAR:
591 time =
reinterpret_cast<xcb_selection_clear_event_t *
>(event)->time;
593 case XCB_SELECTION_REQUEST:
594 time =
reinterpret_cast<xcb_selection_request_event_t *
>(event)->time;
596 case XCB_SELECTION_NOTIFY:
597 time =
reinterpret_cast<xcb_selection_notify_event_t *
>(event)->time;
599 case XCB_COLORMAP_NOTIFY:
600 case XCB_CLIENT_MESSAGE:
601 case XCB_MAPPING_NOTIFY:
609 time =
reinterpret_cast<xcb_shape_notify_event_t *
>(event)->server_time;
612 time =
reinterpret_cast<xcb_damage_notify_event_t *
>(event)->timestamp;
622 if (eventType ==
"xcb_generic_event_t") {
623 return kwinApp()->dispatchEvent(
static_cast<xcb_generic_event_t *
>(message));
630 return m_processEnvironment;
635 m_processEnvironment = environment;
640 Q_ASSERT(!m_outputBackend);
641 m_outputBackend = std::move(backend);
646 Q_ASSERT(!m_session);
647 m_session = std::move(
session);
652 return m_pluginManager.get();
657 return m_inputMethod.get();
662 return m_colorManager.get();
670#if KWIN_BUILD_SCREENLOCKER
673 return m_screenLockerWatcher.get();
677static PlatformCursorImage grabCursorOpenGL()
681 return PlatformCursorImage();
687 const auto texture =
GLTexture::allocate(GL_RGBA8, (cursor->geometry().size() * output->scale()).toSize());
689 return PlatformCursorImage{};
692 GLFramebuffer framebuffer(texture.get());
693 RenderTarget renderTarget(&framebuffer);
695 SceneDelegate delegate(scene, output);
696 scene->prePaint(&delegate);
700 QImage image = texture->toImage();
701 image.setDevicePixelRatio(output->scale());
703 return PlatformCursorImage(image, cursor->hotspot());
706static PlatformCursorImage grabCursorSoftware()
710 return PlatformCursorImage();
716 QImage image((cursor->geometry().size() * output->scale()).toSize(), QImage::Format_ARGB32_Premultiplied);
717 RenderTarget renderTarget(&image);
719 SceneDelegate delegate(scene, output);
720 scene->prePaint(&delegate);
724 image.setDevicePixelRatio(output->scale());
725 return PlatformCursorImage(image, cursor->hotspot());
735 if (
auto shapeSource = qobject_cast<ShapeCursorSource *>(cursor->
source())) {
742 return grabCursorOpenGL();
744 return grabCursorSoftware();
762 callback(QPointF(-1, -1));
770#include "moc_main.cpp"
virtual void createEffectsHandler(Compositor *compositor, WorkspaceScene *scene)
void installNativeX11EventFilter()
virtual PlatformCursorImage cursorImage() const
virtual std::unique_ptr< Cursor > createPlatformCursor()
virtual void performStartup()=0
void destroyColorManager()
static void createAboutData()
void registerEventFilter(X11EventFilter *filter)
virtual std::unique_ptr< OutlineVisual > createOutline(Outline *outline)
void setOperationMode(OperationMode mode)
void createTabletModeManager()
static void setupMalloc()
virtual void startInteractivePositionSelection(std::function< void(const QPointF &)> callback)
virtual XwaylandInterface * xwayland() const
void setSession(std::unique_ptr< Session > &&session)
Application(OperationMode mode, int &argc, char **argv)
void setOutputBackend(std::unique_ptr< OutputBackend > &&backend)
void setX11Time(xcb_timestamp_t timestamp, TimestampUpdate force=TimestampUpdate::OnlyIfLarger)
void processCommandLine(QCommandLineParser *parser)
void setProcessStartupEnvironment(const QProcessEnvironment &environment)
QProcessEnvironment processStartupEnvironment() const
ColorManager * colorManager() const
void setConfigLock(bool lock)
Session * session() const
void removeNativeX11EventFilter()
void destroyInputMethod()
void createColorManager()
void setXwaylandScale(qreal scale)
void updateX11Time(xcb_generic_event_t *event)
static void setupLocalizedString()
PluginManager * pluginManager() const
bool dispatchEvent(xcb_generic_event_t *event)
void xwaylandScaleChanged()
InputMethod * inputMethod() const
TabletModeManager * tabletModeManager() const
virtual void startInteractiveWindowSelection(std::function< void(KWin::Window *)> callback, const QByteArray &cursorName=QByteArray())
virtual std::unique_ptr< Edge > createScreenEdge(ScreenEdges *parent)
void setupCommandLine(QCommandLineParser *parser)
bool shouldUseWaylandForCompositing() const
OperationMode operationMode() const
The operation mode used by KWin.
static void setCrashCount(int count)
void applyXwaylandScale()
OperationMode
This enum provides the various operation modes of KWin depending on the available Windowing Systems a...
@ OperationModeXwayland
KWin uses Wayland and controls a nested Xwayland server.
@ OperationModeX11
KWin uses only X11 for managing windows and compositing.
@ OperationModeWaylandOnly
KWin uses only Wayland.
void unregisterEventFilter(X11EventFilter *filter)
CursorScene * cursorScene() const
static bool compositing()
Static check to test whether the Compositor is available and active.
static Compositor * self()
CursorSource * source() const
Cursor * currentCursor() const
Manager class that handles all the effects.
CompositingType compositingType
static std::unique_ptr< GLTexture > allocate(GLenum internalFormat, const QSize &size, int levels=1)
This class is used to show the outline of a given geometry.
Class for controlling screen edges.
static Workspace * self()
bool workspaceEvent(xcb_generic_event_t *)
Output * outputAt(const QPointF &pos) const
X11EventFilter * filter() const
QList< int > genericEventTypes() const
virtual bool event(xcb_generic_event_t *event)=0
bool isGenericEvent() const
QList< int > eventTypes() const
QList< ExtensionData > extensions() const
int damageNotifyEvent() const
int shapeNotifyEvent() const
static Extensions * self()
bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) override
KWIN_EXPORT QRect infiniteRegion()
InputRedirection * input()
KWIN_EXPORT Atoms * atoms