From 5cbd28f9a0d4a5e94eab0434493e47cd7b650fe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Fl=C3=B6ser?= Date: Wed, 20 Sep 2017 20:02:02 +0200 Subject: [PATCH] Move X11 specific Workspace initialization code into dedicated method Summary: This is required to start KWin/Wayland without XWayland support or delayed XWayland support. Test Plan: Run kwin_x11 in a nested Xephyr Reviewers: #kwin, #plasma Subscribers: plasma-devel, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D7897 --- main.cpp | 3 - workspace.cpp | 254 +++++++++++++++++++++++++++----------------------- workspace.h | 1 + 3 files changed, 140 insertions(+), 118 deletions(-) diff --git a/main.cpp b/main.cpp index 7e15528e73..765c2af510 100644 --- a/main.cpp +++ b/main.cpp @@ -268,9 +268,6 @@ void Application::notifyKSplash() void Application::createWorkspace() { - // ensure the helper atoms are retrieved before we create the Workspace - atoms->retrieveHelpers(); - // we want all QQuickWindows with an alpha buffer, do here as Workspace might create QQuickWindows QQuickWindow::setDefaultAlphaBuffer(true); diff --git a/workspace.cpp b/workspace.cpp index 8610f79e47..2dc16a31fe 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -133,9 +133,6 @@ Workspace::Workspace(const QString &sessionKey) _self = this; - // first initialize the extensions - Xcb::Extensions::self(); - #ifdef KWIN_BUILD_ACTIVITIES Activities *activities = nullptr; if (kwinApp()->usesKActivities()) { @@ -151,8 +148,6 @@ Workspace::Workspace(const QString &sessionKey) options->loadConfig(); options->loadCompositingConfig(false); - ColorMapper *colormaps = new ColorMapper(this); - connect(this, &Workspace::clientActivated, colormaps, &ColorMapper::update); delayFocusTimer = 0; @@ -163,13 +158,6 @@ Workspace::Workspace(const QString &sessionKey) RuleBook::create(this)->load(); - // Call this before XSelectInput() on the root window - startup = new KStartupInfo( - KStartupInfo::DisableKWinModule | KStartupInfo::AnnounceSilenceChanges, this); - - // Select windowmanager privileges - selectWmInputEventMask(); - ScreenEdges::create(this); // VirtualDesktopManager needs to be created prior to init shortcuts @@ -196,12 +184,6 @@ Workspace::Workspace(const QString &sessionKey) new DBusInterface(this); - // Compatibility - int32_t data = 1; - - xcb_change_property(connection(), XCB_PROP_MODE_APPEND, rootWindow(), atoms->kwin_running, - atoms->kwin_running, 32, 1, &data); - Outline::create(this); initShortcuts(); @@ -211,11 +193,6 @@ Workspace::Workspace(const QString &sessionKey) void Workspace::init() { - if (kwinApp()->operationMode() == Application::OperationModeX11) { - m_wasUserInteractionFilter.reset(new WasUserInteractionX11Filter); - m_movingClientFilter.reset(new MovingClientX11Filter); - } - updateXTime(); // Needed for proper initialization of user_time in Client ctor KSharedConfigPtr config = kwinApp()->config(); kwinApp()->createScreens(); Screens *screens = Screens::self(); @@ -239,12 +216,6 @@ void Workspace::init() connect(options, SIGNAL(separateScreenFocusChanged(bool)), focusChain, SLOT(setSeparateScreenFocus(bool))); focusChain->setSeparateScreenFocus(options->isSeparateScreenFocus()); - const uint32_t nullFocusValues[] = {true}; - m_nullFocus.reset(new Xcb::Window(QRect(-1, -1, 1, 1), XCB_WINDOW_CLASS_INPUT_ONLY, XCB_CW_OVERRIDE_REDIRECT, nullFocusValues)); - m_nullFocus->map(); - - RootInfo *rootInfo = RootInfo::create(); - // create VirtualDesktopManager and perform dependency injection VirtualDesktopManager *vds = VirtualDesktopManager::self(); connect(vds, SIGNAL(desktopsRemoved(uint)), SLOT(moveClientsFromRemovedDesktops())); @@ -252,7 +223,6 @@ void Workspace::init() connect(vds, SIGNAL(currentChanged(uint,uint)), SLOT(slotCurrentDesktopChanged(uint,uint))); vds->setNavigationWrappingAround(options->isRollOverDesktops()); connect(options, SIGNAL(rollOverDesktopsChanged(bool)), vds, SLOT(setNavigationWrappingAround(bool))); - vds->setRootInfo(rootInfo); vds->setConfig(config); // Now we know how many desktops we'll have, thus we initialize the positioning object @@ -262,10 +232,6 @@ void Workspace::init() vds->load(); vds->updateLayout(); - // Extra NETRootInfo instance in Client mode is needed to get the values of the properties - NETRootInfo client_info(connection(), NET::ActiveWindow | NET::CurrentDesktop); - if (!qApp->isSessionRestored()) - m_initialDesktop = client_info.currentDesktop(); if (!VirtualDesktopManager::self()->setCurrent(m_initialDesktop)) VirtualDesktopManager::self()->setCurrent(1); @@ -284,87 +250,8 @@ void Workspace::init() this, SLOT(reconfigure())); active_client = NULL; - rootInfo->setActiveWindow(None); - focusToNull(); - if (!qApp->isSessionRestored()) - ++block_focus; // Because it will be set below - { - // Begin updates blocker block - StackingUpdatesBlocker blocker(this); - - Xcb::Tree tree(rootWindow()); - xcb_window_t *wins = xcb_query_tree_children(tree.data()); - - QVector windowAttributes(tree->children_len); - QVector windowGeometries(tree->children_len); - - // Request the attributes and geometries of all toplevel windows - for (int i = 0; i < tree->children_len; i++) { - windowAttributes[i] = Xcb::WindowAttributes(wins[i]); - windowGeometries[i] = Xcb::WindowGeometry(wins[i]); - } - - // Get the replies - for (int i = 0; i < tree->children_len; i++) { - Xcb::WindowAttributes attr(windowAttributes.at(i)); - - if (attr.isNull()) { - continue; - } - - if (attr->override_redirect) { - if (attr->map_state == XCB_MAP_STATE_VIEWABLE && - attr->_class != XCB_WINDOW_CLASS_INPUT_ONLY) - // ### This will request the attributes again - createUnmanaged(wins[i]); - } else if (attr->map_state != XCB_MAP_STATE_UNMAPPED) { - if (Application::wasCrash()) { - fixPositionAfterCrash(wins[i], windowGeometries.at(i).data()); - } - - // ### This will request the attributes again - createClient(wins[i], true); - } - } - - // Propagate clients, will really happen at the end of the updates blocker block - updateStackingOrder(true); - - saveOldScreenSizes(); - updateClientArea(); - - // NETWM spec says we have to set it to (0,0) if we don't support it - NETPoint* viewports = new NETPoint[VirtualDesktopManager::self()->count()]; - rootInfo->setDesktopViewport(VirtualDesktopManager::self()->count(), *viewports); - delete[] viewports; - QRect geom; - for (int i = 0; i < screens->count(); i++) { - geom |= screens->geometry(i); - } - NETSize desktop_geometry; - desktop_geometry.width = geom.width(); - desktop_geometry.height = geom.height(); - rootInfo->setDesktopGeometry(desktop_geometry); - setShowingDesktop(false); - - } // End updates blocker block - - AbstractClient* new_active_client = nullptr; - if (!qApp->isSessionRestored()) { - --block_focus; - new_active_client = findClient(Predicate::WindowMatch, client_info.activeWindow()); - } - if (new_active_client == NULL - && activeClient() == NULL && should_get_focus.count() == 0) { - // No client activated in manage() - if (new_active_client == NULL) - new_active_client = topClientOnDesktop(VirtualDesktopManager::self()->current(), -1); - if (new_active_client == NULL && !desktops.isEmpty()) - new_active_client = findDesktop(true, VirtualDesktopManager::self()->current()); - } - if (new_active_client != NULL) - activateClient(new_active_client); + initWithX11(); Scripting::create(this); @@ -461,6 +348,141 @@ void Workspace::init() // TODO: ungrabXServer() } +void Workspace::initWithX11() +{ + if (!kwinApp()->x11Connection()) { + connect(kwinApp(), &Application::x11ConnectionChanged, this, &Workspace::initWithX11, Qt::UniqueConnection); + return; + } + disconnect(kwinApp(), &Application::x11ConnectionChanged, this, &Workspace::initWithX11); + + atoms->retrieveHelpers(); + + // first initialize the extensions + Xcb::Extensions::self(); + ColorMapper *colormaps = new ColorMapper(this); + connect(this, &Workspace::clientActivated, colormaps, &ColorMapper::update); + + // Call this before XSelectInput() on the root window + startup = new KStartupInfo( + KStartupInfo::DisableKWinModule | KStartupInfo::AnnounceSilenceChanges, this); + + // Select windowmanager privileges + selectWmInputEventMask(); + + // Compatibility + int32_t data = 1; + + xcb_change_property(connection(), XCB_PROP_MODE_APPEND, rootWindow(), atoms->kwin_running, + atoms->kwin_running, 32, 1, &data); + + if (kwinApp()->operationMode() == Application::OperationModeX11) { + m_wasUserInteractionFilter.reset(new WasUserInteractionX11Filter); + m_movingClientFilter.reset(new MovingClientX11Filter); + } + updateXTime(); // Needed for proper initialization of user_time in Client ctor + + const uint32_t nullFocusValues[] = {true}; + m_nullFocus.reset(new Xcb::Window(QRect(-1, -1, 1, 1), XCB_WINDOW_CLASS_INPUT_ONLY, XCB_CW_OVERRIDE_REDIRECT, nullFocusValues)); + m_nullFocus->map(); + + RootInfo *rootInfo = RootInfo::create(); + VirtualDesktopManager::self()->setRootInfo(rootInfo); + + // TODO: only in X11 mode + // Extra NETRootInfo instance in Client mode is needed to get the values of the properties + NETRootInfo client_info(connection(), NET::ActiveWindow | NET::CurrentDesktop); + if (!qApp->isSessionRestored()) + m_initialDesktop = client_info.currentDesktop(); + if (!VirtualDesktopManager::self()->setCurrent(m_initialDesktop)) + VirtualDesktopManager::self()->setCurrent(1); + + // TODO: better value + rootInfo->setActiveWindow(None); + focusToNull(); + + if (!qApp->isSessionRestored()) + ++block_focus; // Because it will be set below + + { + // Begin updates blocker block + StackingUpdatesBlocker blocker(this); + + Xcb::Tree tree(rootWindow()); + xcb_window_t *wins = xcb_query_tree_children(tree.data()); + + QVector windowAttributes(tree->children_len); + QVector windowGeometries(tree->children_len); + + // Request the attributes and geometries of all toplevel windows + for (int i = 0; i < tree->children_len; i++) { + windowAttributes[i] = Xcb::WindowAttributes(wins[i]); + windowGeometries[i] = Xcb::WindowGeometry(wins[i]); + } + + // Get the replies + for (int i = 0; i < tree->children_len; i++) { + Xcb::WindowAttributes attr(windowAttributes.at(i)); + + if (attr.isNull()) { + continue; + } + + if (attr->override_redirect) { + if (attr->map_state == XCB_MAP_STATE_VIEWABLE && + attr->_class != XCB_WINDOW_CLASS_INPUT_ONLY) + // ### This will request the attributes again + createUnmanaged(wins[i]); + } else if (attr->map_state != XCB_MAP_STATE_UNMAPPED) { + if (Application::wasCrash()) { + fixPositionAfterCrash(wins[i], windowGeometries.at(i).data()); + } + + // ### This will request the attributes again + createClient(wins[i], true); + } + } + + // Propagate clients, will really happen at the end of the updates blocker block + updateStackingOrder(true); + + saveOldScreenSizes(); + updateClientArea(); + + // NETWM spec says we have to set it to (0,0) if we don't support it + NETPoint* viewports = new NETPoint[VirtualDesktopManager::self()->count()]; + rootInfo->setDesktopViewport(VirtualDesktopManager::self()->count(), *viewports); + delete[] viewports; + QRect geom; + for (int i = 0; i < screens()->count(); i++) { + geom |= screens()->geometry(i); + } + NETSize desktop_geometry; + desktop_geometry.width = geom.width(); + desktop_geometry.height = geom.height(); + rootInfo->setDesktopGeometry(desktop_geometry); + setShowingDesktop(false); + + } // End updates blocker block + + // TODO: only on X11? + AbstractClient* new_active_client = nullptr; + if (!qApp->isSessionRestored()) { + --block_focus; + new_active_client = findClient(Predicate::WindowMatch, client_info.activeWindow()); + } + if (new_active_client == NULL + && activeClient() == NULL && should_get_focus.count() == 0) { + // No client activated in manage() + if (new_active_client == NULL) + new_active_client = topClientOnDesktop(VirtualDesktopManager::self()->current(), -1); + if (new_active_client == NULL && !desktops.isEmpty()) + new_active_client = findDesktop(true, VirtualDesktopManager::self()->current()); + } + if (new_active_client != NULL) + activateClient(new_active_client); +} + Workspace::~Workspace() { blockStackingUpdates(true); @@ -1207,7 +1229,9 @@ bool Workspace::checkStartupNotification(xcb_window_t w, KStartupInfoId &id, KSt */ void Workspace::focusToNull() { - m_nullFocus->focus(); + if (m_nullFocus) { + m_nullFocus->focus(); + } } void Workspace::setShowingDesktop(bool showing) diff --git a/workspace.h b/workspace.h index e70cf7daf3..012210d958 100644 --- a/workspace.h +++ b/workspace.h @@ -494,6 +494,7 @@ Q_SIGNALS: private: void init(); + void initWithX11(); void initShortcuts(); template void initShortcut(const QString &actionName, const QString &description, const QKeySequence &shortcut,