KDE/kdebase/workspace/kwin

Chani Armitage chanika at gmail.com
Fri Sep 24 14:03:23 CEST 2010


SVN commit 1179043 by chani:

Use an X property for activity associations

the new property name is "_KDE_NET_WM_ACTIVITIES", of type XA_STRING,
and it's a comma-separated list of activity UUIDs.

kwin should respond to other processes changing the activity list for a
window, and filter out any bogus IDs. It also caches KActivityController's
list of activities to prevent dbus deadlocks.

CCMAIL: plasma-devel at kde.org

 M  +3 -0      atoms.cpp  
 M  +1 -0      atoms.h  
 M  +40 -6     client.cpp  
 M  +2 -0      client.h  
 M  +2 -0      events.cpp  
 M  +3 -0      manage.cpp  
 M  +8 -0      workspace.cpp  
 M  +4 -0      workspace.h  


--- trunk/KDE/kdebase/workspace/kwin/atoms.cpp #1179042:1179043
@@ -38,6 +38,9 @@
     atoms[n] = &kwin_running;
     names[n++] = (char *) "KWIN_RUNNING";
 
+    atoms[n] = &activities;
+    names[n++] = (char *) "_KDE_NET_WM_ACTIVITIES";
+
     atoms[n] = &wm_protocols;
     names[n++] = (char *) "WM_PROTOCOLS";
 
--- trunk/KDE/kdebase/workspace/kwin/atoms.h #1179042:1179043
@@ -34,6 +34,7 @@
         Atoms();
 
         Atom kwin_running;
+        Atom activities;
 
         Atom wm_protocols;
         Atom wm_delete_window;
