Instead of snatching the window temporarily from kwin simply tell kwin

what to do with it. I've never liked this hack much, and this should
also take care of #49375, and should make sure kstart options will
have higher priority than settings configured in kwin.

svn path=/trunk/kdebase/kwin/; revision=319662
This commit is contained in:
Luboš Luňák 2004-06-11 15:10:09 +00:00
parent 33b11f1f07
commit 0f972d789f
6 changed files with 124 additions and 18 deletions

View file

@ -344,7 +344,7 @@ private slots:
QString readName() const; QString readName() const;
void setCaption( const QString& s, bool force = false ); void setCaption( const QString& s, bool force = false );
bool hasTransientInternal( const Client* c, bool indirect, ConstClientList& set ) const; bool hasTransientInternal( const Client* c, bool indirect, ConstClientList& set ) const;
void setupWindowRules(); void setupWindowRules( bool ignore_temporary );
void updateWindowRules(); void updateWindowRules();
void finishWindowRules(); void finishWindowRules();

View file

@ -111,7 +111,7 @@ bool Client::manage( Window w, bool isMapped )
// and only then really set the caption using setCaption(), which checks for duplicates etc. // and only then really set the caption using setCaption(), which checks for duplicates etc.
// and also relies on rules already existing // and also relies on rules already existing
cap_normal = readName(); cap_normal = readName();
setupWindowRules(); setupWindowRules( false );
setCaption( cap_normal, true ); setCaption( cap_normal, true );
detectNoBorder(); detectNoBorder();
@ -482,6 +482,9 @@ bool Client::manage( Window w, bool isMapped )
delete session; delete session;
ungrabXServer(); ungrabXServer();
if( client_rules->discardTemporary( true ))
setupWindowRules( true );
return true; return true;
} }

119
rules.cpp
View file

