I guess I could finally find some time to work on things for 3.3.

Initial work on kwin rules, i.e. #36377 , per window specific settings.
So far only desktop/above/below work, no GUI, and settings from the old
'Save window settings' are ignored for now.

svn path=/trunk/kdebase/kwin/; revision=315446
icc-effect-5.14.5
Luboš Luňák 2004-05-28 13:51:11 +00:00
parent 76ed413d94
commit 8e09a9bc22
15 changed files with 409 additions and 198 deletions

View File

@ -11,7 +11,7 @@ kwin_la_SOURCES = workspace.cpp client.cpp placement.cpp atoms.cpp \
options.cpp plugins.cpp events.cpp KWinInterface.skel \
killwindow.cpp geometrytip.cpp sm.cpp group.cpp bridge.cpp \
manage.cpp notifications.cpp activation.cpp useractions.cpp \
geometry.cpp
geometry.cpp rules.cpp
kwin_la_LIBADD = $(LIB_KDEUI) lib/libkdecorations.la
kwin_la_LDFLAGS = $(all_libraries) -module -avoid-version

View File

@ -320,7 +320,11 @@ void Workspace::takeActivity( Client* c, int flags, bool handled )
if( modal != NULL && modal != c )
{
if( !modal->isOnDesktop( c->desktop()))
{
modal->setDesktop( c->desktop());
if( modal->desktop() != c->desktop()) // forced desktop
activateClient( modal );
}
// if the click was inside the window (i.e. handled is set),
// but it has a modal, there's no need to use handled mode, because
// the modal doesn't get the click anyway
@ -663,7 +667,7 @@ KWIN_COMPARE_PREDICATE( SameApplicationActiveHackPredicate, const Client*,
&& Client::belongToSameApplication( cl, value, true ) && cl != value);
Time Client::readUserTimeMapTimestamp( const KStartupInfoId* asn_id, const KStartupInfoData* asn_data,
const SessionInfo* session ) const
bool session ) const
{
Time time = info->userTime();
kdDebug( 1212 ) << "User timestamp, initial:" << time << endl;
@ -727,7 +731,7 @@ Time Client::readUserTimeMapTimestamp( const KStartupInfoId* asn_id, const KStar
// Unless it was the active window at the time
// of session saving and there was no user interaction yet,
// this check will be done in Workspace::allowClientActiovationTimestamp().
if( session && !session->fake )
if( session )
return -1U;
if( ignoreFocusStealing() && act != NULL )
time = act->userTime();

View File

@ -27,6 +27,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include "workspace.h"
#include "atoms.h"
#include "notifications.h"
#include "rules.h"
#include <X11/extensions/shape.h>
@ -78,6 +79,7 @@ Client::Client( Workspace *ws )
transient_for( NULL ),
transient_for_id( None ),
original_transient_for_id( None ),
client_rules( NULL ),
in_group( NULL ),
window_group( None ),
in_layer( UnknownLayer ),
@ -133,10 +135,8 @@ Client::Client( Workspace *ws )
Pcontexthelp = 0;
Pping = 0;
input = FALSE;
store_settings = FALSE;
skip_pager = FALSE;
max_mode = MaximizeRestore;
cmap = None;
@ -175,6 +175,7 @@ void Client::releaseWindow( bool on_shutdown )
{
if (moveResizeMode)
leaveMoveResize();
updateWindowRules();
setModal( false ); // otherwise its mainwindow wouldn't get focus
hidden = true; // so that it's not considered visible anymore (can't use hideClient(), it would set flags)
if( !on_shutdown )
@ -222,6 +223,7 @@ void Client::destroyClient()
{
if (moveResizeMode)
leaveMoveResize();
updateWindowRules();
++block_geometry;
setModal( false );
hidden = true; // so that it's not considered visible anymore
@ -1077,15 +1079,11 @@ void Client::setModal( bool m )
// _NET_WM_STATE_MODAL should possibly rather be _NET_WM_WINDOW_TYPE_MODAL_DIALOG
}
void Client::toggleOnAllDesktops()
{
setOnAllDesktops( !isOnAllDesktops());
}
void Client::setDesktop( int desktop )
{
if( desktop != NET::OnAllDesktops ) // do range check
desktop = KMAX( 1, KMIN( workspace()->numberOfDesktops(), desktop ));
desktop = rules()->checkDesktop( desktop );
if( desk == desktop )
return;
int was_desk = desk;
@ -1264,9 +1262,9 @@ void Client::fetchIconicName()
/*!\reimp
*/
QString Client::caption() const
QString Client::caption( bool full ) const
{
return cap_normal + cap_suffix;
return full ? cap_normal + cap_suffix : cap_normal;
}
void Client::getWMHints()

View File

@ -39,6 +39,7 @@ class Client;
class WinInfo;
class SessionInfo;
class Bridge;
class WindowRules;
class Client : public QObject, public KDecorationDefines
{
@ -66,6 +67,7 @@ class Client : public QObject, public KDecorationDefines
void checkGroup( Group* gr = NULL, bool force = false );
// prefer isXXX() instead
NET::WindowType windowType( bool strict = false, int supported_types = SUPPORTED_WINDOW_TYPES_MASK ) const;
const WindowRules* rules() const;
QRect geometry() const;
QSize size() const;
@ -160,9 +162,6 @@ class Client : public QObject, public KDecorationDefines
void setModal( bool modal );
bool isModal() const;
bool storeSettings() const;
void setStoreSettings( bool );
// auxiliary functions, depend on the windowType
bool wantsTabFocus() const;
bool wantsInput() const;
@ -237,7 +236,7 @@ class Client : public QObject, public KDecorationDefines
// updates visibility depending on whether it's on the current desktop
void virtualDesktopChange();
QString caption() const;
QString caption( bool full = true ) const;
void keyPressEvent( uint key_code ); // FRAME ??
void updateMouseGrab();
@ -275,7 +274,6 @@ class Client : public QObject, public KDecorationDefines
void closeWindow();
void killWindow();
void maximize( MaximizeMode );
void toggleOnAllDesktops();
void toggleShade();
void showContextHelp();
void cancelAutoRaise();
@ -343,6 +341,8 @@ private slots:
void fetchName();
void fetchIconicName();
bool hasTransientInternal( const Client* c, bool indirect, ConstClientList& set ) const;
void initWindowRules();
void updateWindowRules();
void updateWorkareaDiffs();
void checkDirection( int new_diff, int old_diff, QRect& rect, const QRect& area );
@ -380,7 +380,7 @@ private slots:
void rawHide(); // just hides it
Time readUserTimeMapTimestamp( const KStartupInfoId* asn_id, const KStartupInfoData* asn_data,
const SessionInfo* session ) const;
bool session ) const;
Time readUserCreationTime() const;
static bool sameAppWindowRoleMatch( const Client* c1, const Client* c2, bool active_hack );
void startupIdChanged();
@ -438,7 +438,6 @@ private slots:
uint Pcontexthelp : 1; // does the window understand the ContextHelp protocol?
uint Pping : 1; // does it support _NET_WM_PING?
uint input :1; // does the window want input in its wm_hints
uint store_settings : 1;
uint skip_pager : 1;
uint motif_may_resize : 1;
uint motif_may_move :1;
@ -453,6 +452,7 @@ private slots:
uint urgency : 1; // XWMHints, UrgencyHint
uint ignore_focus_stealing : 1; // don't apply focus stealing prevention to this client
uint check_active_modal : 1; // see Client::addTransient()
WindowRules* client_rules;
void getWMHints();
void readIcons();
void getWindowProtocols();
@ -685,17 +685,6 @@ inline bool Client::keepBelow() const
return keep_below;
}
inline bool Client::storeSettings() const
{
return store_settings;
}
inline void Client::setStoreSettings( bool b )
{
store_settings = b;
}
inline bool Client::shape() const
{
return is_shape;
@ -837,6 +826,11 @@ inline bool Client::ignoreFocusStealing() const
return ignore_focus_stealing;
}
inline const WindowRules* Client::rules() const
{
return client_rules;
}
KWIN_PROCEDURE( CheckIgnoreFocusStealingProcedure, cl->ignore_focus_stealing = options->checkIgnoreFocusStealing( cl ));
inline Window Client::moveResizeGrabWindow() const

View File

@ -20,6 +20,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include "atoms.h"
#include "tabbox.h"
#include "group.h"
#include "rules.h"
#include <qwhatsthis.h>
#include <kkeynative.h>

View File

@ -64,13 +64,15 @@ License. See the file "COPYING" for the exact licensing terms.
#include <assert.h>
#include <kdebug.h>
#include "utils.h"
#include "client.h"
#include "workspace.h"
#include "tabbox.h"
#include "popupinfo.h"
#include "group.h"
#include <kdebug.h>
#include "rules.h"
extern Time qt_x_time;
@ -642,22 +644,36 @@ void Client::restackWindow( Window /*above TODO */, int detail, NET::RequestSour
void Client::setKeepAbove( bool b )
{
if ( b == keepAbove() )
b = rules()->checkKeepAbove( b );
if( b )
setKeepBelow( false );
if ( b == keepAbove()
|| ( b && keepBelow())) // forced below
{ // force hint change if different
if( bool( info->state() & NET::KeepAbove ) != keepAbove())
info->setState( keepAbove() ? NET::KeepAbove : 0, NET::KeepAbove );
return;
setKeepBelow( false );
}
keep_above = b;
info->setState( b ? NET::KeepAbove : 0, NET::KeepAbove );
info->setState( keepAbove() ? NET::KeepAbove : 0, NET::KeepAbove );
// TODO emit a signal about the change to the style plugin
workspace()->updateClientLayer( this );
}
void Client::setKeepBelow( bool b )
{
if ( b == keepBelow() )
b = rules()->checkKeepBelow( b );
if( b )
setKeepAbove( false );
if ( b == keepBelow()
|| ( b && keepAbove())) // forced above
{ // force hint change if different
if( bool( info->state() & NET::KeepBelow ) != keepBelow())
info->setState( keepBelow() ? NET::KeepBelow : 0, NET::KeepBelow );
return;
setKeepAbove( false );
}
keep_below = b;
info->setState( b ? NET::KeepBelow : 0, NET::KeepBelow );
info->setState( keepBelow() ? NET::KeepBelow : 0, NET::KeepBelow );
workspace()->updateClientLayer( this );
}

View File

@ -86,7 +86,8 @@ public:
KeepAboveOp,
KeepBelowOp,
OperationsOp,
ToggleStoreSettingsOp,
WindowRulesOp,
ToggleStoreSettingsOp = WindowRulesOp, ///< @obsolete
HMaximizeOp,
VMaximizeOp,
LowerOp,

View File

@ -22,6 +22,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include <X11/extensions/shape.h>
#include "notifications.h"
#include "rules.h"
extern Time qt_x_time;
extern Atom qt_window_role;
@ -105,8 +106,11 @@ bool Client::manage( Window w, bool isMapped )
}
ignore_focus_stealing = options->checkIgnoreFocusStealing( this );
detectNoBorder();
fetchName();
window_role = getStringProperty( w, qt_window_role );
initWindowRules();
detectNoBorder();
fetchIconicName();
getWMHints(); // needs to be done before readTransient() because of reading the group
getWmClientLeader(); // needs to be done before readTransient() because of same app comparing
@ -114,7 +118,6 @@ bool Client::manage( Window w, bool isMapped )
getIcons();
getWindowProtocols();
getWmNormalHints(); // get xSizeHint
window_role = getStringProperty( w, qt_window_role );
// TODO try to obey all state information from info->state()
@ -122,13 +125,6 @@ bool Client::manage( Window w, bool isMapped )
skip_pager = ( info->state() & NET::SkipPager) != 0;
modal = ( info->state() & NET::Modal ) != 0;
// window wants to stay on top?
keep_above = ( info->state() & NET::KeepAbove ) != 0;
// window wants to stay on bottom?
keep_below = ( info->state() & NET::KeepBelow ) != 0;
if( keep_above && keep_below )
keep_above = keep_below = false;
KStartupInfoId asn_id;
KStartupInfoData asn_data;
bool asn_valid = workspace()->checkStartupNotification( window(), asn_id, asn_data );
@ -136,6 +132,7 @@ bool Client::manage( Window w, bool isMapped )
workspace()->updateClientLayer( this );
SessionInfo* session = workspace()->takeSessionInfo( this );
if ( session )
{
if ( session->minimized )
@ -186,6 +183,7 @@ bool Client::manage( Window w, bool isMapped )
desk = workspace()->currentDesktop();
if( desk != NET::OnAllDesktops ) // do range check
desk = KMAX( 1, KMIN( workspace()->numberOfDesktops(), desk ));
desk = rules()->checkDesktop( desk, !isMapped );
info->setDesktop( desk );
workspace()->updateOnAllDesktopsOfTransients( this ); // SELI
// onAllDesktopsChange(); decoration doesn't exist here yet
@ -308,6 +306,8 @@ bool Client::manage( Window w, bool isMapped )
// other settings from the previous session
if ( session )
{
// session restored windows are not considered to be new windows WRT rules,
// i.e. obey only forcing rules
setKeepAbove( session->keepAbove );
setKeepBelow( session->keepBelow );
setSkipTaskbar( session->skipTaskbar, true );
@ -368,10 +368,8 @@ bool Client::manage( Window w, bool isMapped )
// read other initial states
if( info->state() & NET::Shaded )
setShade( ShadeNormal );
if( info->state() & NET::KeepAbove )
setKeepAbove( true );
if( info->state() & NET::KeepBelow )
setKeepBelow( true );
setKeepAbove( rules()->checkKeepAbove( info->state() & NET::KeepAbove, !isMapped ));
setKeepBelow( rules()->checkKeepBelow( info->state() & NET::KeepBelow, !isMapped ));
if( info->state() & NET::SkipTaskbar )
setSkipTaskbar( true, true );
if( info->state() & NET::SkipPager )
@ -433,7 +431,7 @@ bool Client::manage( Window w, bool isMapped )
{
workspace()->restackClientUnderActive( this );
rawShow();
if( ( !session || session->fake ) && ( !isSpecialWindow() || isOverride()))
if( !session && ( !isSpecialWindow() || isOverride()))
demandAttention();
}
}
@ -442,7 +440,7 @@ bool Client::manage( Window w, bool isMapped )
{
virtualDesktopChange();
workspace()->raiseClient( this );
if( ( !session || session->fake ) && !isMapped )
if( !session && !isMapped )
demandAttention();
}
}

238
rules.cpp Normal file
View File

@ -0,0 +1,238 @@
/*****************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2004 Lubos Lunak <l.lunak@kde.org>
You can Freely distribute this program under the GNU General Public
License. See the file "COPYING" for the exact licensing terms.
******************************************************************/
#include "rules.h"
#include <kconfig.h>
#include <qregexp.h>
#include "client.h"
#include "workspace.h"
namespace KWinInternal
{
static WindowRules dummyRules; // dummy used to avoid NULL checks
WindowRules::WindowRules()
: wmclassregexp( false )
, windowroleregexp( false )
, titleregexp( false )
, extraroleregexp( false )
, desktoprule( DontCareRule )
, aboverule( DontCareRule )
, belowrule( DontCareRule )
{
}
WindowRules::WindowRules( KConfig& cfg )
: wmclassregexp( false )
, windowroleregexp( false )
, titleregexp( false )
, extraroleregexp( false )
, desktoprule( DontCareRule )
, aboverule( DontCareRule )
, belowrule( DontCareRule )
{
wmclass = cfg.readEntry( "wmclass" ).lower().latin1();
wmclassregexp = cfg.readBoolEntry( "wmclassregexp" );
windowrole = cfg.readEntry( "windowrole" ).lower().latin1();
windowroleregexp = cfg.readBoolEntry( "windowroleregexp" );
title = cfg.readEntry( "title" );
titleregexp = cfg.readBoolEntry( "titleregexp" );
extrarole = cfg.readEntry( "extrarole" ).lower().latin1();
extraroleregexp = cfg.readBoolEntry( "extraroleregexp" );
desktop = cfg.readNumEntry( "desktop" );
desktoprule = readRule( cfg, "desktoprule" );
above = cfg.readBoolEntry( "above" );
aboverule = readRule( cfg, "aboverule" );
below = cfg.readBoolEntry( "below" );
belowrule = readRule( cfg, "belowrule" );
kdDebug() << "READ RULE:" << wmclass << endl;
}
#define WRITE_MATCH_STRING( var, cast ) \
if( !var.isEmpty()) \
{ \
cfg.writeEntry( #var, cast var ); \
cfg.writeEntry( #var "regexp", var##regexp ); \
} \
else \
{ \
cfg.deleteEntry( #var ); \
cfg.deleteEntry( #var "regexp" ); \
}
#define WRITE_SET_RULE( var ) \
if( var##rule != DontCareRule ) \
{ \
cfg.writeEntry( #var, var ); \
cfg.writeEntry( #var "rule", var##rule ); \
} \
else \
{ \
cfg.deleteEntry( #var ); \
cfg.deleteEntry( #var "rule" ); \
}
void WindowRules::write( KConfig& cfg ) const
{
// always write wmclass
cfg.writeEntry( "wmclass", ( const char* )wmclass );
cfg.writeEntry( "wmclassregexp", wmclassregexp );
WRITE_MATCH_STRING( windowrole, (const char*) );
WRITE_MATCH_STRING( title, );
WRITE_MATCH_STRING( extrarole, (const char*) );
WRITE_SET_RULE( desktop );
WRITE_SET_RULE( above );
WRITE_SET_RULE( below );
}
#undef WRITE_MATCH_STRING
#undef WRITE_SET_RULE
SettingRule WindowRules::readRule( KConfig& cfg, const QString& key )
{
int v = cfg.readNumEntry( key );
if( v >= DontCareRule && v <= LastRule )
return static_cast< SettingRule >( v );
return DontCareRule;
}
void WindowRules::update( Client* c )
{
// TODO check this setting is for this client ?
if( desktoprule == RememberRule )
desktop = c->desktop();
if( aboverule == RememberRule )
above = c->keepAbove();
if( belowrule == RememberRule )
below = c->keepBelow();
}
bool WindowRules::match( const Client* c ) const
{
// TODO exactMatch() for regexp?
if( !wmclass.isEmpty())
{ // TODO optimize?
if( wmclassregexp && !QRegExp( wmclass ).exactMatch( c->resourceClass()))
return false;
if( !wmclassregexp && wmclass != c->resourceClass())
return false;
}
if( !windowrole.isEmpty())
{
if( windowroleregexp && QRegExp( windowrole ).exactMatch( c->windowRole()))
return false;
if( !windowroleregexp && windowrole != c->windowRole())
return false;
}
if( !title.isEmpty())
{
if( titleregexp && QRegExp( title ).exactMatch( c->caption( false )))
return false;
if( !titleregexp && title != c->caption( false ))
return false;
}
// TODO extrarole
return true;
}
int WindowRules::checkDesktop( int req_desktop, bool init ) const
{
// TODO chaining?
return checkRule( desktoprule, init ) ? desktop : req_desktop;
}
bool WindowRules::checkKeepAbove( bool req_above, bool init ) const
{
return checkRule( aboverule, init ) ? above : req_above;
}
bool WindowRules::checkKeepBelow( bool req_below, bool init ) const
{
return checkRule( belowrule, init ) ? below : req_below;
}
// Client
void Client::initWindowRules()
{
client_rules = workspace()->findWindowRules( this );
}
void Client::updateWindowRules()
{
client_rules->update( this );
}
// Workspace
WindowRules* Workspace::findWindowRules( const Client* c ) const
{
if( c->isTopMenu()) // TODO cannot have restrictions
return &dummyRules;
for( QValueList< WindowRules* >::ConstIterator it = windowRules.begin();
it != windowRules.end();
++it )
{
// chaining for wildcard matches
if( (*it)->match( c ))
{
kdDebug() << "RULE FOUND:" << c << endl;
return *it;
}
}
kdDebug() << "RULE DUMMY:" << c << endl;
return &dummyRules;
}
void Workspace::editWindowRules( Client* c )
{
// TODO
}
void Workspace::loadWindowRules()
{
while( !windowRules.isEmpty())
{
delete windowRules.front();
windowRules.pop_front();
}
KConfig cfg( "kwinrulesrc", true );
cfg.setGroup( "General" );
int count = cfg.readNumEntry( "count" );
kdDebug() << "RULES:" << count << endl;
for( int i = 1;
i <= count;
++i )
{
cfg.setGroup( QString::number( i ));
WindowRules* setting = new WindowRules( cfg );
windowRules.append( setting );
}
}
void Workspace::writeWindowRules()
{
KConfig cfg( "kwinrulesrc" );
cfg.setGroup( "General" );
cfg.writeEntry( "count", windowRules.count());
int i = 1;
for( QValueList< WindowRules* >::ConstIterator it = windowRules.begin();
it != windowRules.end();
++it, ++i )
{
cfg.setGroup( QString::number( i ));
(*it)->write( cfg );
}
}
} // namespace

77
rules.h Normal file
View File

@ -0,0 +1,77 @@
/*****************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2004 Lubos Lunak <l.lunak@kde.org>
You can Freely distribute this program under the GNU General Public
License. See the file "COPYING" for the exact licensing terms.
******************************************************************/
#ifndef KWIN_RULES_H
#define KWIN_RULES_H
#include <qstring.h>
class KConfig;
namespace KWinInternal
{
class Client;
enum SettingRule
{
DontCareRule,
ApplyRule,
ForceRule,
RememberRule,
LastRule = RememberRule
};
class WindowRules
{
public:
WindowRules();
WindowRules( KConfig& );
void write( KConfig& ) const;
void update( Client* );
bool match( const Client* c ) const;
int checkDesktop( int desktop, bool init = false ) const;
bool checkKeepAbove( bool above, bool init = false ) const;
bool checkKeepBelow( bool above, bool init = false ) const;
private:
static SettingRule readRule( KConfig&, const QString& key );
static bool checkRule( SettingRule rule, bool init );
QCString wmclass;
bool wmclassregexp;
// TODO bool wmclasscomplete - class+name
QCString windowrole;
bool windowroleregexp;
QString title; // TODO "caption" ?
bool titleregexp;
QCString extrarole;
bool extraroleregexp;
// TODO window type? both to which it applies and to which value to force it
int desktop;
SettingRule desktoprule;
bool above;
SettingRule aboverule;
bool below;
SettingRule belowrule;
};
inline
bool WindowRules::checkRule( SettingRule rule, bool init )
{
if( rule != DontCareRule )
{
if( rule == ForceRule || init )
return true;
}
return false;
}
} // namespace
#endif

121
sm.cpp
View File

@ -178,121 +178,21 @@ void Workspace::loadSessionInfo()
info->userNoBorder = config->readBoolEntry( QString("userNoBorder")+n, FALSE );
info->windowType = txtToWindowType( config->readEntry( QString("windowType")+n ).latin1());
info->active = ( active_client == i );
info->fake = false;
}
}
void Workspace::loadFakeSessionInfo()
{
fakeSession.clear();
KConfig *config = KGlobal::config();
config->setGroup("FakeSession" );
int count = config->readNumEntry( "count" );
for ( int i = 1; i <= count; i++ )
{
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 ).lower().latin1();
info->wmClientMachine = config->readEntry( QString("clientMachine")+n ).latin1();
info->geometry = config->readRectEntry( QString("geometry")+n );
info->restore = config->readRectEntry( QString("restore")+n );
info->fsrestore = config->readRectEntry( QString("fsrestore")+n );
info->maximized = config->readNumEntry( QString("maximize")+n, 0 );
info->fullscreen = config->readNumEntry( QString("fullscreen")+n, 0 );
info->desktop = config->readNumEntry( QString("desktop")+n, 0 );
info->minimized = config->readBoolEntry( QString("iconified")+n, FALSE );
info->onAllDesktops = config->readBoolEntry( QString("sticky")+n, FALSE );
info->shaded = config->readBoolEntry( QString("shaded")+n, FALSE );
info->keepAbove = config->readBoolEntry( QString("staysOnTop")+n, FALSE );
info->keepBelow = config->readBoolEntry( QString("keepBelow")+n, FALSE );
info->skipTaskbar = config->readBoolEntry( QString("skipTaskbar")+n, FALSE );
info->skipPager = config->readBoolEntry( QString("skipPager")+n, FALSE );
info->userNoBorder = config->readBoolEntry( QString("userNoBorder")+n, FALSE );
info->windowType = txtToWindowType( config->readEntry( QString("windowType")+n ).latin1());
info->active = false;
info->fake = true;
}
}
void Workspace::storeFakeSessionInfo( Client* c )
{
if ( !c->storeSettings() )
return;
SessionInfo* info = new SessionInfo;
fakeSession.append( info );
info->windowRole = c->windowRole();
info->resourceName = c->resourceName();
info->resourceClass = c->resourceClass();
info->wmClientMachine = c->wmClientMachine();
info->geometry = QRect( c->calculateGravitation(TRUE), c->clientSize() ) ; // FRAME
info->restore = c->geometryRestore();
info->fsrestore = c->geometryFSRestore();
info->maximized = (int)c->maximizeMode();
info->fullscreen = (int)c->fullScreenMode();
info->desktop = c->desktop();
info->minimized = c->isMinimized();
info->onAllDesktops = c->isOnAllDesktops();
info->shaded = c->isShade();
info->keepAbove = c->keepAbove();
info->keepBelow = c->keepBelow();
info->skipTaskbar = c->skipTaskbar( true );
info->skipPager = c->skipPager();
info->userNoBorder = c->isUserNoBorder();
info->windowType = c->windowType();
info->active = false;
info->fake = true;
}
void Workspace::writeFakeSessionInfo()
{
KConfig *config = KGlobal::config();
config->setGroup("FakeSession" );
int count = 0;
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() );
config->writeEntry( QString("geometry")+n, info->geometry );
config->writeEntry( QString("restore")+n, info->restore );
config->writeEntry( QString("fsrestore")+n, info->fsrestore );
config->writeEntry( QString("maximize")+n, info->maximized );
config->writeEntry( QString("fullscreen")+n, info->fullscreen );
config->writeEntry( QString("desktop")+n, info->desktop );
config->writeEntry( QString("iconified")+n, info->minimized );
config->writeEntry( QString("onAllDesktops")+n, info->onAllDesktops );
config->writeEntry( QString("shaded")+n, info->shaded );
config->writeEntry( QString("staysOnTop")+n, info->keepAbove );
config->writeEntry( QString("keepBelow")+n, info->keepBelow );
config->writeEntry( QString("skipTaskbar")+n, info->skipTaskbar );
config->writeEntry( QString("skipPager")+n, info->skipPager );
config->writeEntry( QString("userNoBorder")+n, info->userNoBorder );
config->writeEntry( QString("windowType")+n, windowTypeToTxt( info->windowType ));
}
config->writeEntry( "count", count );
}
/*!
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.
We try to find a matching entry in the session.
May return 0 if there's no session info for the client.
*/
SessionInfo* Workspace::takeSessionInfo( Client* c )
{
SessionInfo *realInfo = 0;
SessionInfo *fakeInfo = 0;
QCString sessionId = c->sessionId();
QCString windowRole = c->windowRole();
QCString wmCommand = c->wmCommand();
@ -333,24 +233,7 @@ SessionInfo* Workspace::takeSessionInfo( Client* c )
realInfo = session.take();
}
// Now search ``fakeSession''
for (SessionInfo* info = fakeSession.first(); info && !fakeInfo; info = fakeSession.next() )
if ( info->resourceName == resourceName &&
info->resourceClass == resourceClass &&
( windowRole.isEmpty() || windowRole == info->windowRole ) &&
sessionInfoWindowTypeMatch( c, info ))
fakeInfo = fakeSession.take();
// Reconciliate
if (fakeInfo)
c->setStoreSettings( TRUE );
if (fakeInfo && realInfo)
delete fakeInfo;
if (realInfo)
return realInfo;
if (fakeInfo)
return fakeInfo;
return 0;
return realInfo;
}
bool Workspace::sessionInfoWindowTypeMatch( Client* c, SessionInfo* info )

3
sm.h
View File

@ -45,8 +45,7 @@ struct SessionInfo
bool skipPager;
bool userNoBorder;
NET::WindowType windowType;
bool active; // means 'was active in the saved session', not used otherwise
bool fake; // fake session, i.e. 'save window settings', not SM restored
bool active; // means 'was active in the saved session'
};

View File

@ -57,7 +57,7 @@ QPopupMenu* Workspace::clientPopup()
advanced_popup->insertItem( SmallIconSet( "down" ), i18n("Keep &Below Others"), Options::KeepBelowOp );
advanced_popup->insertItem( SmallIconSet( "window_fullscreen" ), i18n("&Fullscreen"), Options::FullScreenOp );
advanced_popup->insertItem( i18n("&No Border"), Options::NoBorderOp );
advanced_popup->insertItem( SmallIconSet( "filesave" ), i18n("Sto&re Window Settings"), Options::ToggleStoreSettingsOp );
advanced_popup->insertItem( SmallIconSet( "filesave" ), i18n("&Special Window Rules"), Options::WindowRulesOp );
popup->insertItem(i18n("Ad&vanced"), advanced_popup );
desk_popup_index = popup->count();
@ -115,7 +115,6 @@ void Workspace::clientPopupAboutToShow()
advanced_popup->setItemChecked( Options::NoBorderOp, popup_client->noBorder() );
advanced_popup->setItemEnabled( Options::NoBorderOp, popup_client->userCanSetNoBorder() );
popup->setItemEnabled( Options::MinimizeOp, popup_client->isMinimizable() );
advanced_popup->setItemChecked( Options::ToggleStoreSettingsOp, popup_client->storeSettings() );
popup->setItemEnabled( Options::CloseOp, popup_client->isCloseable() );
}
@ -129,7 +128,7 @@ void Workspace::initDesktopPopup()
desk_popup->setCheckable( TRUE );
desk_popup->setFont(KGlobalSettings::menuFont());
connect( desk_popup, SIGNAL( activated(int) ),
this, SLOT( sendToDesktop(int) ) );
this, SLOT( slotSendToDesktop(int) ) );
connect( desk_popup, SIGNAL( aboutToShow() ),
this, SLOT( desktopPopupAboutToShow() ) );
@ -278,8 +277,8 @@ void Workspace::performWindowOperation( Client* c, Options::WindowOperation op )
case Options::KeepBelowOp:
c->setKeepBelow( !c->keepBelow() );
break;
case Options::ToggleStoreSettingsOp:
c->setStoreSettings( !c->storeSettings() );
case Options::WindowRulesOp:
editWindowRules( c );
break;
case Options::LowerOp:
lowerClient(c);
@ -666,7 +665,7 @@ void Workspace::slotWindowRaiseOrLower()
void Workspace::slotWindowOnAllDesktops()
{
if( active_client )
active_client->toggleOnAllDesktops();
active_client->setOnAllDesktops( !active_client->isOnAllDesktops());
}
void Workspace::slotWindowFullScreen()
@ -737,7 +736,7 @@ void Workspace::slotKillWindow()
Internal slot for the window operation menu
*/
void Workspace::sendToDesktop( int desk )
void Workspace::slotSendToDesktop( int desk )
{
if ( !popup_client )
return;

View File

@ -36,6 +36,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include "placement.h"
#include "notifications.h"
#include "group.h"
#include "rules.h"
#include <X11/extensions/shape.h>
#include <X11/keysym.h>
@ -118,7 +119,7 @@ Workspace::Workspace( bool restore )
if ( restore )
loadSessionInfo();
loadFakeSessionInfo();
loadWindowRules();
(void) QApplication::desktop(); // trigger creation of desktop widget
@ -393,9 +394,8 @@ Workspace::~Workspace()
++it )
{
// only release the window
if( !(*it)->isDesktop()) // TODO ?
storeFakeSessionInfo( *it );
(*it)->releaseWindow( true );
// no removeClient() is called !
}
delete desktop_widget;
delete tab_box;
@ -404,7 +404,7 @@ Workspace::~Workspace()
if ( root == qt_xrootwin() )
XDeleteProperty(qt_xdisplay(), qt_xrootwin(), atoms->kwin_running);
writeFakeSessionInfo();
writeWindowRules();
KGlobal::config()->sync();
delete rootInfo;
@ -417,6 +417,11 @@ Workspace::~Workspace()
delete topmenu_watcher;
delete topmenu_selection;
delete topmenu_space;
while( !windowRules.isEmpty())
{
delete windowRules.front();
windowRules.pop_front();
}
XDestroyWindow( qt_xdisplay(), null_focus_window );
// TODO ungrabXServer();
_self = 0;
@ -487,8 +492,6 @@ void Workspace::removeClient( Client* c, allowed_t )
if( c->isNormalWindow())
Notify::raise( Notify::Delete );
storeFakeSessionInfo( c );
Q_ASSERT( clients.contains( c ) || desktops.contains( c ));
clients.remove( c );
desktops.remove( c );
@ -1169,11 +1172,10 @@ void Workspace::setNumberOfDesktops( int n )
*/
void Workspace::sendClientToDesktop( Client* c, int desk, bool dont_activate )
{
if ( c->desktop() == desk )
return;
bool was_on_desktop = c->isOnDesktop( desk ) || c->isOnAllDesktops();
c->setDesktop( desk );
if ( c->desktop() == desk ) // no change or desktop forced
return;
desk = c->desktop(); // Client did range checking
if ( c->isOnDesktop( currentDesktop() ) )

View File

@ -40,6 +40,7 @@ class PopupInfo;
class RootInfo;
class PluginMgr;
class Placement;
class WindowRules;
class SystemTrayWindow
{
@ -196,7 +197,7 @@ class Workspace : public QObject, public KWinInterface, public KDecorationDefine
void storeSession( KConfig* config, SMSavePhase phase );
SessionInfo* takeSessionInfo( Client* );
WindowRules* findWindowRules( const Client* ) const;
// dcop interface
void cascadeDesktop();
@ -316,7 +317,7 @@ class Workspace : public QObject, public KWinInterface, public KDecorationDefine
private slots:
void desktopPopupAboutToShow();
void clientPopupAboutToShow();
void sendToDesktop( int );
void slotSendToDesktop( int );
void clientPopupActivated( int );
void configureWM();
void desktopResized();
@ -416,15 +417,15 @@ class Workspace : public QObject, public KWinInterface, public KDecorationDefine
Client* popup_client;
void loadSessionInfo();
QWidget* desktop_widget;
void loadSessionInfo();
void loadWindowRules();
void writeWindowRules();
void editWindowRules( Client* );
QPtrList<SessionInfo> session;
QPtrList<SessionInfo> fakeSession;
void loadFakeSessionInfo();
void storeFakeSessionInfo( Client* c );
void writeFakeSessionInfo();
QValueList<WindowRules*> windowRules;
static const char* windowTypeToTxt( NET::WindowType type );
static NET::WindowType txtToWindowType( const char* txt );
static bool sessionInfoWindowTypeMatch( Client* c, SessionInfo* info );