00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
#include "rules.h"
00012
00013
#include <fixx11h.h>
00014
#include <kconfig.h>
00015
#include <qregexp.h>
00016
#include <ktempfile.h>
00017
#include <ksimpleconfig.h>
00018
#include <qfile.h>
00019
00020
#ifndef KCMRULES
00021
#include "client.h"
00022
#include "workspace.h"
00023
#endif
00024
00025
namespace KWinInternal
00026 {
00027
00028 Rules::Rules()
00029 : temporary_state( 0 )
00030 , wmclassmatch( UnimportantMatch )
00031 , wmclasscomplete( UnimportantMatch )
00032 , windowrolematch( UnimportantMatch )
00033 , titlematch( UnimportantMatch )
00034 , extrarolematch( UnimportantMatch )
00035 , clientmachinematch( UnimportantMatch )
00036 , types( NET::AllTypesMask )
00037 , placementrule( UnusedForceRule )
00038 , positionrule( UnusedSetRule )
00039 , sizerule( UnusedSetRule )
00040 , minsizerule( UnusedForceRule )
00041 , maxsizerule( UnusedForceRule )
00042 , ignorepositionrule( UnusedForceRule )
00043 , desktoprule( UnusedSetRule )
00044 , typerule( UnusedForceRule )
00045 , maximizevertrule( UnusedSetRule )
00046 , maximizehorizrule( UnusedSetRule )
00047 , minimizerule( UnusedSetRule )
00048 , shaderule( UnusedSetRule )
00049 , skiptaskbarrule( UnusedSetRule )
00050 , skippagerrule( UnusedSetRule )
00051 , aboverule( UnusedSetRule )
00052 , belowrule( UnusedSetRule )
00053 , fullscreenrule( UnusedSetRule )
00054 , noborderrule( UnusedSetRule )
00055 , fsplevelrule( UnusedForceRule )
00056 , acceptfocusrule( UnusedForceRule )
00057 , moveresizemoderule( UnusedForceRule )
00058 , closeablerule( UnusedForceRule )
00059 {
00060 }
00061
00062 Rules::Rules(
const QString& str,
bool temporary )
00063 : temporary_state( temporary ? 2 : 0 )
00064 {
00065 KTempFile file;
00066 QFile* f = file.file();
00067
if( f != NULL )
00068 {
00069 QCString s = str.utf8();
00070 f->writeBlock( s.data(), s.length());
00071 }
00072 file.close();
00073 KSimpleConfig cfg( file.name());
00074 readFromCfg( cfg );
00075
if( description.isEmpty())
00076 description =
"temporary";
00077 file.unlink();
00078 }
00079
00080
#define READ_MATCH_STRING( var, func ) \
00081
var = cfg.readEntry( #var ) func; \
00082
var##match = (StringMatch) QMAX( FirstStringMatch, QMIN( LastStringMatch, cfg.readNumEntry( #var "match" )));
00083
00084
#define READ_SET_RULE( var, type, func ) \
00085
var = func ( cfg.read##type##Entry( #var )); \
00086
var##rule = readSetRule( cfg, #var "rule" );
00087
00088
#define READ_SET_RULE_DEF( var, type, func, def ) \
00089
var = func ( cfg.read##type##Entry( #var, def )); \
00090
var##rule = readSetRule( cfg, #var "rule" );
00091
00092
#define READ_SET_RULE_2( var, type, func, funcarg ) \
00093
var = func ( cfg.read##type##Entry( #var ), funcarg ); \
00094
var##rule = readSetRule( cfg, #var "rule" );
00095
00096
#define READ_FORCE_RULE( var, type, func ) \
00097
var = func ( cfg.read##type##Entry( #var )); \
00098
var##rule = readForceRule( cfg, #var "rule" );
00099
00100
#define READ_FORCE_RULE_2( var, type, func, funcarg ) \
00101
var = func ( cfg.read##type##Entry( #var ), funcarg ); \
00102
var##rule = readForceRule( cfg, #var "rule" );
00103
00104
00105 Rules::Rules( KConfig& cfg )
00106 : temporary_state( 0 )
00107 {
00108 readFromCfg( cfg );
00109 }
00110
00111
static int limit0to4(
int i ) {
return QMAX( 0, QMIN( 4, i )); }
00112
00113
void Rules::readFromCfg( KConfig& cfg )
00114 {
00115 description = cfg.readEntry(
"description" );
00116 READ_MATCH_STRING( wmclass, .lower().latin1() );
00117 wmclasscomplete = cfg.readBoolEntry(
"wmclasscomplete" );
00118 READ_MATCH_STRING( windowrole, .lower().latin1() );
00119 READ_MATCH_STRING( title, );
00120 READ_MATCH_STRING( extrarole, .lower().latin1() );
00121 READ_MATCH_STRING( clientmachine, .lower().latin1() );
00122 types = cfg.readUnsignedLongNumEntry(
"types", NET::AllTypesMask );
00123 READ_FORCE_RULE_2( placement,, Placement::policyFromString,
false );
00124 READ_SET_RULE_DEF( position, Point,, &invalidPoint );
00125 READ_SET_RULE( size, Size, );
00126
if( size.isEmpty() && sizerule != ( SetRule )Remember)
00127 sizerule = UnusedSetRule;
00128 READ_FORCE_RULE( minsize, Size, );
00129
if( !minsize.isValid())
00130 minsize = QSize( 1, 1 );
00131 READ_FORCE_RULE( maxsize, Size, );
00132
if( maxsize.isEmpty())
00133 maxsize = QSize( 32767, 32767 );
00134 READ_FORCE_RULE( ignoreposition, Bool, );
00135 READ_SET_RULE( desktop, Num, );
00136 type = readType( cfg,
"type" );
00137 typerule = type != NET::Unknown ? readForceRule( cfg,
"typerule" ) : UnusedForceRule;
00138 READ_SET_RULE( maximizevert, Bool, );
00139 READ_SET_RULE( maximizehoriz, Bool, );
00140 READ_SET_RULE( minimize, Bool, );
00141 READ_SET_RULE( shade, Bool, );
00142 READ_SET_RULE( skiptaskbar, Bool, );
00143 READ_SET_RULE( skippager, Bool, );
00144 READ_SET_RULE( above, Bool, );
00145 READ_SET_RULE( below, Bool, );
00146 READ_SET_RULE( fullscreen, Bool, );
00147 READ_SET_RULE( noborder, Bool, );
00148 READ_FORCE_RULE( fsplevel, Num, limit0to4 );
00149 READ_FORCE_RULE( acceptfocus, Bool, );
00150 READ_FORCE_RULE( moveresizemode, , Options::stringToMoveResizeMode );
00151 READ_FORCE_RULE( closeable, Bool, );
00152 }
00153
00154
#undef READ_MATCH_STRING
00155
#undef READ_SET_RULE
00156
#undef READ_SET_RULE_2
00157
#undef READ_FORCE_RULE
00158
#undef READ_FORCE_RULE_2
00159
00160
#define WRITE_MATCH_STRING( var, cast, force ) \
00161
if( !var.isEmpty() || force ) \
00162
{ \
00163
cfg.writeEntry( #var, cast var ); \
00164
cfg.writeEntry( #var "match", var##match ); \
00165
} \
00166
else \
00167
{ \
00168
cfg.deleteEntry( #var ); \
00169
cfg.deleteEntry( #var "match" ); \
00170
}
00171
00172
#define WRITE_SET_RULE( var, func ) \
00173
if( var##rule != UnusedSetRule ) \
00174
{ \
00175
cfg.writeEntry( #var, func ( var )); \
00176
cfg.writeEntry( #var "rule", var##rule ); \
00177
} \
00178
else \
00179
{ \
00180
cfg.deleteEntry( #var ); \
00181
cfg.deleteEntry( #var "rule" ); \
00182
}
00183
00184
#define WRITE_FORCE_RULE( var, func ) \
00185
if( var##rule != UnusedForceRule ) \
00186
{ \
00187
cfg.writeEntry( #var, func ( var )); \
00188
cfg.writeEntry( #var "rule", var##rule ); \
00189
} \
00190
else \
00191
{ \
00192
cfg.deleteEntry( #var ); \
00193
cfg.deleteEntry( #var "rule" ); \
00194
}
00195
00196
#define WRITE_WITH_DEFAULT( var, default ) \
00197
if( var != default ) \
00198
cfg.writeEntry( #var, var ); \
00199
else \
00200
cfg.deleteEntry( #var );
00201
00202
00203
void Rules::write( KConfig& cfg )
const
00204
{
00205 cfg.writeEntry(
"description", description );
00206
00207 WRITE_MATCH_STRING( wmclass, (
const char*),
true );
00208 cfg.writeEntry(
"wmclasscomplete", wmclasscomplete );
00209 WRITE_MATCH_STRING( windowrole, (
const char*),
false );
00210 WRITE_MATCH_STRING( title,,
false );
00211 WRITE_MATCH_STRING( extrarole, (
const char*),
false );
00212 WRITE_MATCH_STRING( clientmachine, (
const char*),
false );
00213 WRITE_WITH_DEFAULT( types, NET::AllTypesMask );
00214 WRITE_FORCE_RULE( placement, Placement::policyToString );
00215 WRITE_SET_RULE( position, );
00216 WRITE_SET_RULE( size, );
00217 WRITE_FORCE_RULE( minsize, );
00218 WRITE_FORCE_RULE( maxsize, );
00219 WRITE_FORCE_RULE( ignoreposition, );
00220 WRITE_SET_RULE( desktop, );
00221 WRITE_FORCE_RULE( type, );
00222 WRITE_SET_RULE( maximizevert, );
00223 WRITE_SET_RULE( maximizehoriz, );
00224 WRITE_SET_RULE( minimize, );
00225 WRITE_SET_RULE( shade, );
00226 WRITE_SET_RULE( skiptaskbar, );
00227 WRITE_SET_RULE( skippager, );
00228 WRITE_SET_RULE( above, );
00229 WRITE_SET_RULE( below, );
00230 WRITE_SET_RULE( fullscreen, );
00231 WRITE_SET_RULE( noborder, );
00232 WRITE_FORCE_RULE( fsplevel, );
00233 WRITE_FORCE_RULE( acceptfocus, );
00234 WRITE_FORCE_RULE( moveresizemode, Options::moveResizeModeToString );
00235 WRITE_FORCE_RULE( closeable, );
00236 }
00237
00238
#undef WRITE_MATCH_STRING
00239
#undef WRITE_SET_RULE
00240
#undef WRITE_FORCE_RULE
00241
#undef WRITE_WITH_DEFAULT
00242
00243
00244
bool Rules::isEmpty()
const
00245
{
00246
return( placementrule == UnusedForceRule
00247 && positionrule == UnusedSetRule
00248 && sizerule == UnusedSetRule
00249 && minsizerule == UnusedForceRule
00250 && maxsizerule == UnusedForceRule
00251 && ignorepositionrule == UnusedForceRule
00252 && desktoprule == UnusedSetRule
00253 && typerule == UnusedForceRule
00254 && maximizevertrule == UnusedSetRule
00255 && maximizehorizrule == UnusedSetRule
00256 && minimizerule == UnusedSetRule
00257 && shaderule == UnusedSetRule
00258 && skiptaskbarrule == UnusedSetRule
00259 && skippagerrule == UnusedSetRule
00260 && aboverule == UnusedSetRule
00261 && belowrule == UnusedSetRule
00262 && fullscreenrule == UnusedSetRule
00263 && noborderrule == UnusedSetRule
00264 && fsplevelrule == UnusedForceRule
00265 && acceptfocusrule == UnusedForceRule
00266 && moveresizemoderule == UnusedForceRule
00267 && closeablerule == UnusedForceRule );
00268 }
00269
00270 Rules::SetRule Rules::readSetRule( KConfig& cfg,
const QString& key )
00271 {
00272
int v = cfg.readNumEntry( key );
00273
if( v >= DontAffect && v <= Remember )
00274
return static_cast< SetRule >( v );
00275
return UnusedSetRule;
00276 }
00277
00278 Rules::ForceRule Rules::readForceRule( KConfig& cfg,
const QString& key )
00279 {
00280
int v = cfg.readNumEntry( key );
00281
if( v == DontAffect || v == Force )
00282
return static_cast< ForceRule >( v );
00283
return UnusedForceRule;
00284 }
00285
00286 NET::WindowType Rules::readType( KConfig& cfg,
const QString& key )
00287 {
00288
int v = cfg.readNumEntry( key );
00289
if( v >= NET::Normal && v <= NET::Splash )
00290
return static_cast< NET::WindowType >( v );
00291
return NET::Unknown;
00292 }
00293
00294
bool Rules::matchType( NET::WindowType match_type )
const
00295
{
00296
if( types != NET::AllTypesMask )
00297 {
00298
if( match_type == NET::Unknown )
00299 match_type = NET::Normal;
00300
if( !NET::typeMatchesMask( match_type, types ))
00301
return false;
00302 }
00303
return true;
00304 }
00305
00306
bool Rules::matchWMClass(
const QCString& match_class,
const QCString& match_name )
const
00307
{
00308
if( wmclassmatch != UnimportantMatch )
00309 {
00310 QCString cwmclass = wmclasscomplete
00311 ? match_name +
' ' + match_class : match_class;
00312
if( wmclassmatch == RegExpMatch && QRegExp( wmclass ).search( cwmclass ) == -1 )
00313
return false;
00314
if( wmclassmatch == ExactMatch && wmclass != cwmclass )
00315
return false;
00316
if( wmclassmatch == SubstringMatch && !cwmclass.contains( wmclass ))
00317
return false;
00318 }
00319
return true;
00320 }
00321
00322
bool Rules::matchRole(
const QCString& match_role )
const
00323
{
00324
if( windowrolematch != UnimportantMatch )
00325 {
00326
if( windowrolematch == RegExpMatch && QRegExp( windowrole ).search( match_role ) == -1 )
00327
return false;
00328
if( windowrolematch == ExactMatch && windowrole != match_role )
00329
return false;
00330
if( windowrolematch == SubstringMatch && !match_role.contains( windowrole ))
00331
return false;
00332 }
00333
return true;
00334 }
00335
00336
bool Rules::matchTitle(
const QString& match_title )
const
00337
{
00338
if( titlematch != UnimportantMatch )
00339 {
00340
if( titlematch == RegExpMatch && QRegExp( title ).search( match_title ) == -1 )
00341
return false;
00342
if( titlematch == ExactMatch && title != match_title )
00343
return false;
00344
if( titlematch == SubstringMatch && !match_title.contains( title ))
00345
return false;
00346 }
00347
return true;
00348 }
00349
00350
bool Rules::matchClientMachine(
const QCString& match_machine )
const
00351
{
00352
if( clientmachinematch != UnimportantMatch )
00353 {
00354
00355
if( match_machine !=
"localhost" && isLocalMachine( match_machine )
00356 && matchClientMachine(
"localhost" ))
00357
return true;
00358
if( clientmachinematch == RegExpMatch
00359 && QRegExp( clientmachine ).search( match_machine ) == -1 )
00360
return false;
00361
if( clientmachinematch == ExactMatch
00362 && clientmachine != match_machine )
00363
return false;
00364
if( clientmachinematch == SubstringMatch
00365 && !match_machine.contains( clientmachine ))
00366
return false;
00367 }
00368
return true;
00369 }
00370
00371
#ifndef KCMRULES
00372
bool Rules::match(
const Client* c )
const
00373
{
00374
if( !matchType( c->windowType(
true )))
00375
return false;
00376
if( !matchWMClass( c->resourceClass(), c->resourceName()))
00377
return false;
00378
if( !matchRole( c->windowRole()))
00379
return false;
00380
if( !matchTitle( c->caption(
false )))
00381
return false;
00382
00383
if( !matchClientMachine( c->wmClientMachine(
false )))
00384
return false;
00385
return true;
00386 }
00387
00388
bool Rules::update( Client* c )
00389 {
00390
00391
bool updated =
false;
00392
if( positionrule == ( SetRule )Remember)
00393 {
00394
if( !c->isFullScreen())
00395 {
00396 QPoint new_pos = position;
00397
00398
if(( c->maximizeMode() &
MaximizeHorizontal ) == 0 )
00399 new_pos.setX( c->pos().x());
00400
if(( c->maximizeMode() &
MaximizeVertical ) == 0 )
00401 new_pos.setY( c->pos().y());
00402 updated = updated || position != new_pos;
00403 position = new_pos;
00404 }
00405 }
00406
if( sizerule == ( SetRule )Remember)
00407 {
00408
if( !c->isFullScreen())
00409 {
00410 QSize new_size = size;
00411
00412
if(( c->maximizeMode() &
MaximizeHorizontal ) == 0 )
00413 new_size.setWidth( c->size().width());
00414
if(( c->maximizeMode() &
MaximizeVertical ) == 0 )
00415 new_size.setHeight( c->size().height());
00416 updated = updated || size != new_size;
00417 size = new_size;
00418 }
00419 }
00420
if( desktoprule == ( SetRule )Remember)
00421 {
00422 updated = updated ||
desktop != c->desktop();
00423
desktop = c->desktop();
00424 }
00425
if( maximizevertrule == ( SetRule )Remember)
00426 {
00427 updated = updated || maximizevert != bool( c->maximizeMode() &
MaximizeVertical );
00428 maximizevert = c->maximizeMode() &
MaximizeVertical;
00429 }
00430
if( maximizehorizrule == ( SetRule )Remember)
00431 {
00432 updated = updated || maximizehoriz != bool( c->maximizeMode() &
MaximizeHorizontal );
00433 maximizehoriz = c->maximizeMode() &
MaximizeHorizontal;
00434 }
00435
if( minimizerule == ( SetRule )Remember)
00436 {
00437 updated = updated ||
minimize != c->isMinimized();
00438
minimize = c->isMinimized();
00439 }
00440
if( shaderule == ( SetRule )Remember)
00441 {
00442 updated = updated || ( shade != ( c->shadeMode() != ShadeNone ));
00443 shade = c->shadeMode() != ShadeNone;
00444 }
00445
if( skiptaskbarrule == ( SetRule )Remember)
00446 {
00447 updated = updated || skiptaskbar != c->skipTaskbar();
00448 skiptaskbar = c->skipTaskbar();
00449 }
00450
if( skippagerrule == ( SetRule )Remember)
00451 {
00452 updated = updated || skippager != c->skipPager();
00453 skippager = c->skipPager();
00454 }
00455
if( aboverule == ( SetRule )Remember)
00456 {
00457 updated = updated || above != c->keepAbove();
00458 above = c->keepAbove();
00459 }
00460
if( belowrule == ( SetRule )Remember)
00461 {
00462 updated = updated || below != c->keepBelow();
00463 below = c->keepBelow();
00464 }
00465
if( fullscreenrule == ( SetRule )Remember)
00466 {
00467 updated = updated || fullscreen != c->isFullScreen();
00468 fullscreen = c->isFullScreen();
00469 }
00470
if( noborderrule == ( SetRule )Remember)
00471 {
00472 updated = updated || noborder != c->isUserNoBorder();
00473 noborder = c->isUserNoBorder();
00474 }
00475
return updated;
00476 }
00477
00478
#define APPLY_RULE( var, name, type ) \
00479
bool Rules::apply##name( type& arg, bool init ) const \
00480
{ \
00481
if( checkSetRule( var##rule, init )) \
00482
arg = this->var; \
00483
return checkSetStop( var##rule ); \
00484
}
00485
00486
#define APPLY_FORCE_RULE( var, name, type ) \
00487
bool Rules::apply##name( type& arg ) const \
00488
{ \
00489
if( checkForceRule( var##rule )) \
00490
arg = this->var; \
00491
return checkForceStop( var##rule ); \
00492
}
00493
00494 APPLY_FORCE_RULE( placement, Placement, Placement::Policy )
00495
00496 bool Rules::applyGeometry( QRect& rect,
bool init )
const
00497
{
00498 QPoint p = rect.topLeft();
00499 QSize s = rect.size();
00500
bool ret =
false;
00501
if( applyPosition( p, init ))
00502 {
00503 rect.moveTopLeft( p );
00504 ret =
true;
00505 }
00506
if( applySize( s, init ))
00507 {
00508 rect.setSize( s );
00509 ret =
true;
00510 }
00511
return ret;
00512 }
00513
00514
bool Rules::applyPosition( QPoint& pos,
bool init )
const
00515
{
00516
if( this->position != invalidPoint && checkSetRule( positionrule, init ))
00517 pos = this->position;
00518
return checkSetStop( positionrule );
00519 }
00520
00521
bool Rules::applySize( QSize& s,
bool init )
const
00522
{
00523
if( this->size.isValid() && checkSetRule( sizerule, init ))
00524 s = this->size;
00525
return checkSetStop( sizerule );
00526 }
00527
00528 APPLY_FORCE_RULE( minsize, MinSize, QSize )
00529 APPLY_FORCE_RULE( maxsize, MaxSize, QSize )
00530 APPLY_FORCE_RULE( ignoreposition, IgnorePosition,
bool )
00531 APPLY_RULE( desktop, Desktop,
int )
00532 APPLY_FORCE_RULE( type, Type, NET::WindowType )
00533
00534
bool Rules::applyMaximizeHoriz( MaximizeMode& mode,
bool init )
const
00535
{
00536
if( checkSetRule( maximizehorizrule, init ))
00537 mode = static_cast< MaximizeMode >(( maximizehoriz ? MaximizeHorizontal : 0 ) | ( mode & MaximizeVertical ));
00538
return checkSetStop( maximizehorizrule );
00539 }
00540
00541
bool Rules::applyMaximizeVert( MaximizeMode& mode,
bool init )
const
00542
{
00543
if( checkSetRule( maximizevertrule, init ))
00544 mode = static_cast< MaximizeMode >(( maximizevert ?
MaximizeVertical : 0 ) | ( mode &
MaximizeHorizontal ));
00545
return checkSetStop( maximizevertrule );
00546 }
00547
00548 APPLY_RULE( minimize, Minimize,
bool )
00549
00550 bool Rules::applyShade( ShadeMode& sh,
bool init )
const
00551
{
00552
if( checkSetRule( shaderule, init ))
00553 {
00554
if( !this->shade )
00555 sh = ShadeNone;
00556
if( this->shade && sh == ShadeNone )
00557 sh = ShadeNormal;
00558 }
00559
return checkSetStop( shaderule );
00560 }
00561
00562 APPLY_RULE( skiptaskbar, SkipTaskbar,
bool )
00563 APPLY_RULE( skippager, SkipPager,
bool )
00564 APPLY_RULE( above, KeepAbove,
bool )
00565 APPLY_RULE( below, KeepBelow,
bool )
00566 APPLY_RULE( fullscreen, FullScreen,
bool )
00567 APPLY_RULE( noborder, NoBorder,
bool )
00568 APPLY_FORCE_RULE( fsplevel, FSP,
int )
00569 APPLY_FORCE_RULE( acceptfocus, AcceptFocus,
bool )
00570 APPLY_FORCE_RULE( moveresizemode, MoveResizeMode, Options::MoveResizeMode )
00571 APPLY_FORCE_RULE( closeable, Closeable,
bool )
00572
00573 #undef APPLY_RULE
00574 #undef APPLY_FORCE_RULE
00575
00576
bool Rules::isTemporary()
const
00577
{
00578
return temporary_state > 0;
00579 }
00580
00581
bool Rules::discardTemporary(
bool force )
00582 {
00583
if( temporary_state == 0 )
00584
return false;
00585
if( force || --temporary_state == 0 )
00586 {
00587
delete this;
00588
return true;
00589 }
00590
return false;
00591 }
00592
#endif
00593
00594
#ifndef NDEBUG
00595
kdbgstream& operator<<( kdbgstream& stream,
const Rules* r )
00596 {
00597
return stream <<
"[" << r->description <<
"]";
00598 }
00599
#endif
00600
00601
#ifndef KCMRULES
00602
void WindowRules::discardTemporary()
00603 {
00604 QValueVector< Rules* >::Iterator it2 = rules.begin();
00605
for( QValueVector< Rules* >::Iterator it = rules.begin();
00606 it != rules.end();
00607 )
00608 {
00609
if( (*it)->discardTemporary(
false ))
00610 ++it;
00611
else
00612 {
00613 *it2++ = *it++;
00614 }
00615 }
00616 rules.erase( it2, rules.end());
00617 }
00618
00619
void WindowRules::update( Client* c )
00620 {
00621
bool updated =
false;
00622
for( QValueVector< Rules* >::ConstIterator it = rules.begin();
00623 it != rules.end();
00624 ++it )
00625
if( (*it)->update( c ))
00626 updated =
true;
00627
if( updated )
00628 Workspace::self()->rulesUpdated();
00629 }
00630
00631
#define CHECK_RULE( rule, type ) \
00632
type WindowRules::check##rule( type arg, bool init ) const \
00633
{ \
00634
if( rules.count() == 0 ) \
00635
return arg; \
00636
type ret = arg; \
00637
for( QValueVector< Rules* >::ConstIterator it = rules.begin(); \
00638
it != rules.end(); \
00639
++it ) \
00640
{ \
00641
if( (*it)->apply##rule( ret, init )) \
00642
break; \
00643
} \
00644
return ret; \
00645
}
00646
00647
#define CHECK_FORCE_RULE( rule, type ) \
00648
type WindowRules::check##rule( type arg ) const \
00649
{ \
00650
if( rules.count() == 0 ) \
00651
return arg; \
00652
type ret = arg; \
00653
for( QValueVector< Rules* >::ConstIterator it = rules.begin(); \
00654
it != rules.end(); \
00655
++it ) \
00656
{ \
00657
if( (*it)->apply##rule( ret )) \
00658
break; \
00659
} \
00660
return ret; \
00661
}
00662
00663 CHECK_FORCE_RULE( Placement, Placement::Policy )
00664
00665 QRect WindowRules::checkGeometry( QRect rect,
bool init )
const
00666
{
00667
return QRect( checkPosition( rect.topLeft(), init ), checkSize( rect.size(), init ));
00668 }
00669
00670 CHECK_RULE( Position, QPoint )
00671 CHECK_RULE( Size, QSize )
00672 CHECK_FORCE_RULE( MinSize, QSize )
00673 CHECK_FORCE_RULE( MaxSize, QSize )
00674 CHECK_FORCE_RULE( IgnorePosition,
bool )
00675 CHECK_RULE( Desktop,
int )
00676 CHECK_FORCE_RULE( Type, NET::WindowType )
00677 CHECK_RULE( MaximizeVert,
KDecorationDefines::MaximizeMode )
00678 CHECK_RULE( MaximizeHoriz,
KDecorationDefines::MaximizeMode )
00679
00680
KDecorationDefines::MaximizeMode WindowRules::checkMaximize( MaximizeMode mode,
bool init )
const
00681
{
00682
bool vert = checkMaximizeVert( mode, init ) & MaximizeVertical;
00683
bool horiz = checkMaximizeHoriz( mode, init ) & MaximizeHorizontal;
00684
return static_cast< MaximizeMode >(( vert ? MaximizeVertical : 0 ) | ( horiz ? MaximizeHorizontal : 0 ));
00685 }
00686
00687 CHECK_RULE( Minimize,
bool )
00688 CHECK_RULE( Shade, ShadeMode )
00689 CHECK_RULE( SkipTaskbar,
bool )
00690 CHECK_RULE( SkipPager,
bool )
00691 CHECK_RULE( KeepAbove,
bool )
00692 CHECK_RULE( KeepBelow,
bool )
00693 CHECK_RULE( FullScreen,
bool )
00694 CHECK_RULE( NoBorder,
bool )
00695 CHECK_FORCE_RULE( FSP,
int )
00696 CHECK_FORCE_RULE( AcceptFocus,
bool )
00697 CHECK_FORCE_RULE( MoveResizeMode, Options::MoveResizeMode )
00698 CHECK_FORCE_RULE( Closeable,
bool )
00699
00700 #undef CHECK_RULE
00701 #undef CHECK_FORCE_RULE
00702
00703
00704
00705
void Client::setupWindowRules(
bool ignore_temporary )
00706 {
00707 client_rules = workspace()->findWindowRules(
this, ignore_temporary );
00708
00709
if( isTopMenu())
00710 client_rules = WindowRules();
00711 }
00712
00713
void Client::updateWindowRules()
00714 {
00715
if( !isManaged())
00716
return;
00717 client_rules.update(
this );
00718 }
00719
00720
void Client::finishWindowRules()
00721 {
00722 updateWindowRules();
00723 client_rules = WindowRules();
00724 }
00725
00726
00727
00728 WindowRules Workspace::findWindowRules(
const Client* c,
bool ignore_temporary )
00729 {
00730 QValueVector< Rules* > ret;
00731
for( QValueList< Rules* >::Iterator it = rules.begin();
00732 it != rules.end();
00733 )
00734 {
00735
if( ignore_temporary && (*it)->isTemporary())
00736 {
00737 ++it;
00738
continue;
00739 }
00740
if( (*it)->match( c ))
00741 {
00742 Rules* rule = *it;
00743 kdDebug( 1212 ) <<
"Rule found:" << rule <<
":" << c << endl;
00744
if( rule->isTemporary())
00745 it = rules.remove( it );
00746
else
00747 ++it;
00748 ret.append( rule );
00749
continue;
00750 }
00751 ++it;
00752 }
00753
return WindowRules( ret );
00754 }
00755
00756
void Workspace::editWindowRules( Client* c )
00757 {
00758 KApplication::kdeinitExec(
"kwin_rules_dialog", QStringList() <<
"--wid" << QString::number( c->window()));
00759 }
00760
00761
void Workspace::loadWindowRules()
00762 {
00763
while( !rules.isEmpty())
00764 {
00765
delete rules.front();
00766 rules.pop_front();
00767 }
00768 KConfig cfg(
"kwinrulesrc",
true );
00769 cfg.setGroup(
"General" );
00770
int count = cfg.readNumEntry(
"count" );
00771
for(
int i = 1;
00772 i <= count;
00773 ++i )
00774 {
00775 cfg.setGroup( QString::number( i ));
00776 Rules* rule =
new Rules( cfg );
00777 rules.append( rule );
00778 }
00779 }
00780
00781
void Workspace::writeWindowRules()
00782 {
00783 KConfig cfg(
"kwinrulesrc" );
00784 cfg.setGroup(
"General" );
00785 cfg.writeEntry(
"count", rules.count());
00786
int i = 1;
00787
for( QValueList< Rules* >::ConstIterator it = rules.begin();
00788 it != rules.end();
00789 ++it )
00790 {
00791
if( (*it)->isTemporary())
00792
continue;
00793 cfg.setGroup( QString::number( i ));
00794 (*it)->write( cfg );
00795 ++i;
00796 }
00797 }
00798
00799
void Workspace::gotTemporaryRulesMessage(
const QString& message )
00800 {
00801
bool was_temporary =
false;
00802
for( QValueList< Rules* >::ConstIterator it = rules.begin();
00803 it != rules.end();
00804 ++it )
00805
if( (*it)->isTemporary())
00806 was_temporary =
true;
00807 Rules* rule =
new Rules( message,
true );
00808 rules.prepend( rule );
00809
if( !was_temporary )
00810 QTimer::singleShot( 60000,
this, SLOT( cleanupTemporaryRules()));
00811 }
00812
00813
void Workspace::cleanupTemporaryRules()
00814 {
00815
bool has_temporary =
false;
00816
for( QValueList< Rules* >::Iterator it = rules.begin();
00817 it != rules.end();
00818 )
00819 {
00820
if( (*it)->discardTemporary(
false ))
00821 it = rules.remove( it );
00822
else
00823 {
00824
if( (*it)->isTemporary())
00825 has_temporary =
true;
00826 ++it;
00827 }
00828 }
00829
if( has_temporary )
00830 QTimer::singleShot( 60000,
this, SLOT( cleanupTemporaryRules()));
00831 }
00832
00833
void Workspace::rulesUpdated()
00834 {
00835 rulesUpdatedTimer.start( 1000,
true );
00836 }
00837
00838
#endif
00839
00840 }