@ -12,6 +12,9 @@ License. See the file "COPYING" for the exact licensing terms.
#include <kconfig.h> #include <kconfig.h>
#include <qregexp.h> #include <qregexp.h>
#include <ktempfile.h>
#include <ksimpleconfig.h>
#include <qfile.h>
#include "client.h" #include "client.h"
#include "workspace.h" #include "workspace.h"
@ -22,7 +25,8 @@ namespace KWinInternal
static WindowRules dummyRules; // dummy used to avoid NULL checks static WindowRules dummyRules; // dummy used to avoid NULL checks
WindowRules::WindowRules() WindowRules::WindowRules()
: wmclassregexp( false ) : temporary_state( 0 )
, wmclassregexp( false )
, wmclasscomplete( false ) , wmclasscomplete( false )
, windowroleregexp( false ) , windowroleregexp( false )
, titleregexp( false ) , titleregexp( false )
@ -53,6 +57,22 @@ WindowRules::WindowRules()
{ {
} }
WindowRules::WindowRules( const QString& str, bool temporary )
: temporary_state( temporary ? 2 : 0 )
{
KTempFile file;
QFile* f = file.file();
if( f != NULL )
{
QCString s = str.utf8();
f->writeBlock( s.data(), s.length());
}
file.close();
KSimpleConfig cfg( file.name());
readFromCfg( cfg );
file.unlink();
}
#define READ_MATCH_STRING( var, func ) \ #define READ_MATCH_STRING( var, func ) \
var = cfg.readEntry( #var ) func; \ var = cfg.readEntry( #var ) func; \
var##regexp = cfg.readBoolEntry( #var "regexp" ); var##regexp = cfg.readBoolEntry( #var "regexp" );
@ -70,6 +90,12 @@ WindowRules::WindowRules()
var##rule = readForceRule( cfg, #var "rule" ); var##rule = readForceRule( cfg, #var "rule" );
WindowRules::WindowRules( KConfig& cfg ) WindowRules::WindowRules( KConfig& cfg )
: temporary_state( 0 )
{
readFromCfg( cfg );
}
void WindowRules::readFromCfg( KConfig& cfg )
{ {
wmclass = cfg.readEntry( "wmclass" ).lower().latin1(); wmclass = cfg.readEntry( "wmclass" ).lower().latin1();
wmclassregexp = cfg.readBoolEntry( "wmclassregexp" ); wmclassregexp = cfg.readBoolEntry( "wmclassregexp" );
@ -107,7 +133,7 @@ WindowRules::WindowRules( KConfig& cfg )
READ_FORCE_RULE( acceptfocus, Bool, ); READ_FORCE_RULE( acceptfocus, Bool, );
READ_FORCE_RULE( moveresizemode, , Options::stringToMoveResizeMode ); READ_FORCE_RULE( moveresizemode, , Options::stringToMoveResizeMode );
READ_FORCE_RULE( closeable, Bool, ); READ_FORCE_RULE( closeable, Bool, );
kdDebug() << "READ RULE:" << wmclass << endl; kdDebug() << "READ RULE:" << wmclass << "/" << title << endl;
} }
#undef READ_MATCH_STRING #undef READ_MATCH_STRING
@ -212,29 +238,31 @@ bool WindowRules::match( const Client* c ) const
{ {
if( types != NET::AllTypesMask ) if( types != NET::AllTypesMask )
{ {
if( !NET::typeMatchesMask( c->windowType( true ), types )) // direct NET::WindowType t = c->windowType( true ); // direct type
if( t == NET::Unknown )
t = NET::Normal; // NET::Unknown->NET::Normal is only here for matching
if( !NET::typeMatchesMask( t, types ))
return false; return false;
} }
// TODO exactMatch() for regexp?
if( !wmclass.isEmpty()) if( !wmclass.isEmpty())
{ // TODO optimize? { // TODO optimize?
QCString cwmclass = wmclasscomplete QCString cwmclass = wmclasscomplete
? c->resourceName() + ' ' + c->resourceClass() : c->resourceClass(); ? c->resourceName() + ' ' + c->resourceClass() : c->resourceClass();
if( wmclassregexp && !QRegExp( wmclass ).exactMatch( cwmclass )) if( wmclassregexp && QRegExp( wmclass ).search( cwmclass ) == -1 )
return false; return false;
if( !wmclassregexp && wmclass != cwmclass ) if( !wmclassregexp && wmclass != cwmclass )
return false; return false;
} }
if( !windowrole.isEmpty()) if( !windowrole.isEmpty())
{ {
if( windowroleregexp && !QRegExp( windowrole ).exactMatch( c->windowRole())) if( windowroleregexp && QRegExp( windowrole ).search( c->windowRole()) == -1 )
return false; return false;
if( !windowroleregexp && windowrole != c->windowRole()) if( !windowroleregexp && windowrole != c->windowRole())
return false; return false;
} }
if( !title.isEmpty()) if( !title.isEmpty())
{ {
if( titleregexp && !QRegExp( title ).exactMatch( c->caption( false ))) if( titleregexp && QRegExp( title ).search( c->caption( false )) == -1 )
return false; return false;
if( !titleregexp && title != c->caption( false )) if( !titleregexp && title != c->caption( false ))
return false; return false;
@ -243,8 +271,8 @@ bool WindowRules::match( const Client* c ) const
if( !clientmachine.isEmpty()) if( !clientmachine.isEmpty())
{ {
if( clientmachineregexp if( clientmachineregexp
&& !QRegExp( clientmachine ).exactMatch( c->wmClientMachine( true )) && QRegExp( clientmachine ).search( c->wmClientMachine( true )) == -1
&& !QRegExp( clientmachine ).exactMatch( c->wmClientMachine( false ))) && QRegExp( clientmachine ).search( c->wmClientMachine( false )) == -1 )
return false; return false;
if( !clientmachineregexp if( !clientmachineregexp
&& clientmachine != c->wmClientMachine( true ) && clientmachine != c->wmClientMachine( true )
@ -404,11 +432,29 @@ bool WindowRules::checkCloseable( bool closeable ) const
return checkForceRule( closeablerule ) ? this->closeable : closeable; return checkForceRule( closeablerule ) ? this->closeable : closeable;
} }
bool WindowRules::isTemporary() const
{
return temporary_state > 0;
}
bool WindowRules::discardTemporary( bool force )
{
if( temporary_state == 0 ) // not temporary
return false;
if( force || --temporary_state == 0 ) // too old
{
kdDebug() << "DISCARD:" << wmclass << "/" << title << endl;
delete this;
return true;
}
return false;
}
// Client // Client
void Client::setupWindowRules() void Client::setupWindowRules( bool ignore_temporary )
{ {
client_rules = workspace()->findWindowRules( this ); client_rules = workspace()->findWindowRules( this, ignore_temporary );
// check only after getting the rules, because there may be a rule forcing window type // check only after getting the rules, because there may be a rule forcing window type
if( isTopMenu()) // TODO cannot have restrictions if( isTopMenu()) // TODO cannot have restrictions
client_rules = &dummyRules; client_rules = &dummyRules;
@ -427,17 +473,22 @@ void Client::finishWindowRules()
// Workspace // Workspace
WindowRules* Workspace::findWindowRules( const Client* c ) const WindowRules* Workspace::findWindowRules( const Client* c, bool ignore_temporary )
{ {
for( QValueList< WindowRules* >::ConstIterator it = windowRules.begin(); for( QValueList< WindowRules* >::ConstIterator it = windowRules.begin();
it != windowRules.end(); it != windowRules.end();
++it ) ++it )
{ {
// chaining for wildcard matches if( ignore_temporary && (*it)->isTemporary())
continue;
// TODO chaining for wildcard matches
if( (*it)->match( c )) if( (*it)->match( c ))
{ {
kdDebug() << "RULE FOUND:" << c << endl; kdDebug() << "RULE FOUND:" << c << endl;
return *it; WindowRules* ret = *it;
if( ret->isTemporary())
windowRules.remove( *it );
return ret;
} }
} }
kdDebug() << "RULE DUMMY:" << c << endl; kdDebug() << "RULE DUMMY:" << c << endl;
@ -478,11 +529,49 @@ void Workspace::writeWindowRules()
int i = 1; int i = 1;
for( QValueList< WindowRules* >::ConstIterator it = windowRules.begin(); for( QValueList< WindowRules* >::ConstIterator it = windowRules.begin();
it != windowRules.end(); it != windowRules.end();
++it, ++i ) ++it )
{ {
if( (*it)->isTemporary())
continue;
cfg.setGroup( QString::number( i )); cfg.setGroup( QString::number( i ));
(*it)->write( cfg ); (*it)->write( cfg );
++i;
} }
} }
void Workspace::gotTemporaryRulesMessage( const QString& message )
{
bool was_temporary = false;
for( QValueList< WindowRules* >::ConstIterator it = windowRules.begin();
it != windowRules.end();
++it )
if( (*it)->isTemporary())
was_temporary = true;
WindowRules* rule = new WindowRules( message, true );
windowRules.prepend( rule ); // highest priority first
if( !was_temporary )
QTimer::singleShot( 60000, this, SLOT( cleanupTemporaryRules()));
}
void Workspace::cleanupTemporaryRules()
{
kdDebug() << "CLEANUP" << endl;
bool has_temporary = false;
for( QValueList< WindowRules* >::Iterator it = windowRules.begin();
it != windowRules.end();
)
{
if( (*it)->discardTemporary( false ))
it = windowRules.remove( it );
else
{
if( (*it)->isTemporary())
has_temporary = true;
++it;
}
}
if( has_temporary )
QTimer::singleShot( 60000, this, SLOT( cleanupTemporaryRules()));
}
} // namespace } // namespace

View file

@ -42,8 +42,11 @@ class WindowRules
public: public:
WindowRules(); WindowRules();
WindowRules( KConfig& ); WindowRules( KConfig& );
WindowRules( const QString&, bool temporary );
void write( KConfig& ) const; void write( KConfig& ) const;
void update( Client* ); void update( Client* );
bool isTemporary() const;
bool discardTemporary( bool force ); // removes if temporary and forced or too old
bool match( const Client* c ) const; bool match( const Client* c ) const;
Placement::Policy checkPlacement( Placement::Policy placement ) const; Placement::Policy checkPlacement( Placement::Policy placement ) const;
QRect checkGeometry( const QRect& rect, bool init = false ) const; QRect checkGeometry( const QRect& rect, bool init = false ) const;
@ -68,11 +71,13 @@ class WindowRules
Options::MoveResizeMode checkMoveResizeMode( Options::MoveResizeMode mode ) const; Options::MoveResizeMode checkMoveResizeMode( Options::MoveResizeMode mode ) const;
bool checkCloseable( bool closeable ) const; bool checkCloseable( bool closeable ) const;
private: private:
void readFromCfg( KConfig& cfg );
static SettingRule readRule( KConfig&, const QString& key ); static SettingRule readRule( KConfig&, const QString& key );
static SettingRule readForceRule( KConfig&, const QString& key ); static SettingRule readForceRule( KConfig&, const QString& key );
static NET::WindowType readType( KConfig&, const QString& key ); static NET::WindowType readType( KConfig&, const QString& key );
static bool checkRule( SettingRule rule, bool init ); static bool checkRule( SettingRule rule, bool init );
static bool checkForceRule( SettingRule rule ); static bool checkForceRule( SettingRule rule );
int temporary_state; // e.g. for kstart
QCString wmclass; QCString wmclass;
bool wmclassregexp; bool wmclassregexp;
bool wmclasscomplete; bool wmclasscomplete;

View file

@ -66,6 +66,7 @@ Workspace::Workspace( bool restore )
number_of_desktops(0), number_of_desktops(0),
popup_client (0), popup_client (0),
desktop_widget (0), desktop_widget (0),
temporaryRulesMessages( "_KDE_NET_WM_TEMPORARY_RULES", NULL, false ),
active_client (0), active_client (0),
last_active_client (0), last_active_client (0),
most_recently_raised (0), most_recently_raised (0),
@ -109,6 +110,9 @@ Workspace::Workspace( bool restore )
installed_colormap = default_colormap; installed_colormap = default_colormap;
session.setAutoDelete( TRUE ); session.setAutoDelete( TRUE );
connect( &temporaryRulesMessages, SIGNAL( gotMessage( const QString& )),
this, SLOT( gotTemporaryRulesMessage( const QString& )));
updateXTime(); // needed for proper initialization of user_time in Client ctor updateXTime(); // needed for proper initialization of user_time in Client ctor
delayFocusTimer = 0; delayFocusTimer = 0;
@ -247,6 +251,7 @@ void Workspace::init()
NET::WM2RestackWindow | NET::WM2RestackWindow |
NET::WM2MoveResizeWindow | NET::WM2MoveResizeWindow |
NET::WM2ExtendedStrut | NET::WM2ExtendedStrut |
NET::WM2KDETemporaryRules |
0 0
, ,
NET::ActionMove | NET::ActionMove |

View file

@ -16,6 +16,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include <kshortcut.h> #include <kshortcut.h>
#include <qcursor.h> #include <qcursor.h>
#include <netwm.h> #include <netwm.h>
#include <kxmessages.h>
#include "KWinInterface.h" #include "KWinInterface.h"
#include "utils.h" #include "utils.h"
@ -202,7 +203,7 @@ class Workspace : public QObject, public KWinInterface, public KDecorationDefine
void storeSession( KConfig* config, SMSavePhase phase ); void storeSession( KConfig* config, SMSavePhase phase );
SessionInfo* takeSessionInfo( Client* ); SessionInfo* takeSessionInfo( Client* );
WindowRules* findWindowRules( const Client* ) const; WindowRules* findWindowRules( const Client*, bool );
// dcop interface // dcop interface
void cascadeDesktop(); void cascadeDesktop();
@ -330,6 +331,8 @@ class Workspace : public QObject, public KWinInterface, public KDecorationDefine
void lostTopMenuSelection(); void lostTopMenuSelection();
void lostTopMenuOwner(); void lostTopMenuOwner();
void delayFocus(); void delayFocus();
void gotTemporaryRulesMessage( const QString& );
void cleanupTemporaryRules();
protected: protected:
bool keyPressMouseEmulation( XKeyEvent& ev ); bool keyPressMouseEmulation( XKeyEvent& ev );
@ -431,6 +434,7 @@ class Workspace : public QObject, public KWinInterface, public KDecorationDefine
QPtrList<SessionInfo> session; QPtrList<SessionInfo> session;
QValueList<WindowRules*> windowRules; QValueList<WindowRules*> windowRules;
KXMessages temporaryRulesMessages;
static const char* windowTypeToTxt( NET::WindowType type ); static const char* windowTypeToTxt( NET::WindowType type );
static NET::WindowType txtToWindowType( const char* txt ); static NET::WindowType txtToWindowType( const char* txt );
static bool sessionInfoWindowTypeMatch( Client* c, SessionInfo* info ); static bool sessionInfoWindowTypeMatch( Client* c, SessionInfo* info );