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:
parent
33b11f1f07
commit
0f972d789f
6 changed files with 124 additions and 18 deletions
2
client.h
2
client.h
|
@ -344,7 +344,7 @@ private slots:
|
|||
QString readName() const;
|
||||
void setCaption( const QString& s, bool force = false );
|
||||
bool hasTransientInternal( const Client* c, bool indirect, ConstClientList& set ) const;
|
||||
void setupWindowRules();
|
||||
void setupWindowRules( bool ignore_temporary );
|
||||
void updateWindowRules();
|
||||
void finishWindowRules();
|
||||
|
||||
|
|
|
@ -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 also relies on rules already existing
|
||||
cap_normal = readName();
|
||||
setupWindowRules();
|
||||
setupWindowRules( false );
|
||||
setCaption( cap_normal, true );
|
||||
|
||||
detectNoBorder();
|
||||
|
@ -483,6 +483,9 @@ bool Client::manage( Window w, bool isMapped )
|
|||
|
||||
ungrabXServer();
|
||||
|
||||
if( client_rules->discardTemporary( true ))
|
||||
setupWindowRules( true );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
119
rules.cpp
119
rules.cpp
|
@ -12,6 +12,9 @@ License. See the file "COPYING" for the exact licensing terms.
|
|||
|
||||
#include <kconfig.h>
|
||||
#include <qregexp.h>
|
||||
#include <ktempfile.h>
|
||||
#include <ksimpleconfig.h>
|
||||
#include <qfile.h>
|
||||
|
||||
#include "client.h"
|
||||
#include "workspace.h"
|
||||
|
@ -22,7 +25,8 @@ namespace KWinInternal
|
|||
static WindowRules dummyRules; // dummy used to avoid NULL checks
|
||||
|
||||
WindowRules::WindowRules()
|
||||
: wmclassregexp( false )
|
||||
: temporary_state( 0 )
|
||||
, wmclassregexp( false )
|
||||
, wmclasscomplete( false )
|
||||
, windowroleregexp( 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 ) \
|
||||
var = cfg.readEntry( #var ) func; \
|
||||
var##regexp = cfg.readBoolEntry( #var "regexp" );
|
||||
|
@ -70,6 +90,12 @@ WindowRules::WindowRules()
|
|||
var##rule = readForceRule( cfg, #var "rule" );
|
||||
|
||||
WindowRules::WindowRules( KConfig& cfg )
|
||||
: temporary_state( 0 )
|
||||
{
|
||||
readFromCfg( cfg );
|
||||
}
|
||||
|
||||
void WindowRules::readFromCfg( KConfig& cfg )
|
||||
{
|
||||
wmclass = cfg.readEntry( "wmclass" ).lower().latin1();
|
||||
wmclassregexp = cfg.readBoolEntry( "wmclassregexp" );
|
||||
|
@ -107,7 +133,7 @@ WindowRules::WindowRules( KConfig& cfg )
|
|||
READ_FORCE_RULE( acceptfocus, Bool, );
|
||||
READ_FORCE_RULE( moveresizemode, , Options::stringToMoveResizeMode );
|
||||
READ_FORCE_RULE( closeable, Bool, );
|
||||
kdDebug() << "READ RULE:" << wmclass << endl;
|
||||
kdDebug() << "READ RULE:" << wmclass << "/" << title << endl;
|
||||
}
|
||||
|
||||
#undef READ_MATCH_STRING
|
||||
|
@ -212,29 +238,31 @@ bool WindowRules::match( const Client* c ) const
|
|||
{
|
||||
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;
|
||||
}
|
||||
// TODO exactMatch() for regexp?
|
||||
if( !wmclass.isEmpty())
|
||||
{ // TODO optimize?
|
||||
QCString cwmclass = wmclasscomplete
|
||||
? c->resourceName() + ' ' + c->resourceClass() : c->resourceClass();
|
||||
if( wmclassregexp && !QRegExp( wmclass ).exactMatch( cwmclass ))
|
||||
if( wmclassregexp && QRegExp( wmclass ).search( cwmclass ) == -1 )
|
||||
return false;
|
||||
if( !wmclassregexp && wmclass != cwmclass )
|
||||
return false;
|
||||
}
|
||||
if( !windowrole.isEmpty())
|
||||
{
|
||||
if( windowroleregexp && !QRegExp( windowrole ).exactMatch( c->windowRole()))
|
||||
if( windowroleregexp && QRegExp( windowrole ).search( c->windowRole()) == -1 )
|
||||
return false;
|
||||
if( !windowroleregexp && windowrole != c->windowRole())
|
||||
return false;
|
||||
}
|
||||
if( !title.isEmpty())
|
||||
{
|
||||
if( titleregexp && !QRegExp( title ).exactMatch( c->caption( false )))
|
||||
if( titleregexp && QRegExp( title ).search( c->caption( false )) == -1 )
|
||||
return false;
|
||||
if( !titleregexp && title != c->caption( false ))
|
||||
return false;
|
||||
|
@ -243,8 +271,8 @@ bool WindowRules::match( const Client* c ) const
|
|||
if( !clientmachine.isEmpty())
|
||||
{
|
||||
if( clientmachineregexp
|
||||
&& !QRegExp( clientmachine ).exactMatch( c->wmClientMachine( true ))
|
||||
&& !QRegExp( clientmachine ).exactMatch( c->wmClientMachine( false )))
|
||||
&& QRegExp( clientmachine ).search( c->wmClientMachine( true )) == -1
|
||||
&& QRegExp( clientmachine ).search( c->wmClientMachine( false )) == -1 )
|
||||
return false;
|
||||
if( !clientmachineregexp
|
||||
&& clientmachine != c->wmClientMachine( true )
|
||||
|
@ -404,11 +432,29 @@ bool WindowRules::checkCloseable( bool closeable ) const
|
|||
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
|
||||
|
||||
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
|
||||
if( isTopMenu()) // TODO cannot have restrictions
|
||||
client_rules = &dummyRules;
|
||||
|
@ -427,17 +473,22 @@ void Client::finishWindowRules()
|
|||
|
||||
// Workspace
|
||||
|
||||
WindowRules* Workspace::findWindowRules( const Client* c ) const
|
||||
WindowRules* Workspace::findWindowRules( const Client* c, bool ignore_temporary )
|
||||
{
|
||||
for( QValueList< WindowRules* >::ConstIterator it = windowRules.begin();
|
||||
it != windowRules.end();
|
||||
++it )
|
||||
{
|
||||
// chaining for wildcard matches
|
||||
if( ignore_temporary && (*it)->isTemporary())
|
||||
continue;
|
||||
// TODO chaining for wildcard matches
|
||||
if( (*it)->match( c ))
|
||||
{
|
||||
kdDebug() << "RULE FOUND:" << c << endl;
|
||||
return *it;
|
||||
WindowRules* ret = *it;
|
||||
if( ret->isTemporary())
|
||||
windowRules.remove( *it );
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
kdDebug() << "RULE DUMMY:" << c << endl;
|
||||
|
@ -478,11 +529,49 @@ void Workspace::writeWindowRules()
|
|||
int i = 1;
|
||||
for( QValueList< WindowRules* >::ConstIterator it = windowRules.begin();
|
||||
it != windowRules.end();
|
||||
++it, ++i )
|
||||
++it )
|
||||
{
|
||||
if( (*it)->isTemporary())
|
||||
continue;
|
||||
cfg.setGroup( QString::number( i ));
|
||||
(*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
|
||||
|
|
5
rules.h
5
rules.h
|
@ -42,8 +42,11 @@ class WindowRules
|
|||
public:
|
||||
WindowRules();
|
||||
WindowRules( KConfig& );
|
||||
WindowRules( const QString&, bool temporary );
|
||||
void write( KConfig& ) const;
|
||||
void update( Client* );
|
||||
bool isTemporary() const;
|
||||
bool discardTemporary( bool force ); // removes if temporary and forced or too old
|
||||
bool match( const Client* c ) const;
|
||||
Placement::Policy checkPlacement( Placement::Policy placement ) const;
|
||||
QRect checkGeometry( const QRect& rect, bool init = false ) const;
|
||||
|
@ -68,11 +71,13 @@ class WindowRules
|
|||
Options::MoveResizeMode checkMoveResizeMode( Options::MoveResizeMode mode ) const;
|
||||
bool checkCloseable( bool closeable ) const;
|
||||
private:
|
||||
void readFromCfg( KConfig& cfg );
|
||||
static SettingRule readRule( KConfig&, const QString& key );
|
||||
static SettingRule readForceRule( KConfig&, const QString& key );
|
||||
static NET::WindowType readType( KConfig&, const QString& key );
|
||||
static bool checkRule( SettingRule rule, bool init );
|
||||
static bool checkForceRule( SettingRule rule );
|
||||
int temporary_state; // e.g. for kstart
|
||||
QCString wmclass;
|
||||
bool wmclassregexp;
|
||||
bool wmclasscomplete;
|
||||
|
|
|
@ -66,6 +66,7 @@ Workspace::Workspace( bool restore )
|
|||
number_of_desktops(0),
|
||||
popup_client (0),
|
||||
desktop_widget (0),
|
||||
temporaryRulesMessages( "_KDE_NET_WM_TEMPORARY_RULES", NULL, false ),
|
||||
active_client (0),
|
||||
last_active_client (0),
|
||||
most_recently_raised (0),
|
||||
|
@ -109,6 +110,9 @@ Workspace::Workspace( bool restore )
|
|||
installed_colormap = default_colormap;
|
||||
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
|
||||
|
||||
delayFocusTimer = 0;
|
||||
|
@ -247,6 +251,7 @@ void Workspace::init()
|
|||
NET::WM2RestackWindow |
|
||||
NET::WM2MoveResizeWindow |
|
||||
NET::WM2ExtendedStrut |
|
||||
NET::WM2KDETemporaryRules |
|
||||
0
|
||||
,
|
||||
NET::ActionMove |
|
||||
|
|
|
@ -16,6 +16,7 @@ License. See the file "COPYING" for the exact licensing terms.
|
|||
#include <kshortcut.h>
|
||||
#include <qcursor.h>
|
||||
#include <netwm.h>
|
||||
#include <kxmessages.h>
|
||||
|
||||
#include "KWinInterface.h"
|
||||
#include "utils.h"
|
||||
|
@ -202,7 +203,7 @@ class Workspace : public QObject, public KWinInterface, public KDecorationDefine
|
|||
void storeSession( KConfig* config, SMSavePhase phase );
|
||||
|
||||
SessionInfo* takeSessionInfo( Client* );
|
||||
WindowRules* findWindowRules( const Client* ) const;
|
||||
WindowRules* findWindowRules( const Client*, bool );
|
||||
|
||||
// dcop interface
|
||||
void cascadeDesktop();
|
||||
|
@ -330,6 +331,8 @@ class Workspace : public QObject, public KWinInterface, public KDecorationDefine
|
|||
void lostTopMenuSelection();
|
||||
void lostTopMenuOwner();
|
||||
void delayFocus();
|
||||
void gotTemporaryRulesMessage( const QString& );
|
||||
void cleanupTemporaryRules();
|
||||
|
||||
protected:
|
||||
bool keyPressMouseEmulation( XKeyEvent& ev );
|
||||
|
@ -431,6 +434,7 @@ class Workspace : public QObject, public KWinInterface, public KDecorationDefine
|
|||
|
||||
QPtrList<SessionInfo> session;
|
||||
QValueList<WindowRules*> windowRules;
|
||||
KXMessages temporaryRulesMessages;
|
||||
static const char* windowTypeToTxt( NET::WindowType type );
|
||||
static NET::WindowType txtToWindowType( const char* txt );
|
||||
static bool sessionInfoWindowTypeMatch( Client* c, SessionInfo* info );
|
||||
|
|
Loading…
Reference in a new issue