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@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 ); _______________________________________________ Plasma-devel mailing list Plasma-devel@kde.org https://mail.kde.org/mailman/listinfo/plasma-devel