1
/*****************************************************************
2
KWin - the KDE window manager
3
This file is part of the KDE project.
5
Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
6
Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
8
You can Freely distribute this program under the GNU General Public
9
License. See the file "COPYING" for the exact licensing terms.
10
******************************************************************/
15
#include <config-X11.h>
22
#include <kshortcut.h>
25
#include <X11/Xutil.h>
30
#include "workspace.h"
31
#include "kdecoration.h"
36
#include <X11/extensions/sync.h>
41
class KStartupInfoData;
55
Client( Workspace *ws );
56
Window wrapperId() const;
57
Window decorationId() const;
59
const Client* transientFor() const;
60
Client* transientFor();
61
bool isTransient() const;
62
bool groupTransient() const;
63
bool wasOriginallyGroupTransient() const;
64
ClientList mainClients() const; // call once before loop , is not indirect
65
bool hasTransient( const Client* c, bool indirect ) const;
66
const ClientList& transients() const; // is not indirect
67
void checkTransient( Window w );
68
Client* findModal( bool allow_itself = false );
69
const Group* group() const;
71
void checkGroup( Group* gr = NULL, bool force = false );
72
void changeClientLeaderGroup( Group* gr );
73
const WindowRules* rules() const;
74
void removeRule( Rules* r );
75
void setupWindowRules( bool ignore_temporary );
76
void applyWindowRules();
77
void updateWindowRules();
79
// returns true for "special" windows and false for windows which are "normal"
80
// (normal=window which has a border, can be moved by the user, can be closed, etc.)
81
// true for Desktop, Dock, Splash, Override and TopMenu (and Toolbar??? - for now)
82
// false for Normal, Dialog, Utility and Menu (and Toolbar??? - not yet) TODO
83
bool isSpecialWindow() const;
84
bool hasNETSupport() const;
86
QSize minSize() const;
87
QSize maxSize() const;
88
virtual QPoint clientPos() const; // inside of geometry()
89
virtual QSize clientSize() const;
91
bool windowEvent( XEvent* e );
92
virtual bool eventFilter( QObject* o, QEvent* e );
94
void syncEvent( XSyncAlarmNotifyEvent* e );
97
bool manage( Window w, bool isMapped );
98
void releaseWindow( bool on_shutdown = false );
101
enum Sizemode // how to resize the window in order to obey constains (mainly aspect ratios)
104
SizemodeFixedW, // try not to affect width
105
SizemodeFixedH, // try not to affect height
106
SizemodeMax // try not to make it larger in either direction
108
QSize adjustedSize( const QSize&, Sizemode mode = SizemodeAny ) const;
109
QSize adjustedSize() const;
111
QPixmap icon() const;
112
QPixmap miniIcon() const;
114
bool isActive() const;
115
void setActive( bool );
117
virtual int desktop() const;
118
void setDesktop( int );
119
void setOnAllDesktops( bool set );
121
bool isOnScreen( int screen ) const; // true if it's at least partially there
122
int screen() const; // the screen where the center is
124
// !isMinimized() && not hidden, i.e. normally visible on some virtual desktop
125
bool isShown( bool shaded_is_shown ) const;
127
bool isShade() const; // true only for ShadeNormal
128
ShadeMode shadeMode() const; // prefer isShade()
129
void setShade( ShadeMode mode );
130
bool isShadeable() const;
132
bool isMinimized() const;
133
bool isMaximizable() const;
134
QRect geometryRestore() const;
135
MaximizeMode maximizeModeRestore() const;
136
MaximizeMode maximizeMode() const;
137
bool isMinimizable() const;
138
void setMaximize( bool vertically, bool horizontally );
139
QRect iconGeometry() const;
141
void setFullScreen( bool set, bool user );
142
bool isFullScreen() const;
143
bool isFullScreenable( bool fullscreen_hack = false ) const;
144
bool userCanSetFullScreen() const;
145
QRect geometryFSRestore() const { return geom_fs_restore; } // only for session saving
146
int fullScreenMode() const { return fullscreen_mode; } // only for session saving
148
bool isUserNoBorder() const;
149
void setUserNoBorder( bool set );
150
bool userCanSetNoBorder() const;
151
bool noBorder() const;
153
bool skipTaskbar( bool from_outside = false ) const;
154
void setSkipTaskbar( bool set, bool from_outside );
156
bool skipPager() const;
157
void setSkipPager( bool );
159
bool keepAbove() const;
160
void setKeepAbove( bool );
161
bool keepBelow() const;
162
void setKeepBelow( bool );
164
Layer belongsToLayer() const;
165
void invalidateLayer();
166
int sessionStackingOrder() const;
168
void setModal( bool modal );
169
bool isModal() const;
171
// auxiliary functions, depend on the windowType
172
bool wantsTabFocus() const;
173
bool wantsInput() const;
175
bool isResizable() const;
176
bool isMovable() const;
177
bool isCloseable() const; // may be closed by the user (may have a close button)
179
void takeActivity( int flags, bool handled, allowed_t ); // takes ActivityFlags as arg (in utils.h)
180
void takeFocus( allowed_t );
181
void demandAttention( bool set = true );
183
void setMask( const QRegion& r, int mode = X::Unsorted );
184
QRegion mask() const;
186
void updateDecoration( bool check_workspace_pos, bool force = false );
187
void checkBorderSizes();
191
void setGeometry( int x, int y, int w, int h, ForceGeometry_t force = NormalGeometrySet );
192
void setGeometry( const QRect& r, ForceGeometry_t force = NormalGeometrySet );
193
void move( int x, int y, ForceGeometry_t force = NormalGeometrySet );
194
void move( const QPoint & p, ForceGeometry_t force = NormalGeometrySet );
195
// plainResize() simply resizes
196
void plainResize( int w, int h, ForceGeometry_t force = NormalGeometrySet );
197
void plainResize( const QSize& s, ForceGeometry_t force = NormalGeometrySet );
198
// resizeWithChecks() resizes according to gravity, and checks workarea position
199
void resizeWithChecks( int w, int h, ForceGeometry_t force = NormalGeometrySet );
200
void resizeWithChecks( const QSize& s, ForceGeometry_t force = NormalGeometrySet );
201
void keepInArea( QRect area, bool partial = false );
203
void growHorizontal();
204
void shrinkHorizontal();
206
void shrinkVertical();
208
bool providesContextHelp() const;
209
KShortcut shortcut() const;
210
void setShortcut( const QString& cut );
212
bool performMouseCommand( Options::MouseCommand, QPoint globalPos, bool handled = false );
214
QRect adjustedClientArea( const QRect& desktop, const QRect& area ) const;
216
Colormap colormap() const;
218
// updates visibility depending on being shaded, virtual desktop, etc.
219
void updateVisibility();
220
// hides a client - basically like minimize, but without effects, it's simply hidden
221
void hideClient( bool hide );
222
bool hiddenPreview() const; // window is mapped in order to get a window pixmap
224
QString caption( bool full = true ) const;
225
void updateCaption();
227
void keyPressEvent( uint key_code ); // FRAME ??
228
void updateMouseGrab();
229
Window moveResizeGrabWindow() const;
231
const QPoint calculateGravitation( bool invert, int gravity = 0 ) const; // FRAME public?
233
void NETMoveResize( int x_root, int y_root, NET::Direction direction );
234
void NETMoveResizeWindow( int flags, int x, int y, int width, int height );
235
void restackWindow( Window above, int detail, NET::RequestSource source, Time timestamp, bool send_event = false );
237
void gotPing( Time timestamp );
239
void checkWorkspacePosition();
240
void updateUserTime( Time time = CurrentTime );
241
Time userTime() const;
242
bool hasUserTimeSupport() const;
243
bool ignoreFocusStealing() const;
246
static void deleteClient( Client* c, allowed_t );
248
static bool belongToSameApplication( const Client* c1, const Client* c2, bool active_hack = false );
249
static bool sameAppWindowRoleMatch( const Client* c1, const Client* c2, bool active_hack );
250
static void readIcons( Window win, QPixmap* icon, QPixmap* miniicon );
252
void minimize( bool avoid_animation = false );
253
void unminimize( bool avoid_animation = false );
256
void maximize( MaximizeMode );
258
void showContextHelp();
259
void cancelShadeHover();
260
void cancelAutoRaise();
261
void checkActiveModal();
262
bool hasStrut() const;
266
return moveResizeMode && mode == PositionCenter;
268
bool isResize() const
270
return moveResizeMode && mode != PositionCenter;
276
void shortcutActivated();
277
void delayedMoveResize();
280
friend class Bridge; // FRAME
281
virtual void processMousePressEvent( QMouseEvent* e );
283
private: // TODO cleanup the order of things in the .h file
284
// use Workspace::createClient()
285
virtual ~Client(); // use destroyClient() or releaseWindow()
287
Position mousePosition( const QPoint& ) const;
291
void drawbound( const QRect& geom );
293
void doDrawbound( const QRect& geom, bool clear );
295
// handlers for X11 events
296
bool mapRequestEvent( XMapRequestEvent* e );
297
void unmapNotifyEvent( XUnmapEvent*e );
298
void destroyNotifyEvent( XDestroyWindowEvent*e );
299
void configureRequestEvent( XConfigureRequestEvent* e );
300
virtual void propertyNotifyEvent( XPropertyEvent* e );
301
void clientMessageEvent( XClientMessageEvent* e );
302
void enterNotifyEvent( XCrossingEvent* e );
303
void leaveNotifyEvent( XCrossingEvent* e );
304
void focusInEvent( XFocusInEvent* e );
305
void focusOutEvent( XFocusOutEvent* e );
307
virtual void damageNotifyEvent( XDamageNotifyEvent* e );
310
bool buttonPressEvent( Window w, int button, int state, int x, int y, int x_root, int y_root );
311
bool buttonReleaseEvent( Window w, int button, int state, int x, int y, int x_root, int y_root );
312
bool motionNotifyEvent( Window w, int state, int x, int y, int x_root, int y_root );
314
void processDecorationButtonPress( int button, int state, int x, int y, int x_root, int y_root );
317
virtual void debug( kdbgstream& stream ) const;
321
void processKillerExited();
322
void demandAttentionKNotify();
326
void setMappingState( int s ); // ICCCM 4.1.3.1, 4.1.4 , NETWM 2.5.1
327
int mappingState() const;
328
bool isIconicState() const;
329
bool isNormalState() const;
330
bool isManaged() const; // returns false if this client is not yet managed
331
void updateAllowedActions( bool force = false );
332
QSize sizeForClientSize( const QSize&, Sizemode mode = SizemodeAny, bool noframe = false ) const;
333
void changeMaximize( bool horizontal, bool vertical, bool adjust );
334
void checkMaximizeGeometry();
335
int checkFullScreenHack( const QRect& geom ) const; // 0 - none, 1 - one xinerama screen, 2 - full area
336
void updateFullScreenHack( const QRect& geom );
337
void getWmNormalHints();
338
void getMotifHints();
341
void fetchIconicName();
342
QString readName() const;
343
void setCaption( const QString& s, bool force = false );
344
bool hasTransientInternal( const Client* c, bool indirect, ConstClientList& set ) const;
345
void finishWindowRules();
346
void setShortcutInternal( const KShortcut& cut );
348
void updateWorkareaDiffs();
349
void checkDirection( int new_diff, int old_diff, QRect& rect, const QRect& area );
350
static int computeWorkareaDiff( int left, int right, int a_left, int a_right );
351
void configureRequest( int value_mask, int rx, int ry, int rw, int rh, int gravity, bool from_tool );
352
NETExtendedStrut strut() const;
353
int checkShadeGeometry( int w, int h );
354
void blockGeometryUpdates( bool block );
355
void getSyncCounter();
356
void sendSyncRequest();
358
bool startMoveResize();
359
void finishMoveResize( bool cancel );
360
void leaveMoveResize();
361
void checkUnrestrictedMoveResize();
362
void handleMoveResize( int x, int y, int x_root, int y_root );
363
void startDelayedMoveResize();
364
void stopDelayedMoveResize();
365
void positionGeometryTip();
366
void grabButton( int mod );
367
void ungrabButton( int mod );
368
void resetMaximize();
369
void resizeDecoration( const QSize& s );
370
void performMoveResize();
373
void killProcess( bool ask, Time timestamp = CurrentTime );
374
void updateUrgency();
375
static void sendClientMessage( Window w, Atom a, Atom protocol,
376
long data1 = 0, long data2 = 0, long data3 = 0 );
378
void embedClient( Window w, const XWindowAttributes &attr );
379
void detectNoBorder();
380
void destroyDecoration();
381
void updateFrameExtents();
383
void rawShow(); // just shows it
384
void rawHide(); // just hides it
385
void setHiddenPreview( bool set, allowed_t );
386
void updateInputShape();
388
Time readUserTimeMapTimestamp( const KStartupInfoId* asn_id, const KStartupInfoData* asn_data,
389
bool session ) const;
390
Time readUserCreationTime() const;
391
void startupIdChanged();
395
KDecoration* decoration;
400
bool move_faked_activity;
401
Window move_resize_grab_window;
402
bool move_resize_has_keyboard_grab;
403
bool unrestrictedMoveResize;
407
QPoint invertedMoveOffset;
408
QRect moveResizeGeom;
409
QRect initialMoveResizeGeom;
410
XSizeHints xSizeHint;
411
void sendSyntheticConfigureNotify();
413
void readTransient();
414
Window verifyTransientFor( Window transient_for, bool set );
415
void addTransient( Client* cl );
416
void removeTransient( Client* cl );
417
void removeFromMainClients();
418
void cleanGrouping();
419
void checkGroupTransients();
420
void setTransient( Window new_transient_for_id );
421
Client* transient_for;
422
Window transient_for_id;
423
Window original_transient_for_id;
424
ClientList transients_list; // SELI make this ordered in stacking order?
425
ShadeMode shade_mode;
427
uint deleting : 1; // true when doing cleanup and destroying the client
428
uint keep_above : 1; // NET::KeepAbove (was stays_on_top)
429
uint skip_taskbar :1;
430
uint original_skip_taskbar :1; // unaffected by KWin
431
uint Pdeletewindow :1; // does the window understand the DeleteWindow protocol?
432
uint Ptakefocus :1;// does the window understand the TakeFocus protocol?
433
uint Ptakeactivity : 1; // does it support _NET_WM_TAKE_ACTIVITY
434
uint Pcontexthelp : 1; // does the window understand the ContextHelp protocol?
435
uint Pping : 1; // does it support _NET_WM_PING?
436
uint input :1; // does the window want input in its wm_hints
438
uint motif_noborder : 1;
439
uint motif_may_resize : 1;
440
uint motif_may_move :1;
441
uint motif_may_close : 1;
442
uint keep_below : 1; // NET::KeepBelow
444
uint hidden : 1; // forcibly hidden by calling hide()
445
uint modal : 1; // NET::Modal
447
uint user_noborder : 1;
448
uint urgency : 1; // XWMHints, UrgencyHint
449
uint ignore_focus_stealing : 1; // don't apply focus stealing prevention to this client
450
uint demands_attention : 1;
451
uint hidden_preview : 1; // mapped only to get a window pixmap for compositing
452
WindowRules client_rules;
455
void getWindowProtocols();
457
QPixmap miniicon_pix;
459
// FullScreenHack - non-NETWM fullscreen (noborder,size of desktop)
460
// DON'T reorder - saved to config files !!!
461
enum FullScreenMode { FullScreenNone, FullScreenNormal, FullScreenHack };
462
FullScreenMode fullscreen_mode;
463
MaximizeMode max_mode;
465
QRect geom_fs_restore;
466
MaximizeMode maxmode_restore;
467
int workarea_diff_x, workarea_diff_y;
468
QTimer* autoRaiseTimer;
469
QTimer* shadeHoverTimer;
470
QTimer* delayedMoveResizeTimer;
472
QString cap_normal, cap_iconic, cap_suffix;
477
K3Process* process_killer;
480
unsigned long allowed_actions;
482
int block_geometry_updates; // >0 - new geometry is remembered, but not actually set
483
enum PendingGeometry_t { PendingGeometryNone, PendingGeometryNormal, PendingGeometryForced };
484
PendingGeometry_t pending_geometry_update;
485
QRect geom_before_block;
486
bool shade_geometry_change;
488
XSyncCounter sync_counter;
489
XSyncValue sync_counter_value;
490
XSyncAlarm sync_alarm;
492
QTimer* sync_timeout;
493
bool sync_resize_pending;
494
int border_left, border_right, border_top, border_bottom;
496
static bool check_active_modal; // see Client::checkActiveModal()
498
int sm_stacking_order;
499
friend struct FetchNameInternalPredicate;
500
friend struct CheckIgnoreFocusStealingProcedure;
501
friend struct ResetupRulesProcedure;
502
friend class GeometryUpdatesBlocker;
503
QTimer* demandAttentionKNotifyTimer;
505
friend bool performTransiencyCheck();
508
// helper for Client::blockGeometryUpdates() being called in pairs (true/false)
509
class GeometryUpdatesBlocker
512
GeometryUpdatesBlocker( Client* c )
513
: cl( c ) { cl->blockGeometryUpdates( true ); }
514
~GeometryUpdatesBlocker()
515
{ cl->blockGeometryUpdates( false ); }
521
// NET WM Protocol handler class
522
class WinInfo : public NETWinInfo
525
typedef KWin::Client Client; // because of NET::Client
527
WinInfo( Client* c, Display * display, Window window,
528
Window rwin, const unsigned long pr[], int pr_size );
529
virtual void changeDesktop(int desktop);
530
virtual void changeState( unsigned long state, unsigned long mask );
536
inline Window Client::wrapperId() const
541
inline Window Client::decorationId() const
543
return decoration != NULL ? decoration->widget()->winId() : None;
546
inline const Client* Client::transientFor() const
548
return transient_for;
551
inline Client* Client::transientFor()
553
return transient_for;
556
inline bool Client::groupTransient() const
558
return transient_for_id == rootWindow();
561
// needed because verifyTransientFor() may set transient_for_id to root window,
562
// if the original value has a problem (window doesn't exist, etc.)
563
inline bool Client::wasOriginallyGroupTransient() const
565
return original_transient_for_id == rootWindow();
568
inline bool Client::isTransient() const
570
return transient_for_id != None;
573
inline const ClientList& Client::transients() const
575
return transients_list;
578
inline const Group* Client::group() const
583
inline Group* Client::group()
588
inline int Client::mappingState() const
590
return mapping_state;
594
bool Client::isMinimized() const
599
inline bool Client::isActive() const
605
bool Client::isShown( bool shaded_is_shown ) const
607
return !isMinimized() && ( !isShade() || shaded_is_shown ) && !hidden;
611
bool Client::isShade() const
613
return shade_mode == ShadeNormal;
617
ShadeMode Client::shadeMode() const
622
inline QPixmap Client::icon() const
627
inline QPixmap Client::miniIcon() const
632
inline QRect Client::geometryRestore() const
637
inline Client::MaximizeMode Client::maximizeModeRestore() const
639
return maxmode_restore;
642
inline Client::MaximizeMode Client::maximizeMode() const
647
inline bool Client::skipTaskbar( bool from_outside ) const
649
return from_outside ? original_skip_taskbar : skip_taskbar;
652
inline bool Client::skipPager() const
657
inline bool Client::keepAbove() const
662
inline bool Client::keepBelow() const
667
inline bool Client::isFullScreen() const
669
return fullscreen_mode != FullScreenNone;
672
inline bool Client::isModal() const
677
inline bool Client::hasNETSupport() const
679
return info->hasNETSupport();
682
inline Colormap Client::colormap() const
687
inline void Client::invalidateLayer()
689
in_layer = UnknownLayer;
692
inline int Client::sessionStackingOrder() const
694
return sm_stacking_order;
697
inline bool Client::isIconicState() const
699
return mapping_state == IconicState;
702
inline bool Client::isNormalState() const
704
return mapping_state == NormalState;
707
inline bool Client::isManaged() const
709
return mapping_state != WithdrawnState;
712
inline QPoint Client::clientPos() const
714
return QPoint( border_left, border_top );
717
inline QSize Client::clientSize() const
722
inline void Client::setGeometry( const QRect& r, ForceGeometry_t force )
724
setGeometry( r.x(), r.y(), r.width(), r.height(), force );
727
inline void Client::move( const QPoint & p, ForceGeometry_t force )
729
move( p.x(), p.y(), force );
732
inline void Client::plainResize( const QSize& s, ForceGeometry_t force )
734
plainResize( s.width(), s.height(), force );
737
inline void Client::resizeWithChecks( const QSize& s, ForceGeometry_t force )
739
resizeWithChecks( s.width(), s.height(), force );
742
inline bool Client::hasUserTimeSupport() const
744
return info->userTime() != -1U;
747
inline bool Client::ignoreFocusStealing() const
749
return ignore_focus_stealing;
752
inline const WindowRules* Client::rules() const
754
return &client_rules;
757
KWIN_PROCEDURE( CheckIgnoreFocusStealingProcedure, Client, cl->ignore_focus_stealing = options->checkIgnoreFocusStealing( cl ));
759
inline Window Client::moveResizeGrabWindow() const
761
return move_resize_grab_window;
764
inline KShortcut Client::shortcut() const
769
inline void Client::removeRule( Rules* rule )
771
client_rules.remove( rule );
774
inline bool Client::hiddenPreview() const
776
return hidden_preview;
779
KWIN_COMPARE_PREDICATE( WrapperIdMatchPredicate, Client, Window, cl->wrapperId() == value );