/***************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 1999, 2000 Matthias Ettrich Copyright (C) 2003 Lubos Lunak You can Freely distribute this program under the GNU General Public License. See the file "COPYING" for the exact licensing terms. ******************************************************************/ #ifndef KWIN_WORKSPACE_H #define KWIN_WORKSPACE_H #include #include #include #include #include #include #include "KWinInterface.h" #include "utils.h" #include "kdecoration.h" #include "sm.h" #include class TQPopupMenu; class TDEConfig; class TDEGlobalAccel; class TDEShortcutDialog; class TDEStartupInfo; class TDEStartupInfoId; class TDEStartupInfoData; class TQSlider; class TQPushButton; class TDEProcess; namespace KWinInternal { class Client; class TabBox; class PopupInfo; class RootInfo; class PluginMgr; class Placement; class Rules; class WindowRules; class SystemTrayWindow { public: SystemTrayWindow() : win(0),winFor(0) {} SystemTrayWindow( WId w ) : win(w),winFor(0) {} SystemTrayWindow( WId w, WId wf ) : win(w),winFor(wf) {} bool operator==( const SystemTrayWindow& other ) { return win == other.win; } WId win; WId winFor; }; typedef TQValueList SystemTrayWindowList; class Workspace : public TQObject, public KWinInterface, public KDecorationDefines { Q_OBJECT public: Workspace( bool restore = FALSE ); virtual ~Workspace(); static Workspace * self() { return _self; } bool workspaceEvent( XEvent * ); KDecoration* createDecoration( KDecorationBridge* bridge ); bool hasClient( const Client * ); template< typename T > Client* findClient( T predicate ); template< typename T1, typename T2 > void forEachClient( T1 procedure, T2 predicate ); template< typename T > void forEachClient( T procedure ); TQRect clientArea( clientAreaOption, const TQPoint& p, int desktop ) const; TQRect clientArea( clientAreaOption, const Client* c ) const; TQRect clientArea( clientAreaOption, int screen, int desktop ) const; /** * @internal */ void killWindowId( Window window ); void suspendWindowId( Window window ); void resumeWindowId( Window window ); bool isResumeableWindowID( Window window ); void killWindow() { slotKillWindow(); } void suspendWindow() { slotSuspendWindow(); } void resumeWindow() { slotResumeWindow(); } WId rootWin() const; bool initializing() const; /** * Returns the active client, i.e. the client that has the focus (or None * if no client has the focus) */ Client* activeClient() const; // Client that was activated, but it's not yet really activeClient(), because // we didn't process yet the matching FocusIn event. Used mostly in focus // stealing prevention code. Client* mostRecentlyActivatedClient() const; void activateClient( Client*, bool force = FALSE ); void requestFocus( Client* c, bool force = FALSE ); void takeActivity( Client* c, int flags, bool handled ); // flags are ActivityFlags void handleTakeActivity( Client* c, Time timestamp, int flags ); // flags are ActivityFlags bool allowClientActivation( const Client* c, Time time = -1U, bool focus_in = false ); void restoreFocus(); void gotFocusIn( const Client* ); void setShouldGetFocus( Client* ); bool fakeRequestedActivity( Client* c ); void unfakeActivity( Client* c ); bool activateNextClient( Client* c ); bool focusChangeEnabled() { return block_focus == 0; } void updateColormap(); /** * Indicates that the client c is being moved around by the user. */ void setClientIsMoving( Client *c ); void place( Client *c, TQRect& area ); void placeSmart( Client* c, const TQRect& area ); TQPoint adjustClientPosition( Client* c, TQPoint pos ); TQRect adjustClientSize( Client* c, TQRect moveResizeGeom, int mode ); void raiseClient( Client* c ); void lowerClient( Client* c ); void raiseClientRequest( Client* c, NET::RequestSource src, Time timestamp ); void lowerClientRequest( Client* c, NET::RequestSource src, Time timestamp ); void restackClientUnderActive( Client* ); void updateClientLayer( Client* c ); void raiseOrLowerClient( Client * ); void reconfigure(); void clientHidden( Client* ); void clientAttentionChanged( Client* c, bool set ); void clientMoved(const TQPoint &pos, Time time); /** * Returns the current virtual desktop of this workspace */ int currentDesktop() const; /** * Returns the number of virtual desktops of this workspace */ int numberOfDesktops() const; void setNumberOfDesktops( int n ); int activeScreen() const; int numScreens() const; void checkActiveScreen( const Client* c ); void setActiveScreenMouse( TQPoint mousepos ); TQRect screenGeometry( int screen ) const; int screenNumber( TQPoint pos ) const; TQWidget* desktopWidget(); // for TabBox Client* nextFocusChainClient(Client*) const; Client* previousFocusChainClient(Client*) const; Client* nextStaticClient(Client*) const; Client* previousStaticClient(Client*) const; int nextDesktopFocusChain( int iDesktop ) const; int previousDesktopFocusChain( int iDesktop ) const; void closeTabBox(); /** * Returns the list of clients sorted in stacking order, with topmost client * at the last position */ const ClientList& stackingOrder() const; ClientList ensureStackingOrder( const ClientList& clients ) const; Client* topClientOnDesktop( int desktop, bool unconstrained = false, bool only_normal = true ) const; Client* findDesktop( bool topmost, int desktop ) const; void sendClientToDesktop( Client* c, int desktop, bool dont_activate ); void windowToPreviousDesktop( Client* c ); void windowToNextDesktop( Client* c ); void sendClientToScreen( Client* c, int screen ); // KDE4 remove me - and it's also in the DCOP interface :( void showWindowMenuAt( unsigned long id, int x, int y ); void kDestopResized(); /** * Shows the menu operations menu for the client and makes it active if * it's not already. */ void showWindowMenu( const TQRect &pos, Client* cl ); /** * Backwards compatibility. */ void showWindowMenu( int x, int y, Client* cl ); void showWindowMenu( TQPoint pos, Client* cl ); void updateMinimizedOfTransients( Client* ); void updateOnAllDesktopsOfTransients( Client* ); void checkTransients( Window w ); void performWindowOperation( Client* c, WindowOperation op ); void storeSession( TDEConfig* config, SMSavePhase phase ); SessionInfo* takeSessionInfo( Client* ); WindowRules findWindowRules( const Client*, bool ); void rulesUpdated(); void discardUsedWindowRules( Client* c, bool withdraw ); void disableRulesUpdates( bool disable ); bool rulesUpdatesDisabled() const; // dcop interface void cascadeDesktop(); void unclutterDesktop(); void doNotManage(TQString); bool setCurrentDesktop( int new_desktop ); void updateOverlappingShadows(WId window); void setShadowed(WId window, bool shadowed); void nextDesktop(); void previousDesktop(); void circulateDesktopApplications(); void setCurrentScreen( int new_screen ); TQString desktopName( int desk ) const; virtual void setDesktopLayout(int , int , int ); void updateDesktopLayout(); void setShowingDesktop( bool showing ); void resetShowingDesktop( bool keep_hidden ); bool showingDesktop() const; bool isNotManaged( const TQString& title ); // ### setter or getter ? void sendPingToWindow( Window w, Time timestamp ); // called from Client::pingWindow() void sendTakeActivity( Client* c, Time timestamp, long flags ); // called from Client::takeActivity() bool kompmgrIsRunning(); void setOpacity(unsigned long winId, unsigned int opacityPercent); void setShadowSize(unsigned long winId, unsigned int shadowSizePercent); void setUnshadowed(unsigned long winId); // redundant, equals setShadowSize(inId, 0) // only called from Client::destroyClient() or Client::releaseWindow() void removeClient( Client*, allowed_t ); void setActiveClient( Client*, allowed_t ); Group* findGroup( Window leader ) const; void addGroup( Group* group, allowed_t ); void removeGroup( Group* group, allowed_t ); Group* findClientLeaderGroup( const Client* c ) const; bool checkStartupNotification( Window w, TDEStartupInfoId& id, TDEStartupInfoData& data ); void focusToNull(); // SELI public? enum FocusChainChange { FocusChainMakeFirst, FocusChainMakeLast, FocusChainUpdate }; void updateFocusChains( Client* c, FocusChainChange change ); bool forcedGlobalMouseGrab() const; void clientShortcutUpdated( Client* c ); bool shortcutAvailable( const TDEShortcut& cut, Client* ignore = NULL ) const; bool globalShortcutsDisabled() const; void disableGlobalShortcuts( bool disable ); void disableGlobalShortcutsForClient( bool disable ); void sessionSaveStarted(); void sessionSaveDone(); void setWasUserInteraction(); bool wasUserInteraction() const; bool sessionSaving() const; bool managingTopMenus() const; int topMenuHeight() const; void updateCurrentTopMenu(); int packPositionLeft( const Client* cl, int oldx, bool left_edge ) const; int packPositionRight( const Client* cl, int oldx, bool right_edge ) const; int packPositionUp( const Client* cl, int oldy, bool top_edge ) const; int packPositionDown( const Client* cl, int oldy, bool bottom_edge ) const; static TQStringList configModules(bool controlCenter); void cancelDelayFocus(); void requestDelayFocus( Client* ); void updateFocusMousePosition( const TQPoint& pos ); TQPoint focusMousePosition() const; void toggleTopDockShadows(bool on); public slots: void refresh(); // keybindings void slotSwitchDesktopNext(); void slotSwitchDesktopPrevious(); void slotSwitchDesktopRight(); void slotSwitchDesktopLeft(); void slotSwitchDesktopUp(); void slotSwitchDesktopDown(); void slotSwitchToDesktop( int ); //void slotSwitchToWindow( int ); void slotWindowToDesktop( int ); //void slotWindowToListPosition( int ); void slotSwitchToScreen( int ); void slotWindowToScreen( int ); void slotSwitchToNextScreen(); void slotWindowToNextScreen(); void slotWindowMaximize(); void slotWindowMaximizeVertical(); void slotWindowMaximizeHorizontal(); void slotWindowMinimize(); void slotWindowShade(); void slotWindowRaise(); void slotWindowLower(); void slotWindowRaiseOrLower(); void slotActivateAttentionWindow(); void slotWindowPackLeft(); void slotWindowPackRight(); void slotWindowPackUp(); void slotWindowPackDown(); void slotWindowGrowHorizontal(); void slotWindowGrowVertical(); void slotWindowShrinkHorizontal(); void slotWindowShrinkVertical(); void slotWalkThroughDesktops(); void slotWalkBackThroughDesktops(); void slotWalkThroughApps(); void slotWalkBackThroughApps(); void slotWalkThroughDesktopList(); void slotWalkBackThroughDesktopList(); void slotWalkThroughWindows(); void slotWalkBackThroughWindows(); void slotWindowOperations(); void slotWindowClose(); void slotWindowMove(); void slotWindowResize(); void slotWindowAbove(); void slotWindowBelow(); void slotWindowOnAllDesktops(); void slotWindowFullScreen(); void slotWindowNoBorder(); void slotWindowToNextDesktop(); void slotWindowToPreviousDesktop(); void slotWindowToDesktopRight(); void slotWindowToDesktopLeft(); void slotWindowToDesktopUp(); void slotWindowToDesktopDown(); void slotMouseEmulation(); void slotDisableGlobalShortcuts(); void slotSettingsChanged( int category ); void slotReconfigure(); void slotKillWindow(); void slotSuspendWindow(); void slotResumeWindow(); void slotGrabWindow(); void slotGrabDesktop(); void slotSetupWindowShortcut(); void setupWindowShortcutDone( bool ); void updateClientArea(); // kompmgr, also dcop void startKompmgr(); private slots: void desktopPopupAboutToShow(); void clientPopupAboutToShow(); void slotSendToDesktop( int ); void clientPopupActivated( int ); void configureWM(); void desktopResized(); void slotUpdateToolWindows(); void lostTopMenuSelection(); void lostTopMenuOwner(); void delayFocus(); void gotTemporaryRulesMessage( const TQString& ); void cleanupTemporaryRules(); void writeWindowRules(); void kipcMessage( int id, int data ); // kompmgr void setPopupClientOpacity(int v); void resetClientOpacity(); void setTransButtonText(int value); void unblockKompmgrRestart(); void restartKompmgr( TDEProcess *proc ); void handleKompmgrOutput( TDEProcess *proc, char *buffer, int buflen); void stopKompmgr(); void kompmgrReloadSettings(); // end protected: bool keyPressMouseEmulation( XKeyEvent& ev ); private: void init(); void initShortcuts(); void readShortcuts(); void initDesktopPopup(); void setupWindowShortcut( Client* c ); bool startKDEWalkThroughWindows(); bool startWalkThroughDesktops( int mode ); // TabBox::Mode::DesktopMode | DesktopListMode bool startWalkThroughDesktops(); bool startWalkThroughDesktopList(); void KDEWalkThroughWindows( bool forward ); void CDEWalkThroughWindows( bool forward ); void walkThroughDesktops( bool forward ); void KDEOneStepThroughWindows( bool forward ); void oneStepThroughDesktops( bool forward, int mode ); // TabBox::Mode::DesktopMode | DesktopListMode void oneStepThroughDesktops( bool forward ); void oneStepThroughDesktopList( bool forward ); bool establishTabBoxGrab(); void removeTabBoxGrab(); int desktopToRight( int desktop ) const; int desktopToLeft( int desktop ) const; int desktopUp( int desktop ) const; int desktopDown( int desktop ) const; void updateStackingOrder( bool propagate_new_clients = false ); void propagateClients( bool propagate_new_clients ); // called only from updateStackingOrder ClientList constrainedStackingOrder(); void raiseClientWithinApplication( Client* c ); void lowerClientWithinApplication( Client* c ); bool allowFullClientRaising( const Client* c, Time timestamp ); bool keepTransientAbove( const Client* mainwindow, const Client* transient ); void blockStackingUpdates( bool block ); void addTopMenu( Client* c ); void removeTopMenu( Client* c ); void setupTopMenuHandling(); void updateTopMenuGeometry( Client* c = NULL ); void updateToolWindows( bool also_hide ); // this is the right way to create a new client Client* createClient( Window w, bool is_mapped ); void addClient( Client* c, allowed_t ); Window findSpecialEventWindow( XEvent* e ); void randomPlacement(Client* c); void smartPlacement(Client* c); void cascadePlacement(Client* c, bool re_init = false); bool addSystemTrayWin( WId w ); bool removeSystemTrayWin( WId w, bool check ); void propagateSystemTrayWins(); SystemTrayWindow findSystemTrayWin( WId w ); // desktop names and number of desktops void loadDesktopSettings(); void saveDesktopSettings(); // mouse emulation WId getMouseEmulationWindow(); enum MouseEmulation { EmuPress, EmuRelease, EmuMove }; unsigned int sendFakedMouseEvent( TQPoint pos, WId win, MouseEmulation type, int button, unsigned int state ); // returns the new state void tabBoxKeyPress( const KKeyNative& keyX ); void tabBoxKeyRelease( const XKeyEvent& ev ); // electric borders void checkElectricBorders( bool force = false ); void createBorderWindows(); void destroyBorderWindows(); bool electricBorder(XEvent * e); void raiseElectricBorders(); // ------------------ void helperDialog( const TQString& message, const Client* c ); void calcDesktopLayout(int &x, int &y) const; TQPopupMenu* clientPopup(); void closeActivePopup(); void updateClientArea( bool force ); SystemTrayWindowList systemTrayWins; int current_desktop; int number_of_desktops; TQMemArray desktop_focus_chain; int active_screen; TQWidget* active_popup; Client* active_popup_client; TQWidget* desktop_widget; void loadSessionInfo(); void loadWindowRules(); void editWindowRules( Client* c, bool whole_app ); TQPtrList session; TQValueList rules; KXMessages temporaryRulesMessages; TQTimer rulesUpdatedTimer; bool rules_updates_disabled; static const char* windowTypeToTxt( NET::WindowType type ); static NET::WindowType txtToWindowType( const char* txt ); static bool sessionInfoWindowTypeMatch( Client* c, SessionInfo* info ); Client* active_client; Client* last_active_client; Client* next_active_client; // will be active after active_client deactivates Client* most_recently_raised; // used _only_ by raiseOrLowerClient() Client* movingClient; Client* pending_take_activity; // delay(ed) window focus timer and client TQTimer* delayFocusTimer; Client* delayfocus_client; TQPoint focusMousePos; ClientList clients; ClientList desktops; ClientList unconstrained_stacking_order; // topmost last ClientList stacking_order; // topmost last TQValueVector< ClientList > focus_chain; // currently active last ClientList global_focus_chain; // this one is only for things like tabbox's MRU ClientList should_get_focus; // last is most recent ClientList attention_chain; bool showing_desktop; ClientList showing_desktop_clients; int block_showing_desktop; GroupList groups; bool was_user_interaction; bool session_saving; int session_active_client; int session_desktop; bool control_grab; bool tab_grab; //KKeyNative walkThroughDesktopsKeycode, walkBackThroughDesktopsKeycode; //KKeyNative walkThroughDesktopListKeycode, walkBackThroughDesktopListKeycode; //KKeyNative walkThroughWindowsKeycode, walkBackThroughWindowsKeycode; TDEShortcut cutWalkThroughDesktops, cutWalkThroughDesktopsReverse; TDEShortcut cutWalkThroughDesktopList, cutWalkThroughDesktopListReverse; TDEShortcut cutWalkThroughWindows, cutWalkThroughWindowsReverse; TDEShortcut cutWalkThroughApps, cutWalkThroughAppsReverse; bool mouse_emulation; unsigned int mouse_emulation_state; WId mouse_emulation_window; int block_focus; TabBox* tab_box; PopupInfo* popupinfo; TQPopupMenu *popup; TQPopupMenu *advanced_popup; TQPopupMenu *desk_popup; int desk_popup_index; TDEGlobalAccel *keys; TDEGlobalAccel *client_keys; ShortcutDialog* client_keys_dialog; Client* client_keys_client; TDEGlobalAccel *disable_shortcuts_keys; bool global_shortcuts_disabled; bool global_shortcuts_disabled_for_client; WId root; PluginMgr *mgr; RootInfo *rootInfo; TQWidget* supportWindow; // swallowing TQStringList doNotManageList; // colormap handling Colormap default_colormap; Colormap installed_colormap; // Timer to collect requests for 'reconfigure' TQTimer reconfigureTimer; TQTimer updateToolWindowsTimer; static Workspace *_self; bool workspaceInit; TDEStartupInfo* startup; bool electric_have_borders; int electric_current_border; WId electric_top_border; WId electric_bottom_border; WId electric_left_border; WId electric_right_border; int electricLeft; int electricRight; int electricTop; int electricBottom; Time electric_time_first; Time electric_time_last; TQPoint electric_push_point; Qt::Orientation layoutOrientation; int layoutX; int layoutY; Placement *initPositioning; TQRect* workarea; // array of workareas for virtual desktops TQRect** screenarea; // array of workareas per xinerama screen for all virtual desktops bool managing_topmenus; TDESelectionOwner* topmenu_selection; TDESelectionWatcher* topmenu_watcher; ClientList topmenus; // doesn't own them mutable int topmenu_height; TQWidget* topmenu_space; int set_active_client_recursion; int block_stacking_updates; // when >0, stacking updates are temporarily disabled bool blocked_propagating_new_clients; // propagate also new clients after enabling stacking updates? Window null_focus_window; bool forced_global_mouse_grab; friend class StackingUpdatesBlocker; friend class Client; //kompmgr TQSlider *transSlider; TQPushButton *transButton; // not used yet /*Client* topDock; int maximizedWindowCounter; int topDockShadowSize;*/ //end signals: void kompmgrStarted(); void kompmgrStopped(); private: friend bool performTransiencyCheck(); }; // helper for Workspace::blockStackingUpdates() being called in pairs (true/false) class StackingUpdatesBlocker { public: StackingUpdatesBlocker( Workspace* w ) : ws( w ) { ws->blockStackingUpdates( true ); } ~StackingUpdatesBlocker() { ws->blockStackingUpdates( false ); } private: Workspace* ws; }; // NET WM Protocol handler class class RootInfo : public NETRootInfo4 { private: typedef KWinInternal::Client Client; // because of NET::Client public: RootInfo( Workspace* ws, Display *dpy, Window w, const char *name, unsigned long pr[], int pr_num, int scr= -1); protected: virtual void changeNumberOfDesktops(int n); virtual void changeCurrentDesktop(int d); // virtual void changeActiveWindow(Window w); the extended version is used virtual void changeActiveWindow(Window w,NET::RequestSource src, Time timestamp, Window active_window); virtual void closeWindow(Window w); virtual void moveResize(Window w, int x_root, int y_root, unsigned long direction); virtual void moveResizeWindow(Window w, int flags, int x, int y, int width, int height ); virtual void gotPing(Window w, Time timestamp); virtual void restackWindow(Window w, RequestSource source, Window above, int detail, Time timestamp); virtual void gotTakeActivity(Window w, Time timestamp, long flags ); virtual void changeShowingDesktop( bool showing ); private: Workspace* workspace; }; inline WId Workspace::rootWin() const { return root; } inline bool Workspace::initializing() const { return workspaceInit; } inline Client* Workspace::activeClient() const { // next_active_client is a kludge for drop shadows. If a window that is // activated is not also raised (i.e. when focus follows mouse), then the // newly activated window and its shadow won't cover visual artifacts that // might exist in the inactive window's shadow. We work around this by // (re)drawing the inactive window's shadow after the active window's shadow // is drawn, but to do that the inactive window needs to know which window // will become active next. next_active_client is a Client pointer for that // purpose. return next_active_client != NULL ? next_active_client : active_client; } inline Client* Workspace::mostRecentlyActivatedClient() const { return should_get_focus.count() > 0 ? should_get_focus.last() : active_client; } inline int Workspace::currentDesktop() const { return current_desktop; } inline int Workspace::numberOfDesktops() const { return number_of_desktops; } inline void Workspace::addGroup( Group* group, allowed_t ) { groups.append( group ); } inline void Workspace::removeGroup( Group* group, allowed_t ) { groups.remove( group ); } inline const ClientList& Workspace::stackingOrder() const { // TODO Q_ASSERT( block_stacking_updates == 0 ); return stacking_order; } inline void Workspace::showWindowMenu(TQPoint pos, Client* cl) { showWindowMenu(TQRect(pos, pos), cl); } inline void Workspace::showWindowMenu(int x, int y, Client* cl) { showWindowMenu(TQRect(TQPoint(x, y), TQPoint(x, y)), cl); } inline void Workspace::setWasUserInteraction() { was_user_interaction = true; } inline bool Workspace::wasUserInteraction() const { return was_user_interaction; } inline bool Workspace::managingTopMenus() const { return managing_topmenus; } inline void Workspace::sessionSaveStarted() { session_saving = true; } inline void Workspace::sessionSaveDone() { session_saving = false; } inline bool Workspace::sessionSaving() const { return session_saving; } inline bool Workspace::forcedGlobalMouseGrab() const { return forced_global_mouse_grab; } inline bool Workspace::showingDesktop() const { return showing_desktop; } inline bool Workspace::globalShortcutsDisabled() const { return global_shortcuts_disabled || global_shortcuts_disabled_for_client; } inline bool Workspace::rulesUpdatesDisabled() const { return rules_updates_disabled; } inline void Workspace::updateFocusMousePosition( const TQPoint& pos ) { focusMousePos = pos; } inline TQPoint Workspace::focusMousePosition() const { return focusMousePos; } template< typename T > inline Client* Workspace::findClient( T predicate ) { if( Client* ret = findClientInList( clients, predicate )) return ret; if( Client* ret = findClientInList( desktops, predicate )) return ret; return NULL; } template< typename T1, typename T2 > inline void Workspace::forEachClient( T1 procedure, T2 predicate ) { for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it) if ( predicate( const_cast< const Client* >( *it))) procedure( *it ); for ( ClientList::ConstIterator it = desktops.begin(); it != desktops.end(); ++it) if ( predicate( const_cast< const Client* >( *it))) procedure( *it ); } template< typename T > inline void Workspace::forEachClient( T procedure ) { return forEachClient( procedure, TruePredicate()); } KWIN_COMPARE_PREDICATE( ClientMatchPredicate, const Client*, cl == value ); inline bool Workspace::hasClient( const Client* c ) { return findClient( ClientMatchPredicate( c )); } } // namespace #endif