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 svn path=/trunk/KDE/kdebase/workspace/; revision=1179043
This commit is contained in:
parent
19a9fb6e37
commit
3c633a48ab
8 changed files with 64 additions and 7 deletions
|
@ -38,6 +38,9 @@ Atoms::Atoms()
|
|||
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";
|
||||
|
||||
|
|
1
atoms.h
1
atoms.h
|
@ -34,6 +34,7 @@ class Atoms
|
|||
Atoms();
|
||||
|
||||
Atom kwin_running;
|
||||
Atom activities;
|
||||
|
||||
Atom wm_protocols;
|
||||
Atom wm_delete_window;
|
||||
|
|
46
client.cpp
46
client.cpp
|
@ -1523,13 +1523,12 @@ void Client::setDesktop( int desktop )
|
|||
*/
|
||||
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::setOnActivity( const QString &activity, bool enable )
|
|||
*/
|
||||
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 @@ int Client::desktop() const
|
|||
* 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 @@ void Client::setOnAllActivities( bool on )
|
|||
if( on )
|
||||
{
|
||||
activityList.clear();
|
||||
XDeleteProperty( display(), window(), atoms->activities );
|
||||
updateActivities( true );
|
||||
}
|
||||
else
|
||||
|
@ -2216,6 +2221,35 @@ QPixmap* kwin_get_menu_pix_hack()
|
|||
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"
|
||||
|
|
4
client.h
4
client.h
|
@ -690,7 +690,9 @@ class Client
|
|||
ElectricMaximizingMode electricMode;
|
||||
|
||||
friend bool performTransiencyCheck();
|
||||
friend class SWrapper::Client;
|
||||
friend class SWrapper::Client;
|
||||
|
||||
void checkActivities();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -942,6 +942,8 @@ void Client::propertyNotifyEvent( XPropertyEvent* e )
|
|||
getMotifHints();
|
||||
else if( e->atom == atoms->net_wm_sync_request_counter )
|
||||
getSyncCounter();
|
||||
else if( e->atom == atoms->activities )
|
||||
checkActivities();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -159,6 +159,8 @@ bool Client::manage( Window w, bool isMapped )
|
|||
init_minimize = rules()->checkMinimize( init_minimize, !isMapped );
|
||||
noborder = rules()->checkNoBorder( noborder, !isMapped );
|
||||
|
||||
checkActivities();
|
||||
|
||||
// Initial desktop placement
|
||||
if( session )
|
||||
{
|
||||
|
@ -171,6 +173,7 @@ bool Client::manage( Window w, bool isMapped )
|
|||
// 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();
|
||||
|
|
|
@ -248,6 +248,7 @@ Workspace::Workspace( bool restore )
|
|||
|
||||
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 @@ void Workspace::init()
|
|||
}
|
||||
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::updateCurrentActivity(const QString &new_activity)
|
|||
*/
|
||||
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
|
||||
*/
|
||||
|
|
|
@ -46,6 +46,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
class QMenu;
|
||||
class QActionGroup;
|
||||
class QStringList;
|
||||
class KConfig;
|
||||
class KActionCollection;
|
||||
class KStartupInfo;
|
||||
|
@ -315,6 +316,7 @@ class Workspace : public QObject, public KDecorationDefines
|
|||
int* desktopGrid_;
|
||||
int currentDesktop_;
|
||||
QString activity_;
|
||||
QStringList allActivities_;
|
||||
bool desktopLayoutDynamicity_;
|
||||
|
||||
KActivityController activityController_;
|
||||
|
@ -337,6 +339,7 @@ class Workspace : public QObject, public KDecorationDefines
|
|||
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 @@ class Workspace : public QObject, public KDecorationDefines
|
|||
|
||||
void updateCurrentActivity(const QString &new_activity);
|
||||
void activityRemoved(const QString &activity);
|
||||
void activityAdded(const QString &activity);
|
||||
|
||||
protected:
|
||||
bool keyPressMouseEmulation( XKeyEvent& ev );
|
||||
|
|
Loading…
Reference in a new issue