• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • twin
 

twin

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 <tdeconfig.h>
00015 #include <tqregexp.h>
00016 #include <tdetempfile.h>
00017 #include <ksimpleconfig.h>
00018 #include <tqfile.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     , opacityactiverule( UnusedForceRule )
00043     , opacityinactiverule( UnusedForceRule )
00044     , ignorepositionrule( UnusedForceRule )
00045     , desktoprule( UnusedSetRule )
00046     , typerule( UnusedForceRule )
00047     , maximizevertrule( UnusedSetRule )
00048     , maximizehorizrule( UnusedSetRule )
00049     , minimizerule( UnusedSetRule )
00050     , shaderule( UnusedSetRule )
00051     , skiptaskbarrule( UnusedSetRule )
00052     , skippagerrule( UnusedSetRule )
00053     , aboverule( UnusedSetRule )
00054     , belowrule( UnusedSetRule )
00055     , fullscreenrule( UnusedSetRule )
00056     , noborderrule( UnusedSetRule )
00057     , fsplevelrule( UnusedForceRule )
00058     , acceptfocusrule( UnusedForceRule )
00059     , moveresizemoderule( UnusedForceRule )
00060     , closeablerule( UnusedForceRule )
00061     , strictgeometryrule( UnusedForceRule )
00062     , shortcutrule( UnusedSetRule )
00063     , disableglobalshortcutsrule( UnusedForceRule )
00064     {
00065     }
00066 
00067 Rules::Rules( const TQString& str, bool temporary )
00068     : temporary_state( temporary ? 2 : 0 )
00069     {
00070     KTempFile file;
00071     TQFile* f = file.file();
00072     if( f != NULL )
00073         {
00074         TQCString s = str.utf8();
00075         f->writeBlock( s.data(), s.length());
00076         }
00077     file.close();
00078     KSimpleConfig cfg( file.name());
00079     readFromCfg( cfg );
00080     if( description.isEmpty())
00081         description = "temporary";
00082     file.unlink();
00083     }
00084 
00085 #define READ_MATCH_STRING( var, func ) \
00086     var = cfg.readEntry( #var ) func; \
00087     var##match = (StringMatch) TQMAX( FirstStringMatch, TQMIN( LastStringMatch, cfg.readNumEntry( #var "match" )));
00088     
00089 #define READ_SET_RULE( var, type, func ) \
00090     var = func ( cfg.read##type##Entry( #var )); \
00091     var##rule = readSetRule( cfg, #var "rule" );
00092     
00093 #define READ_SET_RULE_DEF( var, type, func, def ) \
00094     var = func ( cfg.read##type##Entry( #var, def )); \
00095     var##rule = readSetRule( cfg, #var "rule" );
00096     
00097 #define READ_SET_RULE_2( var, type, func, funcarg ) \
00098     var = func ( cfg.read##type##Entry( #var ), funcarg ); \
00099     var##rule = readSetRule( cfg, #var "rule" );
00100 
00101 #define READ_FORCE_RULE( var, type, func ) \
00102     var = func ( cfg.read##type##Entry( #var )); \
00103     var##rule = readForceRule( cfg, #var "rule" );
00104 
00105 #define READ_FORCE_RULE_2( var, type, func, funcarg ) \
00106     var = func ( cfg.read##type##Entry( #var ), funcarg ); \
00107     var##rule = readForceRule( cfg, #var "rule" );
00108 
00109 
00110 Rules::Rules( TDEConfig& cfg )
00111     : temporary_state( 0 )
00112     {
00113     readFromCfg( cfg );
00114     }
00115 
00116 static int limit0to4( int i ) { return TQMAX( 0, TQMIN( 4, i )); }
00117 
00118 void Rules::readFromCfg( TDEConfig& cfg )
00119     {
00120     description = cfg.readEntry( "Description" );
00121     if( description.isEmpty()) // capitalized first, lowercase for backwards compatibility
00122         description = cfg.readEntry( "description" );
00123     READ_MATCH_STRING( wmclass, .lower().latin1() );
00124     wmclasscomplete = cfg.readBoolEntry( "wmclasscomplete" );
00125     READ_MATCH_STRING( windowrole, .lower().latin1() );
00126     READ_MATCH_STRING( title, );
00127     READ_MATCH_STRING( extrarole, .lower().latin1() );
00128     READ_MATCH_STRING( clientmachine, .lower().latin1() );
00129     types = cfg.readUnsignedLongNumEntry( "types", NET::AllTypesMask );
00130     READ_FORCE_RULE_2( placement,, Placement::policyFromString, false );
00131     READ_SET_RULE_DEF( position, Point,, &invalidPoint );
00132     READ_SET_RULE( size, Size, );
00133     if( size.isEmpty() && sizerule != ( SetRule )Remember)
00134         sizerule = UnusedSetRule;
00135     READ_FORCE_RULE( minsize, Size, );
00136     if( !minsize.isValid())
00137         minsize = TQSize( 1, 1 );
00138     READ_FORCE_RULE( maxsize, Size, );
00139     if( maxsize.isEmpty())
00140         maxsize = TQSize( 32767, 32767 );
00141     READ_FORCE_RULE( opacityactive, Num, );
00142     if( opacityactive < 0 || opacityactive > 100 )
00143         opacityactive = 100;
00144     READ_FORCE_RULE( opacityinactive, Num, );
00145     if( opacityinactive < 0 || opacityinactive > 100 )
00146         opacityinactive = 100;
00147     READ_FORCE_RULE( ignoreposition, Bool, );
00148     READ_SET_RULE( desktop, Num, );
00149     type = readType( cfg, "type" );
00150     typerule = type != NET::Unknown ? readForceRule( cfg, "typerule" ) : UnusedForceRule;
00151     READ_SET_RULE( maximizevert, Bool, );
00152     READ_SET_RULE( maximizehoriz, Bool, );
00153     READ_SET_RULE( minimize, Bool, );
00154     READ_SET_RULE( shade, Bool, );
00155     READ_SET_RULE( skiptaskbar, Bool, );
00156     READ_SET_RULE( skippager, Bool, );
00157     READ_SET_RULE( above, Bool, );
00158     READ_SET_RULE( below, Bool, );
00159     READ_SET_RULE( fullscreen, Bool, );
00160     READ_SET_RULE( noborder, Bool, );
00161     READ_FORCE_RULE( fsplevel, Num, limit0to4 ); // fsp is 0-4
00162     READ_FORCE_RULE( acceptfocus, Bool, );
00163     READ_FORCE_RULE( moveresizemode, , Options::stringToMoveResizeMode );
00164     READ_FORCE_RULE( closeable, Bool, );
00165     READ_FORCE_RULE( strictgeometry, Bool, );
00166     READ_SET_RULE( shortcut, , );
00167     READ_FORCE_RULE( disableglobalshortcuts, Bool, );
00168     }
00169 
00170 #undef READ_MATCH_STRING
00171 #undef READ_SET_RULE
00172 #undef READ_SET_RULE_2
00173 #undef READ_FORCE_RULE
00174 #undef READ_FORCE_RULE_2
00175 
00176 #define WRITE_MATCH_STRING( var, cast, force ) \
00177     if( !var.isEmpty() || force ) \
00178         { \
00179         cfg.writeEntry( #var, cast var ); \
00180         cfg.writeEntry( #var "match", var##match ); \
00181         } \
00182     else \
00183         { \
00184         cfg.deleteEntry( #var ); \
00185         cfg.deleteEntry( #var "match" ); \
00186         }
00187 
00188 #define WRITE_SET_RULE( var, func ) \
00189     if( var##rule != UnusedSetRule ) \
00190         { \
00191         cfg.writeEntry( #var, func ( var )); \
00192         cfg.writeEntry( #var "rule", var##rule ); \
00193         } \
00194     else \
00195         { \
00196         cfg.deleteEntry( #var ); \
00197         cfg.deleteEntry( #var "rule" ); \
00198         }
00199 
00200 #define WRITE_FORCE_RULE( var, func ) \
00201     if( var##rule != UnusedForceRule ) \
00202         { \
00203         cfg.writeEntry( #var, func ( var )); \
00204         cfg.writeEntry( #var "rule", var##rule ); \
00205         } \
00206     else \
00207         { \
00208         cfg.deleteEntry( #var ); \
00209         cfg.deleteEntry( #var "rule" ); \
00210         }
00211 
00212 #define WRITE_WITH_DEFAULT( var, default ) \
00213     if( var != default ) \
00214         cfg.writeEntry( #var, var ); \
00215     else \
00216         cfg.deleteEntry( #var );
00217 
00218 
00219 void Rules::write( TDEConfig& cfg ) const
00220     {
00221     cfg.writeEntry( "Description", description );
00222     // always write wmclass
00223     WRITE_MATCH_STRING( wmclass, (const char*), true );
00224     cfg.writeEntry( "wmclasscomplete", wmclasscomplete );
00225     WRITE_MATCH_STRING( windowrole, (const char*), false );
00226     WRITE_MATCH_STRING( title,, false );
00227     WRITE_MATCH_STRING( extrarole, (const char*), false );
00228     WRITE_MATCH_STRING( clientmachine, (const char*), false );
00229     WRITE_WITH_DEFAULT( types, NET::AllTypesMask );
00230     WRITE_FORCE_RULE( placement, Placement::policyToString );
00231     WRITE_SET_RULE( position, );
00232     WRITE_SET_RULE( size, );
00233     WRITE_FORCE_RULE( minsize, );
00234     WRITE_FORCE_RULE( maxsize, );
00235     WRITE_FORCE_RULE( opacityactive, );
00236     WRITE_FORCE_RULE( opacityinactive, );
00237     WRITE_FORCE_RULE( ignoreposition, );
00238     WRITE_SET_RULE( desktop, );
00239     WRITE_FORCE_RULE( type, );
00240     WRITE_SET_RULE( maximizevert, );
00241     WRITE_SET_RULE( maximizehoriz, );
00242     WRITE_SET_RULE( minimize, );
00243     WRITE_SET_RULE( shade, );
00244     WRITE_SET_RULE( skiptaskbar, );
00245     WRITE_SET_RULE( skippager, );
00246     WRITE_SET_RULE( above, );
00247     WRITE_SET_RULE( below, );
00248     WRITE_SET_RULE( fullscreen, );
00249     WRITE_SET_RULE( noborder, );
00250     WRITE_FORCE_RULE( fsplevel, );
00251     WRITE_FORCE_RULE( acceptfocus, );
00252     WRITE_FORCE_RULE( moveresizemode, Options::moveResizeModeToString );
00253     WRITE_FORCE_RULE( closeable, );
00254     WRITE_FORCE_RULE( strictgeometry, );
00255     WRITE_SET_RULE( shortcut, );
00256     WRITE_FORCE_RULE( disableglobalshortcuts, );
00257     }
00258     
00259 #undef WRITE_MATCH_STRING
00260 #undef WRITE_SET_RULE
00261 #undef WRITE_FORCE_RULE
00262 #undef WRITE_WITH_DEFAULT
00263 
00264 // returns true if it doesn't affect anything
00265 bool Rules::isEmpty() const
00266     {
00267     return( placementrule == UnusedForceRule
00268         && positionrule == UnusedSetRule
00269         && sizerule == UnusedSetRule
00270         && minsizerule == UnusedForceRule
00271         && maxsizerule == UnusedForceRule
00272         && opacityactiverule == UnusedForceRule
00273         && opacityinactiverule == UnusedForceRule
00274         && ignorepositionrule == UnusedForceRule
00275         && desktoprule == UnusedSetRule
00276         && typerule == UnusedForceRule
00277         && maximizevertrule == UnusedSetRule
00278         && maximizehorizrule == UnusedSetRule
00279         && minimizerule == UnusedSetRule
00280         && shaderule == UnusedSetRule
00281         && skiptaskbarrule == UnusedSetRule
00282         && skippagerrule == UnusedSetRule
00283         && aboverule == UnusedSetRule
00284         && belowrule == UnusedSetRule
00285         && fullscreenrule == UnusedSetRule
00286         && noborderrule == UnusedSetRule
00287         && fsplevelrule == UnusedForceRule
00288         && acceptfocusrule == UnusedForceRule
00289         && moveresizemoderule == UnusedForceRule
00290         && closeablerule == UnusedForceRule
00291         && strictgeometryrule == UnusedForceRule
00292         && shortcutrule == UnusedSetRule
00293         && disableglobalshortcutsrule == UnusedForceRule );
00294     }
00295 
00296 Rules::SetRule Rules::readSetRule( TDEConfig& cfg, const TQString& key )
00297     {
00298     int v = cfg.readNumEntry( key );
00299     if( v >= DontAffect && v <= ForceTemporarily )
00300         return static_cast< SetRule >( v );
00301     return UnusedSetRule;
00302     }
00303 
00304 Rules::ForceRule Rules::readForceRule( TDEConfig& cfg, const TQString& key )
00305     {
00306     int v = cfg.readNumEntry( key );
00307     if( v == DontAffect || v == Force || v == ForceTemporarily )
00308         return static_cast< ForceRule >( v );
00309     return UnusedForceRule;
00310     }
00311 
00312 NET::WindowType Rules::readType( TDEConfig& cfg, const TQString& key )
00313     {
00314     int v = cfg.readNumEntry( key );
00315     if( v >= NET::Normal && v <= NET::Splash )
00316         return static_cast< NET::WindowType >( v );
00317     return NET::Unknown;
00318     }
00319 
00320 bool Rules::matchType( NET::WindowType match_type ) const
00321     {
00322     if( types != NET::AllTypesMask )
00323         {
00324         if( match_type == NET::Unknown )
00325             match_type = NET::Normal; // NET::Unknown->NET::Normal is only here for matching
00326         if( !NET::typeMatchesMask( match_type, types ))
00327             return false;
00328         }
00329     return true;
00330     }
00331     
00332 bool Rules::matchWMClass( const TQCString& match_class, const TQCString& match_name ) const
00333     {
00334     if( wmclassmatch != UnimportantMatch )
00335         { // TODO optimize?
00336         TQCString cwmclass = wmclasscomplete
00337             ? match_name + ' ' + match_class : match_class;
00338         if( wmclassmatch == RegExpMatch && TQRegExp( wmclass ).search( cwmclass ) == -1 )
00339             return false;
00340         if( wmclassmatch == ExactMatch && wmclass != cwmclass )
00341             return false;
00342         if( wmclassmatch == SubstringMatch && !cwmclass.contains( wmclass ))
00343             return false;
00344         }
00345     return true;
00346     }
00347     
00348 bool Rules::matchRole( const TQCString& match_role ) const
00349     {
00350     if( windowrolematch != UnimportantMatch )
00351         {
00352         if( windowrolematch == RegExpMatch && TQRegExp( windowrole ).search( match_role ) == -1 )
00353             return false;
00354         if( windowrolematch == ExactMatch && windowrole != match_role )
00355             return false;
00356         if( windowrolematch == SubstringMatch && !match_role.contains( windowrole ))
00357             return false;
00358         }
00359     return true;
00360     }
00361     
00362 bool Rules::matchTitle( const TQString& match_title ) const
00363     {
00364     if( titlematch != UnimportantMatch )
00365         {
00366         if( titlematch == RegExpMatch && TQRegExp( title ).search( match_title ) == -1 )
00367             return false;
00368         if( titlematch == ExactMatch && title != match_title )
00369             return false;
00370         if( titlematch == SubstringMatch && !match_title.contains( title ))
00371             return false;
00372         }
00373     return true;
00374     }
00375 
00376 bool Rules::matchClientMachine( const TQCString& match_machine ) const
00377     {
00378     if( clientmachinematch != UnimportantMatch )
00379         {
00380         // if it's localhost, check also "localhost" before checking hostname
00381         if( match_machine != "localhost" && isLocalMachine( match_machine )
00382             && matchClientMachine( "localhost" ))
00383             return true;
00384         if( clientmachinematch == RegExpMatch
00385             && TQRegExp( clientmachine ).search( match_machine ) == -1 )
00386             return false;
00387         if( clientmachinematch == ExactMatch
00388             && clientmachine != match_machine )
00389             return false;
00390         if( clientmachinematch == SubstringMatch
00391             && !match_machine.contains( clientmachine ))
00392             return false;
00393         }
00394     return true;
00395     }
00396 
00397 #ifndef KCMRULES
00398 bool Rules::match( const Client* c ) const
00399     {
00400     if( !matchType( c->windowType( true )))
00401         return false;
00402     if( !matchWMClass( c->resourceClass(), c->resourceName()))
00403         return false;
00404     if( !matchRole( c->windowRole()))
00405         return false;
00406     if( !matchTitle( c->caption( false )))
00407         return false;
00408     // TODO extrarole
00409     if( !matchClientMachine( c->wmClientMachine( false )))
00410         return false;
00411     return true;
00412     }
00413 
00414 bool Rules::update( Client* c )
00415     {
00416     // TODO check this setting is for this client ?
00417     bool updated = false;
00418     if( positionrule == ( SetRule )Remember)
00419         {
00420         if( !c->isFullScreen())
00421             {
00422             TQPoint new_pos = position;
00423             // don't use the position in the direction which is maximized
00424             if(( c->maximizeMode() & MaximizeHorizontal ) == 0 )
00425                 new_pos.setX( c->pos().x());
00426             if(( c->maximizeMode() & MaximizeVertical ) == 0 )
00427                 new_pos.setY( c->pos().y());
00428             updated = updated || position != new_pos;
00429             position = new_pos;
00430             }
00431         }
00432     if( sizerule == ( SetRule )Remember)
00433         {
00434         if( !c->isFullScreen())
00435             {
00436             TQSize new_size = size;
00437             // don't use the position in the direction which is maximized
00438             if(( c->maximizeMode() & MaximizeHorizontal ) == 0 )
00439                 new_size.setWidth( c->size().width());
00440             if(( c->maximizeMode() & MaximizeVertical ) == 0 )
00441                 new_size.setHeight( c->size().height());
00442             updated = updated || size != new_size;
00443             size = new_size;
00444             }
00445         }
00446     if( desktoprule == ( SetRule )Remember)
00447         {
00448         updated = updated || desktop != c->desktop();
00449         desktop = c->desktop();
00450         }
00451     if( maximizevertrule == ( SetRule )Remember)
00452         {
00453         updated = updated || maximizevert != bool( c->maximizeMode() & MaximizeVertical );
00454         maximizevert = c->maximizeMode() & MaximizeVertical;
00455         }
00456     if( maximizehorizrule == ( SetRule )Remember)
00457         {
00458         updated = updated || maximizehoriz != bool( c->maximizeMode() & MaximizeHorizontal );
00459         maximizehoriz = c->maximizeMode() & MaximizeHorizontal;
00460         }
00461     if( minimizerule == ( SetRule )Remember)
00462         {
00463         updated = updated || minimize != c->isMinimized();
00464         minimize = c->isMinimized();
00465         }
00466     if( shaderule == ( SetRule )Remember)
00467         {
00468         updated = updated || ( shade != ( c->shadeMode() != ShadeNone ));
00469         shade = c->shadeMode() != ShadeNone;
00470         }
00471     if( skiptaskbarrule == ( SetRule )Remember)
00472         {
00473         updated = updated || skiptaskbar != c->skipTaskbar();
00474         skiptaskbar = c->skipTaskbar();
00475         }
00476     if( skippagerrule == ( SetRule )Remember)
00477         {
00478         updated = updated || skippager != c->skipPager();
00479         skippager = c->skipPager();
00480         }
00481     if( aboverule == ( SetRule )Remember)
00482         {
00483         updated = updated || above != c->keepAbove();
00484         above = c->keepAbove();
00485         }
00486     if( belowrule == ( SetRule )Remember)
00487         {
00488         updated = updated || below != c->keepBelow();
00489         below = c->keepBelow();
00490         }
00491     if( fullscreenrule == ( SetRule )Remember)
00492         {
00493         updated = updated || fullscreen != c->isFullScreen();
00494         fullscreen = c->isFullScreen();
00495         }
00496     if( noborderrule == ( SetRule )Remember)
00497         {
00498         updated = updated || noborder != c->isUserNoBorder();
00499         noborder = c->isUserNoBorder();
00500         }
00501     if (opacityactiverule == ( ForceRule )Force)
00502         {
00503         updated = updated || (uint) (opacityactive/100.0*0xffffffff) != c->ruleOpacityActive();
00504         opacityactive = (uint)(((double)c->ruleOpacityActive())/0xffffffff*100);
00505         }
00506     if (opacityinactiverule == ( ForceRule )Force)
00507         {
00508         updated = updated || (uint) (opacityinactive/100.0*0xffffffff) != c->ruleOpacityInactive();
00509         opacityinactive = (uint)(((double)c->ruleOpacityInactive())/0xffffffff*100);
00510         }
00511     return updated;
00512     }
00513 
00514 #define APPLY_RULE( var, name, type ) \
00515 bool Rules::apply##name( type& arg, bool init ) const \
00516     { \
00517     if( checkSetRule( var##rule, init )) \
00518         arg = this->var; \
00519     return checkSetStop( var##rule ); \
00520     }
00521 
00522 #define APPLY_FORCE_RULE( var, name, type ) \
00523 bool Rules::apply##name( type& arg ) const \
00524     { \
00525     if( checkForceRule( var##rule )) \
00526         arg = this->var; \
00527     return checkForceStop( var##rule ); \
00528     }
00529 
00530 APPLY_FORCE_RULE( placement, Placement, Placement::Policy )
00531 
00532 bool Rules::applyGeometry( TQRect& rect, bool init ) const
00533     {
00534     TQPoint p = rect.topLeft();
00535     TQSize s = rect.size();
00536     bool ret = false; // no short-circuiting
00537     if( applyPosition( p, init ))
00538         {
00539         rect.moveTopLeft( p );
00540         ret = true;
00541         }
00542     if( applySize( s, init ))
00543         {
00544         rect.setSize( s );
00545         ret = true;
00546         }
00547     return ret;
00548     }
00549 
00550 bool Rules::applyPosition( TQPoint& pos, bool init ) const
00551     {
00552     if( this->position != invalidPoint && checkSetRule( positionrule, init ))
00553         pos = this->position;
00554     return checkSetStop( positionrule );
00555     }
00556 
00557 bool Rules::applySize( TQSize& s, bool init ) const
00558     {
00559     if( this->size.isValid() && checkSetRule( sizerule, init ))
00560         s = this->size;
00561     return checkSetStop( sizerule );
00562     }
00563 
00564 APPLY_FORCE_RULE( minsize, MinSize, TQSize )
00565 APPLY_FORCE_RULE( maxsize, MaxSize, TQSize )
00566 APPLY_FORCE_RULE( opacityactive, OpacityActive, int )
00567 APPLY_FORCE_RULE( opacityinactive, OpacityInactive, int )
00568 APPLY_FORCE_RULE( ignoreposition, IgnorePosition, bool )
00569 
00570 // the cfg. entry needs to stay named the say for backwards compatibility
00571 bool Rules::applyIgnoreGeometry( bool& ignore ) const
00572     {
00573     return applyIgnorePosition( ignore );
00574     }
00575 
00576 APPLY_RULE( desktop, Desktop, int )
00577 APPLY_FORCE_RULE( type, Type, NET::WindowType )
00578 
00579 bool Rules::applyMaximizeHoriz( MaximizeMode& mode, bool init ) const
00580     {
00581     if( checkSetRule( maximizehorizrule, init ))
00582         mode = static_cast< MaximizeMode >(( maximizehoriz ? MaximizeHorizontal : 0 ) | ( mode & MaximizeVertical ));
00583     return checkSetStop( maximizehorizrule );
00584     }
00585 
00586 bool Rules::applyMaximizeVert( MaximizeMode& mode, bool init ) const
00587     {
00588     if( checkSetRule( maximizevertrule, init ))
00589         mode = static_cast< MaximizeMode >(( maximizevert ? MaximizeVertical : 0 ) | ( mode & MaximizeHorizontal ));
00590     return checkSetStop( maximizevertrule );
00591     }
00592 
00593 APPLY_RULE( minimize, Minimize, bool )
00594 
00595 bool Rules::applyShade( ShadeMode& sh, bool init ) const
00596     {
00597     if( checkSetRule( shaderule, init ))
00598         {
00599         if( !this->shade )
00600             sh = ShadeNone;
00601         if( this->shade && sh == ShadeNone )
00602             sh = ShadeNormal;
00603         }
00604     return checkSetStop( shaderule );
00605     }
00606 
00607 APPLY_RULE( skiptaskbar, SkipTaskbar, bool )
00608 APPLY_RULE( skippager, SkipPager, bool )
00609 APPLY_RULE( above, KeepAbove, bool )
00610 APPLY_RULE( below, KeepBelow, bool )
00611 APPLY_RULE( fullscreen, FullScreen, bool )
00612 APPLY_RULE( noborder, NoBorder, bool )
00613 APPLY_FORCE_RULE( fsplevel, FSP, int )
00614 APPLY_FORCE_RULE( acceptfocus, AcceptFocus, bool )
00615 APPLY_FORCE_RULE( moveresizemode, MoveResizeMode, Options::MoveResizeMode )
00616 APPLY_FORCE_RULE( closeable, Closeable, bool )
00617 APPLY_FORCE_RULE( strictgeometry, StrictGeometry, bool )
00618 APPLY_RULE( shortcut, Shortcut, TQString )
00619 APPLY_FORCE_RULE( disableglobalshortcuts, DisableGlobalShortcuts, bool )
00620 
00621 
00622 #undef APPLY_RULE
00623 #undef APPLY_FORCE_RULE
00624 
00625 bool Rules::isTemporary() const
00626     {
00627     return temporary_state > 0;
00628     }
00629 
00630 bool Rules::discardTemporary( bool force )
00631     {
00632     if( temporary_state == 0 ) // not temporary
00633         return false;
00634     if( force || --temporary_state == 0 ) // too old
00635         {
00636         delete this;
00637         return true;
00638         }
00639     return false;
00640     }
00641     
00642 #define DISCARD_USED_SET_RULE( var ) \
00643     do { \
00644     if( var##rule == ( SetRule ) ApplyNow || ( withdrawn && var##rule == ( SetRule ) ForceTemporarily )) \
00645         var##rule = UnusedSetRule; \
00646     } while( false )
00647 #define DISCARD_USED_FORCE_RULE( var ) \
00648     do { \
00649     if( withdrawn && var##rule == ( ForceRule ) ForceTemporarily ) \
00650         var##rule = UnusedForceRule; \
00651     } while( false )
00652 
00653 void Rules::discardUsed( bool withdrawn )
00654     {
00655     DISCARD_USED_FORCE_RULE( placement );
00656     DISCARD_USED_SET_RULE( position );
00657     DISCARD_USED_SET_RULE( size );
00658     DISCARD_USED_FORCE_RULE( minsize );
00659     DISCARD_USED_FORCE_RULE( maxsize );
00660     DISCARD_USED_FORCE_RULE( opacityactive );
00661     DISCARD_USED_FORCE_RULE( opacityinactive );
00662     DISCARD_USED_FORCE_RULE( ignoreposition );
00663     DISCARD_USED_SET_RULE( desktop );
00664     DISCARD_USED_FORCE_RULE( type );
00665     DISCARD_USED_SET_RULE( maximizevert );
00666     DISCARD_USED_SET_RULE( maximizehoriz );
00667     DISCARD_USED_SET_RULE( minimize );
00668     DISCARD_USED_SET_RULE( shade );
00669     DISCARD_USED_SET_RULE( skiptaskbar );
00670     DISCARD_USED_SET_RULE( skippager );
00671     DISCARD_USED_SET_RULE( above );
00672     DISCARD_USED_SET_RULE( below );
00673     DISCARD_USED_SET_RULE( fullscreen );
00674     DISCARD_USED_SET_RULE( noborder );
00675     DISCARD_USED_FORCE_RULE( fsplevel );
00676     DISCARD_USED_FORCE_RULE( acceptfocus );
00677     DISCARD_USED_FORCE_RULE( moveresizemode );
00678     DISCARD_USED_FORCE_RULE( closeable );
00679     DISCARD_USED_FORCE_RULE( strictgeometry );
00680     DISCARD_USED_SET_RULE( shortcut );
00681     DISCARD_USED_FORCE_RULE( disableglobalshortcuts );
00682     }
00683 #undef DISCARD_USED_SET_RULE
00684 #undef DISCARD_USED_FORCE_RULE
00685 
00686 #endif
00687 
00688 #ifndef NDEBUG
00689 kdbgstream& operator<<( kdbgstream& stream, const Rules* r )
00690     {
00691     return stream << "[" << r->description << ":" << r->wmclass << "]" ;
00692     }
00693 #endif
00694 
00695 #ifndef KCMRULES
00696 void WindowRules::discardTemporary()
00697     {
00698     TQValueVector< Rules* >::Iterator it2 = rules.begin();
00699     for( TQValueVector< Rules* >::Iterator it = rules.begin();
00700          it != rules.end();
00701          )
00702         {
00703         if( (*it)->discardTemporary( true ))
00704             ++it;
00705         else
00706             {
00707             *it2++ = *it++;
00708             }
00709         }
00710     rules.erase( it2, rules.end());
00711     }
00712 
00713 void WindowRules::update( Client* c )
00714     {
00715     bool updated = false;
00716     for( TQValueVector< Rules* >::ConstIterator it = rules.begin();
00717          it != rules.end();
00718          ++it )
00719         if( (*it)->update( c )) // no short-circuiting here
00720             updated = true;
00721     if( updated )
00722         Workspace::self()->rulesUpdated();
00723     }
00724 
00725 #define CHECK_RULE( rule, type ) \
00726 type WindowRules::check##rule( type arg, bool init ) const \
00727     { \
00728     if( rules.count() == 0 ) \
00729         return arg; \
00730     type ret = arg; \
00731     for( TQValueVector< Rules* >::ConstIterator it = rules.begin(); \
00732          it != rules.end(); \
00733          ++it ) \
00734         { \
00735         if( (*it)->apply##rule( ret, init )) \
00736             break; \
00737         } \
00738     return ret; \
00739     }
00740 
00741 #define CHECK_FORCE_RULE( rule, type ) \
00742 type WindowRules::check##rule( type arg ) const \
00743     { \
00744     if( rules.count() == 0 ) \
00745         return arg; \
00746     type ret = arg; \
00747     for( TQValueVector< Rules* >::ConstIterator it = rules.begin(); \
00748          it != rules.end(); \
00749          ++it ) \
00750         { \
00751         if( (*it)->apply##rule( ret )) \
00752             break; \
00753         } \
00754     return ret; \
00755     }
00756 
00757 CHECK_FORCE_RULE( Placement, Placement::Policy )
00758 
00759 TQRect WindowRules::checkGeometry( TQRect rect, bool init ) const
00760     {
00761     return TQRect( checkPosition( rect.topLeft(), init ), checkSize( rect.size(), init ));
00762     }
00763 
00764 CHECK_RULE( Position, TQPoint )
00765 CHECK_RULE( Size, TQSize )
00766 CHECK_FORCE_RULE( MinSize, TQSize )
00767 CHECK_FORCE_RULE( MaxSize, TQSize )
00768 CHECK_FORCE_RULE( OpacityActive, int )
00769 CHECK_FORCE_RULE( OpacityInactive, int )
00770 CHECK_FORCE_RULE( IgnorePosition, bool )
00771 
00772 bool WindowRules::checkIgnoreGeometry( bool ignore ) const
00773     {
00774     return checkIgnorePosition( ignore );
00775     }
00776 
00777 CHECK_RULE( Desktop, int )
00778 CHECK_FORCE_RULE( Type, NET::WindowType )
00779 CHECK_RULE( MaximizeVert, KDecorationDefines::MaximizeMode )
00780 CHECK_RULE( MaximizeHoriz, KDecorationDefines::MaximizeMode )
00781 
00782 KDecorationDefines::MaximizeMode WindowRules::checkMaximize( MaximizeMode mode, bool init ) const
00783     {
00784     bool vert = checkMaximizeVert( mode, init ) & MaximizeVertical;
00785     bool horiz = checkMaximizeHoriz( mode, init ) & MaximizeHorizontal;
00786     return static_cast< MaximizeMode >(( vert ? MaximizeVertical : 0 ) | ( horiz ? MaximizeHorizontal : 0 ));
00787     }
00788 
00789 CHECK_RULE( Minimize, bool )
00790 CHECK_RULE( Shade, ShadeMode )
00791 CHECK_RULE( SkipTaskbar, bool )
00792 CHECK_RULE( SkipPager, bool )
00793 CHECK_RULE( KeepAbove, bool )
00794 CHECK_RULE( KeepBelow, bool )
00795 CHECK_RULE( FullScreen, bool )
00796 CHECK_RULE( NoBorder, bool )
00797 CHECK_FORCE_RULE( FSP, int )
00798 CHECK_FORCE_RULE( AcceptFocus, bool )
00799 CHECK_FORCE_RULE( MoveResizeMode, Options::MoveResizeMode )
00800 CHECK_FORCE_RULE( Closeable, bool )
00801 CHECK_FORCE_RULE( StrictGeometry, bool )
00802 CHECK_RULE( Shortcut, TQString )
00803 CHECK_FORCE_RULE( DisableGlobalShortcuts, bool )
00804 
00805 #undef CHECK_RULE
00806 #undef CHECK_FORCE_RULE
00807 
00808 // Client
00809 
00810 void Client::setupWindowRules( bool ignore_temporary )
00811     {
00812     client_rules = workspace()->findWindowRules( this, ignore_temporary );
00813     // check only after getting the rules, because there may be a rule forcing window type
00814     if( isTopMenu()) // TODO cannot have restrictions
00815         client_rules = WindowRules();
00816     }
00817 
00818 // Applies Force, ForceTemporarily and ApplyNow rules
00819 // Used e.g. after the rules have been modified using the kcm.    
00820 void Client::applyWindowRules()
00821     {
00822     checkAndSetInitialRuledOpacity();        
00823     // apply force rules
00824     // Placement - does need explicit update, just like some others below
00825     // Geometry : setGeometry() doesn't check rules
00826     TQRect orig_geom = TQRect( pos(), sizeForClientSize( clientSize())); // handle shading
00827     TQRect geom = client_rules.checkGeometry( orig_geom );
00828     if( geom != orig_geom )
00829         setGeometry( geom );
00830     // MinSize, MaxSize handled by Geometry
00831     // IgnorePosition
00832     setDesktop( desktop());
00833     // Type
00834     maximize( maximizeMode());
00835     // Minimize : functions don't check, and there are two functions
00836     if( client_rules.checkMinimize( isMinimized()))
00837         minimize();
00838     else
00839         unminimize();
00840     setShade( shadeMode());
00841     setSkipTaskbar( skipTaskbar(), true );
00842     setSkipPager( skipPager());
00843     setKeepAbove( keepAbove());
00844     setKeepBelow( keepBelow());
00845     setFullScreen( isFullScreen(), true );
00846     setUserNoBorder( isUserNoBorder());
00847     // FSP
00848     // AcceptFocus :
00849     if( workspace()->mostRecentlyActivatedClient() == this
00850         && !client_rules.checkAcceptFocus( true ))
00851         workspace()->activateNextClient( this );
00852     // MoveResizeMode
00853     // Closeable
00854     TQSize s = adjustedSize();
00855     if( s != size())
00856         resizeWithChecks( s );
00857     // StrictGeometry
00858     setShortcut( rules()->checkShortcut( shortcut().toString()));
00859     // see also Client::setActive()
00860     if( isActive())
00861         workspace()->disableGlobalShortcutsForClient( rules()->checkDisableGlobalShortcuts( false ));
00862     }
00863 
00864 void Client::updateWindowRules()
00865     {
00866     if( !isManaged()) // not fully setup yet
00867         return;
00868     if( workspace()->rulesUpdatesDisabled())
00869         return;
00870     client_rules.update( this );
00871     }
00872 
00873 void Client::finishWindowRules()
00874     {
00875     updateWindowRules();
00876     client_rules = WindowRules();
00877     }
00878     
00879 void Client::checkAndSetInitialRuledOpacity()
00880 //apply twin-rules for window-translucency upon hitting apply or starting to manage client
00881     {
00882     int tmp;
00883     
00884     //active translucency
00885     tmp = -1;
00886     tmp = rules()->checkOpacityActive(tmp);
00887     if( tmp != -1 ) //rule did apply and returns valid value
00888         {
00889         rule_opacity_active = (uint)((tmp/100.0)*0xffffffff);
00890         }
00891     else
00892         rule_opacity_active = 0;
00893 
00894     //inactive translucency
00895     tmp = -1;
00896     tmp = rules()->checkOpacityInactive(tmp);
00897     if( tmp != -1 ) //rule did apply and returns valid value
00898         {
00899         rule_opacity_inactive = (uint)((tmp/100.0)*0xffffffff);
00900         }
00901     else
00902         rule_opacity_inactive = 0;
00903 
00904     return;
00905         
00906     if( isDock() )
00907      //workaround for docks, as they don't have active/inactive settings and don't aut, therefore we take only the active one...
00908         {
00909         uint tmp = rule_opacity_active ? rule_opacity_active : options->dockOpacity;
00910         setOpacity(tmp < 0xFFFFFFFF && (rule_opacity_active || options->translucentDocks), tmp);
00911         }
00912     else
00913         updateOpacity();
00914     }
00915 
00916 // Workspace
00917 
00918 WindowRules Workspace::findWindowRules( const Client* c, bool ignore_temporary )
00919     {
00920     TQValueVector< Rules* > ret;
00921     for( TQValueList< Rules* >::Iterator it = rules.begin();
00922          it != rules.end();
00923          )
00924         {
00925         if( ignore_temporary && (*it)->isTemporary())
00926             {
00927             ++it;
00928             continue;
00929             }
00930         if( (*it)->match( c ))
00931             {
00932             Rules* rule = *it;
00933             kdDebug( 1212 ) << "Rule found:" << rule << ":" << c << endl;
00934             if( rule->isTemporary())
00935                 it = rules.remove( it );
00936             else
00937                 ++it;
00938             ret.append( rule );
00939             continue;
00940             }
00941         ++it;
00942         }
00943     return WindowRules( ret );
00944     }
00945 
00946 void Workspace::editWindowRules( Client* c, bool whole_app )
00947     {
00948     writeWindowRules();
00949     TQStringList args;
00950     args << "--wid" << TQString::number( c->window());
00951     if( whole_app )
00952         args << "--whole-app";
00953     TDEApplication::tdeinitExec( "twin_rules_dialog", args );
00954     }
00955 
00956 void Workspace::loadWindowRules()
00957     {
00958     while( !rules.isEmpty())
00959         {
00960         delete rules.front();
00961         rules.pop_front();
00962         }
00963     TDEConfig cfg( "twinrulesrc", true );
00964     cfg.setGroup( "General" );
00965     int count = cfg.readNumEntry( "count" );
00966     for( int i = 1;
00967          i <= count;
00968          ++i )
00969         {
00970         cfg.setGroup( TQString::number( i ));
00971         Rules* rule = new Rules( cfg );
00972         rules.append( rule );
00973         }
00974     }
00975 
00976 void Workspace::writeWindowRules()
00977     {
00978     rulesUpdatedTimer.stop();
00979     TDEConfig cfg( "twinrulesrc" );
00980     TQStringList groups = cfg.groupList();
00981     for( TQStringList::ConstIterator it = groups.begin();
00982          it != groups.end();
00983          ++it )
00984         cfg.deleteGroup( *it );
00985     cfg.setGroup( "General" );
00986     cfg.writeEntry( "count", rules.count());
00987     int i = 1;
00988     for( TQValueList< Rules* >::ConstIterator it = rules.begin();
00989          it != rules.end();
00990          ++it )
00991         {
00992         if( (*it)->isTemporary())
00993             continue;
00994         cfg.setGroup( TQString::number( i ));
00995         (*it)->write( cfg );
00996         ++i;
00997         }
00998     }
00999 
01000 void Workspace::gotTemporaryRulesMessage( const TQString& message )
01001     {
01002     bool was_temporary = false;
01003     for( TQValueList< Rules* >::ConstIterator it = rules.begin();
01004          it != rules.end();
01005          ++it )
01006         if( (*it)->isTemporary())
01007             was_temporary = true;
01008     Rules* rule = new Rules( message, true );
01009     rules.prepend( rule ); // highest priority first
01010     if( !was_temporary )
01011         TQTimer::singleShot( 60000, this, TQT_SLOT( cleanupTemporaryRules()));
01012     }
01013 
01014 void Workspace::cleanupTemporaryRules()
01015     {
01016     bool has_temporary = false;
01017     for( TQValueList< Rules* >::Iterator it = rules.begin();
01018          it != rules.end();
01019          )
01020         {
01021         if( (*it)->discardTemporary( false ))
01022             it = rules.remove( it );
01023         else
01024             {
01025             if( (*it)->isTemporary())
01026                 has_temporary = true;
01027             ++it;
01028             }
01029         }
01030     if( has_temporary )
01031         TQTimer::singleShot( 60000, this, TQT_SLOT( cleanupTemporaryRules()));
01032     }
01033 
01034 void Workspace::discardUsedWindowRules( Client* c, bool withdrawn )
01035     {
01036     bool updated = false;
01037     for( TQValueList< Rules* >::Iterator it = rules.begin();
01038          it != rules.end();
01039          )
01040         {
01041         if( c->rules()->contains( *it ))
01042             {
01043             updated = true;
01044             (*it)->discardUsed( withdrawn );
01045             if( (*it)->isEmpty())
01046                 {
01047                 c->removeRule( *it );
01048                 Rules* r = *it;
01049                 it = rules.remove( it );
01050                 delete r;
01051                 continue;
01052                 }
01053             }
01054         ++it;
01055         }
01056     if( updated )
01057         rulesUpdated();
01058     }
01059 
01060 void Workspace::rulesUpdated()
01061     {
01062     rulesUpdatedTimer.start( 1000, true );
01063     }
01064 
01065 void Workspace::disableRulesUpdates( bool disable )
01066     {
01067     rules_updates_disabled = disable;
01068     if( !disable )
01069         for( ClientList::ConstIterator it = clients.begin();
01070              it != clients.end();
01071              ++it )
01072             (*it)->updateWindowRules();
01073     }
01074 
01075 #endif
01076 
01077 } // namespace

twin

Skip menu "twin"
  • Main Page
  • Alphabetical List
  • Class List
  • File List
  • Class Members

twin

Skip menu "twin"
  • kate
  • libkonq
  • twin
  •   lib
Generated for twin by doxygen 1.7.1
This website is maintained by Timothy Pearson.