00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef KWIN_WORKSPACE_H
00013 #define KWIN_WORKSPACE_H
00014
00015 #include <qtimer.h>
00016 #include <kshortcut.h>
00017 #include <qcursor.h>
00018 #include <netwm.h>
00019 #include <kxmessages.h>
00020
00021 #include "KWinInterface.h"
00022 #include "utils.h"
00023 #include "kdecoration.h"
00024 #include "sm.h"
00025
00026 #include <X11/Xlib.h>
00027
00028 class QPopupMenu;
00029 class KConfig;
00030 class KGlobalAccel;
00031 class KStartupInfo;
00032 class KStartupInfoId;
00033 class KStartupInfoData;
00034
00035 namespace KWinInternal
00036 {
00037
00038 class Client;
00039 class TabBox;
00040 class PopupInfo;
00041 class RootInfo;
00042 class PluginMgr;
00043 class Placement;
00044 class Rules;
00045 class WindowRules;
00046
00047 class SystemTrayWindow
00048 {
00049 public:
00050 SystemTrayWindow()
00051 : win(0),winFor(0)
00052 {}
00053 SystemTrayWindow( WId w )
00054 : win(w),winFor(0)
00055 {}
00056 SystemTrayWindow( WId w, WId wf )
00057 : win(w),winFor(wf)
00058 {}
00059
00060 bool operator==( const SystemTrayWindow& other )
00061 { return win == other.win; }
00062 WId win;
00063 WId winFor;
00064 };
00065
00066 typedef QValueList<SystemTrayWindow> SystemTrayWindowList;
00067
00068 class Workspace : public QObject, public KWinInterface, public KDecorationDefines
00069 {
00070 Q_OBJECT
00071 public:
00072 Workspace( bool restore = FALSE );
00073 virtual ~Workspace();
00074
00075 static Workspace * self() { return _self; }
00076
00077 bool workspaceEvent( XEvent * );
00078
00079 KDecoration* createDecoration( KDecorationBridge* bridge );
00080
00081 bool hasClient( const Client * );
00082
00083 template< typename T > Client* findClient( T predicate );
00084 template< typename T1, typename T2 > void forEachClient( T1 procedure, T2 predicate );
00085 template< typename T > void forEachClient( T procedure );
00086
00087 QRect clientArea( clientAreaOption, const QPoint& p, int desktop ) const;
00088 QRect clientArea( clientAreaOption, const Client* c ) const;
00089
00093 void killWindowId( Window window);
00094
00095 void killWindow() { slotKillWindow(); }
00096
00097 WId rootWin() const;
00098
00099 bool initializing() const;
00100
00105 Client* activeClient() const;
00106
00107
00108
00109 Client* mostRecentlyActivatedClient() const;
00110
00111 void activateClient( Client*, bool force = FALSE );
00112 void requestFocus( Client* c, bool force = FALSE );
00113 void takeActivity( Client* c, int flags, bool handled );
00114 void handleTakeActivity( Client* c, Time timestamp, int flags );
00115 bool allowClientActivation( const Client* c, Time time = -1U, bool focus_in = false );
00116 void restoreFocus();
00117 void gotFocusIn( const Client* );
00118 void setShouldGetFocus( Client* );
00119 bool fakeRequestedActivity( Client* c );
00120 void unfakeActivity( Client* c );
00121 void activateNextClient( Client* c );
00122 bool focusChangeEnabled() { return block_focus == 0; }
00123
00124 void updateColormap();
00125
00129 void setClientIsMoving( Client *c );
00130
00131 void place( Client *c, QRect& area );
00132 void placeSmart( Client* c, const QRect& area );
00133
00134 QPoint adjustClientPosition( Client* c, QPoint pos );
00135 QRect adjustClientSize( Client* c, QRect moveResizeGeom, int mode );
00136 void raiseClient( Client* c );
00137 void lowerClient( Client* c );
00138 void raiseClientRequest( Client* c, NET::RequestSource src, Time timestamp );
00139 void lowerClientRequest( Client* c, NET::RequestSource src, Time timestamp );
00140 void restackClientUnderActive( Client* );
00141 void updateClientLayer( Client* c );
00142 void raiseOrLowerClient( Client * );
00143 void reconfigure();
00144
00145 void clientHidden( Client* );
00146 void clientAttentionChanged( Client* c, bool set );
00147
00148 void clientMoved(const QPoint &pos, Time time);
00149
00153 int currentDesktop() const;
00157 int numberOfDesktops() const;
00158 void setNumberOfDesktops( int n );
00159
00160 QWidget* desktopWidget();
00161
00162
00163 Client* nextFocusChainClient(Client*) const;
00164 Client* previousFocusChainClient(Client*) const;
00165 Client* nextStaticClient(Client*) const;
00166 Client* previousStaticClient(Client*) const;
00167 int nextDesktopFocusChain( int iDesktop ) const;
00168 int previousDesktopFocusChain( int iDesktop ) const;
00169 void closeTabBox();
00170
00175 const ClientList& stackingOrder() const;
00176
00177 ClientList ensureStackingOrder( const ClientList& clients ) const;
00178
00179 Client* topClientOnDesktop( int desktop, bool unconstrained = false ) const;
00180 Client* findDesktop( bool topmost, int desktop ) const;
00181 void sendClientToDesktop( Client* c, int desktop, bool dont_activate );
00182
00183
00184 void showWindowMenuAt( unsigned long id, int x, int y );
00185
00190 void showWindowMenu( const QRect &pos, Client* cl );
00194 void showWindowMenu( int x, int y, Client* cl );
00195 void showWindowMenu( QPoint pos, Client* cl );
00196
00197 void updateMinimizedOfTransients( Client* );
00198 void updateOnAllDesktopsOfTransients( Client* );
00199 void checkTransients( Window w );
00200
00201 void performWindowOperation( Client* c, WindowOperation op );
00202
00203 void storeSession( KConfig* config, SMSavePhase phase );
00204
00205 SessionInfo* takeSessionInfo( Client* );
00206 WindowRules findWindowRules( const Client*, bool );
00207 void rulesUpdated();
00208
00209
00210 void cascadeDesktop();
00211 void unclutterDesktop();
00212 void doNotManage(QString);
00213 bool setCurrentDesktop( int new_desktop );
00214 void nextDesktop();
00215 void previousDesktop();
00216 void circulateDesktopApplications();
00217
00218 QString desktopName( int desk ) const;
00219 void setDesktopLayout(int o, int x, int y);
00220
00221 bool isNotManaged( const QString& title );
00222
00223 void sendPingToWindow( Window w, Time timestamp );
00224 void sendTakeActivity( Client* c, Time timestamp, long flags );
00225
00226
00227 void removeClient( Client*, allowed_t );
00228 void setActiveClient( Client*, allowed_t );
00229 Group* findGroup( Window leader ) const;
00230 void addGroup( Group* group, allowed_t );
00231 void removeGroup( Group* group, allowed_t );
00232 Group* findClientLeaderGroup( const Client* c ) const;
00233
00234 bool checkStartupNotification( Window w, KStartupInfoId& id, KStartupInfoData& data );
00235
00236 void focusToNull();
00237
00238 bool forcedGlobalMouseGrab() const;
00239
00240 void sessionSaveStarted();
00241 void sessionSaveDone();
00242 void setWasUserInteraction();
00243 bool wasUserInteraction() const;
00244 bool sessionSaving() const;
00245
00246 bool managingTopMenus() const;
00247 int topMenuHeight() const;
00248 void updateCurrentTopMenu();
00249
00250 int packPositionLeft( const Client* cl, int oldx, bool left_edge ) const;
00251 int packPositionRight( const Client* cl, int oldx, bool right_edge ) const;
00252 int packPositionUp( const Client* cl, int oldy, bool top_edge ) const;
00253 int packPositionDown( const Client* cl, int oldy, bool bottom_edge ) const;
00254
00255 static QStringList configModules(bool controlCenter);
00256
00257 void cancelDelayFocus();
00258 void requestDelayFocus( Client* );
00259
00260 public slots:
00261 void refresh();
00262
00263 void slotSwitchDesktopNext();
00264 void slotSwitchDesktopPrevious();
00265 void slotSwitchDesktopRight();
00266 void slotSwitchDesktopLeft();
00267 void slotSwitchDesktopUp();
00268 void slotSwitchDesktopDown();
00269
00270 void slotSwitchToDesktop( int );
00271
00272 void slotWindowToDesktop( int );
00273
00274
00275 void slotWindowMaximize();
00276 void slotWindowMaximizeVertical();
00277 void slotWindowMaximizeHorizontal();
00278 void slotWindowMinimize();
00279 void slotWindowShade();
00280 void slotWindowRaise();
00281 void slotWindowLower();
00282 void slotWindowRaiseOrLower();
00283 void slotActivateAttentionWindow();
00284 void slotWindowPackLeft();
00285 void slotWindowPackRight();
00286 void slotWindowPackUp();
00287 void slotWindowPackDown();
00288 void slotWindowGrowHorizontal();
00289 void slotWindowGrowVertical();
00290 void slotWindowShrinkHorizontal();
00291 void slotWindowShrinkVertical();
00292
00293 void slotWalkThroughDesktops();
00294 void slotWalkBackThroughDesktops();
00295 void slotWalkThroughDesktopList();
00296 void slotWalkBackThroughDesktopList();
00297 void slotWalkThroughWindows();
00298 void slotWalkBackThroughWindows();
00299
00300 void slotWindowOperations();
00301 void slotWindowClose();
00302 void slotWindowMove();
00303 void slotWindowResize();
00304 void slotWindowAbove();
00305 void slotWindowBelow();
00306 void slotWindowOnAllDesktops();
00307 void slotWindowFullScreen();
00308 void slotWindowNoBorder();
00309
00310 void slotWindowToNextDesktop();
00311 void slotWindowToPreviousDesktop();
00312
00313 void slotMouseEmulation();
00314
00315 void slotSettingsChanged( int category );
00316
00317 void slotReconfigure();
00318
00319 void slotKillWindow();
00320
00321 void slotGrabWindow();
00322 void slotGrabDesktop();
00323
00324 void updateClientArea();
00325
00326 private slots:
00327 void desktopPopupAboutToShow();
00328 void clientPopupAboutToShow();
00329 void slotSendToDesktop( int );
00330 void clientPopupActivated( int );
00331 void configureWM();
00332 void desktopResized();
00333 void slotUpdateToolWindows();
00334 void lostTopMenuSelection();
00335 void lostTopMenuOwner();
00336 void delayFocus();
00337 void gotTemporaryRulesMessage( const QString& );
00338 void cleanupTemporaryRules();
00339 void writeWindowRules();
00340
00341 protected:
00342 bool keyPressMouseEmulation( XKeyEvent& ev );
00343 bool netCheck( XEvent* e );
00344
00345 private:
00346 void init();
00347 void initShortcuts();
00348 void readShortcuts();
00349 void initDesktopPopup();
00350
00351 bool startKDEWalkThroughWindows();
00352 bool startWalkThroughDesktops( int mode );
00353 bool startWalkThroughDesktops();
00354 bool startWalkThroughDesktopList();
00355 void KDEWalkThroughWindows( bool forward );
00356 void CDEWalkThroughWindows( bool forward );
00357 void walkThroughDesktops( bool forward );
00358 void KDEOneStepThroughWindows( bool forward );
00359 void oneStepThroughDesktops( bool forward, int mode );
00360 void oneStepThroughDesktops( bool forward );
00361 void oneStepThroughDesktopList( bool forward );
00362 bool establishTabBoxGrab();
00363 void removeTabBoxGrab();
00364
00365 void updateStackingOrder( bool propagate_new_clients = false );
00366 void propagateClients( bool propagate_new_clients );
00367 ClientList constrainedStackingOrder();
00368 void raiseClientWithinApplication( Client* c );
00369 void lowerClientWithinApplication( Client* c );
00370 bool allowFullClientRaising( const Client* c, Time timestamp );
00371 bool keepTransientAbove( const Client* mainwindow, const Client* transient );
00372 void blockStackingUpdates( bool block );
00373 void addTopMenu( Client* c );
00374 void removeTopMenu( Client* c );
00375 void setupTopMenuHandling();
00376 void updateTopMenuGeometry( Client* c = NULL );
00377 void updateToolWindows( bool also_hide );
00378
00379
00380 Client* createClient( Window w, bool is_mapped );
00381 void addClient( Client* c, allowed_t );
00382
00383 Window findSpecialEventWindow( XEvent* e );
00384
00385 void randomPlacement(Client* c);
00386 void smartPlacement(Client* c);
00387 void cascadePlacement(Client* c, bool re_init = false);
00388
00389 bool addSystemTrayWin( WId w );
00390 bool removeSystemTrayWin( WId w, bool check );
00391 void propagateSystemTrayWins();
00392 SystemTrayWindow findSystemTrayWin( WId w );
00393
00394
00395 void loadDesktopSettings();
00396 void saveDesktopSettings();
00397
00398
00399 WId getMouseEmulationWindow();
00400 enum MouseEmulation { EmuPress, EmuRelease, EmuMove };
00401 unsigned int sendFakedMouseEvent( QPoint pos, WId win, MouseEmulation type, int button, unsigned int state );
00402
00403 void tabBoxKeyPress( const KKeyNative& keyX );
00404 void tabBoxKeyRelease( const XKeyEvent& ev );
00405
00406
00407 void checkElectricBorders( bool force = false );
00408 void createBorderWindows();
00409 void destroyBorderWindows();
00410 void electricBorder(XEvent * e);
00411 void raiseElectricBorders();
00412
00413
00414
00415 void helperDialog( const QString& message, const Client* c );
00416
00417 void calcDesktopLayout(int &x, int &y);
00418
00419 QPopupMenu* clientPopup();
00420
00421 void updateClientArea( bool force );
00422
00423 SystemTrayWindowList systemTrayWins;
00424
00425 int current_desktop;
00426 int number_of_desktops;
00427 QMemArray<int> desktop_focus_chain;
00428
00429 Client* popup_client;
00430
00431 QWidget* desktop_widget;
00432
00433 void loadSessionInfo();
00434 void loadWindowRules();
00435 void editWindowRules( Client* );
00436
00437 QPtrList<SessionInfo> session;
00438 QValueList<Rules*> rules;
00439 KXMessages temporaryRulesMessages;
00440 QTimer rulesUpdatedTimer;
00441 static const char* windowTypeToTxt( NET::WindowType type );
00442 static NET::WindowType txtToWindowType( const char* txt );
00443 static bool sessionInfoWindowTypeMatch( Client* c, SessionInfo* info );
00444
00445 Client* active_client;
00446 Client* last_active_client;
00447 Client* most_recently_raised;
00448 Client* movingClient;
00449 Client* pending_take_activity;
00450
00451
00452 QTimer* delayFocusTimer;
00453 Client* delayfocus_client;
00454
00455 ClientList clients;
00456 ClientList desktops;
00457
00458 ClientList unconstrained_stacking_order;
00459 ClientList stacking_order;
00460 ClientList focus_chain;
00461 ClientList should_get_focus;
00462 ClientList attention_chain;
00463
00464 GroupList groups;
00465
00466 bool was_user_interaction;
00467 bool session_saving;
00468 int session_active_client;
00469 int session_desktop;
00470
00471 bool control_grab;
00472 bool tab_grab;
00473
00474
00475
00476 KShortcut cutWalkThroughDesktops, cutWalkThroughDesktopsReverse;
00477 KShortcut cutWalkThroughDesktopList, cutWalkThroughDesktopListReverse;
00478 KShortcut cutWalkThroughWindows, cutWalkThroughWindowsReverse;
00479 bool mouse_emulation;
00480 unsigned int mouse_emulation_state;
00481 WId mouse_emulation_window;
00482 int block_focus;
00483
00484 TabBox* tab_box;
00485 PopupInfo* popupinfo;
00486
00487 QPopupMenu *popup;
00488 QPopupMenu *advanced_popup;
00489 QPopupMenu *desk_popup;
00490 int desk_popup_index;
00491
00492 KGlobalAccel *keys;
00493 WId root;
00494
00495 PluginMgr *mgr;
00496
00497 RootInfo *rootInfo;
00498 QWidget* supportWindow;
00499
00500
00501 QStringList doNotManageList;
00502
00503
00504 Colormap default_colormap;
00505 Colormap installed_colormap;
00506
00507
00508 QTimer reconfigureTimer;
00509
00510 QTimer updateToolWindowsTimer;
00511
00512 static Workspace *_self;
00513
00514 bool workspaceInit;
00515
00516 KStartupInfo* startup;
00517
00518 bool electric_have_borders;
00519 int electric_current_border;
00520 WId electric_top_border;
00521 WId electric_bottom_border;
00522 WId electric_left_border;
00523 WId electric_right_border;
00524 int electricLeft;
00525 int electricRight;
00526 int electricTop;
00527 int electricBottom;
00528 Time electric_time_first;
00529 Time electric_time_last;
00530 QPoint electric_push_point;
00531
00532 Qt::Orientation layoutOrientation;
00533 int layoutX;
00534 int layoutY;
00535
00536 Placement *initPositioning;
00537
00538 QRect* workarea;
00539 QRect** screenarea;
00540
00541 bool managing_topmenus;
00542 KSelectionOwner* topmenu_selection;
00543 KSelectionWatcher* topmenu_watcher;
00544 ClientList topmenus;
00545 mutable int topmenu_height;
00546 QWidget* topmenu_space;
00547
00548 int set_active_client_recursion;
00549 int block_stacking_updates;
00550 bool blocked_propagating_new_clients;
00551 Window null_focus_window;
00552 bool forced_global_mouse_grab;
00553 friend class StackingUpdatesBlocker;
00554 };
00555
00556
00557 class StackingUpdatesBlocker
00558 {
00559 public:
00560 StackingUpdatesBlocker( Workspace* w )
00561 : ws( w ) { ws->blockStackingUpdates( true ); }
00562 ~StackingUpdatesBlocker()
00563 { ws->blockStackingUpdates( false ); }
00564 private:
00565 Workspace* ws;
00566 };
00567
00568
00569 class RootInfo : public NETRootInfo3
00570 {
00571 private:
00572 typedef KWinInternal::Client Client;
00573 public:
00574 RootInfo( Workspace* ws, Display *dpy, Window w, const char *name, unsigned long pr[], int pr_num, int scr= -1);
00575 protected:
00576 virtual void changeNumberOfDesktops(int n);
00577 virtual void changeCurrentDesktop(int d);
00578
00579 virtual void changeActiveWindow(Window w,NET::RequestSource src, Time timestamp, Window active_window);
00580 virtual void closeWindow(Window w);
00581 virtual void moveResize(Window w, int x_root, int y_root, unsigned long direction);
00582 virtual void moveResizeWindow(Window w, int flags, int x, int y, int width, int height );
00583 virtual void gotPing(Window w, Time timestamp);
00584 virtual void restackWindow(Window w, RequestSource source, Window above, int detail, Time timestamp);
00585 virtual void gotTakeActivity(Window w, Time timestamp, long flags );
00586 private:
00587 Workspace* workspace;
00588 };
00589
00590
00591 inline WId Workspace::rootWin() const
00592 {
00593 return root;
00594 }
00595
00596 inline bool Workspace::initializing() const
00597 {
00598 return workspaceInit;
00599 }
00600
00601 inline Client* Workspace::activeClient() const
00602 {
00603 return active_client;
00604 }
00605
00606 inline Client* Workspace::mostRecentlyActivatedClient() const
00607 {
00608 return should_get_focus.count() > 0 ? should_get_focus.last() : active_client;
00609 }
00610
00611 inline int Workspace::currentDesktop() const
00612 {
00613 return current_desktop;
00614 }
00615
00616 inline int Workspace::numberOfDesktops() const
00617 {
00618 return number_of_desktops;
00619 }
00620
00621 inline void Workspace::addGroup( Group* group, allowed_t )
00622 {
00623 groups.append( group );
00624 }
00625
00626 inline void Workspace::removeGroup( Group* group, allowed_t )
00627 {
00628 groups.remove( group );
00629 }
00630
00631 inline const ClientList& Workspace::stackingOrder() const
00632 {
00633
00634 return stacking_order;
00635 }
00636
00637 inline void Workspace::showWindowMenu(QPoint pos, Client* cl)
00638 {
00639 showWindowMenu(QRect(pos, pos), cl);
00640 }
00641
00642 inline void Workspace::showWindowMenu(int x, int y, Client* cl)
00643 {
00644 showWindowMenu(QRect(QPoint(x, y), QPoint(x, y)), cl);
00645 }
00646
00647 inline
00648 void Workspace::setWasUserInteraction()
00649 {
00650 was_user_interaction = true;
00651 }
00652
00653 inline
00654 bool Workspace::wasUserInteraction() const
00655 {
00656 return was_user_interaction;
00657 }
00658
00659 inline
00660 bool Workspace::managingTopMenus() const
00661 {
00662 return managing_topmenus;
00663 }
00664
00665 inline void Workspace::sessionSaveStarted()
00666 {
00667 session_saving = true;
00668 }
00669
00670 inline void Workspace::sessionSaveDone()
00671 {
00672 session_saving = false;
00673 }
00674
00675 inline bool Workspace::sessionSaving() const
00676 {
00677 return session_saving;
00678 }
00679
00680 inline bool Workspace::forcedGlobalMouseGrab() const
00681 {
00682 return forced_global_mouse_grab;
00683 }
00684
00685 template< typename T >
00686 inline Client* Workspace::findClient( T predicate )
00687 {
00688 if( Client* ret = findClientInList( clients, predicate ))
00689 return ret;
00690 if( Client* ret = findClientInList( desktops, predicate ))
00691 return ret;
00692 return NULL;
00693 }
00694
00695 template< typename T1, typename T2 >
00696 inline void Workspace::forEachClient( T1 procedure, T2 predicate )
00697 {
00698 for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it)
00699 if ( predicate( const_cast< const Client* >( *it)))
00700 procedure( *it );
00701 for ( ClientList::ConstIterator it = desktops.begin(); it != desktops.end(); ++it)
00702 if ( predicate( const_cast< const Client* >( *it)))
00703 procedure( *it );
00704 }
00705
00706 template< typename T >
00707 inline void Workspace::forEachClient( T procedure )
00708 {
00709 return forEachClient( procedure, TruePredicate());
00710 }
00711
00712 KWIN_COMPARE_PREDICATE( ClientMatchPredicate, const Client*, cl == value );
00713 inline bool Workspace::hasClient( const Client* c )
00714 {
00715 return findClient( ClientMatchPredicate( c ));
00716 }
00717
00718 }
00719
00720 #endif