• 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
5Copyright (C) 2004 Lubos Lunak <l.lunak@kde.org>
6
7You can Freely distribute this program under the GNU General Public
8License. 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
25namespace KWinInternal
26{
27
28Rules::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
67Rules::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
110Rules::Rules( TDEConfig& cfg )
111 : temporary_state( 0 )
112 {
113 readFromCfg( cfg );
114 }
115
116static int limit0to4( int i ) { return TQMAX( 0, TQMIN( 4, i )); }
117
118void 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
219void 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
265bool 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
296Rules::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
304Rules::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
312NET::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
320bool 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
332bool 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
348bool 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
362bool 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
376bool 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
398bool 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
414bool 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 ) \
515bool 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 ) \
523bool Rules::apply##name( type& arg ) const \
524 { \
525 if( checkForceRule( var##rule )) \
526 arg = this->var; \
527 return checkForceStop( var##rule ); \
528 }
529
530APPLY_FORCE_RULE( placement, Placement, Placement::Policy )
531
532bool 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
550bool 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
557bool 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
564APPLY_FORCE_RULE( minsize, MinSize, TQSize )
565APPLY_FORCE_RULE( maxsize, MaxSize, TQSize )
566APPLY_FORCE_RULE( opacityactive, OpacityActive, int )
567APPLY_FORCE_RULE( opacityinactive, OpacityInactive, int )
568APPLY_FORCE_RULE( ignoreposition, IgnorePosition, bool )
569
570// the cfg. entry needs to stay named the say for backwards compatibility
571bool Rules::applyIgnoreGeometry( bool& ignore ) const
572 {
573 return applyIgnorePosition( ignore );
574 }
575
576APPLY_RULE( desktop, Desktop, int )
577APPLY_FORCE_RULE( type, Type, NET::WindowType )
578
579bool 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
586bool 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
593APPLY_RULE( minimize, Minimize, bool )
594
595bool 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
607APPLY_RULE( skiptaskbar, SkipTaskbar, bool )
608APPLY_RULE( skippager, SkipPager, bool )
609APPLY_RULE( above, KeepAbove, bool )
610APPLY_RULE( below, KeepBelow, bool )
611APPLY_RULE( fullscreen, FullScreen, bool )
612APPLY_RULE( noborder, NoBorder, bool )
613APPLY_FORCE_RULE( fsplevel, FSP, int )
614APPLY_FORCE_RULE( acceptfocus, AcceptFocus, bool )
615APPLY_FORCE_RULE( moveresizemode, MoveResizeMode, Options::MoveResizeMode )
616APPLY_FORCE_RULE( closeable, Closeable, bool )
617APPLY_FORCE_RULE( strictgeometry, StrictGeometry, bool )
618APPLY_RULE( shortcut, Shortcut, TQString )
619APPLY_FORCE_RULE( disableglobalshortcuts, DisableGlobalShortcuts, bool )
620
621
622#undef APPLY_RULE
623#undef APPLY_FORCE_RULE
624
625bool Rules::isTemporary() const
626 {
627 return temporary_state > 0;
628 }
629
630bool 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
653void 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
689kdbgstream& operator<<( kdbgstream& stream, const Rules* r )
690 {
691 return stream << "[" << r->description << ":" << r->wmclass << "]" ;
692 }
693#endif
694
695#ifndef KCMRULES
696void 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
713void 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 ) \
726type 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 ) \
742type 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
757CHECK_FORCE_RULE( Placement, Placement::Policy )
758
759TQRect WindowRules::checkGeometry( TQRect rect, bool init ) const
760 {
761 return TQRect( checkPosition( rect.topLeft(), init ), checkSize( rect.size(), init ));
762 }
763
764CHECK_RULE( Position, TQPoint )
765CHECK_RULE( Size, TQSize )
766CHECK_FORCE_RULE( MinSize, TQSize )
767CHECK_FORCE_RULE( MaxSize, TQSize )
768CHECK_FORCE_RULE( OpacityActive, int )
769CHECK_FORCE_RULE( OpacityInactive, int )
770CHECK_FORCE_RULE( IgnorePosition, bool )
771
772bool WindowRules::checkIgnoreGeometry( bool ignore ) const
773 {
774 return checkIgnorePosition( ignore );
775 }
776
777CHECK_RULE( Desktop, int )
778CHECK_FORCE_RULE( Type, NET::WindowType )
779CHECK_RULE( MaximizeVert, KDecorationDefines::MaximizeMode )
780CHECK_RULE( MaximizeHoriz, KDecorationDefines::MaximizeMode )
781
782KDecorationDefines::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
789CHECK_RULE( Minimize, bool )
790CHECK_RULE( Shade, ShadeMode )
791CHECK_RULE( SkipTaskbar, bool )
792CHECK_RULE( SkipPager, bool )
793CHECK_RULE( KeepAbove, bool )
794CHECK_RULE( KeepBelow, bool )
795CHECK_RULE( FullScreen, bool )
796CHECK_RULE( NoBorder, bool )
797CHECK_FORCE_RULE( FSP, int )
798CHECK_FORCE_RULE( AcceptFocus, bool )
799CHECK_FORCE_RULE( MoveResizeMode, Options::MoveResizeMode )
800CHECK_FORCE_RULE( Closeable, bool )
801CHECK_FORCE_RULE( StrictGeometry, bool )
802CHECK_RULE( Shortcut, TQString )
803CHECK_FORCE_RULE( DisableGlobalShortcuts, bool )
804
805#undef CHECK_RULE
806#undef CHECK_FORCE_RULE
807
808// Client
809
810void 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.
820void 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
864void 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
873void Client::finishWindowRules()
874 {
875 updateWindowRules();
876 client_rules = WindowRules();
877 }
878
879void 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
918WindowRules 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
946void 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
956void 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
976void 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
1000void 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
1014void 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
1034void 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
1060void Workspace::rulesUpdated()
1061 {
1062 rulesUpdatedTimer.start( 1000, true );
1063 }
1064
1065void 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.4
This website is maintained by Timothy Pearson.