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
This commit is contained in:
Martin Gräßlin 2013-04-29 12:17:42 +02:00
parent 2320b71cb7
commit b6681ddc3a
8 changed files with 154 additions and 113 deletions

View file

@ -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);

View file

@ -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)

View file

@ -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();

View file

@ -157,7 +157,7 @@ void Workspace::updateStackingOrder(bool propagate_new_clients)
*/
void Workspace::stackScreenEdgesUnderOverrideRedirect()
{
Xcb::restackWindows(QVector<xcb_window_t>() << supportWindow->winId() << ScreenEdges::self()->windows());
Xcb::restackWindows(QVector<xcb_window_t>() << 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

View file

@ -21,15 +21,135 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
// own
#include "netinfo.h"
// kwin libs
#include <kdecorationfactory.h>
// 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<xcb_generic_error_t> 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)
{
}

View file

@ -25,6 +25,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <KDE/NETRootInfo>
#include <xcb/xcb.h>
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
*/

View file

@ -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) {

View file

@ -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;