--- trunk/KDE/kdebase/workspace/kwin/client.cpp #1179042:1179043
@@ -1523,13 +1523,12 @@
  */
 void Client::setOnActivity( const QString &activity, bool enable )
     {
-    if( activityList.contains(activity) == enable ) //nothing to do
+    QStringList newActivitiesList = activities();
+    if( newActivitiesList.contains(activity) == enable ) //nothing to do
         return;
-    //check whether we should set it to all activities
-    QStringList newActivitiesList = activityList;
     if (enable)
         {
-        QStringList allActivities = KActivityConsumer().availableActivities();
+        QStringList allActivities = workspace()->activityList();
         if( !allActivities.contains(activity) ) //bogus ID
             return;
         newActivitiesList.append(activity);
@@ -1544,13 +1543,19 @@
  */
 void Client::setOnActivities( QStringList newActivitiesList )
     {
-    QStringList allActivities = KActivityConsumer().availableActivities();
+    QStringList allActivities = workspace()->activityList();
     if( newActivitiesList.size() == allActivities.size() || newActivitiesList.isEmpty() )
         {
         setOnAllActivities(true);
         return;
         }
+
+    QByteArray joined = newActivitiesList.join(",").toAscii();
+    char *data = joined.data();
     activityList = newActivitiesList;
+    XChangeProperty(display(), window(), atoms->activities, XA_STRING, 8,
+        PropModeReplace, (unsigned char *)data, joined.size());
+
     updateActivities( false );
     }
 
@@ -1589,7 +1594,6 @@
  * Returns the list of activities the client window is on.
  * if it's on all activities, the list will be empty.
  * Don't use this, use isOnActivity() and friends (from class Toplevel)
- * FIXME do I need to consider if it's not mapped yet?
  */
 QStringList Client::activities() const
     {
@@ -1622,6 +1626,7 @@
     if( on )
         {
         activityList.clear();
+        XDeleteProperty( display(), window(), atoms->activities );
         updateActivities( true );
         }
     else
@@ -2216,6 +2221,35 @@
     return &p;
     }
 
+void Client::checkActivities()
+    {
+    QStringList newActivitiesList;
+    QByteArray prop = getStringProperty(window(), atoms->activities);
+    if ( ! prop.isEmpty() )
+        newActivitiesList = QString(prop).split(',');
+
+    if (newActivitiesList == activityList)
+        return; //expected change, it's ok.
+
+    //otherwise, somebody else changed it. we need to validate before reacting
+    QStringList allActivities = workspace()->activityList();
+    if (allActivities.isEmpty())
+        {
+        kDebug() << "no activities!?!?";
+        //don't touch anything, there's probably something bad going on and we don't wanna make it worse
+        return;
+        }
+    for ( int i = 0; i < newActivitiesList.size(); ++i )
+        {
+        if ( ! allActivities.contains( newActivitiesList.at(i) ) )
+            {
+            kDebug() << "invalid:" << newActivitiesList.at(i);
+            newActivitiesList.removeAt( i-- );
+            }
+        }
+    setOnActivities( newActivitiesList );
+    }
+
 } // namespace
 
 #include "client.moc"
--- trunk/KDE/kdebase/workspace/kwin/client.h #1179042:1179043
@@ -691,6 +691,8 @@
 
         friend bool performTransiencyCheck();
 	friend class SWrapper::Client;
+
+        void checkActivities();
     };
 
 /**
--- trunk/KDE/kdebase/workspace/kwin/events.cpp #1179042:1179043
@@ -942,6 +942,8 @@
                 getMotifHints();
             else if( e->atom == atoms->net_wm_sync_request_counter )
                 getSyncCounter();
+            else if( e->atom == atoms->activities )
+                checkActivities();
             break;
         }
     }
--- trunk/KDE/kdebase/workspace/kwin/manage.cpp #1179042:1179043
@@ -159,6 +159,8 @@
     init_minimize = rules()->checkMinimize( init_minimize, !isMapped );
     noborder = rules()->checkNoBorder( noborder, !isMapped );
 
+    checkActivities();
+
     // Initial desktop placement
     if( session )
         {
@@ -171,6 +173,7 @@
         // If this window is transient, ensure that it is opened on the
         // same window as its parent.  this is necessary when an application
         // starts up on a different desktop than is currently displayed
+        //FIXME do the same for activities too
         if( isTransient() )
             {
             ClientList mainclients = mainClients();
--- trunk/KDE/kdebase/workspace/kwin/workspace.cpp #1179042:1179043
@@ -248,6 +248,7 @@
 
     connect( &activityController_, SIGNAL( currentActivityChanged(QString) ), SLOT( updateCurrentActivity(QString) ));
     connect( &activityController_, SIGNAL( activityRemoved(QString) ), SLOT( activityRemoved(QString) ));
+    connect( &activityController_, SIGNAL( activityAdded(QString) ), SLOT( activityAdded(QString) ));
     }
 
 void Workspace::init()
@@ -372,6 +373,7 @@
         }
     if( !setCurrentDesktop( initial_desktop ))
         setCurrentDesktop( 1 );
+    allActivities_ = activityController_.availableActivities();
     updateCurrentActivity( activityController_.currentActivity() );
 
     // Now we know how many desktops we'll have, thus we initialize the positioning object
@@ -1674,12 +1676,18 @@
  */
 void Workspace::activityRemoved(const QString &activity)
     {
+    allActivities_.removeOne(activity);
     foreach (Client *client, stacking_order)
         {
         client->setOnActivity(activity, false);
         }
     }
 
+void Workspace::activityAdded(const QString &activity)
+    {
+    allActivities_ << activity;
+    }
+
 /**
  * Called only from D-Bus
  */
--- trunk/KDE/kdebase/workspace/kwin/workspace.h #1179042:1179043
@@ -46,6 +46,7 @@
 
 class QMenu;
 class QActionGroup;
+class QStringList;
 class KConfig;
 class KActionCollection;
 class KStartupInfo;
@@ -315,6 +316,7 @@
         int* desktopGrid_;
         int currentDesktop_;
         QString activity_;
+        QStringList allActivities_;
         bool desktopLayoutDynamicity_;
 
         KActivityController activityController_;
@@ -337,6 +339,7 @@
         QRect screenGeometry( int screen ) const;
         int screenNumber( const QPoint& pos ) const;
         QString currentActivity() const { return activity_; }
+        QStringList activityList() const { return allActivities_; }
 
         // Tab box
         Client* currentTabBoxClient() const;
@@ -759,6 +762,7 @@
 
         void updateCurrentActivity(const QString &new_activity);
         void activityRemoved(const QString &activity);
+        void activityAdded(const QString &activity);
 
     protected:
         bool keyPressMouseEmulation( XKeyEvent& ev );


More information about the Plasma-devel mailing list