From b6681ddc3a6969e852966326d51c3ba062408d13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Mon, 29 Apr 2013 12:17:42 +0200 Subject: [PATCH] Turn RootInfo into a KWIN_SINGLETON It's not a typical singleton as the ctor is not taking a Workspace* and needs addtional data to be passed to NETRootInfo. All the initialization code is moved to RootInfo::create() and the tear- down code is moved to RootInfo::destroyed(). This includes the support window which used to be a member of Workspace. It's only needed by RootInfo, so there is no need to have the ownership inside Workspace. Instead of using a QWidget we just create a normal window through xcb. It gets destroyed again in the tear-down code after the RootInfo got destroyed. REVIEW: 110238 --- activation.cpp | 2 +- events.cpp | 2 +- geometry.cpp | 4 +- layers.cpp | 10 ++-- netinfo.cpp | 122 ++++++++++++++++++++++++++++++++++++++++++++++++- netinfo.h | 17 ++++++- workspace.cpp | 106 ++++-------------------------------------- workspace.h | 4 -- 8 files changed, 154 insertions(+), 113 deletions(-) diff --git a/activation.cpp b/activation.cpp index 57a09c5890..4972842824 100644 --- a/activation.cpp +++ b/activation.cpp @@ -263,7 +263,7 @@ void Workspace::setActiveClient(Client* c) updateStackingOrder(); // e.g. fullscreens have different layer when active/not-active - rootInfo->setActiveWindow(active_client ? active_client->window() : 0); + rootInfo()->setActiveWindow(active_client ? active_client->window() : 0); updateColormap(); emit clientActivated(active_client); diff --git a/events.cpp b/events.cpp index 67aa5e5c00..0858f1baff 100644 --- a/events.cpp +++ b/events.cpp @@ -87,7 +87,7 @@ bool Workspace::workspaceEvent(XEvent * e) if (e->type == PropertyNotify || e->type == ClientMessage) { unsigned long dirty[ NETRootInfo::PROPERTIES_SIZE ]; - rootInfo->event(e, dirty, NETRootInfo::PROPERTIES_SIZE); + rootInfo()->event(e, dirty, NETRootInfo::PROPERTIES_SIZE); if (dirty[ NETRootInfo::PROTOCOLS ] & NET::DesktopNames) VirtualDesktopManager::self()->save(); if (dirty[ NETRootInfo::PROTOCOLS2 ] & NET::WM2DesktopLayout) diff --git a/geometry.cpp b/geometry.cpp index 1233d601a7..3ff95cce01 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -77,7 +77,7 @@ void Workspace::desktopResized() NETSize desktop_geometry; desktop_geometry.width = geom.width(); desktop_geometry.height = geom.height(); - rootInfo->setDesktopGeometry(-1, desktop_geometry); + rootInfo()->setDesktopGeometry(-1, desktop_geometry); updateClientArea(); saveOldScreenSizes(); // after updateClientArea(), so that one still uses the previous one @@ -231,7 +231,7 @@ void Workspace::updateClientArea(bool force) r.pos.y = workarea[ i ].y(); r.size.width = workarea[ i ].width(); r.size.height = workarea[ i ].height(); - rootInfo->setWorkArea(i, r); + rootInfo()->setWorkArea(i, r); } for (ClientList::ConstIterator it = clients.constBegin(); diff --git a/layers.cpp b/layers.cpp index c1c4782b07..225c869c4a 100644 --- a/layers.cpp +++ b/layers.cpp @@ -157,7 +157,7 @@ void Workspace::updateStackingOrder(bool propagate_new_clients) */ void Workspace::stackScreenEdgesUnderOverrideRedirect() { - Xcb::restackWindows(QVector() << supportWindow->winId() << ScreenEdges::self()->windows()); + Xcb::restackWindows(QVector() << rootInfo()->supportWindow() << ScreenEdges::self()->windows()); } #endif @@ -176,7 +176,7 @@ void Workspace::propagateClients(bool propagate_new_clients) // but it was lowered after kwin startup. Stacking all clients below // it ensures that no client will be ever shown above override-redirect // windows (e.g. popups). - newWindowStack << supportWindow->winId(); + newWindowStack << rootInfo()->supportWindow(); #ifdef KWIN_BUILD_SCREENEDGES newWindowStack << ScreenEdges::self()->windows(); @@ -208,7 +208,7 @@ void Workspace::propagateClients(bool propagate_new_clients) } // TODO isn't it too inefficient to restack always all clients? // TODO don't restack not visible windows? - assert(newWindowStack.at(0) == supportWindow->winId()); + assert(newWindowStack.at(0) == rootInfo()->supportWindow()); Xcb::restackWindows(newWindowStack); int pos = 0; @@ -220,7 +220,7 @@ void Workspace::propagateClients(bool propagate_new_clients) cl[pos++] = (*it)->window(); for (ClientList::ConstIterator it = clients.constBegin(); it != clients.constEnd(); ++it) cl[pos++] = (*it)->window(); - rootInfo->setClientList(cl, pos); + rootInfo()->setClientList(cl, pos); delete [] cl; } @@ -230,7 +230,7 @@ void Workspace::propagateClients(bool propagate_new_clients) if ((*it)->isClient()) cl[pos++] = (*it)->window(); } - rootInfo->setClientListStacking(cl, pos); + rootInfo()->setClientListStacking(cl, pos); delete [] cl; // Make the cached stacking order invalid here, in case we need the new stacking order before we get diff --git a/netinfo.cpp b/netinfo.cpp index dd674ef367..666385098c 100644 --- a/netinfo.cpp +++ b/netinfo.cpp @@ -21,15 +21,135 @@ along with this program. If not, see . *********************************************************************/ // own #include "netinfo.h" +// kwin libs +#include // kwin #include "client.h" +#include "decorations.h" #include "virtualdesktops.h" #include "workspace.h" namespace KWin { +extern int screen_number; -RootInfo::RootInfo(Window w, const char *name, unsigned long pr[], int pr_num, int scr) +RootInfo *RootInfo::s_self = NULL; + +RootInfo *RootInfo::create() +{ + Q_ASSERT(!s_self); + xcb_window_t supportWindow = xcb_generate_id(connection()); + const uint32_t values[] = {true}; + xcb_create_window(connection(), XCB_COPY_FROM_PARENT, supportWindow, KWin::rootWindow(), + 0, 0, 0, 0, 0, XCB_COPY_FROM_PARENT, + XCB_COPY_FROM_PARENT, XCB_CW_OVERRIDE_REDIRECT, values); + + const uint32_t lowerValues[] = { XCB_STACK_MODE_BELOW }; // See usage in layers.cpp + // we need to do the lower window with a roundtrip, otherwise NETRootInfo is not functioning + QScopedPointer error(xcb_request_check(connection(), + xcb_configure_window_checked(connection(), supportWindow, XCB_CONFIG_WINDOW_STACK_MODE, lowerValues))); + if (!error.isNull()) { + kDebug(1212) << "Error occurred while lowering support window: " << error->error_code; + } + + unsigned long protocols[5] = { + NET::Supported | + NET::SupportingWMCheck | + NET::ClientList | + NET::ClientListStacking | + NET::DesktopGeometry | + NET::NumberOfDesktops | + NET::CurrentDesktop | + NET::ActiveWindow | + NET::WorkArea | + NET::CloseWindow | + NET::DesktopNames | + NET::WMName | + NET::WMVisibleName | + NET::WMDesktop | + NET::WMWindowType | + NET::WMState | + NET::WMStrut | + NET::WMIconGeometry | + NET::WMIcon | + NET::WMPid | + NET::WMMoveResize | + NET::WMFrameExtents | + NET::WMPing + , + NET::NormalMask | + NET::DesktopMask | + NET::DockMask | + NET::ToolbarMask | + NET::MenuMask | + NET::DialogMask | + NET::OverrideMask | + NET::UtilityMask | + NET::SplashMask | + // No compositing window types here unless we support them also as managed window types + 0 + , + NET::Modal | + //NET::Sticky | // Large desktops not supported (and probably never will be) + NET::MaxVert | + NET::MaxHoriz | + NET::Shaded | + NET::SkipTaskbar | + NET::KeepAbove | + //NET::StaysOnTop | // The same like KeepAbove + NET::SkipPager | + NET::Hidden | + NET::FullScreen | + NET::KeepBelow | + NET::DemandsAttention | + 0 + , + NET::WM2UserTime | + NET::WM2StartupId | + NET::WM2AllowedActions | + NET::WM2RestackWindow | + NET::WM2MoveResizeWindow | + NET::WM2ExtendedStrut | + NET::WM2KDETemporaryRules | + NET::WM2ShowingDesktop | + NET::WM2DesktopLayout | + NET::WM2FullPlacement | + NET::WM2FullscreenMonitors | + NET::WM2KDEShadow | + 0 + , + NET::ActionMove | + NET::ActionResize | + NET::ActionMinimize | + NET::ActionShade | + //NET::ActionStick | // Sticky state is not supported + NET::ActionMaxVert | + NET::ActionMaxHoriz | + NET::ActionFullScreen | + NET::ActionChangeDesktop | + NET::ActionClose | + 0 + , + }; + + DecorationPlugin *deco = DecorationPlugin::self(); + if (!deco->isDisabled() && deco->factory()->supports(KDecorationDefines::AbilityExtendIntoClientArea)) + protocols[ NETRootInfo::PROTOCOLS2 ] |= NET::WM2FrameOverlap; + + s_self = new RootInfo(supportWindow, "KWin", protocols, 5, screen_number); + return s_self; +} + +void RootInfo::destroy() +{ + Q_ASSERT(s_self); + xcb_window_t supportWindow = s_self->supportWindow(); + delete s_self; + s_self = NULL; + xcb_destroy_window(connection(), supportWindow); +} + +RootInfo::RootInfo(xcb_window_t w, const char *name, unsigned long pr[], int pr_num, int scr) : NETRootInfo(display(), w, name, pr, pr_num, scr) { } diff --git a/netinfo.h b/netinfo.h index 5539154c98..c992eeb10a 100644 --- a/netinfo.h +++ b/netinfo.h @@ -25,6 +25,8 @@ along with this program. If not, see . #include +#include + namespace KWin { @@ -39,8 +41,8 @@ private: typedef KWin::Client Client; // Because of NET::Client public: - RootInfo(Window w, const char* name, unsigned long pr[], - int pr_num, int scr = -1); + static RootInfo *create(); + static void destroy(); protected: virtual void changeNumberOfDesktops(int n); @@ -53,8 +55,19 @@ protected: virtual void restackWindow(Window w, RequestSource source, Window above, int detail, Time timestamp); virtual void gotTakeActivity(Window w, Time timestamp, long flags); virtual void changeShowingDesktop(bool showing); + +private: + RootInfo(xcb_window_t w, const char* name, unsigned long pr[], + int pr_num, int scr = -1); + static RootInfo *s_self; + friend RootInfo *rootInfo(); }; +inline RootInfo *rootInfo() +{ + return RootInfo::s_self; +} + /** * NET WM Protocol handler class */ diff --git a/workspace.cpp b/workspace.cpp index ffaddd6035..b4fdc2fdc3 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -237,98 +237,11 @@ void Workspace::init() connect(options, SIGNAL(separateScreenFocusChanged(bool)), focusChain, SLOT(setSeparateScreenFocus(bool))); focusChain->setSeparateScreenFocus(options->isSeparateScreenFocus()); - supportWindow = new QWidget(NULL, Qt::X11BypassWindowManagerHint); - XLowerWindow(display(), supportWindow->winId()); // See usage in layers.cpp - 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(); - unsigned long protocols[5] = { - NET::Supported | - NET::SupportingWMCheck | - NET::ClientList | - NET::ClientListStacking | - NET::DesktopGeometry | - NET::NumberOfDesktops | - NET::CurrentDesktop | - NET::ActiveWindow | - NET::WorkArea | - NET::CloseWindow | - NET::DesktopNames | - NET::WMName | - NET::WMVisibleName | - NET::WMDesktop | - NET::WMWindowType | - NET::WMState | - NET::WMStrut | - NET::WMIconGeometry | - NET::WMIcon | - NET::WMPid | - NET::WMMoveResize | - NET::WMFrameExtents | - NET::WMPing - , - NET::NormalMask | - NET::DesktopMask | - NET::DockMask | - NET::ToolbarMask | - NET::MenuMask | - NET::DialogMask | - NET::OverrideMask | - NET::UtilityMask | - NET::SplashMask | - // No compositing window types here unless we support them also as managed window types - 0 - , - NET::Modal | - //NET::Sticky | // Large desktops not supported (and probably never will be) - NET::MaxVert | - NET::MaxHoriz | - NET::Shaded | - NET::SkipTaskbar | - NET::KeepAbove | - //NET::StaysOnTop | // The same like KeepAbove - NET::SkipPager | - NET::Hidden | - NET::FullScreen | - NET::KeepBelow | - NET::DemandsAttention | - 0 - , - NET::WM2UserTime | - NET::WM2StartupId | - NET::WM2AllowedActions | - NET::WM2RestackWindow | - NET::WM2MoveResizeWindow | - NET::WM2ExtendedStrut | - NET::WM2KDETemporaryRules | - NET::WM2ShowingDesktop | - NET::WM2DesktopLayout | - NET::WM2FullPlacement | - NET::WM2FullscreenMonitors | - NET::WM2KDEShadow | - 0 - , - NET::ActionMove | - NET::ActionResize | - NET::ActionMinimize | - NET::ActionShade | - //NET::ActionStick | // Sticky state is not supported - NET::ActionMaxVert | - NET::ActionMaxHoriz | - NET::ActionFullScreen | - NET::ActionChangeDesktop | - NET::ActionClose | - 0 - , - }; - - DecorationPlugin *deco = DecorationPlugin::self(); - if (!deco->isDisabled() && deco->factory()->supports(AbilityExtendIntoClientArea)) - protocols[ NETRootInfo::PROTOCOLS2 ] |= NET::WM2FrameOverlap; - - rootInfo = new RootInfo(supportWindow->winId(), "KWin", protocols, 5, screen_number); + RootInfo *rootInfo = RootInfo::create(); // create VirtualDesktopManager and perform dependency injection VirtualDesktopManager *vds = VirtualDesktopManager::self(); @@ -502,8 +415,7 @@ Workspace::~Workspace() delete RuleBook::self(); KGlobal::config()->sync(); - delete rootInfo; - delete supportWindow; + RootInfo::destroy(); delete startup; delete Placement::self(); delete client_keys_dialog; @@ -918,9 +830,9 @@ void Workspace::slotReconfigure() } if (!deco->isDisabled()) { - rootInfo->setSupported(NET::WM2FrameOverlap, deco->factory()->supports(AbilityExtendIntoClientArea)); + rootInfo()->setSupported(NET::WM2FrameOverlap, deco->factory()->supports(AbilityExtendIntoClientArea)); } else { - rootInfo->setSupported(NET::WM2FrameOverlap, false); + rootInfo()->setSupported(NET::WM2FrameOverlap, false); } } @@ -1019,7 +931,7 @@ void Workspace::updateClientVisibilityOnDesktopChange(uint oldDesktop, uint newD } } // Now propagate the change, after hiding, before showing - rootInfo->setCurrentDesktop(VirtualDesktopManager::self()->current()); + rootInfo()->setCurrentDesktop(VirtualDesktopManager::self()->current()); if (movingClient && !movingClient->isOnDesktop(newDesktop)) { movingClient->setDesktop(newDesktop); @@ -1330,12 +1242,12 @@ void Workspace::sendClientToScreen(Client* c, int screen) void Workspace::sendPingToWindow(xcb_window_t window, xcb_timestamp_t timestamp) { - rootInfo->sendPing(window, timestamp); + rootInfo()->sendPing(window, timestamp); } void Workspace::sendTakeActivity(KWin::Client *c, xcb_timestamp_t timestamp, long int flags) { - rootInfo->takeActivity(c->window(), timestamp, flags); + rootInfo()->takeActivity(c->window(), timestamp, flags); pending_take_activity = c; } @@ -1380,7 +1292,7 @@ void Workspace::focusToNull() void Workspace::setShowingDesktop(bool showing) { - rootInfo->setShowingDesktop(showing); + rootInfo()->setShowingDesktop(showing); showing_desktop = showing; ++block_showing_desktop; if (showing_desktop) { @@ -1433,7 +1345,7 @@ void Workspace::resetShowingDesktop(bool keep_hidden) { if (block_showing_desktop > 0) return; - rootInfo->setShowingDesktop(false); + rootInfo()->setShowingDesktop(false); showing_desktop = false; ++block_showing_desktop; if (!keep_hidden) { diff --git a/workspace.h b/workspace.h index 076aa0b30e..a5e0d98bf4 100644 --- a/workspace.h +++ b/workspace.h @@ -53,7 +53,6 @@ class Window; class Client; class KillWindow; -class RootInfo; class ShortcutDialog; class UserActionsMenu; class Compositor; @@ -531,9 +530,6 @@ private: bool global_shortcuts_disabled; bool global_shortcuts_disabled_for_client; - RootInfo* rootInfo; - QWidget* supportWindow; - // Colormap handling Colormap default_colormap; Colormap installed_colormap;