kwin/workspace.h

1163 lines
34 KiB
C
Raw Normal View History

/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
Copyright (C) 2009 Lucas Murray <lmurray@undefinedfire.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef KWIN_WORKSPACE_H
#define KWIN_WORKSPACE_H
#include <QTimer>
#include <QVector>
#include <kshortcut.h>
#include <QCursor>
#include <netwm.h>
#include <kxmessages.h>
#include <QElapsedTimer>
#include <kmanagerselection.h>
// need to include utils.h before we use the ifdefs
#include "utils.h"
#ifdef KWIN_BUILD_ACTIVITIES
2011-12-05 18:33:14 +04:00
#include <KActivities/Controller>
#endif
#include "plugins.h"
#include "kdecoration.h"
#include "kdecorationfactory.h"
#ifdef KWIN_BUILD_SCREENEDGES
#include "screenedge.h"
#endif
#include "sm.h"
#include <X11/Xlib.h>
// TODO: Cleanup the order of things in this .h file
class QMenu;
class QActionGroup;
class QStringList;
class KConfig;
class KActionCollection;
class KStartupInfo;
class KStartupInfoId;
class KStartupInfoData;
class QSlider;
class QPushButton;
namespace KWin
{
#ifdef KWIN_BUILD_TABBOX
namespace TabBox
{
class TabBox;
}
#endif
class Client;
class Outline;
class RootInfo;
class PluginMgr;
class Placement;
class Rules;
class Scripting;
class UserActionsMenu;
class WindowRules;
class Compositor;
class Workspace : public QObject, public KDecorationDefines
2011-01-30 17:34:42 +03:00
{
Q_OBJECT
2011-01-30 17:34:42 +03:00
public:
Workspace(bool restore = false);
virtual ~Workspace();
static Workspace* self() {
return _self;
}
bool workspaceEvent(XEvent*);
bool workspaceEvent(QEvent*);
KDecoration* createDecoration(KDecorationBridge* bridge);
bool hasDecorationPlugin() const;
2011-01-30 17:34:42 +03:00
bool hasClient(const Client*);
template<typename T> Client* findClient(T predicate) const;
template<typename T1, typename T2> void forEachClient(T1 procedure, T2 predicate);
template<typename T> void forEachClient(T procedure);
template<typename T> Unmanaged* findUnmanaged(T predicate) const;
template<typename T1, typename T2> void forEachUnmanaged(T1 procedure, T2 predicate);
template<typename T> void forEachUnmanaged(T procedure);
QRect clientArea(clientAreaOption, const QPoint& p, int desktop) const;
QRect clientArea(clientAreaOption, const Client* c) const;
QRect clientArea(clientAreaOption, int screen, int desktop) const;
QRegion restrictedMoveArea(int desktop, StrutAreas areas = StrutAreaAll) const;
/**
* @internal
*/
void killWindowId(Window window);
void killWindow() {
slotKillWindow();
}
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;
Client* clientUnderMouse(int screen) const;
2011-01-30 17:34:42 +03:00
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,
bool ignore_desktop = false);
void restoreFocus();
void gotFocusIn(const Client*);
void setShouldGetFocus(Client*);
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, QRect& area);
void placeSmart(Client* c, const QRect& area);
QPoint adjustClientPosition(Client* c, QPoint pos, bool unrestricted, double snapAdjust = 1.0);
QRect adjustClientSize(Client* c, QRect moveResizeGeom, int mode);
void raiseClient(Client* c, bool nogroup = false);
void lowerClient(Client* c, bool nogroup = false);
void raiseClientRequest(Client* c, NET::RequestSource src, Time timestamp);
void lowerClientRequest(Client* c, NET::RequestSource src, Time timestamp);
void restackClientUnderActive(Client*);
void restack(Client *c, Client *under);
void updateClientLayer(Client* c);
void raiseOrLowerClient(Client*);
void resetUpdateToolWindowsTimer();
void restoreSessionStackingOrder(Client* c);
void updateStackingOrder(bool propagate_new_clients = false);
void forceRestacking();
void clientHidden(Client*);
void clientAttentionChanged(Client* c, bool set);
/**
* @return List of clients currently managed by Workspace
**/
const ClientList &clientList() const {
return clients;
}
/**
* @return List of unmanaged "clients" currently registered in Workspace
**/
const UnmanagedList &unmanagedList() const {
return unmanaged;
}
/**
* @return List of desktop "clients" currently managed by Workspace
**/
const ClientList &desktopList() const {
return desktops;
}
/**
* @return List of deleted "clients" currently managed by Workspace
**/
const DeletedList &deletedList() const {
return deleted;
}
Outline* outline();
#ifdef KWIN_BUILD_SCREENEDGES
ScreenEdge* screenEdge();
#endif
2011-01-30 17:34:42 +03:00
//-------------------------------------------------
// Desktop layout
public:
/**
* @returns Total number of desktops currently in existence.
*/
int numberOfDesktops() const;
/**
* @returns The maximum number of desktops that KWin supports.
*/
int maxNumberOfDesktops() const;
2011-01-30 17:34:42 +03:00
/**
* Set the number of available desktops to @a count. This function overrides any previous
* grid layout.
*/
void setNumberOfDesktops(int count);
/**
* Called from within setNumberOfDesktops() to ensure the desktop layout is still valid.
*/
void updateDesktopLayout();
/**
* @returns The size of desktop layout in grid units.
*/
QSize desktopGridSize() const;
/**
* @returns The width of desktop layout in grid units.
*/
int desktopGridWidth() const;
/**
* @returns The height of desktop layout in grid units.
*/
int desktopGridHeight() const;
/**
* @returns The width of desktop layout in pixels. Equivalent to gridWidth() *
* ::displayWidth().
*/
int workspaceWidth() const;
/**
* @returns The height of desktop layout in pixels. Equivalent to gridHeight() *
* ::displayHeight().
*/
int workspaceHeight() const;
/**
* @returns The ID of the current desktop.
*/
int currentDesktop() const;
/**
* Set the current desktop to @a current.
* @returns True on success, false otherwise.
*/
bool setCurrentDesktop(int current);
/**
* Generate a desktop layout from EWMH _NET_DESKTOP_LAYOUT property parameters.
*/
void setNETDesktopLayout(Qt::Orientation orientation, int width, int height, int startingCorner);
/**
* @returns The ID of the desktop at the point @a coords or 0 if no desktop exists at that
* point. @a coords is to be in grid units.
*/
int desktopAtCoords(QPoint coords) const;
/**
* @returns The coords of desktop @a id in grid units.
*/
QPoint desktopGridCoords(int id) const;
/**
* @returns The coords of the top-left corner of desktop @a id in pixels.
*/
QPoint desktopCoords(int id) const;
/**
* @returns The ID of the desktop above desktop @a id. Wraps around to the bottom of
* the layout if @a wrap is set. If @a id is not set use the current one.
*/
int desktopAbove(int id = 0, bool wrap = true) const;
/**
* @returns The ID of the desktop to the right of desktop @a id. Wraps around to the
* left of the layout if @a wrap is set. If @a id is not set use the current one.
*/
int desktopToRight(int id = 0, bool wrap = true) const;
/**
* @returns The ID of the desktop below desktop @a id. Wraps around to the top of the
* layout if @a wrap is set. If @a id is not set use the current one.
*/
int desktopBelow(int id = 0, bool wrap = true) const;
/**
* @returns The ID of the desktop to the left of desktop @a id. Wraps around to the
* right of the layout if @a wrap is set. If @a id is not set use the current one.
*/
int desktopToLeft(int id = 0, bool wrap = true) const;
QPoint cascadeOffset(const Client *c) const;
2011-01-30 17:34:42 +03:00
private:
int desktopCount_;
QSize desktopGridSize_;
int* desktopGrid_;
int currentDesktop_;
QString activity_;
QStringList allActivities_, openActivities_;
#ifdef KWIN_BUILD_ACTIVITIES
2011-11-05 02:23:52 +04:00
KActivities::Controller activityController_;
#endif
2011-01-30 17:34:42 +03:00
Outline* m_outline;
#ifdef KWIN_BUILD_SCREENEDGES
ScreenEdge m_screenEdge;
Qt::Orientations m_screenEdgeOrientation;
#endif
Compositor *m_compositor;
2011-01-30 17:34:42 +03:00
//-------------------------------------------------
// Unsorted
public:
int activeScreen() const;
int numScreens() const;
void checkActiveScreen(const Client* c);
void setActiveScreenMouse(const QPoint& mousepos);
QRect screenGeometry(int screen) const;
int screenNumber(const QPoint& pos) const;
QString currentActivity() const {
return activity_;
}
QStringList activityList() const {
return allActivities_;
}
const QStringList &openActivities() const {
return openActivities_;
}
#ifdef KWIN_BUILD_ACTIVITIES
void updateActivityList(bool running, bool updateCurrent, QObject *target = NULL, QString slot = QString());
#endif
// True when performing Workspace::updateClientArea().
// The calls below are valid only in that case.
bool inUpdateClientArea() const;
QRegion previousRestrictedMoveArea(int desktop, StrutAreas areas = StrutAreaAll) const;
QVector< QRect > previousScreenSizes() const;
int oldDisplayWidth() const;
int oldDisplayHeight() const;
2011-01-30 17:34:42 +03:00
// Tab box
#ifdef KWIN_BUILD_TABBOX
TabBox::TabBox *tabBox() const;
#endif
bool hasTabBox() const;
const QVector<int> &desktopFocusChain() const {
return m_desktopFocusChain.value();
}
const ClientList &globalFocusChain() const {
return global_focus_chain;
}
KActionCollection* actionCollection() const {
return keys;
}
KActionCollection* disableShortcutsKeys() const {
return disable_shortcuts_keys;
}
KActionCollection* clientKeys() const {
return client_keys;
}
2011-01-30 17:34:42 +03:00
#ifdef KWIN_BUILD_SCRIPTING
Scripting *scripting() {
return m_scripting;
}
#endif
2011-01-30 17:34:42 +03:00
/**
* Returns the list of clients sorted in stacking order, with topmost client
* at the last position
*/
const ToplevelList& stackingOrder() const;
2011-01-30 17:34:42 +03:00
ToplevelList xStackingOrder() const;
ClientList ensureStackingOrder(const ClientList& clients) const;
Client* topClientOnDesktop(int desktop, int screen, 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 toggleClientOnActivity(Client* c, const QString &activity, 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);
/**
* Shows the menu operations menu for the client and makes it active if
* it's not already.
*/
void showWindowMenu(const QRect& pos, Client* cl);
/**
* Backwards compatibility.
*/
void showWindowMenu(int x, int y, Client* cl);
void showWindowMenu(QPoint pos, Client* cl);
const UserActionsMenu *userActionsMenu() const {
return m_userActionsMenu;
}
2011-01-30 17:34:42 +03:00
void updateMinimizedOfTransients(Client*);
void updateOnAllDesktopsOfTransients(Client*);
void updateOnAllActivitiesOfTransients(Client*);
void checkTransients(Window w);
void performWindowOperation(Client* c, WindowOperation op);
void storeSession(KConfig* config, SMSavePhase phase);
void storeClient(KConfigGroup &cg, int num, Client *c);
void storeSubSession(const QString &name, QSet<QByteArray> sessionIds);
SessionInfo* takeSessionInfo(Client*);
WindowRules findWindowRules(const Client*, bool);
void rulesUpdated();
void discardUsedWindowRules(Client* c, bool withdraw);
void disableRulesUpdates(bool disable);
bool rulesUpdatesDisabled() const;
bool hasDecorationShadows() const;
Qt::Corner decorationCloseButtonCorner();
2011-01-30 17:34:42 +03:00
bool decorationHasAlpha() const;
bool decorationSupportsTabbing() const; // Returns true if the decoration supports tabs.
2011-01-30 17:34:42 +03:00
bool decorationSupportsFrameOverlap() const;
bool decorationSupportsBlurBehind() const;
// D-Bus interface
void cascadeDesktop();
void unclutterDesktop();
void doNotManage(const QString&);
/**
* @deprecated
* @todo: remove KDE5
**/
2011-01-30 17:34:42 +03:00
QList<int> decorationSupportedColors() const;
void nextDesktop();
void previousDesktop();
void circulateDesktopApplications();
bool waitForCompositingSetup();
bool stopActivity(const QString &id);
bool startActivity(const QString &id);
QString supportInformation() const;
2011-01-30 17:34:42 +03:00
void setCurrentScreen(int new_screen);
QString desktopName(int desk) const;
void setShowingDesktop(bool showing);
void resetShowingDesktop(bool keep_hidden);
bool showingDesktop() const;
bool isNotManaged(const QString& title); // TODO: 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()
void removeClient(Client*, allowed_t); // Only called from Client::destroyClient() or Client::releaseWindow()
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;
void removeUnmanaged(Unmanaged*, allowed_t); // Only called from Unmanaged::release()
void removeDeleted(Deleted*, allowed_t);
void addDeleted(Deleted*, Toplevel*, allowed_t);
2011-01-30 17:34:42 +03:00
bool checkStartupNotification(Window w, KStartupInfoId& id, KStartupInfoData& data);
void focusToNull(); // SELI TODO: Public?
enum FocusChainChange {
FocusChainMakeFirst,
FocusChainMakeLast,
FocusChainUpdate
};
void updateFocusChains(Client* c, FocusChainChange change);
bool forcedGlobalMouseGrab() const;
void clientShortcutUpdated(Client* c);
bool shortcutAvailable(const KShortcut& cut, Client* ignore = NULL) const;
bool globalShortcutsDisabled() const;
void disableGlobalShortcuts(bool disable);
void disableGlobalShortcutsForClient(bool disable);
QPoint cursorPos() const;
void checkCursorPos();
2011-01-30 17:34:42 +03:00
void sessionSaveStarted();
void sessionSaveDone();
void setWasUserInteraction();
bool wasUserInteraction() const;
bool sessionSaving() const;
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;
void cancelDelayFocus();
void requestDelayFocus(Client*);
void updateFocusMousePosition(const QPoint& pos);
QPoint focusMousePosition() const;
void toggleTopDockShadows(bool on);
Client* getMovingClient() {
return movingClient;
}
2011-01-30 17:34:42 +03:00
public slots:
2011-01-30 17:34:42 +03:00
// Keybindings
void slotSwitchDesktopNext();
void slotSwitchDesktopPrevious();
void slotSwitchDesktopRight();
void slotSwitchDesktopLeft();
void slotSwitchDesktopUp();
void slotSwitchDesktopDown();
void slotSwitchToDesktop();
2011-01-30 17:34:42 +03:00
//void slotSwitchToWindow( int );
void slotWindowToDesktop();
2011-01-30 17:34:42 +03:00
//void slotWindowToListPosition( int );
void slotSwitchToScreen();
void slotWindowToScreen();
2011-01-30 17:34:42 +03:00
void slotSwitchToNextScreen();
void slotWindowToNextScreen();
void slotToggleShowDesktop();
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 slotWindowQuickTileLeft();
void slotWindowQuickTileRight();
void slotWindowQuickTileTopLeft();
void slotWindowQuickTileTopRight();
void slotWindowQuickTileBottomLeft();
void slotWindowQuickTileBottomRight();
2011-01-30 17:34:42 +03:00
void slotSwitchWindowUp();
void slotSwitchWindowDown();
void slotSwitchWindowRight();
void slotSwitchWindowLeft();
void slotIncreaseWindowOpacity();
void slotLowerWindowOpacity();
2011-01-30 17:34:42 +03:00
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 slotDisableGlobalShortcuts();
void slotSettingsChanged(int category);
void reconfigure();
void slotReconfigure();
void slotCompositingToggled();
2011-01-30 17:34:42 +03:00
void slotKillWindow();
void slotSetupWindowShortcut();
void setupWindowShortcutDone(bool);
void slotToggleCompositing();
void slotInvertScreen();
2011-01-30 17:34:42 +03:00
void updateClientArea();
void slotActivateNextTab(); // Slot to move left the active Client.
void slotActivatePrevTab(); // Slot to move right the active Client.
void slotUntab(); // Slot to remove the active client from its group.
2011-01-30 17:34:42 +03:00
private slots:
void desktopResized();
void screenChangeTimeout();
2011-01-30 17:34:42 +03:00
void slotUpdateToolWindows();
void delayFocus();
void gotTemporaryRulesMessage(const QString&);
void cleanupTemporaryRules();
void writeWindowRules();
void slotBlockShortcuts(int data);
void slotReloadConfig();
void resetCursorPosTime();
void updateCurrentActivity(const QString &new_activity);
void slotActivityRemoved(const QString &activity);
void slotActivityAdded(const QString &activity);
2011-01-30 17:34:42 +03:00
void reallyStopActivity(const QString &id); //dbus deadlocks suck
void handleActivityReply();
2011-01-30 17:34:42 +03:00
Q_SIGNALS:
/**
* Emitted after the Workspace has setup the complete initialization process.
* This can be used to connect to for performing post-workspace initialization.
**/
void workspaceInitialized();
2011-01-30 17:34:42 +03:00
//Signals required for the scripting interface
2011-01-30 17:34:42 +03:00
signals:
void desktopPresenceChanged(KWin::Client*, int);
void currentDesktopChanged(int, KWin::Client*);
void numberDesktopsChanged(int oldNumberOfDesktops);
2011-01-30 17:34:42 +03:00
void clientAdded(KWin::Client*);
void clientRemoved(KWin::Client*);
void clientActivated(KWin::Client*);
void clientDemandsAttentionChanged(KWin::Client*, bool);
2011-01-30 17:34:42 +03:00
void groupAdded(KWin::Group*);
void unmanagedAdded(KWin::Unmanaged*);
void deletedRemoved(KWin::Deleted*);
2011-03-12 16:37:30 +03:00
void mouseChanged(const QPoint& pos, const QPoint& oldpos,
Qt::MouseButtons buttons, Qt::MouseButtons oldbuttons,
Qt::KeyboardModifiers modifiers, Qt::KeyboardModifiers oldmodifiers);
2011-03-12 21:18:19 +03:00
void propertyNotify(long a);
void configChanged();
void reinitializeCompositing();
/**
* This signal is emitted when the global
* activity is changed
* @param id id of the new current activity
*/
void currentActivityChanged(const QString &id);
/**
* This signal is emitted when a new activity is added
* @param id id of the new activity
*/
void activityAdded(const QString &id);
/**
* This signal is emitted when the activity
* is removed
* @param id id of the removed activity
*/
void activityRemoved(const QString &id);
2011-01-30 17:34:42 +03:00
private:
void init();
void initShortcuts();
void setupWindowShortcut(Client* c);
enum Direction {
DirectionNorth,
DirectionEast,
DirectionSouth,
DirectionWest
};
2011-01-30 17:34:42 +03:00
void switchWindow(Direction direction);
void propagateClients(bool propagate_new_clients); // Called only from updateStackingOrder
ToplevelList constrainedStackingOrder();
2011-01-30 17:34:42 +03:00
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 updateToolWindows(bool also_hide);
void fixPositionAfterCrash(Window w, const XWindowAttributes& attr);
void saveOldScreenSizes();
2011-01-30 17:34:42 +03:00
/// This is the right way to create a new client
Client* createClient(Window w, bool is_mapped);
void addClient(Client* c, allowed_t);
Unmanaged* createUnmanaged(Window w);
void addUnmanaged(Unmanaged* c, allowed_t);
Window findSpecialEventWindow(XEvent* e);
void randomPlacement(Client* c);
void smartPlacement(Client* c);
void cascadePlacement(Client* c, bool re_init = false);
// Desktop names and number of desktops
void loadDesktopSettings();
void saveDesktopSettings();
//---------------------------------------------------------------------
void closeActivePopup();
void updateClientArea(bool force);
typedef QHash< QString, QVector<int> > DesktopFocusChains;
DesktopFocusChains::Iterator m_desktopFocusChain;
DesktopFocusChains m_activitiesDesktopFocusChain;
2011-01-30 17:34:42 +03:00
QWidget* active_popup;
Client* active_popup_client;
void loadSessionInfo();
void addSessionInfo(KConfigGroup &cg);
void loadSubSessionInfo(const QString &name);
void loadWindowRules();
void editWindowRules(Client* c, bool whole_app);
QList<SessionInfo*> session;
QList<Rules*> rules;
KXMessages temporaryRulesMessages;
QTimer rulesUpdatedTimer;
QTimer screenChangedTimer;
2011-01-30 17:34:42 +03:00
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);
/**
* @returns Whether we have a Compositor and it is active (Scene created)
**/
bool compositing() const;
2011-01-30 17:34:42 +03:00
Client* active_client;
Client* last_active_client;
Client* most_recently_raised; // Used ONLY by raiseOrLowerClient()
Client* movingClient;
Client* pending_take_activity;
int active_screen;
// Delay(ed) window focus timer and client
QTimer* delayFocusTimer;
Client* delayfocus_client;
QPoint focusMousePos;
ClientList clients;
ClientList desktops;
UnmanagedList unmanaged;
DeletedList deleted;
ToplevelList unconstrained_stacking_order; // Topmost last
ToplevelList stacking_order; // Topmost last
2011-01-30 17:34:42 +03:00
bool force_restacking;
mutable ToplevelList x_stacking; // From XQueryTree()
mutable bool x_stacking_dirty;
QVector< ClientList > focus_chain; // Currently ative 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;
int block_focus;
#ifdef KWIN_BUILD_TABBOX
2011-01-30 17:34:42 +03:00
TabBox::TabBox* tab_box;
#endif
2011-01-30 17:34:42 +03:00
/**
* Holds the menu containing the user actions which is shown
* on e.g. right click the window decoration.
**/
UserActionsMenu *m_userActionsMenu;
2011-01-30 17:34:42 +03:00
void modalActionsSwitch(bool enabled);
KActionCollection* keys;
KActionCollection* client_keys;
KActionCollection* disable_shortcuts_keys;
2011-01-30 17:34:42 +03:00
ShortcutDialog* client_keys_dialog;
Client* client_keys_client;
bool global_shortcuts_disabled;
bool global_shortcuts_disabled_for_client;
PluginMgr* mgr;
RootInfo* rootInfo;
QWidget* supportWindow;
// Swallowing
QStringList doNotManageList;
// Colormap handling
Colormap default_colormap;
Colormap installed_colormap;
// Timer to collect requests for 'reconfigure'
QTimer reconfigureTimer;
QTimer updateToolWindowsTimer;
static Workspace* _self;
bool workspaceInit;
KStartupInfo* startup;
Placement* initPositioning;
QVector<QRect> workarea; // Array of workareas for virtual desktops
// Array of restricted areas that window cannot be moved into
QVector<StrutRects> restrictedmovearea;
// Array of the previous restricted areas that window cannot be moved into
QVector<StrutRects> oldrestrictedmovearea;
QVector< QVector<QRect> > screenarea; // Array of workareas per xinerama screen for all virtual desktops
QVector< QRect > oldscreensizes; // array of previous sizes of xinerama screens
QSize olddisplaysize; // previous sizes od displayWidth()/displayHeight()
2011-01-30 17:34:42 +03:00
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;
QSlider* transSlider;
QPushButton* transButton;
Scripting *m_scripting;
2011-01-30 17:34:42 +03:00
private:
friend bool performTransiencyCheck();
};
/**
* Helper for Workspace::blockStackingUpdates() being called in pairs (True/false)
*/
class StackingUpdatesBlocker
2011-01-30 17:34:42 +03:00
{
public:
StackingUpdatesBlocker(Workspace* w)
: ws(w) {
ws->blockStackingUpdates(true);
}
~StackingUpdatesBlocker() {
ws->blockStackingUpdates(false);
}
private:
Workspace* ws;
};
/**
* NET WM Protocol handler class
*/
class RootInfo : public NETRootInfo
2011-01-30 17:34:42 +03:00
{
private:
typedef KWin::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, 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;
};
//---------------------------------------------------------
// Desktop layout
inline int Workspace::numberOfDesktops() const
2011-01-30 17:34:42 +03:00
{
return desktopCount_;
2011-01-30 17:34:42 +03:00
}
inline QSize Workspace::desktopGridSize() const
2011-01-30 17:34:42 +03:00
{
return desktopGridSize_;
2011-01-30 17:34:42 +03:00
}
inline int Workspace::desktopGridWidth() const
2011-01-30 17:34:42 +03:00
{
return desktopGridSize_.width();
2011-01-30 17:34:42 +03:00
}
inline int Workspace::desktopGridHeight() const
2011-01-30 17:34:42 +03:00
{
return desktopGridSize_.height();
2011-01-30 17:34:42 +03:00
}
inline int Workspace::workspaceWidth() const
2011-01-30 17:34:42 +03:00
{
return desktopGridSize_.width() * displayWidth();
2011-01-30 17:34:42 +03:00
}
inline int Workspace::workspaceHeight() const
2011-01-30 17:34:42 +03:00
{
return desktopGridSize_.height() * displayHeight();
2011-01-30 17:34:42 +03:00
}
inline int Workspace::currentDesktop() const
2011-01-30 17:34:42 +03:00
{
return currentDesktop_;
2011-01-30 17:34:42 +03:00
}
2011-01-30 17:34:42 +03:00
inline int Workspace::desktopAtCoords(QPoint coords) const
{
return desktopGrid_[coords.y() * desktopGridSize_.width() + coords.x()];
2011-01-30 17:34:42 +03:00
}
//---------------------------------------------------------
// Unsorted
inline bool Workspace::initializing() const
2011-01-30 17:34:42 +03:00
{
return workspaceInit;
2011-01-30 17:34:42 +03:00
}
inline Client* Workspace::activeClient() const
2011-01-30 17:34:42 +03:00
{
return active_client;
2011-01-30 17:34:42 +03:00
}
inline Client* Workspace::mostRecentlyActivatedClient() const
2011-01-30 17:34:42 +03:00
{
return should_get_focus.count() > 0 ? should_get_focus.last() : active_client;
2011-01-30 17:34:42 +03:00
}
2011-01-30 17:34:42 +03:00
inline void Workspace::addGroup(Group* group, allowed_t)
{
emit groupAdded(group);
2011-01-30 17:34:42 +03:00
groups.append(group);
}
2011-01-30 17:34:42 +03:00
inline void Workspace::removeGroup(Group* group, allowed_t)
{
groups.removeAll(group);
}
inline const ToplevelList& Workspace::stackingOrder() const
2011-01-30 17:34:42 +03:00
{
// TODO: Q_ASSERT( block_stacking_updates == 0 );
return stacking_order;
2011-01-30 17:34:42 +03:00
}
2011-01-30 17:34:42 +03:00
inline void Workspace::showWindowMenu(QPoint pos, Client* cl)
{
showWindowMenu(QRect(pos, pos), cl);
}
2011-01-30 17:34:42 +03:00
inline void Workspace::showWindowMenu(int x, int y, Client* cl)
{
showWindowMenu(QRect(QPoint(x, y), QPoint(x, y)), cl);
}
inline void Workspace::setWasUserInteraction()
2011-01-30 17:34:42 +03:00
{
was_user_interaction = true;
2011-01-30 17:34:42 +03:00
}
inline bool Workspace::wasUserInteraction() const
2011-01-30 17:34:42 +03:00
{
return was_user_interaction;
2011-01-30 17:34:42 +03:00
}
inline void Workspace::sessionSaveStarted()
2011-01-30 17:34:42 +03:00
{
session_saving = true;
2011-01-30 17:34:42 +03:00
}
inline bool Workspace::sessionSaving() const
2011-01-30 17:34:42 +03:00
{
return session_saving;
2011-01-30 17:34:42 +03:00
}
inline bool Workspace::forcedGlobalMouseGrab() const
2011-01-30 17:34:42 +03:00
{
return forced_global_mouse_grab;
2011-01-30 17:34:42 +03:00
}
inline bool Workspace::showingDesktop() const
2011-01-30 17:34:42 +03:00
{
return showing_desktop;
2011-01-30 17:34:42 +03:00
}
inline bool Workspace::globalShortcutsDisabled() const
2011-01-30 17:34:42 +03:00
{
return global_shortcuts_disabled || global_shortcuts_disabled_for_client;
2011-01-30 17:34:42 +03:00
}
inline bool Workspace::rulesUpdatesDisabled() const
2011-01-30 17:34:42 +03:00
{
return rules_updates_disabled;
2011-01-30 17:34:42 +03:00
}
inline void Workspace::forceRestacking()
2011-01-30 17:34:42 +03:00
{
force_restacking = true;
2011-01-30 17:34:42 +03:00
StackingUpdatesBlocker blocker(this); // Do restacking if not blocked
}
2011-01-30 17:34:42 +03:00
inline void Workspace::updateFocusMousePosition(const QPoint& pos)
{
focusMousePos = pos;
2011-01-30 17:34:42 +03:00
}
inline QPoint Workspace::focusMousePosition() const
2011-01-30 17:34:42 +03:00
{
return focusMousePos;
2011-01-30 17:34:42 +03:00
}
template< typename T >
2011-01-30 17:34:42 +03:00
inline Client* Workspace::findClient(T predicate) const
{
if (Client* ret = findClientInList(clients, predicate))
return ret;
2011-01-30 17:34:42 +03:00
if (Client* ret = findClientInList(desktops, predicate))
return ret;
return NULL;
2011-01-30 17:34:42 +03:00
}
template< typename T1, typename T2 >
2011-01-30 17:34:42 +03:00
inline void Workspace::forEachClient(T1 procedure, T2 predicate)
{
for (ClientList::ConstIterator it = clients.constBegin(); it != clients.constEnd(); ++it)
if (predicate(const_cast<const Client*>(*it)))
procedure(*it);
for (ClientList::ConstIterator it = desktops.constBegin(); it != desktops.constEnd(); ++it)
if (predicate(const_cast<const Client*>(*it)))
procedure(*it);
}
template< typename T >
2011-01-30 17:34:42 +03:00
inline void Workspace::forEachClient(T procedure)
{
return forEachClient(procedure, TruePredicate());
}
template< typename T >
2011-01-30 17:34:42 +03:00
inline Unmanaged* Workspace::findUnmanaged(T predicate) const
{
return findUnmanagedInList(unmanaged, predicate);
}
template< typename T1, typename T2 >
2011-01-30 17:34:42 +03:00
inline void Workspace::forEachUnmanaged(T1 procedure, T2 predicate)
{
for (UnmanagedList::ConstIterator it = unmanaged.constBegin(); it != unmanaged.constEnd(); ++it)
if (predicate(const_cast<const Unmanaged*>(*it)))
procedure(*it);
}
template< typename T >
2011-01-30 17:34:42 +03:00
inline void Workspace::forEachUnmanaged(T procedure)
{
return forEachUnmanaged(procedure, TruePredicate());
}
2011-01-30 17:34:42 +03:00
KWIN_COMPARE_PREDICATE(ClientMatchPredicate, Client, const Client*, cl == value);
2011-01-30 17:34:42 +03:00
inline bool Workspace::hasClient(const Client* c)
{
return findClient(ClientMatchPredicate(c));
}
inline bool Workspace::hasDecorationPlugin() const
{
if (!mgr) {
return false;
}
return !mgr->hasNoDecoration();
}
inline bool Workspace::hasDecorationShadows() const
2011-01-30 17:34:42 +03:00
{
if (!hasDecorationPlugin()) {
return false;
}
2011-01-30 17:34:42 +03:00
return mgr->factory()->supports(AbilityProvidesShadow);
}
inline Qt::Corner Workspace::decorationCloseButtonCorner()
{
if (!hasDecorationPlugin()) {
return Qt::TopRightCorner;
}
return mgr->factory()->closeButtonCorner();
}
inline bool Workspace::decorationHasAlpha() const
2011-01-30 17:34:42 +03:00
{
if (!hasDecorationPlugin()) {
return false;
}
2011-01-30 17:34:42 +03:00
return mgr->factory()->supports(AbilityUsesAlphaChannel);
}
inline bool Workspace::decorationSupportsTabbing() const
2011-01-30 17:34:42 +03:00
{
if (!hasDecorationPlugin()) {
return false;
}
return mgr->factory()->supports(AbilityTabbing);
2011-01-30 17:34:42 +03:00
}
inline bool Workspace::decorationSupportsFrameOverlap() const
2011-01-30 17:34:42 +03:00
{
if (!hasDecorationPlugin()) {
return false;
}
2011-01-30 17:34:42 +03:00
return mgr->factory()->supports(AbilityExtendIntoClientArea);
}
inline bool Workspace::decorationSupportsBlurBehind() const
2011-01-30 17:34:42 +03:00
{
if (!hasDecorationPlugin()) {
return false;
}
2011-01-30 17:34:42 +03:00
return mgr->factory()->supports(AbilityUsesBlurBehind);
}
} // namespace
#endif