kwin Library API Documentation

rules.cpp

00001 /***************************************************************** 00002 KWin - the KDE window manager 00003 This file is part of the KDE project. 00004 00005 Copyright (C) 2004 Lubos Lunak <l.lunak@kde.org> 00006 00007 You can Freely distribute this program under the GNU General Public 00008 License. See the file "COPYING" for the exact licensing terms. 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 ); // fsp is 0-4 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 // always write wmclass 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 // returns true if it doesn't affect anything 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; // NET::Unknown->NET::Normal is only here for matching 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 { // TODO optimize? 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 // if it's localhost, check also "localhost" before checking hostname 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 // TODO extrarole 00383 if( !matchClientMachine( c->wmClientMachine( false ))) 00384 return false; 00385 return true; 00386 } 00387 00388 bool Rules::update( Client* c ) 00389 { 00390 // TODO check this setting is for this client ? 00391 bool updated = false; 00392 if( positionrule == ( SetRule )Remember) 00393 { 00394 if( !c->isFullScreen()) 00395 { 00396 QPoint new_pos = position; 00397 // don't use the position in the direction which is maximized 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 // don't use the position in the direction which is maximized 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; // no short-circuiting 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 ) // not temporary 00584 return false; 00585 if( force || --temporary_state == 0 ) // too old 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 )) // no short-circuiting here 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 // Client 00704 00705 void Client::setupWindowRules( bool ignore_temporary ) 00706 { 00707 client_rules = workspace()->findWindowRules( this, ignore_temporary ); 00708 // check only after getting the rules, because there may be a rule forcing window type 00709 if( isTopMenu()) // TODO cannot have restrictions 00710 client_rules = WindowRules(); 00711 } 00712 00713 void Client::updateWindowRules() 00714 { 00715 if( !isManaged()) // not fully setup yet 00716 return; 00717 client_rules.update( this ); 00718 } 00719 00720 void Client::finishWindowRules() 00721 { 00722 updateWindowRules(); 00723 client_rules = WindowRules(); 00724 } 00725 00726 // Workspace 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 ); // highest priority first 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 } // namespace
KDE Logo
This file is part of the documentation for kwin Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Aug 13 21:47:06 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003