[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-bugs-dist
Subject: Bug#9394: PATCH] legacy session management in kwin
From: Leon Bottou <leonb () research ! att ! com>
Date: 2001-03-12 20:05:05
[Download RAW message or body]
Attached are my updated patches.
I believe that these make a good candidate for
insertion into the CVS.
- Leon Bottou
FYI: Updated list of changes / cvs
> [atoms.h, atoms.cpp]
> * inserted new atom names.
> [client.h, client.cpp]
> * implemented staticPROPERTYNAME() static methods
> for accession props in any window.
> * re-implemented the PROPERTYNAME() methods to use the above.
> * added support for cached WM_CLIENT_LEADER property.
> * added support for WM_CLIENT_MACHINE property.
> * if sessionId, wmCommand, wmClientMachine is not found
> also look into the leader window
> [workspace.cpp, workspace,h]
> * rewrote code to match window geometry takeSessionInfo().
> * function storeSession() saves more fields
> * session config file now has a new section [LegacySession]
> containing the commands to restart legacy applications.
> * added function restoreLegacySession()
> * added function storeLegacySession()
Compared to my last set of patches, this version
- has a restoreLegacySession() function
- has a better implementation of takeSessionInfo()
- uses more robust stuff in storeLegacySession()
i.e. QTime instead of gettimeofday()
::select located with a method similar to QT's
I did not move the staticPROPERTYNAME() methods into atoms.cpp
because there was too little overlap between these methods
and the atoms defined by atoms.cpp. Such a change does not
make sense unless we make it a lot more pervasive.
- Leon Bottou
["2001-03-12.diff" (text/plain)]
? 2001-03-12.diff
? 2001-03-10.diff
Index: atoms.cpp
===================================================================
RCS file: /home/kde/kdebase/kwin/atoms.cpp,v
retrieving revision 1.13
diff -u -3 -p -r1.13 atoms.cpp
--- atoms.cpp 2000/06/24 17:58:10 1.13
+++ atoms.cpp 2001/03/12 17:14:37
@@ -30,6 +30,12 @@ Atoms::Atoms()
atoms[n] = &wm_change_state;
names[n++] = (char *) "WM_CHANGE_STATE";
+ atoms[n] = &wm_client_leader;
+ names[n++] = (char *) "WM_CLIENT_LEADER";
+
+ atoms[n] = &wm_save_yourself;
+ names[n++] = (char *) "WM_SAVE_YOURSELF";
+
atoms[n] = &motif_wm_hints;
names[n++] = (char *) "_MOTIF_WM_HINTS";
Index: atoms.h
===================================================================
RCS file: /home/kde/kdebase/kwin/atoms.h,v
retrieving revision 1.13
diff -u -3 -p -r1.13 atoms.h
--- atoms.h 2000/06/24 17:58:10 1.13
+++ atoms.h 2001/03/12 17:14:37
@@ -17,6 +17,8 @@ public:
Atom wm_delete_window;
Atom wm_take_focus;
Atom wm_change_state;
+ Atom wm_client_leader;
+ Atom wm_save_yourself;
Atom motif_wm_hints;
Atom net_wm_context_help;
Index: client.cpp
===================================================================
RCS file: /home/kde/kdebase/kwin/client.cpp,v
retrieving revision 1.226
diff -u -3 -p -r1.226 client.cpp
--- client.cpp 2001/03/06 09:17:43 1.226
+++ client.cpp 2001/03/12 17:14:37
@@ -516,6 +516,7 @@ Client::Client( Workspace *ws, WId w, QW
getWMHints();
getWindowProtocols();
getWmNormalHints(); // get xSizeHint
+ getWmClientLeader();
fetchName();
if ( mainClient()->isSticky() )
@@ -1145,6 +1146,8 @@ bool Client::propertyNotify( XPropertyEv
default:
if ( e.atom == atoms->wm_protocols )
getWindowProtocols();
+ else if (e.atom == atoms->wm_client_leader )
+ getWmClientLeader();
break;
}
return TRUE;
@@ -2589,79 +2592,172 @@ void Client::keyPressEvent( QKeyEvent *
QCursor::setPos( pos );
}
-
-QCString Client::windowRole()
+static QCString getStringProperty(WId w, Atom prop, char separator=0)
{
Atom type;
int format;
- unsigned long length, after;
- unsigned char *data;
- QCString result;
- if ( XGetWindowProperty( qt_xdisplay(), win, qt_window_role, 0, 1024,
+ unsigned long nitems = 0;
+ unsigned long extra = 0;
+ unsigned char *data = 0;
+ QCString result = "";
+ if ( XGetWindowProperty( qt_xdisplay(), w, prop, 0, 10000,
FALSE, XA_STRING, &type, &format,
- &length, &after, &data ) == Success ) {
- if ( data )
- result = (const char*) data;
- XFree( data );
+ &nitems, &extra, &data ) == Success ) {
+ if (data && separator) {
+ for (int i=0; i<(int)nitems; i++)
+ if (!data[i] && i+1<(int)nitems)
+ data[i] = separator;
+ }
+ if (data)
+ result = (const char*) data;
+ XFree(data);
}
return result;
}
-QCString Client::sessionId()
+/*!
+ Returns WINDOW_ROLE property for a given window.
+ */
+QCString Client::staticWindowRole(WId w)
+{
+ return getStringProperty(w, qt_window_role);
+}
+
+/*!
+ Returns SM_CLIENT_ID property for a given window.
+ */
+QCString Client::staticSessionId(WId w)
+{
+ return getStringProperty(w, qt_sm_client_id);
+}
+
+/*!
+ Returns WM_COMMAND property for a given window.
+ */
+QCString Client::staticWmCommand(WId w)
+{
+ return getStringProperty(w, XA_WM_COMMAND, ' ');
+}
+
+/*!
+ Returns WM_CLIENT_MACHINE property for a given window.
+ Local machine is always returned as "localhost".
+ */
+QCString Client::staticWmClientMachine(WId w)
+{
+ QCString result = getStringProperty(w, XA_WM_CLIENT_MACHINE);
+ if (result.isEmpty()) {
+ result = "localhost";
+ } else {
+ // special name for the local machine (localhost)
+ char hostnamebuf[80];
+ if (gethostname (hostnamebuf, sizeof hostnamebuf) >= 0) {
+ hostnamebuf[sizeof(hostnamebuf)-1] = 0;
+ if (result == hostnamebuf)
+ result = "localhost";
+ char *dot = strchr(hostnamebuf, '.');
+ if (dot && !(*dot = 0) && result == hostnamebuf)
+ result = "localhost";
+ }
+ }
+ return result;
+}
+
+/*!
+ Returns WM_CLIENT_LEADER property for a given window.
+ */
+Window Client::staticWmClientLeader(WId w)
{
Atom type;
int format;
- unsigned long length, after;
- unsigned char *data;
- QCString result;
- if ( XGetWindowProperty( qt_xdisplay(), win, qt_sm_client_id, 0, 1024,
- FALSE, XA_STRING, &type, &format,
- &length, &after, &data ) == Success ) {
- if ( data )
- result = (const char*) data;
- XFree( data );
+ unsigned long nitems = 0;
+ unsigned long extra = 0;
+ unsigned char *data = 0;
+ Window result = w;
+ if ( XGetWindowProperty( qt_xdisplay(), w, atoms->wm_client_leader, 0, 10000,
+ FALSE, XA_WINDOW, &type, &format,
+ &nitems, &extra, &data ) == Success ) {
+ if (data && nitems > 0)
+ result = *((Window*) data);
+ XFree(data);
}
return result;
}
-
-static int getprop(Window w, Atom a, Atom type, long len, unsigned char **p)
+void Client::getWmClientLeader()
{
- Atom real_type;
- int format;
- unsigned long n, extra;
- int status;
+ wmClientLeaderWin = staticWmClientLeader(win);
+}
- status = XGetWindowProperty(qt_xdisplay(), w, a, 0L, len, False, type, \
&real_type, &format, &n, &extra, p);
- if (status != Success || *p == 0)
- return -1;
- if (n == 0)
- XFree((void*) *p);
- return n;
+/*!
+ Returns WINDOW_ROLE for this client
+ */
+QCString Client::windowRole()
+{
+ return staticWindowRole(win);
}
-QCString Client::wmCommand()
+/*!
+ Returns sessionId for this client,
+ taken either from its window or from the leader window.
+ */
+QCString Client::sessionId()
{
- QCString result;
- char *p;
- int i,n;
- if ((n = getprop(win, XA_WM_COMMAND, XA_STRING, 100L, (unsigned char **)&p)) > 0){
- result = p;
- for ( i = 0; (i += strlen(p+i)+1) < n; result.append(p+i) )
- result.append(" ");
- XFree((char *) p);
- }
- return result;
+ QCString result = staticSessionId(win);
+ if (result.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=win)
+ result = staticSessionId(wmClientLeaderWin);
+ return result;
}
+/*!
+ Returns the classhint resource name for this client,
+ */
QCString Client::resourceName()
{
return resource_name;
}
+/*!
+ Returns the classhint resource class for this client,
+ */
QCString Client::resourceClass()
{
return resource_class;
+}
+
+/*!
+ Returns command property for this client,
+ taken either from its window or from the leader window.
+ */
+QCString Client::wmCommand()
+{
+ QCString result = staticWmCommand(win);
+ if (result.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=win)
+ result = staticWmCommand(wmClientLeaderWin);
+ return result;
+}
+
+/*!
+ Returns client machine for this client,
+ taken either from its window or from the leader window.
+*/
+QCString Client::wmClientMachine()
+{
+ QCString result = staticWmClientMachine(win);
+ if (result.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=win)
+ result = staticWmClientMachine(wmClientLeaderWin);
+ return result;
+}
+
+/*!
+ Returns client leader window for this client.
+ Returns the client window itself if no leader window is defined.
+*/
+Window Client::wmClientLeader()
+{
+ if (wmClientLeaderWin)
+ return wmClientLeaderWin;
+ return win;
}
Index: client.h
===================================================================
RCS file: /home/kde/kdebase/kwin/client.h,v
retrieving revision 1.64
diff -u -3 -p -r1.64 client.h
--- client.h 2001/02/20 01:20:36 1.64
+++ client.h 2001/03/12 17:14:37
@@ -178,9 +178,11 @@ public:
QCString windowRole();
QCString sessionId();
- QCString wmCommand();
QCString resourceName();
QCString resourceClass();
+ QCString wmCommand();
+ QCString wmClientMachine();
+ Window wmClientLeader();
QRect adjustedClientArea( const QRect& area ) const;
@@ -314,6 +316,16 @@ private:
void verifyTransientFor();
friend class WindowWrapper;
QString cap;
+ WId wmClientLeaderWin;
+ void getWmClientLeader();
+
+ public:
+ static QCString staticWindowRole(WId);
+ static QCString staticSessionId(WId);
+ static QCString staticWmCommand(WId);
+ static QCString staticWmClientMachine(WId);
+ static Window staticWmClientLeader(WId);
+
};
inline WId Client::window() const
Index: workspace.cpp
===================================================================
RCS file: /home/kde/kdebase/kwin/workspace.cpp,v
retrieving revision 1.217
diff -u -3 -p -r1.217 workspace.cpp
--- workspace.cpp 2001/03/02 10:35:25 1.217
+++ workspace.cpp 2001/03/12 17:14:38
@@ -3,7 +3,10 @@ kwin - the KDE window manager
Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
******************************************************************/
+
//#define QT_CLEAN_NAMESPACE
+#define select kwin_hide_select
+
#include <kconfig.h>
#include <kglobal.h>
#include <kglobalsettings.h>
@@ -42,6 +45,15 @@ const int XIconicState = IconicState;
#include <kwin.h>
#include <kdebug.h>
+// Possible protoypes for select() were hidden as `kwin_hide_select.
+// Undo the hiding definition and defines an acceptable prototype.
+// This is how QT does this. It should work where QT works.
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#undef select
+extern "C" int select(int,void*,void*,void*,struct timeval*);
+
namespace KWinInternal {
// NET WM Protocol handler class
@@ -280,15 +292,8 @@ Workspace::Workspace( bool restore )
init();
- if ( restore ) { // pseudo session management with wmCommand
- for (SessionInfo* info = session.first(); info; info = session.next() ) {
- if ( info->sessionId.isEmpty() && !info->wmCommand.isEmpty() ) {
- KShellProcess proc;
- proc << QString::fromLatin1( info->wmCommand );
- proc.start(KShellProcess::DontCare);
- }
- }
- }
+ if ( restore )
+ restoreLegacySession(kapp->sessionConfig());
}
void Workspace::init()
@@ -2888,35 +2893,220 @@ void Workspace::slotResetAllClients()
requestFocus( active );
}
+
+/*
+ * Legacy session management
+ */
+
+#ifndef NO_LEGACY_SESSION_MANAGEMENT
+
+#define WM_SAVE_YOURSELF_TIMEOUT 2000
+
+enum WinState { W_INVALID, W_VALID, W_SAVE_YOURSELF, W_SAVE_YOURSELF_OK };
+typedef QMap<WId,WinState> WinMap;
+
+static WinMap *winsPtr = 0;
+
+static int winsErrorHandler(Display *, XErrorEvent *ev)
+{
+ if (winsPtr) {
+ WinMap::Iterator it = winsPtr->find(ev->resourceid);
+ if (it != winsPtr->end())
+ it.data() = W_INVALID;
+ }
+ return 0;
+}
+
/*!
+ Stores legacy session management data
+*/
+void Workspace::storeLegacySession( KConfig* config )
+{
+ // Compute set of leader windows that
+ // might require legacy session management
+ WinMap wins;
+ for (ClientList::Iterator it = clients.begin(); it != clients.end(); ++it) {
+ Client* c = (*it);
+ WId leader = c->wmClientLeader();
+ if (!wins.contains(leader) && c->sessionId().isEmpty())
+ wins.insert(leader, W_VALID);
+ }
+
+ // Open a new display for safely doing the WM_SAVE_YOURSELF protocol
+ XSync(qt_xdisplay(), False);
+ Display *newdisplay = XOpenDisplay(DisplayString(qt_xdisplay()));
+ if (!newdisplay) return;
+ WId root = DefaultRootWindow(newdisplay);
+ XGrabKeyboard(newdisplay, root, False,
+ GrabModeAsync, GrabModeAsync, CurrentTime);
+ XGrabPointer(newdisplay, root, False, Button1Mask|Button2Mask|Button3Mask,
+ GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
+ winsPtr = &wins;
+ XErrorHandler oldHandler = XSetErrorHandler(winsErrorHandler);
+
+ // Send WM_SAVE_YOURSELF messages to relevant windows
+ XEvent ev;
+ int awaiting_replies = 0;
+ for (WinMap::Iterator it = wins.begin(); it != wins.end(); ++it) {
+ if ( atoms->wm_protocols == None || atoms->wm_save_yourself == None)
+ break;
+ if ( it.data() == W_VALID ) {
+ WId w = it.key();
+ Atom *protocols = 0;
+ int nprotocols = 0;
+ XGetWMProtocols(newdisplay, w, &protocols, &nprotocols);
+ for (int i=0; i<nprotocols; i++)
+ if (protocols[i] == atoms->wm_save_yourself) {
+ it.data() = W_SAVE_YOURSELF;
+ break;
+ }
+ XFree((void*) protocols);
+ }
+ if ( it.data() == W_SAVE_YOURSELF ) {
+ WId w = it.key();
+ awaiting_replies += 1;
+ memset(&ev, 0, sizeof(ev));
+ ev.xclient.type = ClientMessage;
+ ev.xclient.window = w;
+ ev.xclient.message_type = atoms->wm_protocols;
+ ev.xclient.format = 32;
+ ev.xclient.data.l[0] = atoms->wm_save_yourself;
+ ev.xclient.data.l[1] = CurrentTime;
+ XSelectInput(newdisplay, w, PropertyChangeMask|StructureNotifyMask);
+ XSendEvent(newdisplay, w, False, 0, &ev);
+ }
+ }
+
+ // Wait for change in WM_COMMAND (with timeout)
+ XFlush(newdisplay);
+ QTime start = QTime::currentTime();
+ while (awaiting_replies > 0) {
+ if (XPending(newdisplay)) {
+ /* Process pending event */
+ XNextEvent(newdisplay, &ev);
+ WinMap::Iterator it = wins.find( ev.xany.window );
+ if (it == wins.end() || it.data() == W_SAVE_YOURSELF_OK)
+ continue;
+ if ( ev.type == UnmapNotify ||
+ ( ev.xany.type == PropertyNotify
+ && ev.xproperty.atom == XA_WM_COMMAND ) ) {
+ awaiting_replies -= 1;
+ it.data() = W_SAVE_YOURSELF_OK;
+ }
+ } else {
+ /* Check timeout */
+ int msecs = start.elapsed();
+ if (msecs >= WM_SAVE_YOURSELF_TIMEOUT)
+ break;
+ /* Wait for more events */
+ struct timeval tmwait;
+ int fd = ConnectionNumber(newdisplay);
+ fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+ tmwait.tv_sec = (WM_SAVE_YOURSELF_TIMEOUT - msecs) / 1000;
+ tmwait.tv_usec = ((WM_SAVE_YOURSELF_TIMEOUT - msecs) % 1000) * 1000;
+ ::select(fd+1, &fds, NULL, &fds, &tmwait);
+ }
+ }
+
+ // Terminate work in new display
+ XAllowEvents(newdisplay, ReplayPointer, CurrentTime);
+ XAllowEvents(newdisplay, ReplayKeyboard, CurrentTime);
+ XSync(newdisplay, False);
+ XCloseDisplay(newdisplay);
+
+ // Write LegacySession data
+ config->setGroup("LegacySession" );
+ int count = 0;
+ for (WinMap::Iterator it = wins.begin(); it != wins.end(); ++it) {
+ if (it.data() != W_INVALID) {
+ WId w = it.key();
+ QCString wmCommand = Client::staticWmCommand(w);
+ QCString wmClientMachine = Client::staticWmClientMachine(w);
+ if ( !wmCommand.isEmpty() && !wmClientMachine.isEmpty() ) {
+ count++;
+ QString n = QString::number(count);
+ config->writeEntry( QString("command")+n, wmCommand.data() );
+ config->writeEntry( QString("clientMachine")+n, wmClientMachine.data() );
+ }
+ }
+ }
+ config->writeEntry( "count", count );
+
+ // Restore old error handler
+ XSync(qt_xdisplay(), False);
+ XSetErrorHandler(oldHandler);
+
+ // Process a few events to update the client list.
+ // All events should be there because of the XSync above.
+ kapp->processEvents(10);
+}
+#endif
+
+/*!
+ Restores legacy session management data (i.e. restart applications)
+*/
+void Workspace::restoreLegacySession( KConfig* config )
+{
+ if (config) {
+ config->setGroup("LegacySession" );
+ int count = config->readNumEntry( "count" );
+ for ( int i = 1; i <= count; i++ ) {
+ QString n = QString::number(i);
+ QCString wmCommand = config->readEntry( QString("command")+n ).latin1();
+ QCString wmClientMachine = config->readEntry( QString("clientMachine")+n \
).latin1(); + if ( !wmCommand.isEmpty() && !wmClientMachine.isEmpty() ) {
+ KShellProcess proc;
+ if ( wmClientMachine != "localhost" )
+ proc << "xon" << wmClientMachine;
+ proc << QString::fromLatin1( wmCommand );
+ proc.start(KShellProcess::DontCare);
+ }
+ }
+ }
+}
+
+/*!
Stores the current session in the config file
\sa loadSessionInfo()
*/
void Workspace::storeSession( KConfig* config )
{
+#ifndef NO_LEGACY_SESSION_MANAGEMENT
+ storeLegacySession(config);
+#endif
config->setGroup("Session" );
int count = 0;
for (ClientList::Iterator it = clients.begin(); it != clients.end(); ++it) {
Client* c = (*it);
QCString sessionId = c->sessionId();
- QCString windowRole = c->windowRole();
QCString wmCommand = c->wmCommand();
- if ( !sessionId.isEmpty() || !wmCommand.isEmpty() ) {
- count++;
- QString n = QString::number(count);
- config->writeEntry( QString("sessionId")+n, sessionId.data() );
- config->writeEntry( QString("windowRole")+n, windowRole.data() );
- config->writeEntry( QString("wmCommand")+n, wmCommand.data() );
- config->writeEntry( QString("geometry")+n, QRect( c->pos(), \
c->windowWrapper()->size() ) );
- config->writeEntry( QString("restore")+n, c->geometryRestore() );
- config->writeEntry( QString("maximize")+n, (int) c->maximizeMode() );
- config->writeEntry( QString("desktop")+n, c->desktop() );
- config->writeEntry( QString("iconified")+n, c->isIconified() );
- config->writeEntry( QString("sticky")+n, c->isSticky() );
- config->writeEntry( QString("shaded")+n, c->isShade() );
- config->writeEntry( QString("staysOnTop")+n, c->staysOnTop() );
- }
+ if ( sessionId.isEmpty() )
+#ifndef NO_LEGACY_SESSION_MANAGEMENT
+ // This is the only connection between the determination of legacy
+ // session managed applications (storeLegacySession) and the
+ // recollection of the window geometries (this function).
+ if ( wmCommand.isEmpty() )
+#endif
+ continue;
+ count++;
+ QString n = QString::number(count);
+ config->writeEntry( QString("sessionId")+n, sessionId.data() );
+ config->writeEntry( QString("windowRole")+n, c->windowRole().data() );
+ config->writeEntry( QString("wmCommand")+n, wmCommand.data() );
+ config->writeEntry( QString("wmClientMachine")+n, \
c->wmClientMachine().data() ); + config->writeEntry( \
QString("resourceName")+n, c->resourceName().data() ); + config->writeEntry( \
QString("resourceClass")+n, c->resourceClass().data() ); + config->writeEntry( \
QString("geometry")+n, QRect( c->pos(), c->windowWrapper()->size() ) ); + \
config->writeEntry( QString("restore")+n, c->geometryRestore() ); + \
config->writeEntry( QString("maximize")+n, (int) c->maximizeMode() ); + \
config->writeEntry( QString("desktop")+n, c->desktop() ); + \
config->writeEntry( QString("iconified")+n, c->isIconified() ); + \
config->writeEntry( QString("sticky")+n, c->isSticky() ); + \
config->writeEntry( QString("shaded")+n, c->isShade() ); + config->writeEntry( \
QString("staysOnTop")+n, c->staysOnTop() ); }
config->writeEntry( "count", count );
}
@@ -2940,6 +3130,9 @@ void Workspace::loadSessionInfo()
info->sessionId = config->readEntry( QString("sessionId")+n ).latin1();
info->windowRole = config->readEntry( QString("windowRole")+n ).latin1();
info->wmCommand = config->readEntry( QString("wmCommand")+n ).latin1();
+ info->wmClientMachine = config->readEntry( QString("wmClientMachine")+n \
).latin1(); + info->resourceName = config->readEntry( \
QString("resourceName")+n ).latin1(); + info->resourceClass = \
config->readEntry( QString("resourceClass")+n ).latin1(); info->geometry = \
config->readRectEntry( QString("geometry")+n ); info->restore = \
config->readRectEntry( QString("restore")+n );
info->maximize = config->readNumEntry( QString("maximize")+n, 0 );
@@ -2963,6 +3156,7 @@ void Workspace::loadFakeSessionInfo()
fakeSession.append( info );
info->resourceName = config->readEntry( QString("resourceName")+n \
).latin1();
info->resourceClass = config->readEntry( QString("resourceClass")+n \
).latin1(); + info->wmClientMachine = config->readEntry( \
QString("clientMachine")+n ).latin1(); info->geometry = config->readRectEntry( \
QString("geometry")+n ); info->restore = config->readRectEntry( QString("restore")+n \
);
info->maximize = config->readNumEntry( QString("maximize")+n, 0 );
@@ -2982,6 +3176,7 @@ void Workspace::storeFakeSessionInfo( Cl
fakeSession.append( info );
info->resourceName = c->resourceName();
info->resourceClass = c->resourceClass();
+ info->wmClientMachine = c->wmClientMachine();
info->geometry = QRect( c->pos(), c->windowWrapper()->size() ) ;
info->restore = c->geometryRestore();
info->maximize = (int)c->maximizeMode();
@@ -3002,6 +3197,7 @@ void Workspace::writeFakeSessionInfo()
QString n = QString::number(count);
config->writeEntry( QString("resourceName")+n, info->resourceName.data() );
config->writeEntry( QString("resourceClass")+n, info->resourceClass.data() \
); + config->writeEntry( QString("clientMachine")+n, \
info->wmClientMachine.data() ); config->writeEntry( QString("geometry")+n, \
info->geometry ); config->writeEntry( QString("restore")+n, info->restore );
config->writeEntry( QString("maximize")+n, info->maximize );
@@ -3015,47 +3211,68 @@ void Workspace::writeFakeSessionInfo()
}
/*!
- Returns the SessionInfo for client \a c. The returned session
+ Returns a SessionInfo for client \a c. The returned session
info is removed from the storage. It's up to the caller to delete it.
+ This function is called when a new window is mapped and must be managed.
+ We try to find a matching entry in the session. We also try to find
+ a matching entry in the fakeSession to see if the user had seclected the
+ ``store settings'' menu entry.
+
May return 0 if there's no session info for the client.
*/
SessionInfo* Workspace::takeSessionInfo( Client* c )
{
-
- if ( !session.isEmpty() ) {
- QCString sessionId = c->sessionId();
- QCString windowRole = c->windowRole();
- QCString wmCommand = c->wmCommand();
-
- for (SessionInfo* info = session.first(); info; info = session.next() ) {
-
- // a real session managed client
- if ( info->sessionId == sessionId &&
- ( ( info->windowRole.isEmpty() && windowRole.isEmpty() )
- || (info->windowRole == windowRole ) ) )
- return session.take();
-
- // pseudo session management
- if ( info->sessionId.isEmpty() && !info->wmCommand.isEmpty() &&
- info->wmCommand == wmCommand &&
- ( ( info->windowRole.isEmpty() && windowRole.isEmpty() )
- || (info->windowRole == windowRole ) ) )
- return session.take();
- }
- }
-
- // fakeSession, the "Store Settings" option in the window operation popup menu
- if ( !fakeSession.isEmpty() ) {
- QCString resourceName = c->resourceName();
- QCString resourceClass = c->resourceClass();
- for (SessionInfo* info = fakeSession.first(); info; info = \
fakeSession.next() ) {
- if ( info->resourceName == resourceName && info->resourceClass == \
resourceClass ) {
- c->setStoreSettings( TRUE );
- return fakeSession.take();
+ SessionInfo *realInfo = 0;
+ SessionInfo *fakeInfo = 0;
+ QCString sessionId = c->sessionId();
+ QCString windowRole = c->windowRole();
+ QCString wmCommand = c->wmCommand();
+ QCString wmClientMachine = c->wmClientMachine();
+ QCString resourceName = c->resourceName();
+ QCString resourceClass = c->resourceClass();
+
+ // First search ``session''
+ if (! sessionId.isEmpty() ) {
+ // look for a real session managed client (algorithm suggested by ICCCM)
+ for (SessionInfo* info = session.first(); info && !realInfo; info = \
session.next() ) + if ( info->sessionId == sessionId ) {
+ if ( ! windowRole.isEmpty() ) {
+ if ( info->windowRole == windowRole )
+ realInfo = session.take();
+ } else {
+ if ( info->windowRole.isEmpty() &&
+ info->resourceName == resourceName &&
+ info->resourceClass == resourceClass )
+ realInfo = session.take();
+ }
}
- }
- }
+ } else {
+ // look for a sessioninfo with matching features.
+ for (SessionInfo* info = session.first(); info && !realInfo; info = \
session.next() ) + if ( info->resourceName == resourceName &&
+ info->resourceClass == resourceClass &&
+ info->wmClientMachine == wmClientMachine )
+ if ( wmCommand.isEmpty() || info->wmCommand == wmCommand )
+ realInfo = session.take();
+ }
+
+ // Now search ``fakeSession''
+ for (SessionInfo* info = fakeSession.first(); info && !fakeInfo; info = \
fakeSession.next() ) + if ( info->resourceName == resourceName &&
+ info->resourceClass == resourceClass &&
+ info->wmClientMachine == wmClientMachine )
+ fakeInfo = fakeSession.take();
+
+ // Reconciliate
+ if (fakeInfo)
+ c->setStoreSettings( TRUE );
+ if (fakeInfo && realInfo)
+ delete fakeInfo;
+ if (realInfo)
+ return realInfo;
+ if (fakeInfo)
+ return fakeInfo;
return 0;
}
Index: workspace.h
===================================================================
RCS file: /home/kde/kdebase/kwin/workspace.h,v
retrieving revision 1.69
diff -u -3 -p -r1.69 workspace.h
--- workspace.h 2001/03/08 14:28:07 1.69
+++ workspace.h 2001/03/12 17:14:38
@@ -56,10 +56,9 @@ struct SessionInfo
{
QCString sessionId;
QCString windowRole;
-
- QCString wmCommand; // compatibility
-
- QCString resourceName; // for faked session info
+ QCString wmCommand;
+ QCString wmClientMachine;
+ QCString resourceName;
QCString resourceClass;
QRect geometry;
@@ -177,6 +176,8 @@ public:
void performWindowOperation( Client* c, Options::WindowOperation op );
+ void restoreLegacySession( KConfig* config );
+ void storeLegacySession( KConfig* config );
void storeSession( KConfig* config );
SessionInfo* takeSessionInfo( Client* );
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic