Fix #49369 and generally try to improve window matching.
Use WM_WINDOW_ROLE also for fake sessions (Save window settings). Remember also window type. svn path=/trunk/kdebase/kwin/; revision=185456
This commit is contained in:
parent
7c33e280ef
commit
dfcc58b00f
3 changed files with 80 additions and 9 deletions
10
client.cpp
10
client.cpp
|
@ -95,6 +95,7 @@ class ClientPrivate
|
|||
{
|
||||
public:
|
||||
ClientPrivate() {};
|
||||
QCString windowRole;
|
||||
};
|
||||
|
||||
};
|
||||
|
@ -118,6 +119,8 @@ static bool blockAnimation = FALSE;
|
|||
|
||||
static QRect* visible_bound = 0;
|
||||
|
||||
static QCString getStringProperty(WId w, Atom prop, char separator=0);
|
||||
|
||||
void Client::drawbound( const QRect& geom )
|
||||
{
|
||||
if ( visible_bound )
|
||||
|
@ -570,6 +573,7 @@ Client::Client( Workspace *ws, WId w, QWidget *parent, const char *name, WFlags
|
|||
getWmNormalHints(); // get xSizeHint
|
||||
getWmClientLeader();
|
||||
fetchName();
|
||||
d->windowRole = getStringProperty( w, qt_window_role );
|
||||
|
||||
if ( mainClient()->isSticky() )
|
||||
setSticky( TRUE );
|
||||
|
@ -1368,6 +1372,8 @@ bool Client::propertyNotify( XPropertyEvent& e )
|
|||
getWindowProtocols();
|
||||
else if (e.atom == atoms->wm_client_leader )
|
||||
getWmClientLeader();
|
||||
else if( e.atom == qt_window_role )
|
||||
d->windowRole = getStringProperty( win, qt_window_role );
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
|
@ -2838,7 +2844,7 @@ void Client::keyPressEvent( uint key_code )
|
|||
QCursor::setPos( pos );
|
||||
}
|
||||
|
||||
static QCString getStringProperty(WId w, Atom prop, char separator=0)
|
||||
static QCString getStringProperty(WId w, Atom prop, char separator)
|
||||
{
|
||||
Atom type;
|
||||
int format, status;
|
||||
|
@ -2947,7 +2953,7 @@ void Client::getWmClientLeader()
|
|||
*/
|
||||
QCString Client::windowRole()
|
||||
{
|
||||
return staticWindowRole(win);
|
||||
return d->windowRole;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
@ -3706,6 +3706,7 @@ void Workspace::storeSession( KConfig* config )
|
|||
config->writeEntry( QString("staysOnTop")+n, c->staysOnTop() );
|
||||
config->writeEntry( QString("skipTaskbar")+n, c->skipTaskbar() );
|
||||
config->writeEntry( QString("skipPager")+n, c->skipPager() );
|
||||
config->writeEntry( QString("windowType")+n, windowTypeToTxt( c->windowType()));
|
||||
}
|
||||
config->writeEntry( "count", count );
|
||||
}
|
||||
|
@ -3742,6 +3743,7 @@ void Workspace::loadSessionInfo()
|
|||
info->staysOnTop = config->readBoolEntry( QString("staysOnTop")+n, FALSE );
|
||||
info->skipTaskbar = config->readBoolEntry( QString("skipTaskbar")+n, FALSE );
|
||||
info->skipPager = config->readBoolEntry( QString("skipPager")+n, FALSE );
|
||||
info->windowType = txtToWindowType( config->readEntry( QString("windowType")+n ).latin1());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3755,6 +3757,7 @@ void Workspace::loadFakeSessionInfo()
|
|||
QString n = QString::number(i);
|
||||
SessionInfo* info = new SessionInfo;
|
||||
fakeSession.append( info );
|
||||
info->windowRole = config->readEntry( QString("windowRole")+n ).latin1();
|
||||
info->resourceName = config->readEntry( QString("resourceName")+n ).latin1();
|
||||
info->resourceClass = config->readEntry( QString("resourceClass")+n ).latin1();
|
||||
info->wmClientMachine = config->readEntry( QString("clientMachine")+n ).latin1();
|
||||
|
@ -3768,6 +3771,7 @@ void Workspace::loadFakeSessionInfo()
|
|||
info->staysOnTop = config->readBoolEntry( QString("staysOnTop")+n, FALSE );
|
||||
info->skipTaskbar = config->readBoolEntry( QString("skipTaskbar")+n, FALSE );
|
||||
info->skipPager = config->readBoolEntry( QString("skipPager")+n, FALSE );
|
||||
info->windowType = txtToWindowType( config->readEntry( QString("windowType")+n ).latin1());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3777,6 +3781,7 @@ void Workspace::storeFakeSessionInfo( Client* c )
|
|||
return;
|
||||
SessionInfo* info = new SessionInfo;
|
||||
fakeSession.append( info );
|
||||
info->windowRole = c->windowRole();
|
||||
info->resourceName = c->resourceName();
|
||||
info->resourceClass = c->resourceClass();
|
||||
info->wmClientMachine = c->wmClientMachine();
|
||||
|
@ -3790,6 +3795,7 @@ void Workspace::storeFakeSessionInfo( Client* c )
|
|||
info->staysOnTop = c->staysOnTop();
|
||||
info->skipTaskbar = c->skipTaskbar();
|
||||
info->skipPager = c->skipPager();
|
||||
info->windowType = c->windowType();
|
||||
}
|
||||
|
||||
void Workspace::writeFakeSessionInfo()
|
||||
|
@ -3800,6 +3806,7 @@ void Workspace::writeFakeSessionInfo()
|
|||
for ( SessionInfo* info = fakeSession.first(); info; info = fakeSession.next() ) {
|
||||
count++;
|
||||
QString n = QString::number(count);
|
||||
config->writeEntry( QString("windowRole")+n, info->windowRole.data() );
|
||||
config->writeEntry( QString("resourceName")+n, info->resourceName.data() );
|
||||
config->writeEntry( QString("resourceClass")+n, info->resourceClass.data() );
|
||||
config->writeEntry( QString("clientMachine")+n, info->wmClientMachine.data() );
|
||||
|
@ -3813,6 +3820,7 @@ void Workspace::writeFakeSessionInfo()
|
|||
config->writeEntry( QString("staysOnTop")+n, info->staysOnTop );
|
||||
config->writeEntry( QString("skipTaskbar")+n, info->skipTaskbar );
|
||||
config->writeEntry( QString("skipPager")+n, info->skipPager );
|
||||
config->writeEntry( QString("windowType")+n, windowTypeToTxt( info->windowType ));
|
||||
}
|
||||
config->writeEntry( "count", count );
|
||||
}
|
||||
|
@ -3843,7 +3851,7 @@ SessionInfo* Workspace::takeSessionInfo( Client* c )
|
|||
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 ( info->sessionId == sessionId && sessionInfoWindowTypeMatch( c, info )) {
|
||||
if ( ! windowRole.isEmpty() ) {
|
||||
if ( info->windowRole == windowRole )
|
||||
realInfo = session.take();
|
||||
|
@ -3859,7 +3867,8 @@ SessionInfo* Workspace::takeSessionInfo( Client* c )
|
|||
for (SessionInfo* info = session.first(); info && !realInfo; info = session.next() )
|
||||
if ( info->resourceName == resourceName &&
|
||||
info->resourceClass == resourceClass &&
|
||||
info->wmClientMachine == wmClientMachine )
|
||||
info->wmClientMachine == wmClientMachine &&
|
||||
sessionInfoWindowTypeMatch( c, info ))
|
||||
if ( wmCommand.isEmpty() || info->wmCommand == wmCommand )
|
||||
realInfo = session.take();
|
||||
}
|
||||
|
@ -3868,7 +3877,8 @@ SessionInfo* Workspace::takeSessionInfo( Client* c )
|
|||
for (SessionInfo* info = fakeSession.first(); info && !fakeInfo; info = fakeSession.next() )
|
||||
if ( info->resourceName == resourceName &&
|
||||
info->resourceClass == resourceClass &&
|
||||
info->wmClientMachine == wmClientMachine )
|
||||
( windowRole.isEmpty() || windowRole == info->windowRole ) &&
|
||||
sessionInfoWindowTypeMatch( c, info ))
|
||||
fakeInfo = fakeSession.take();
|
||||
|
||||
// Reconciliate
|
||||
|
@ -3883,6 +3893,60 @@ SessionInfo* Workspace::takeSessionInfo( Client* c )
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool Workspace::sessionInfoWindowTypeMatch( Client* c, SessionInfo* info )
|
||||
{
|
||||
if( info->windowType == -2 ) { // undefined (not really part of NET::WindowType)
|
||||
return c->windowType() == NET::Unknown || c->windowType() == NET::Normal
|
||||
|| c->windowType() == NET::Dialog || c->windowType() == NET::Override;
|
||||
}
|
||||
return info->windowType == c->windowType();
|
||||
}
|
||||
|
||||
// maybe needed later
|
||||
#if 0
|
||||
// KMainWindow's without name() given have WM_WINDOW_ROLE in the form
|
||||
// of <appname>-mainwindow#<number>
|
||||
// when comparing them for fake session info, it's probably better to check
|
||||
// them without the trailing number
|
||||
bool Workspace::windowRoleMatch( const QCString& role1, const QCString& role2 )
|
||||
{
|
||||
if( role1.isEmpty() && role2.isEmpty())
|
||||
return true;
|
||||
int pos1 = role1.find( '#' );
|
||||
int pos2 = role2.find( '#' );
|
||||
bool ret;
|
||||
if( pos1 < 0 || pos2 < 0 || pos1 != pos2 )
|
||||
ret = role1 == role2;
|
||||
else
|
||||
ret = qstrncmp( role1, role2, pos1 ) == 0;
|
||||
kdDebug() << "WR:" << role1 << ":" << pos1 << ":" << role2 << ":" << pos2 << ":::" << ret << endl;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char* const window_type_names[] = {
|
||||
"Unknown", "Normal" , "Desktop", "Dock", "Toolbar", "Menu", "Dialog",
|
||||
"Override", "TopMenu" };
|
||||
|
||||
const char* Workspace::windowTypeToTxt( NET::WindowType type )
|
||||
{
|
||||
if( type >= NET::Unknown && type <= NET::TopMenu )
|
||||
return window_type_names[ type + 1 ]; // +1 (unknown==-1)
|
||||
if( type == -2 ) // undefined (not really part of NET::WindowType)
|
||||
return "Undefined";
|
||||
kdFatal() << "Unknown Window Type" << endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NET::WindowType Workspace::txtToWindowType( const char* txt )
|
||||
{
|
||||
for( int i = NET::Unknown;
|
||||
i <= NET::TopMenu;
|
||||
++i )
|
||||
if( qstrcmp( txt, window_type_names[ i + 1 ] ) == 0 ) // +1
|
||||
return static_cast< NET::WindowType >( i );
|
||||
return static_cast< NET::WindowType >( -2 ); // undefined
|
||||
}
|
||||
|
||||
/*!
|
||||
Updates the current client area according to the current clients.
|
||||
|
|
|
@ -17,6 +17,7 @@ Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
|
|||
#include "KWinInterface.h"
|
||||
#include <kshortcut.h>
|
||||
#include <qcursor.h>
|
||||
#include <netwm_def.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
|
@ -54,7 +55,6 @@ public:
|
|||
|
||||
typedef QValueList<SystemTrayWindow> SystemTrayWindowList;
|
||||
|
||||
struct SessionInfoPrivate;
|
||||
struct SessionInfo
|
||||
{
|
||||
QCString sessionId;
|
||||
|
@ -74,9 +74,7 @@ struct SessionInfo
|
|||
bool staysOnTop;
|
||||
bool skipTaskbar;
|
||||
bool skipPager;
|
||||
|
||||
private:
|
||||
SessionInfoPrivate* d;
|
||||
NET::WindowType windowType;
|
||||
};
|
||||
|
||||
|
||||
|
@ -415,6 +413,9 @@ private:
|
|||
void loadFakeSessionInfo();
|
||||
void storeFakeSessionInfo( Client* c );
|
||||
void writeFakeSessionInfo();
|
||||
static const char* windowTypeToTxt( NET::WindowType type );
|
||||
static NET::WindowType txtToWindowType( const char* txt );
|
||||
static bool sessionInfoWindowTypeMatch( Client* c, SessionInfo* info );
|
||||
|
||||
Client* active_client;
|
||||
Client* last_active_client;
|
||||
|
|
Loading…
Reference in a new issue