On Monday 18 July 2011, Aaron J. Seigo wrote:
> On Saturday, July 16, 2011 15:36:19 Martin Gräßlin wrote:
> > The bug is much simpler - Plasma just simply fails to recognize that a
> > compositing manager is active. I can see this each time I restart kwin
> > (which is considerable often). In order to get translucent panels back, I
> > have to kquitapp plasma-desktop, plasma-desktop.
> 
> Plasma::Theme uses a KSelectionWatcher which watches _NET_WM_CM_S# where # is 
> the number of the default screen.
> 
> i can imagine a few things going wrong with this:
> 
> * the default screen # changes or even goes away completely; that could 
> render 
> the selection manager useless. why is the CM atom per screen again? *sigh*

Screen here is about traditional multi-head where you can have different
window managers / compositing managers managing each screen.

> * a race condition as Alex outlined. if kwin is indeed responding to each 
> xrandr even with a change in the CM, that seems like a perfect candidate for 
> event compression if at all possible: don't tell the world outside that 
> things 
> have changed until the events have stopped coming in. the timeout for this 
> shouldn't need to be long at all, so the user shouldn't see a big change at 
> all
> 
> * KSelectionWatcher itself and/or kwin's setting of the atom could be broken. 
> in times past we've had isses where the KSelectionWatcher object simply did 
> not emit any signals at all when kwin changed compositing.

I thought this bug was fixed, because I haven't seen it in a long time.
But I realized that I still have a patch applied that I created a couple
of years ago.

It adds a compositingChanged() signal to KWindowSystem and makes
Plasma::Theme use it. It also uses Xfixes instead of KSelectionWatcher
to monitor the selection.

I never committed the patch because Lubos didn't like the idea. IIRC the
reason was that the signal would be emitted before the compositing
plugins are initialized in kwin.

I have attached the diff in case it fixes the problem for those who are
still seeing it.

Regards,
Fredrik

diff --git a/kdeui/windowmanagement/kwindowsystem.h b/kdeui/windowmanagement/kwindowsystem.h
index dba1da4..6b79cb0 100644
--- a/kdeui/windowmanagement/kwindowsystem.h
+++ b/kdeui/windowmanagement/kwindowsystem.h
@@ -621,6 +621,12 @@ Q_SIGNALS:
      */
     void showingDesktopChanged( bool showing );
 
+    /**
+     * Compositing was enabled or disabled.
+     * @since 4.4
+     */
+    void compositingChanged( bool enabled );
+
 protected:
     virtual void connectNotify( const char* signal );
 
diff --git a/kdeui/windowmanagement/kwindowsystem_x11.cpp b/kdeui/windowmanagement/kwindowsystem_x11.cpp
index 51b8e56..741393c 100644
--- a/kdeui/windowmanagement/kwindowsystem_x11.cpp
+++ b/kdeui/windowmanagement/kwindowsystem_x11.cpp
@@ -36,6 +36,12 @@
 #include <QtGui/QX11Info>
 #include <X11/Xatom.h>
 
+#include <config.h>
+
+#ifdef HAVE_XFIXES
+#include <X11/extensions/Xfixes.h>
+#endif
+
 class KWindowSystemStaticContainer {
 public:
     KWindowSystemStaticContainer() : d(0) {}
@@ -46,6 +52,8 @@ public:
 
 K_GLOBAL_STATIC(KWindowSystemStaticContainer, g_kwmInstanceContainer)
 
+static Atom net_wm_cm;
+static void create_atoms( Display* dpy = QX11Info::display() );
 
 static unsigned long windows_properties[ 2 ] = { NET::ClientList | NET::ClientListStacking |
                                      NET::Supported |
@@ -92,7 +100,10 @@ public:
     QList<StrutData> strutWindows;
     QList<WId> possibleStrutWindows;
     bool strutSignalConnected;
+    bool compositingEnabled;
+    bool haveXfixes;
     int what;
+    int xfixesEventBase;
     bool mapViewport();
 
     void addClient(Window);
@@ -110,10 +121,23 @@ KWindowSystemPrivate::KWindowSystemPrivate(int _what)
                    _what >= KWindowSystem::INFO_WINDOWS ? windows_properties : desktop_properties,
                    2, -1, false ),
       strutSignalConnected( false ),
+      haveXfixes( false ),
       what( _what )
 {
     KSystemEventFilter::installEventFilter(this);
     (void ) qApp->desktop(); //trigger desktop widget creation to select root window events
+
+#ifdef HAVE_XFIXES
+    int errorBase;
+    if ((haveXfixes = XFixesQueryExtension(QX11Info::display(), &xfixesEventBase, &errorBase))) {
+        create_atoms();
+        XFixesSelectSelectionInput(QX11Info::display(), winId(), net_wm_cm,
+                                   XFixesSetSelectionOwnerNotifyMask |
+                                   XFixesSelectionWindowDestroyNotifyMask |
+                                   XFixesSelectionClientCloseNotifyMask);
+        compositingEnabled = XGetSelectionOwner(QX11Info::display(), net_wm_cm) != None;
+    }
+#endif
 }
 
 // not virtual, but it's called directly only from init()
@@ -127,6 +151,18 @@ bool KWindowSystemPrivate::x11Event( XEvent * ev )
 {
     KWindowSystem* s_q = KWindowSystem::self();
 
+#ifdef HAVE_XFIXES
+    if ( ev->type == xfixesEventBase + XFixesSelectionNotify && ev->xany.window == winId() ) {
+        XFixesSelectionNotifyEvent *event = reinterpret_cast<XFixesSelectionNotifyEvent*>(ev);
+        bool haveOwner = event->owner != None;
+        if (compositingEnabled != haveOwner) {
+            compositingEnabled = haveOwner;
+            emit s_q->compositingChanged( compositingEnabled );
+        }
+        return true;
+    }
+#endif
+
     if ( ev->xany.window == QX11Info::appRootWindow() ) {
         int old_current_desktop = currentDesktop();
         WId old_active_window = activeWindow();
@@ -273,9 +309,8 @@ static bool atoms_created = false;
 static Atom kde_wm_change_state;
 static Atom _wm_protocols;
 static Atom kwm_utf8_string;
-static Atom net_wm_cm;
 
-static void create_atoms( Display* dpy = QX11Info::display()) {
+static void create_atoms( Display* dpy ) {
     if (!atoms_created){
 	const int max = 20;
 	Atom* atoms[max];
@@ -759,8 +794,13 @@ void KWindowSystem::lowerWindow( WId win )
 bool KWindowSystem::compositingActive()
 {
     if( QX11Info::display()) {
-        create_atoms();
-        return XGetSelectionOwner( QX11Info::display(), net_wm_cm ) != None;
+        init( INFO_BASIC );
+        if (s_d_func()->haveXfixes) {
+            return s_d_func()->compositingEnabled;
+        } else {
+            create_atoms();
+            return XGetSelectionOwner( QX11Info::display(), net_wm_cm );
+        }
     } else { // work even without QApplication instance
         Display* dpy = XOpenDisplay( NULL );
         create_atoms( dpy );
diff --git a/plasma/theme.cpp b/plasma/theme.cpp
index c7cc7a3..e21e818 100644
--- a/plasma/theme.cpp
+++ b/plasma/theme.cpp
@@ -97,23 +97,13 @@ public:
         ThemeConfig config;
         cacheTheme = config.cacheTheme();
 
-#ifdef Q_WS_X11
-        Display *dpy = QX11Info::display();
-        int screen = DefaultScreen(dpy);
-        locolor = DefaultDepth(dpy, screen) < 16;
-
-        if (!locolor) {
-            char net_wm_cm_name[100];
-            sprintf(net_wm_cm_name, "_NET_WM_CM_S%d", screen);
-            compositeWatch = new KSelectionWatcher(net_wm_cm_name, -1, q);
-            QObject::connect(compositeWatch, SIGNAL(newOwner(Window)), q, SLOT(compositingChanged()));
-            QObject::connect(compositeWatch, SIGNAL(lostOwner()), q, SLOT(compositingChanged()));
+        if (QPixmap::defaultDepth() > 8) {
+            QObject::connect(KWindowSystem::self(), SIGNAL(compositingChanged(bool)), q, SLOT(compositingChanged(bool)));
             //watch for blur effect property changes as well
             effectWatcher = 0;
             effectWatcher = new EffectWatcher("_KDE_NET_WM_BLUR_BEHIND_REGION");
             QObject::connect(effectWatcher, SIGNAL(blurBehindChanged(bool)), q, SLOT(blurBehindChanged(bool)));
         }
-#endif
 
         saveTimer = new QTimer(q);
         saveTimer->setSingleShot(true);
@@ -149,7 +139,7 @@ public:
     }
 
     QString findInTheme(const QString &image, const QString &theme) const;
-    void compositingChanged();
+    void compositingChanged(bool active);
     void discardCache(CacheTypes caches);
     void scheduledCacheUpdate();
     void colorsChanged();
@@ -266,12 +256,11 @@ QString ThemePrivate::findInTheme(const QString &image, const QString &theme) co
     return search;
 }
 
-void ThemePrivate::compositingChanged()
+void ThemePrivate::compositingChanged(bool active)
 {
 #ifdef Q_WS_X11
-    bool nowCompositingActive = compositeWatch->owner() != None;
-    if (compositingActive != nowCompositingActive) {
-        compositingActive = nowCompositingActive;
+    if (compositingActive != active) {
+        compositingActive = active;
         discardCache(PixmapCache | SvgElementsCache);
         emit q->themeChanged();
     }
diff --git a/plasma/theme.h b/plasma/theme.h
index e4618e2..b511827 100644
--- a/plasma/theme.h
+++ b/plasma/theme.h
@@ -397,7 +397,7 @@ class PLASMA_EXPORT Theme : public QObject
         friend class ThemePrivate;
         ThemePrivate *const d;
 
-        Q_PRIVATE_SLOT(d, void compositingChanged())
+        Q_PRIVATE_SLOT(d, void compositingChanged(bool))
         Q_PRIVATE_SLOT(d, void colorsChanged())
         Q_PRIVATE_SLOT(d, void blurBehindChanged(bool blur))
         Q_PRIVATE_SLOT(d, void settingsFileChanged(const QString &))
_______________________________________________
Plasma-devel mailing list
Plasma-devel@kde.org
https://mail.kde.org/mailman/listinfo/plasma-devel

Reply via email to