diff --git a/client.cpp b/client.cpp index b9b4fe7a6b..3641c367bc 100644 --- a/client.cpp +++ b/client.cpp @@ -128,6 +128,8 @@ Client::Client( Workspace* ws ) , demandAttentionKNotifyTimer( NULL ) , paintRedirector( 0 ) , electricMaximizing( false ) + , activitiesDefined( false ) + , needsSessionInteract(false) { // TODO: Do all as initialization scriptCache = new QHash(); @@ -1606,9 +1608,12 @@ void Client::updateActivities( bool includeTransients ) * isOnDesktop() instead. */ int Client::desktop() const - { - return desk; +{ + if (needsSessionInteract) { + return NET::OnAllDesktops; } + return desk; +} /** * Returns the list of activities the client window is on. @@ -1617,6 +1622,9 @@ int Client::desktop() const */ QStringList Client::activities() const { + if (needsSessionInteract) { + return QStringList(); + } return activityList; } @@ -1646,7 +1654,8 @@ void Client::setOnAllActivities( bool on ) if( on ) { activityList.clear(); - XDeleteProperty( display(), window(), atoms->activities ); + XChangeProperty(display(), window(), atoms->activities, XA_STRING, 8, + PropModeReplace, (const unsigned char *)"ALL", 3); updateActivities( true ); } else @@ -2247,9 +2256,25 @@ void Client::checkActivities() { QStringList newActivitiesList; QByteArray prop = getStringProperty(window(), atoms->activities); - if ( ! prop.isEmpty() ) - newActivitiesList = QString(prop).split(','); + activitiesDefined = !prop.isEmpty(); + if (prop == "ALL") { + //copied from setOnAllActivities to avoid a redundant XChangeProperty. + if (!activityList.isEmpty()) { + activityList.clear(); + updateActivities( true ); + } + return; + } + if (prop.isEmpty()) { + //note: this makes it *act* like it's on all activities but doesn't set the property to 'ALL' + if (!activityList.isEmpty()) { + activityList.clear(); + updateActivities( true ); + } + return; + } + newActivitiesList = QString(prop).split(','); if (newActivitiesList == activityList) return; //expected change, it's ok. @@ -2272,6 +2297,11 @@ void Client::checkActivities() setOnActivities( newActivitiesList ); } +void Client::setSessionInteract(bool needed) +{ + needsSessionInteract = needed; +} + } // namespace #include "client.moc" diff --git a/client.h b/client.h index f8d67d3372..d36ab61582 100644 --- a/client.h +++ b/client.h @@ -400,6 +400,9 @@ class Client TabBox::TabBoxClientImpl* tabBoxClient() const { return m_tabBoxClient; } + //sets whether the client should be treated as a SessionInteract window + void setSessionInteract(bool needed); + private slots: void autoRaise(); void shadeHover(); @@ -694,6 +697,9 @@ class Client friend class SWrapper::Client; void checkActivities(); + bool activitiesDefined; //whether the x property was actually set + + bool needsSessionInteract; }; /** diff --git a/manage.cpp b/manage.cpp index fbb531dad0..cd1e75dc9b 100644 --- a/manage.cpp +++ b/manage.cpp @@ -207,7 +207,7 @@ bool Client::manage( Window w, bool isMapped ) desk = info->desktop(); // Window had the initial desktop property, force it if( desktop() == 0 && asn_valid && asn_data.desktop() != 0 ) desk = asn_data.desktop(); - if (!isMapped && !noborder && isNormalWindow() && isOnAllActivities()) { + if (!isMapped && !noborder && isNormalWindow() && !activitiesDefined) { //a new, regular window, when we're not recovering from a crash, //and it hasn't got an activity. let's try giving it the current one. //TODO: decide whether to keep this before the 4.6 release @@ -551,10 +551,33 @@ bool Client::manage( Window w, bool isMapped ) else allow = workspace()->allowClientActivation( this, userTime(), false ); - // If session saving, force showing new windows (i.e. "save file?" dialogs etc.) - // also force if activation is allowed - if( !isOnCurrentDesktop() && !isMapped && !session && ( allow || workspace()->sessionSaving() )) - workspace()->setCurrentDesktop( desktop() ); + if (!(isMapped || session)) { + if (workspace()->sessionSaving()) { + /* + * If we get a new window during session saving, we assume it's some 'save file?' dialog + * which the user really needs to see (to know why logout's stalled). + * We also assume it'll be destroyed when it's done - we never unset this flag. + * + * Given the current session management protocol, I can't see a nicer way of doing this. + * Someday I'd like to see a protocol that tells the windowmanager who's doing SessionInteract. + */ + needsSessionInteract = true; + //show the parent too + ClientList mainclients = mainClients(); + for( ClientList::ConstIterator it = mainclients.constBegin(); + it != mainclients.constEnd(); ++it ) { + (*it)->setSessionInteract(true); + } + } else if (allow) { + // also force if activation is allowed + if( !isOnCurrentDesktop() ) { + workspace()->setCurrentDesktop( desktop() ); + } + /*if (!isOnCurrentActivity()) { + workspace()->setCurrentActivity( activities().first() ); + } FIXME no such method*/ + } + } bool belongs_to_desktop = false; for( ClientList::ConstIterator it = group()->members().constBegin(); diff --git a/sm.cpp b/sm.cpp index ad3b5e2321..163fd403d4 100644 --- a/sm.cpp +++ b/sm.cpp @@ -134,6 +134,7 @@ void Workspace::storeSession( KConfig* config, SMSavePhase phase ) void Workspace::storeClient( KConfigGroup &cg, int num, Client *c ) { + c->setSessionInteract(false); //make sure we get the real values QString n = QString::number(num); cg.writeEntry( QString("sessionId")+n, c->sessionId().constData() ); cg.writeEntry( QString("windowRole")+n, c->windowRole().constData() ); @@ -613,6 +614,15 @@ void SessionSaveDoneHelper::processData() IceProcessMessages( SmcGetIceConnection( conn ), 0, 0 ); } +void Workspace::sessionSaveDone() +{ + session_saving = false; + //remove sessionInteract flag from all clients + foreach( Client* c, clients ) { + c->setSessionInteract(false); + } +} + } // namespace #include "sm.moc" diff --git a/workspace.h b/workspace.h index 12ec259200..0eec15df34 100644 --- a/workspace.h +++ b/workspace.h @@ -1246,11 +1246,6 @@ inline void Workspace::sessionSaveStarted() session_saving = true; } -inline void Workspace::sessionSaveDone() - { - session_saving = false; - } - inline bool Workspace::sessionSaving() const { return session_saving;