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

twin

  • twin
rules.cpp
1 /*****************************************************************
2  KWin - the KDE window manager
3  This file is part of the KDE project.
4 
5 Copyright (C) 2004 Lubos Lunak <l.lunak@kde.org>
6 
7 You can Freely distribute this program under the GNU General Public
8 License. See the file "COPYING" for the exact licensing terms.
9 ******************************************************************/
10 
11 #include "rules.h"
12 
13 #include <fixx11h.h>
14 #include <tdeconfig.h>
15 #include <tqregexp.h>
16 #include <tdetempfile.h>
17 #include <ksimpleconfig.h>
18 #include <tqfile.h>
19 
20 #ifndef KCMRULES
21 #include "client.h"
22 #include "workspace.h"
23 #endif
24 
25 namespace KWinInternal
26 {
27 
28 Rules::Rules()
29  : temporary_state( 0 )
30  , wmclassmatch( UnimportantMatch )
31  , wmclasscomplete( UnimportantMatch )
32  , windowrolematch( UnimportantMatch )
33  , titlematch( UnimportantMatch )
34  , extrarolematch( UnimportantMatch )
35  , clientmachinematch( UnimportantMatch )
36  , types( NET::AllTypesMask )
37  , placementrule( UnusedForceRule )
38  , positionrule( UnusedSetRule )
39  , sizerule( UnusedSetRule )
40  , minsizerule( UnusedForceRule )
41  , maxsizerule( UnusedForceRule )
42  , opacityactiverule( UnusedForceRule )
43  , opacityinactiverule( UnusedForceRule )
44  , ignorepositionrule( UnusedForceRule )
45  , desktoprule( UnusedSetRule )
46  , typerule( UnusedForceRule )
47  , maximizevertrule( UnusedSetRule )
48  , maximizehorizrule( UnusedSetRule )
49  , minimizerule( UnusedSetRule )
50  , shaderule( UnusedSetRule )
51  , skiptaskbarrule( UnusedSetRule )
52  , skippagerrule( UnusedSetRule )
53  , aboverule( UnusedSetRule )
54  , belowrule( UnusedSetRule )
55  , fullscreenrule( UnusedSetRule )
56  , noborderrule( UnusedSetRule )
57  , fsplevelrule( UnusedForceRule )
58  , acceptfocusrule( UnusedForceRule )
59  , moveresizemoderule( UnusedForceRule )
60  , closeablerule( UnusedForceRule )
61  , strictgeometryrule( UnusedForceRule )
62  , shortcutrule( UnusedSetRule )
63  , disableglobalshortcutsrule( UnusedForceRule )
64  {
65  }
66 
67 Rules::Rules( const TQString& str, bool temporary )
68  : temporary_state( temporary ? 2 : 0 )
69  {
70  KTempFile file;
71  TQFile* f = file.file();
72  if( f != NULL )
73  {
74  TQCString s = str.utf8();
75  f->writeBlock( s.data(), s.length());
76  }
77  file.close();
78  KSimpleConfig cfg( file.name());
79  readFromCfg( cfg );
80  if( description.isEmpty())
81  description = "temporary";
82  file.unlink();
83  }
84 
85 #define READ_MATCH_STRING( var, func ) \
86  var = cfg.readEntry( #var ) func; \
87  var##match = (StringMatch) TQMAX( FirstStringMatch, TQMIN( LastStringMatch, cfg.readNumEntry( #var "match" )));
88 
89 #define READ_SET_RULE( var, type, func ) \
90  var = func ( cfg.read##type##Entry( #var )); \
91  var##rule = readSetRule( cfg, #var "rule" );
92 
93 #define READ_SET_RULE_DEF( var, type, func, def ) \
94  var = func ( cfg.read##type##Entry( #var, def )); \
95  var##rule = readSetRule( cfg, #var "rule" );
96 
97 #define READ_SET_RULE_2( var, type, func, funcarg ) \
98  var = func ( cfg.read##type##Entry( #var ), funcarg ); \
99  var##rule = readSetRule( cfg, #var "rule" );
100 
101 #define READ_FORCE_RULE( var, type, func ) \
102  var = func ( cfg.read##type##Entry( #var )); \
103  var##rule = readForceRule( cfg, #var "rule" );
104 
105 #define READ_FORCE_RULE_2( var, type, func, funcarg ) \
106  var = func ( cfg.read##type##Entry( #var ), funcarg ); \
107  var##rule = readForceRule( cfg, #var "rule" );
108 
109 
110 Rules::Rules( TDEConfig& cfg )
111  : temporary_state( 0 )
112  {
113  readFromCfg( cfg );
114  }
115 
116 static int limit0to4( int i ) { return TQMAX( 0, TQMIN( 4, i )); }
117 
118 void Rules::readFromCfg( TDEConfig& cfg )
119  {
120  description = cfg.readEntry( "Description" );
121  if( description.isEmpty()) // capitalized first, lowercase for backwards compatibility
122  description = cfg.readEntry( "description" );
123  READ_MATCH_STRING( wmclass, .lower().latin1() );
124  wmclasscomplete = cfg.readBoolEntry( "wmclasscomplete" );
125  READ_MATCH_STRING( windowrole, .lower().latin1() );
126  READ_MATCH_STRING( title, );
127  READ_MATCH_STRING( extrarole, .lower().latin1() );
128  READ_MATCH_STRING( clientmachine, .lower().latin1() );
129  types = cfg.readUnsignedLongNumEntry( "types", NET::AllTypesMask );
130  READ_FORCE_RULE_2( placement,, Placement::policyFromString, false );
131  READ_SET_RULE_DEF( position, Point,, &invalidPoint );
132  READ_SET_RULE( size, Size, );
133  if( size.isEmpty() && sizerule != ( SetRule )Remember)
134  sizerule = UnusedSetRule;
135  READ_FORCE_RULE( minsize, Size, );
136  if( !minsize.isValid())
137  minsize = TQSize( 1, 1 );
138  READ_FORCE_RULE( maxsize, Size, );
139  if( maxsize.isEmpty())
140  maxsize = TQSize( 32767, 32767 );
141  READ_FORCE_RULE( opacityactive, Num, );
142  if( opacityactive < 0 || opacityactive > 100 )
143  opacityactive = 100;
144  READ_FORCE_RULE( opacityinactive, Num, );
145  if( opacityinactive < 0 || opacityinactive > 100 )
146  opacityinactive = 100;
147  READ_FORCE_RULE( ignoreposition, Bool, );
148  READ_SET_RULE( desktop, Num, );
149  type = readType( cfg, "type" );
150  typerule = type != NET::Unknown ? readForceRule( cfg, "typerule" ) : UnusedForceRule;
151  READ_SET_RULE( maximizevert, Bool, );
152  READ_SET_RULE( maximizehoriz, Bool, );
153  READ_SET_RULE( minimize, Bool, );
154  READ_SET_RULE( shade, Bool, );
155  READ_SET_RULE( skiptaskbar, Bool, );
156  READ_SET_RULE( skippager, Bool, );
157  READ_SET_RULE( above, Bool, );
158  READ_SET_RULE( below, Bool, );
159  READ_SET_RULE( fullscreen, Bool, );
160  READ_SET_RULE( noborder, Bool, );
161  READ_FORCE_RULE( fsplevel, Num, limit0to4 ); // fsp is 0-4
162  READ_FORCE_RULE( acceptfocus, Bool, );
163  READ_FORCE_RULE( moveresizemode, , Options::stringToMoveResizeMode );
164  READ_FORCE_RULE( closeable, Bool, );
165  READ_FORCE_RULE( strictgeometry, Bool, );
166  READ_SET_RULE( shortcut, , );
167  READ_FORCE_RULE( disableglobalshortcuts, Bool, );
168  }
169 
170 #undef READ_MATCH_STRING
171 #undef READ_SET_RULE
172 #undef READ_SET_RULE_2
173 #undef READ_FORCE_RULE
174 #undef READ_FORCE_RULE_2
175 
176 #define WRITE_MATCH_STRING( var, cast, force ) \
177  if( !var.isEmpty() || force ) \
178  { \
179  cfg.writeEntry( #var, cast var ); \
180  cfg.writeEntry( #var "match", var##match ); \
181  } \
182  else \
183  { \
184  cfg.deleteEntry( #var ); \
185  cfg.deleteEntry( #var "match" ); \
186  }
187 
188 #define WRITE_SET_RULE( var, func ) \
189  if( var##rule != UnusedSetRule ) \
190  { \
191  cfg.writeEntry( #var, func ( var )); \
192  cfg.writeEntry( #var "rule", var##rule ); \
193  } \
194  else \
195  { \
196  cfg.deleteEntry( #var ); \
197  cfg.deleteEntry( #var "rule" ); \
198  }
199 
200 #define WRITE_FORCE_RULE( var, func ) \
201  if( var##rule != UnusedForceRule ) \
202  { \
203  cfg.writeEntry( #var, func ( var )); \
204  cfg.writeEntry( #var "rule", var##rule ); \
205  } \
206  else \
207  { \
208  cfg.deleteEntry( #var ); \
209  cfg.deleteEntry( #var "rule" ); \
210  }
211 
212 #define WRITE_WITH_DEFAULT( var, default ) \
213  if( var != default ) \
214  cfg.writeEntry( #var, var ); \
215  else \
216  cfg.deleteEntry( #var );
217 
218 
219 void Rules::write( TDEConfig& cfg ) const
220  {
221  cfg.writeEntry( "Description", description );
222  // always write wmclass
223  WRITE_MATCH_STRING( wmclass, (const char*), true );
224  cfg.writeEntry( "wmclasscomplete", wmclasscomplete );
225  WRITE_MATCH_STRING( windowrole, (const char*), false );
226  WRITE_MATCH_STRING( title,, false );
227  WRITE_MATCH_STRING( extrarole, (const char*), false );
228  WRITE_MATCH_STRING( clientmachine, (const char*), false );
229  WRITE_WITH_DEFAULT( types, NET::AllTypesMask );
230  WRITE_FORCE_RULE( placement, Placement::policyToString );
231  WRITE_SET_RULE( position, );
232  WRITE_SET_RULE( size, );
233  WRITE_FORCE_RULE( minsize, );
234  WRITE_FORCE_RULE( maxsize, );
235  WRITE_FORCE_RULE( opacityactive, );
236  WRITE_FORCE_RULE( opacityinactive, );
237  WRITE_FORCE_RULE( ignoreposition, );
238  WRITE_SET_RULE( desktop, );
239  WRITE_FORCE_RULE( type, );
240  WRITE_SET_RULE( maximizevert, );
241  WRITE_SET_RULE( maximizehoriz, );
242  WRITE_SET_RULE( minimize, );
243  WRITE_SET_RULE( shade, );
244  WRITE_SET_RULE( skiptaskbar, );
245  WRITE_SET_RULE( skippager, );
246  WRITE_SET_RULE( above, );
247  WRITE_SET_RULE( below, );
248  WRITE_SET_RULE( fullscreen, );
249  WRITE_SET_RULE( noborder, );
250  WRITE_FORCE_RULE( fsplevel, );
251  WRITE_FORCE_RULE( acceptfocus, );
252  WRITE_FORCE_RULE( moveresizemode, Options::moveResizeModeToString );
253  WRITE_FORCE_RULE( closeable, );
254  WRITE_FORCE_RULE( strictgeometry, );
255  WRITE_SET_RULE( shortcut, );
256  WRITE_FORCE_RULE( disableglobalshortcuts, );
257  }
258 
259 #undef WRITE_MATCH_STRING
260 #undef WRITE_SET_RULE
261 #undef WRITE_FORCE_RULE
262 #undef WRITE_WITH_DEFAULT
263 
264 // returns true if it doesn't affect anything
265 bool Rules::isEmpty() const
266  {
267  return( placementrule == UnusedForceRule
268  && positionrule == UnusedSetRule
269  && sizerule == UnusedSetRule
270  && minsizerule == UnusedForceRule
271  && maxsizerule == UnusedForceRule
272  && opacityactiverule == UnusedForceRule
273  && opacityinactiverule == UnusedForceRule
274  && ignorepositionrule == UnusedForceRule
275  && desktoprule == UnusedSetRule
276  && typerule == UnusedForceRule
277  && maximizevertrule == UnusedSetRule
278  && maximizehorizrule == UnusedSetRule
279  && minimizerule == UnusedSetRule
280  && shaderule == UnusedSetRule
281  && skiptaskbarrule == UnusedSetRule
282  && skippagerrule == UnusedSetRule
283  && aboverule == UnusedSetRule
284  && belowrule == UnusedSetRule
285  && fullscreenrule == UnusedSetRule
286  && noborderrule == UnusedSetRule
287  && fsplevelrule == UnusedForceRule
288  && acceptfocusrule == UnusedForceRule
289  && moveresizemoderule == UnusedForceRule
290  && closeablerule == UnusedForceRule
291  && strictgeometryrule == UnusedForceRule
292  && shortcutrule == UnusedSetRule
293  && disableglobalshortcutsrule == UnusedForceRule );
294  }
295 
296 Rules::SetRule Rules::readSetRule( TDEConfig& cfg, const TQString& key )
297  {
298  int v = cfg.readNumEntry( key );
299  if( v >= DontAffect && v <= ForceTemporarily )
300  return static_cast< SetRule >( v );
301  return UnusedSetRule;
302  }
303 
304 Rules::ForceRule Rules::readForceRule( TDEConfig& cfg, const TQString& key )
305  {
306  int v = cfg.readNumEntry( key );
307  if( v == DontAffect || v == Force || v == ForceTemporarily )
308  return static_cast< ForceRule >( v );
309  return UnusedForceRule;
310  }
311 
312 NET::WindowType Rules::readType( TDEConfig& cfg, const TQString& key )
313  {
314  int v = cfg.readNumEntry( key );
315  if( v >= NET::Normal && v <= NET::Splash )
316  return static_cast< NET::WindowType >( v );
317  return NET::Unknown;
318  }
319 
320 bool Rules::matchType( NET::WindowType match_type ) const
321  {
322  if( types != NET::AllTypesMask )
323  {
324  if( match_type == NET::Unknown )
325  match_type = NET::Normal; // NET::Unknown->NET::Normal is only here for matching
326  if( !NET::typeMatchesMask( match_type, types ))
327  return false;
328  }
329  return true;
330  }
331 
332 bool Rules::matchWMClass( const TQCString& match_class, const TQCString& match_name ) const
333  {
334  if( wmclassmatch != UnimportantMatch )
335  { // TODO optimize?
336  TQCString cwmclass = wmclasscomplete
337  ? match_name + ' ' + match_class : match_class;
338  if( wmclassmatch == RegExpMatch && TQRegExp( wmclass ).search( cwmclass ) == -1 )
339  return false;
340  if( wmclassmatch == ExactMatch && wmclass != cwmclass )
341  return false;
342  if( wmclassmatch == SubstringMatch && !cwmclass.contains( wmclass ))
343  return false;
344  }
345  return true;
346  }
347 
348 bool Rules::matchRole( const TQCString& match_role ) const
349  {
350  if( windowrolematch != UnimportantMatch )
351  {
352  if( windowrolematch == RegExpMatch && TQRegExp( windowrole ).search( match_role ) == -1 )
353  return false;
354  if( windowrolematch == ExactMatch && windowrole != match_role )
355  return false;
356  if( windowrolematch == SubstringMatch && !match_role.contains( windowrole ))
357  return false;
358  }
359  return true;
360  }
361 
362 bool Rules::matchTitle( const TQString& match_title ) const
363  {
364  if( titlematch != UnimportantMatch )
365  {
366  if( titlematch == RegExpMatch && TQRegExp( title ).search( match_title ) == -1 )
367  return false;
368  if( titlematch == ExactMatch && title != match_title )
369  return false;
370  if( titlematch == SubstringMatch && !match_title.contains( title ))
371  return false;
372  }
373  return true;
374  }
375 
376 bool Rules::matchClientMachine( const TQCString& match_machine ) const
377  {
378  if( clientmachinematch != UnimportantMatch )
379  {
380  // if it's localhost, check also "localhost" before checking hostname
381  if( match_machine != "localhost" && isLocalMachine( match_machine )
382  && matchClientMachine( "localhost" ))
383  return true;
384  if( clientmachinematch == RegExpMatch
385  && TQRegExp( clientmachine ).search( match_machine ) == -1 )
386  return false;
387  if( clientmachinematch == ExactMatch
388  && clientmachine != match_machine )
389  return false;
390  if( clientmachinematch == SubstringMatch
391  && !match_machine.contains( clientmachine ))
392  return false;
393  }
394  return true;
395  }
396 
397 #ifndef KCMRULES
398 bool Rules::match( const Client* c ) const
399  {
400  if( !matchType( c->windowType( true )))
401  return false;
402  if( !matchWMClass( c->resourceClass(), c->resourceName()))
403  return false;
404  if( !matchRole( c->windowRole()))
405  return false;
406  if( !matchTitle( c->caption( false )))
407  return false;
408  // TODO extrarole
409  if( !matchClientMachine( c->wmClientMachine( false )))
410  return false;
411  return true;
412  }
413 
414 bool Rules::update( Client* c )
415  {
416  // TODO check this setting is for this client ?
417  bool updated = false;
418  if( positionrule == ( SetRule )Remember)
419  {
420  if( !c->isFullScreen())
421  {
422  TQPoint new_pos = position;
423  // don't use the position in the direction which is maximized
424  if(( c->maximizeMode() & MaximizeHorizontal ) == 0 )
425  new_pos.setX( c->pos().x());
426  if(( c->maximizeMode() & MaximizeVertical ) == 0 )
427  new_pos.setY( c->pos().y());
428  updated = updated || position != new_pos;
429  position = new_pos;
430  }
431  }
432  if( sizerule == ( SetRule )Remember)
433  {
434  if( !c->isFullScreen())
435  {
436  TQSize new_size = size;
437  // don't use the position in the direction which is maximized
438  if(( c->maximizeMode() & MaximizeHorizontal ) == 0 )
439  new_size.setWidth( c->size().width());
440  if(( c->maximizeMode() & MaximizeVertical ) == 0 )
441  new_size.setHeight( c->size().height());
442  updated = updated || size != new_size;
443  size = new_size;
444  }
445  }
446  if( desktoprule == ( SetRule )Remember)
447  {
448  updated = updated || desktop != c->desktop();
449  desktop = c->desktop();
450  }
451  if( maximizevertrule == ( SetRule )Remember)
452  {
453  updated = updated || maximizevert != bool( c->maximizeMode() & MaximizeVertical );
454  maximizevert = c->maximizeMode() & MaximizeVertical;
455  }
456  if( maximizehorizrule == ( SetRule )Remember)
457  {
458  updated = updated || maximizehoriz != bool( c->maximizeMode() & MaximizeHorizontal );
459  maximizehoriz = c->maximizeMode() & MaximizeHorizontal;
460  }
461  if( minimizerule == ( SetRule )Remember)
462  {
463  updated = updated || minimize != c->isMinimized();
464  minimize = c->isMinimized();
465  }
466  if( shaderule == ( SetRule )Remember)
467  {
468  updated = updated || ( shade != ( c->shadeMode() != ShadeNone ));
469  shade = c->shadeMode() != ShadeNone;
470  }
471  if( skiptaskbarrule == ( SetRule )Remember)
472  {
473  updated = updated || skiptaskbar != c->skipTaskbar();
474  skiptaskbar = c->skipTaskbar();
475  }
476  if( skippagerrule == ( SetRule )Remember)
477  {
478  updated = updated || skippager != c->skipPager();
479  skippager = c->skipPager();
480  }
481  if( aboverule == ( SetRule )Remember)
482  {
483  updated = updated || above != c->keepAbove();
484  above = c->keepAbove();
485  }
486  if( belowrule == ( SetRule )Remember)
487  {
488  updated = updated || below != c->keepBelow();
489  below = c->keepBelow();
490  }
491  if( fullscreenrule == ( SetRule )Remember)
492  {
493  updated = updated || fullscreen != c->isFullScreen();
494  fullscreen = c->isFullScreen();
495  }
496  if( noborderrule == ( SetRule )Remember)
497  {
498  updated = updated || noborder != c->isUserNoBorder();
499  noborder = c->isUserNoBorder();
500  }
501  if (opacityactiverule == ( ForceRule )Force)
502  {
503  updated = updated || (uint) (opacityactive/100.0*0xffffffff) != c->ruleOpacityActive();
504  opacityactive = (uint)(((double)c->ruleOpacityActive())/0xffffffff*100);
505  }
506  if (opacityinactiverule == ( ForceRule )Force)
507  {
508  updated = updated || (uint) (opacityinactive/100.0*0xffffffff) != c->ruleOpacityInactive();
509  opacityinactive = (uint)(((double)c->ruleOpacityInactive())/0xffffffff*100);
510  }
511  return updated;
512  }
513 
514 #define APPLY_RULE( var, name, type ) \
515 bool Rules::apply##name( type& arg, bool init ) const \
516  { \
517  if( checkSetRule( var##rule, init )) \
518  arg = this->var; \
519  return checkSetStop( var##rule ); \
520  }
521 
522 #define APPLY_FORCE_RULE( var, name, type ) \
523 bool Rules::apply##name( type& arg ) const \
524  { \
525  if( checkForceRule( var##rule )) \
526  arg = this->var; \
527  return checkForceStop( var##rule ); \
528  }
529 
530 APPLY_FORCE_RULE( placement, Placement, Placement::Policy )
531 
532 bool Rules::applyGeometry( TQRect& rect, bool init ) const
533  {
534  TQPoint p = rect.topLeft();
535  TQSize s = rect.size();
536  bool ret = false; // no short-circuiting
537  if( applyPosition( p, init ))
538  {
539  rect.moveTopLeft( p );
540  ret = true;
541  }
542  if( applySize( s, init ))
543  {
544  rect.setSize( s );
545  ret = true;
546  }
547  return ret;
548  }
549 
550 bool Rules::applyPosition( TQPoint& pos, bool init ) const
551  {
552  if( this->position != invalidPoint && checkSetRule( positionrule, init ))
553  pos = this->position;
554  return checkSetStop( positionrule );
555  }
556 
557 bool Rules::applySize( TQSize& s, bool init ) const
558  {
559  if( this->size.isValid() && checkSetRule( sizerule, init ))
560  s = this->size;
561  return checkSetStop( sizerule );
562  }
563 
564 APPLY_FORCE_RULE( minsize, MinSize, TQSize )
565 APPLY_FORCE_RULE( maxsize, MaxSize, TQSize )
566 APPLY_FORCE_RULE( opacityactive, OpacityActive, int )
567 APPLY_FORCE_RULE( opacityinactive, OpacityInactive, int )
568 APPLY_FORCE_RULE( ignoreposition, IgnorePosition, bool )
569 
570 // the cfg. entry needs to stay named the say for backwards compatibility
571 bool Rules::applyIgnoreGeometry( bool& ignore ) const
572  {
573  return applyIgnorePosition( ignore );
574  }
575 
576 APPLY_RULE( desktop, Desktop, int )
577 APPLY_FORCE_RULE( type, Type, NET::WindowType )
578 
579 bool Rules::applyMaximizeHoriz( MaximizeMode& mode, bool init ) const
580  {
581  if( checkSetRule( maximizehorizrule, init ))
582  mode = static_cast< MaximizeMode >(( maximizehoriz ? MaximizeHorizontal : 0 ) | ( mode & MaximizeVertical ));
583  return checkSetStop( maximizehorizrule );
584  }
585 
586 bool Rules::applyMaximizeVert( MaximizeMode& mode, bool init ) const
587  {
588  if( checkSetRule( maximizevertrule, init ))
589  mode = static_cast< MaximizeMode >(( maximizevert ? MaximizeVertical : 0 ) | ( mode & MaximizeHorizontal ));
590  return checkSetStop( maximizevertrule );
591  }
592 
593 APPLY_RULE( minimize, Minimize, bool )
594 
595 bool Rules::applyShade( ShadeMode& sh, bool init ) const
596  {
597  if( checkSetRule( shaderule, init ))
598  {
599  if( !this->shade )
600  sh = ShadeNone;
601  if( this->shade && sh == ShadeNone )
602  sh = ShadeNormal;
603  }
604  return checkSetStop( shaderule );
605  }
606 
607 APPLY_RULE( skiptaskbar, SkipTaskbar, bool )
608 APPLY_RULE( skippager, SkipPager, bool )
609 APPLY_RULE( above, KeepAbove, bool )
610 APPLY_RULE( below, KeepBelow, bool )
611 APPLY_RULE( fullscreen, FullScreen, bool )
612 APPLY_RULE( noborder, NoBorder, bool )
613 APPLY_FORCE_RULE( fsplevel, FSP, int )
614 APPLY_FORCE_RULE( acceptfocus, AcceptFocus, bool )
615 APPLY_FORCE_RULE( moveresizemode, MoveResizeMode, Options::MoveResizeMode )
616 APPLY_FORCE_RULE( closeable, Closeable, bool )
617 APPLY_FORCE_RULE( strictgeometry, StrictGeometry, bool )
618 APPLY_RULE( shortcut, Shortcut, TQString )
619 APPLY_FORCE_RULE( disableglobalshortcuts, DisableGlobalShortcuts, bool )
620 
621 
622 #undef APPLY_RULE
623 #undef APPLY_FORCE_RULE
624 
625 bool Rules::isTemporary() const
626  {
627  return temporary_state > 0;
628  }
629 
630 bool Rules::discardTemporary( bool force )
631  {
632  if( temporary_state == 0 ) // not temporary
633  return false;
634  if( force || --temporary_state == 0 ) // too old
635  {
636  delete this;
637  return true;
638  }
639  return false;
640  }
641 
642 #define DISCARD_USED_SET_RULE( var ) \
643  do { \
644  if( var##rule == ( SetRule ) ApplyNow || ( withdrawn && var##rule == ( SetRule ) ForceTemporarily )) \
645  var##rule = UnusedSetRule; \
646  } while( false )
647 #define DISCARD_USED_FORCE_RULE( var ) \
648  do { \
649  if( withdrawn && var##rule == ( ForceRule ) ForceTemporarily ) \
650  var##rule = UnusedForceRule; \
651  } while( false )
652 
653 void Rules::discardUsed( bool withdrawn )
654  {
655  DISCARD_USED_FORCE_RULE( placement );
656  DISCARD_USED_SET_RULE( position );
657  DISCARD_USED_SET_RULE( size );
658  DISCARD_USED_FORCE_RULE( minsize );
659  DISCARD_USED_FORCE_RULE( maxsize );
660  DISCARD_USED_FORCE_RULE( opacityactive );
661  DISCARD_USED_FORCE_RULE( opacityinactive );
662  DISCARD_USED_FORCE_RULE( ignoreposition );
663  DISCARD_USED_SET_RULE( desktop );
664  DISCARD_USED_FORCE_RULE( type );
665  DISCARD_USED_SET_RULE( maximizevert );
666  DISCARD_USED_SET_RULE( maximizehoriz );
667  DISCARD_USED_SET_RULE( minimize );
668  DISCARD_USED_SET_RULE( shade );
669  DISCARD_USED_SET_RULE( skiptaskbar );
670  DISCARD_USED_SET_RULE( skippager );
671  DISCARD_USED_SET_RULE( above );
672  DISCARD_USED_SET_RULE( below );
673  DISCARD_USED_SET_RULE( fullscreen );
674  DISCARD_USED_SET_RULE( noborder );
675  DISCARD_USED_FORCE_RULE( fsplevel );
676  DISCARD_USED_FORCE_RULE( acceptfocus );
677  DISCARD_USED_FORCE_RULE( moveresizemode );
678  DISCARD_USED_FORCE_RULE( closeable );
679  DISCARD_USED_FORCE_RULE( strictgeometry );
680  DISCARD_USED_SET_RULE( shortcut );
681  DISCARD_USED_FORCE_RULE( disableglobalshortcuts );
682  }
683 #undef DISCARD_USED_SET_RULE
684 #undef DISCARD_USED_FORCE_RULE
685 
686 #endif
687 
688 #ifndef NDEBUG
689 kdbgstream& operator<<( kdbgstream& stream, const Rules* r )
690  {
691  return stream << "[" << r->description << ":" << r->wmclass << "]" ;
692  }
693 #endif
694 
695 #ifndef KCMRULES
696 void WindowRules::discardTemporary()
697  {
698  TQValueVector< Rules* >::Iterator it2 = rules.begin();
699  for( TQValueVector< Rules* >::Iterator it = rules.begin();
700  it != rules.end();
701  )
702  {
703  if( (*it)->discardTemporary( true ))
704  ++it;
705  else
706  {
707  *it2++ = *it++;
708  }
709  }
710  rules.erase( it2, rules.end());
711  }
712 
713 void WindowRules::update( Client* c )
714  {
715  bool updated = false;
716  for( TQValueVector< Rules* >::ConstIterator it = rules.begin();
717  it != rules.end();
718  ++it )
719  if( (*it)->update( c )) // no short-circuiting here
720  updated = true;
721  if( updated )
722  Workspace::self()->rulesUpdated();
723  }
724 
725 #define CHECK_RULE( rule, type ) \
726 type WindowRules::check##rule( type arg, bool init ) const \
727  { \
728  if( rules.count() == 0 ) \
729  return arg; \
730  type ret = arg; \
731  for( TQValueVector< Rules* >::ConstIterator it = rules.begin(); \
732  it != rules.end(); \
733  ++it ) \
734  { \
735  if( (*it)->apply##rule( ret, init )) \
736  break; \
737  } \
738  return ret; \
739  }
740 
741 #define CHECK_FORCE_RULE( rule, type ) \
742 type WindowRules::check##rule( type arg ) const \
743  { \
744  if( rules.count() == 0 ) \
745  return arg; \
746  type ret = arg; \
747  for( TQValueVector< Rules* >::ConstIterator it = rules.begin(); \
748  it != rules.end(); \
749  ++it ) \
750  { \
751  if( (*it)->apply##rule( ret )) \
752  break; \
753  } \
754  return ret; \
755  }
756 
757 CHECK_FORCE_RULE( Placement, Placement::Policy )
758 
759 TQRect WindowRules::checkGeometry( TQRect rect, bool init ) const
760  {
761  return TQRect( checkPosition( rect.topLeft(), init ), checkSize( rect.size(), init ));
762  }
763 
764 CHECK_RULE( Position, TQPoint )
765 CHECK_RULE( Size, TQSize )
766 CHECK_FORCE_RULE( MinSize, TQSize )
767 CHECK_FORCE_RULE( MaxSize, TQSize )
768 CHECK_FORCE_RULE( OpacityActive, int )
769 CHECK_FORCE_RULE( OpacityInactive, int )
770 CHECK_FORCE_RULE( IgnorePosition, bool )
771 
772 bool WindowRules::checkIgnoreGeometry( bool ignore ) const
773  {
774  return checkIgnorePosition( ignore );
775  }
776 
777 CHECK_RULE( Desktop, int )
778 CHECK_FORCE_RULE( Type, NET::WindowType )
779 CHECK_RULE( MaximizeVert, KDecorationDefines::MaximizeMode )
780 CHECK_RULE( MaximizeHoriz, KDecorationDefines::MaximizeMode )
781 
782 KDecorationDefines::MaximizeMode WindowRules::checkMaximize( MaximizeMode mode, bool init ) const
783  {
784  bool vert = checkMaximizeVert( mode, init ) & MaximizeVertical;
785  bool horiz = checkMaximizeHoriz( mode, init ) & MaximizeHorizontal;
786  return static_cast< MaximizeMode >(( vert ? MaximizeVertical : 0 ) | ( horiz ? MaximizeHorizontal : 0 ));
787  }
788 
789 CHECK_RULE( Minimize, bool )
790 CHECK_RULE( Shade, ShadeMode )
791 CHECK_RULE( SkipTaskbar, bool )
792 CHECK_RULE( SkipPager, bool )
793 CHECK_RULE( KeepAbove, bool )
794 CHECK_RULE( KeepBelow, bool )
795 CHECK_RULE( FullScreen, bool )
796 CHECK_RULE( NoBorder, bool )
797 CHECK_FORCE_RULE( FSP, int )
798 CHECK_FORCE_RULE( AcceptFocus, bool )
799 CHECK_FORCE_RULE( MoveResizeMode, Options::MoveResizeMode )
800 CHECK_FORCE_RULE( Closeable, bool )
801 CHECK_FORCE_RULE( StrictGeometry, bool )
802 CHECK_RULE( Shortcut, TQString )
803 CHECK_FORCE_RULE( DisableGlobalShortcuts, bool )
804 
805 #undef CHECK_RULE
806 #undef CHECK_FORCE_RULE
807 
808 // Client
809 
810 void Client::setupWindowRules( bool ignore_temporary )
811  {
812  client_rules = workspace()->findWindowRules( this, ignore_temporary );
813  // check only after getting the rules, because there may be a rule forcing window type
814  if( isTopMenu()) // TODO cannot have restrictions
815  client_rules = WindowRules();
816  }
817 
818 // Applies Force, ForceTemporarily and ApplyNow rules
819 // Used e.g. after the rules have been modified using the kcm.
820 void Client::applyWindowRules()
821  {
822  checkAndSetInitialRuledOpacity();
823  // apply force rules
824  // Placement - does need explicit update, just like some others below
825  // Geometry : setGeometry() doesn't check rules
826  TQRect orig_geom = TQRect( pos(), sizeForClientSize( clientSize())); // handle shading
827  TQRect geom = client_rules.checkGeometry( orig_geom );
828  if( geom != orig_geom )
829  setGeometry( geom );
830  // MinSize, MaxSize handled by Geometry
831  // IgnorePosition
832  setDesktop( desktop());
833  // Type
834  maximize( maximizeMode());
835  // Minimize : functions don't check, and there are two functions
836  if( client_rules.checkMinimize( isMinimized()))
837  minimize();
838  else
839  unminimize();
840  setShade( shadeMode());
841  setSkipTaskbar( skipTaskbar(), true );
842  setSkipPager( skipPager());
843  setKeepAbove( keepAbove());
844  setKeepBelow( keepBelow());
845  setFullScreen( isFullScreen(), true );
846  setUserNoBorder( isUserNoBorder());
847  // FSP
848  // AcceptFocus :
849  if( workspace()->mostRecentlyActivatedClient() == this
850  && !client_rules.checkAcceptFocus( true ))
851  workspace()->activateNextClient( this );
852  // MoveResizeMode
853  // Closeable
854  TQSize s = adjustedSize();
855  if( s != size())
856  resizeWithChecks( s );
857  // StrictGeometry
858  setShortcut( rules()->checkShortcut( shortcut().toString()));
859  // see also Client::setActive()
860  if( isActive())
861  workspace()->disableGlobalShortcutsForClient( rules()->checkDisableGlobalShortcuts( false ));
862  }
863 
864 void Client::updateWindowRules()
865  {
866  if( !isManaged()) // not fully setup yet
867  return;
868  if( workspace()->rulesUpdatesDisabled())
869  return;
870  client_rules.update( this );
871  }
872 
873 void Client::finishWindowRules()
874  {
875  updateWindowRules();
876  client_rules = WindowRules();
877  }
878 
879 void Client::checkAndSetInitialRuledOpacity()
880 //apply twin-rules for window-translucency upon hitting apply or starting to manage client
881  {
882  int tmp;
883 
884  //active translucency
885  tmp = -1;
886  tmp = rules()->checkOpacityActive(tmp);
887  if( tmp != -1 ) //rule did apply and returns valid value
888  {
889  rule_opacity_active = (uint)((tmp/100.0)*0xffffffff);
890  }
891  else
892  rule_opacity_active = 0;
893 
894  //inactive translucency
895  tmp = -1;
896  tmp = rules()->checkOpacityInactive(tmp);
897  if( tmp != -1 ) //rule did apply and returns valid value
898  {
899  rule_opacity_inactive = (uint)((tmp/100.0)*0xffffffff);
900  }
901  else
902  rule_opacity_inactive = 0;
903 
904  return;
905 
906  if( isDock() )
907  //workaround for docks, as they don't have active/inactive settings and don't aut, therefore we take only the active one...
908  {
909  uint tmp = rule_opacity_active ? rule_opacity_active : options->dockOpacity;
910  setOpacity(tmp < 0xFFFFFFFF && (rule_opacity_active || options->translucentDocks), tmp);
911  }
912  else
913  updateOpacity();
914  }
915 
916 // Workspace
917 
918 WindowRules Workspace::findWindowRules( const Client* c, bool ignore_temporary )
919  {
920  TQValueVector< Rules* > ret;
921  for( TQValueList< Rules* >::Iterator it = rules.begin();
922  it != rules.end();
923  )
924  {
925  if( ignore_temporary && (*it)->isTemporary())
926  {
927  ++it;
928  continue;
929  }
930  if( (*it)->match( c ))
931  {
932  Rules* rule = *it;
933  kdDebug( 1212 ) << "Rule found:" << rule << ":" << c << endl;
934  if( rule->isTemporary())
935  it = rules.remove( it );
936  else
937  ++it;
938  ret.append( rule );
939  continue;
940  }
941  ++it;
942  }
943  return WindowRules( ret );
944  }
945 
946 void Workspace::editWindowRules( Client* c, bool whole_app )
947  {
948  writeWindowRules();
949  TQStringList args;
950  args << "--wid" << TQString::number( c->window());
951  if( whole_app )
952  args << "--whole-app";
953  TDEApplication::tdeinitExec( "twin_rules_dialog", args );
954  }
955 
956 void Workspace::loadWindowRules()
957  {
958  while( !rules.isEmpty())
959  {
960  delete rules.front();
961  rules.pop_front();
962  }
963  TDEConfig cfg( "twinrulesrc", true );
964  cfg.setGroup( "General" );
965  int count = cfg.readNumEntry( "count" );
966  for( int i = 1;
967  i <= count;
968  ++i )
969  {
970  cfg.setGroup( TQString::number( i ));
971  Rules* rule = new Rules( cfg );
972  rules.append( rule );
973  }
974  }
975 
976 void Workspace::writeWindowRules()
977  {
978  rulesUpdatedTimer.stop();
979  TDEConfig cfg( "twinrulesrc" );
980  TQStringList groups = cfg.groupList();
981  for( TQStringList::ConstIterator it = groups.begin();
982  it != groups.end();
983  ++it )
984  cfg.deleteGroup( *it );
985  cfg.setGroup( "General" );
986  cfg.writeEntry( "count", rules.count());
987  int i = 1;
988  for( TQValueList< Rules* >::ConstIterator it = rules.begin();
989  it != rules.end();
990  ++it )
991  {
992  if( (*it)->isTemporary())
993  continue;
994  cfg.setGroup( TQString::number( i ));
995  (*it)->write( cfg );
996  ++i;
997  }
998  }
999 
1000 void Workspace::gotTemporaryRulesMessage( const TQString& message )
1001  {
1002  bool was_temporary = false;
1003  for( TQValueList< Rules* >::ConstIterator it = rules.begin();
1004  it != rules.end();
1005  ++it )
1006  if( (*it)->isTemporary())
1007  was_temporary = true;
1008  Rules* rule = new Rules( message, true );
1009  rules.prepend( rule ); // highest priority first
1010  if( !was_temporary )
1011  TQTimer::singleShot( 60000, this, TQ_SLOT( cleanupTemporaryRules()));
1012  }
1013 
1014 void Workspace::cleanupTemporaryRules()
1015  {
1016  bool has_temporary = false;
1017  for( TQValueList< Rules* >::Iterator it = rules.begin();
1018  it != rules.end();
1019  )
1020  {
1021  if( (*it)->discardTemporary( false ))
1022  it = rules.remove( it );
1023  else
1024  {
1025  if( (*it)->isTemporary())
1026  has_temporary = true;
1027  ++it;
1028  }
1029  }
1030  if( has_temporary )
1031  TQTimer::singleShot( 60000, this, TQ_SLOT( cleanupTemporaryRules()));
1032  }
1033 
1034 void Workspace::discardUsedWindowRules( Client* c, bool withdrawn )
1035  {
1036  bool updated = false;
1037  for( TQValueList< Rules* >::Iterator it = rules.begin();
1038  it != rules.end();
1039  )
1040  {
1041  if( c->rules()->contains( *it ))
1042  {
1043  updated = true;
1044  (*it)->discardUsed( withdrawn );
1045  if( (*it)->isEmpty())
1046  {
1047  c->removeRule( *it );
1048  Rules* r = *it;
1049  it = rules.remove( it );
1050  delete r;
1051  continue;
1052  }
1053  }
1054  ++it;
1055  }
1056  if( updated )
1057  rulesUpdated();
1058  }
1059 
1060 void Workspace::rulesUpdated()
1061  {
1062  rulesUpdatedTimer.start( 1000, true );
1063  }
1064 
1065 void Workspace::disableRulesUpdates( bool disable )
1066  {
1067  rules_updates_disabled = disable;
1068  if( !disable )
1069  for( ClientList::ConstIterator it = clients.begin();
1070  it != clients.end();
1071  ++it )
1072  (*it)->updateWindowRules();
1073  }
1074 
1075 #endif
1076 
1077 } // 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.9.1
This website is maintained by Timothy Pearson.