35237aadcb
Two new interfaces are introduced: * org.kde.kwin.Compositing * org.kde.kwin.Effects The Compositing interface is generated from scriptable elements on the KWin::Compositor class and the Compositor is exported as /Compositor. It provides the general Compositing related D-Bus methods like whether the compositor is active and toggling and so on. The Effects interface is generated from scriptable elements on the KWin::EffectsHandlerImpl class and the instance is exported as /Effects. It provides all the effects related D-Bus methods like loading an effect or the list of all effects. This removes the need to have all these methods provided on the global org.kde.KWin interface. For backwards compatibility they are kept, but no longer provided by the Workspace class. Instead a new DBusInterface is generated which wrapps the calls and delegates it to one of our three related Singleton objects: * Workspace * Compositor * EffectsHandlerImpl
1152 lines
34 KiB
C++
1152 lines
34 KiB
C++
/********************************************************************
|
|
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
|
|
#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
|
|
{
|
|
Q_OBJECT
|
|
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;
|
|
|
|
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;
|
|
|
|
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
|
|
|
|
//-------------------------------------------------
|
|
// 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;
|
|
/**
|
|
* 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;
|
|
|
|
private:
|
|
int desktopCount_;
|
|
QSize desktopGridSize_;
|
|
int* desktopGrid_;
|
|
int currentDesktop_;
|
|
QString activity_;
|
|
QStringList allActivities_, openActivities_;
|
|
#ifdef KWIN_BUILD_ACTIVITIES
|
|
KActivities::Controller activityController_;
|
|
#endif
|
|
|
|
Outline* m_outline;
|
|
#ifdef KWIN_BUILD_SCREENEDGES
|
|
ScreenEdge m_screenEdge;
|
|
Qt::Orientations m_screenEdgeOrientation;
|
|
#endif
|
|
Compositor *m_compositor;
|
|
|
|
//-------------------------------------------------
|
|
// 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;
|
|
|
|
// 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;
|
|
}
|
|
|
|
/**
|
|
* Returns the list of clients sorted in stacking order, with topmost client
|
|
* at the last position
|
|
*/
|
|
const ToplevelList& stackingOrder() const;
|
|
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;
|
|
}
|
|
|
|
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();
|
|
bool decorationHasAlpha() const;
|
|
bool decorationSupportsTabbing() const; // Returns true if the decoration supports tabs.
|
|
bool decorationSupportsFrameOverlap() const;
|
|
bool decorationSupportsBlurBehind() const;
|
|
|
|
// D-Bus interface
|
|
void cascadeDesktop();
|
|
void unclutterDesktop();
|
|
void doNotManage(const QString&);
|
|
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;
|
|
|
|
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);
|
|
|
|
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();
|
|
|
|
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;
|
|
}
|
|
|
|
public slots:
|
|
// Keybindings
|
|
void slotSwitchDesktopNext();
|
|
void slotSwitchDesktopPrevious();
|
|
void slotSwitchDesktopRight();
|
|
void slotSwitchDesktopLeft();
|
|
void slotSwitchDesktopUp();
|
|
void slotSwitchDesktopDown();
|
|
|
|
void slotSwitchToDesktop();
|
|
//void slotSwitchToWindow( int );
|
|
void slotWindowToDesktop();
|
|
|
|
//void slotWindowToListPosition( int );
|
|
void slotSwitchToScreen();
|
|
void slotWindowToScreen();
|
|
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();
|
|
|
|
void slotSwitchWindowUp();
|
|
void slotSwitchWindowDown();
|
|
void slotSwitchWindowRight();
|
|
void slotSwitchWindowLeft();
|
|
|
|
void slotIncreaseWindowOpacity();
|
|
void slotLowerWindowOpacity();
|
|
|
|
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();
|
|
|
|
void slotKillWindow();
|
|
|
|
void slotSetupWindowShortcut();
|
|
void setupWindowShortcutDone(bool);
|
|
void slotToggleCompositing();
|
|
void slotInvertScreen();
|
|
|
|
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.
|
|
|
|
private slots:
|
|
void desktopResized();
|
|
void screenChangeTimeout();
|
|
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);
|
|
void reallyStopActivity(const QString &id); //dbus deadlocks suck
|
|
void handleActivityReply();
|
|
|
|
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();
|
|
|
|
//Signals required for the scripting interface
|
|
signals:
|
|
void desktopPresenceChanged(KWin::Client*, int);
|
|
void currentDesktopChanged(int, KWin::Client*);
|
|
void numberDesktopsChanged(int oldNumberOfDesktops);
|
|
void clientAdded(KWin::Client*);
|
|
void clientRemoved(KWin::Client*);
|
|
void clientActivated(KWin::Client*);
|
|
void clientDemandsAttentionChanged(KWin::Client*, bool);
|
|
void groupAdded(KWin::Group*);
|
|
void unmanagedAdded(KWin::Unmanaged*);
|
|
void deletedRemoved(KWin::Deleted*);
|
|
void mouseChanged(const QPoint& pos, const QPoint& oldpos,
|
|
Qt::MouseButtons buttons, Qt::MouseButtons oldbuttons,
|
|
Qt::KeyboardModifiers modifiers, Qt::KeyboardModifiers oldmodifiers);
|
|
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);
|
|
|
|
private:
|
|
void init();
|
|
void initShortcuts();
|
|
void setupWindowShortcut(Client* c);
|
|
enum Direction {
|
|
DirectionNorth,
|
|
DirectionEast,
|
|
DirectionSouth,
|
|
DirectionWest
|
|
};
|
|
void switchWindow(Direction direction);
|
|
|
|
void propagateClients(bool propagate_new_clients); // Called only from updateStackingOrder
|
|
ToplevelList 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 updateToolWindows(bool also_hide);
|
|
void fixPositionAfterCrash(Window w, const XWindowAttributes& attr);
|
|
void saveOldScreenSizes();
|
|
|
|
/// 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;
|
|
|
|
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;
|
|
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;
|
|
|
|
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
|
|
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
|
|
TabBox::TabBox* tab_box;
|
|
#endif
|
|
|
|
/**
|
|
* Holds the menu containing the user actions which is shown
|
|
* on e.g. right click the window decoration.
|
|
**/
|
|
UserActionsMenu *m_userActionsMenu;
|
|
|
|
void modalActionsSwitch(bool enabled);
|
|
|
|
KActionCollection* keys;
|
|
KActionCollection* client_keys;
|
|
KActionCollection* disable_shortcuts_keys;
|
|
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()
|
|
|
|
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;
|
|
|
|
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 NETRootInfo
|
|
{
|
|
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
|
|
{
|
|
return desktopCount_;
|
|
}
|
|
|
|
inline QSize Workspace::desktopGridSize() const
|
|
{
|
|
return desktopGridSize_;
|
|
}
|
|
|
|
inline int Workspace::desktopGridWidth() const
|
|
{
|
|
return desktopGridSize_.width();
|
|
}
|
|
|
|
inline int Workspace::desktopGridHeight() const
|
|
{
|
|
return desktopGridSize_.height();
|
|
}
|
|
|
|
inline int Workspace::workspaceWidth() const
|
|
{
|
|
return desktopGridSize_.width() * displayWidth();
|
|
}
|
|
|
|
inline int Workspace::workspaceHeight() const
|
|
{
|
|
return desktopGridSize_.height() * displayHeight();
|
|
}
|
|
|
|
inline int Workspace::currentDesktop() const
|
|
{
|
|
return currentDesktop_;
|
|
}
|
|
|
|
inline int Workspace::desktopAtCoords(QPoint coords) const
|
|
{
|
|
return desktopGrid_[coords.y() * desktopGridSize_.width() + coords.x()];
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// Unsorted
|
|
|
|
inline bool Workspace::initializing() const
|
|
{
|
|
return workspaceInit;
|
|
}
|
|
|
|
inline Client* Workspace::activeClient() const
|
|
{
|
|
return active_client;
|
|
}
|
|
|
|
inline Client* Workspace::mostRecentlyActivatedClient() const
|
|
{
|
|
return should_get_focus.count() > 0 ? should_get_focus.last() : active_client;
|
|
}
|
|
|
|
inline void Workspace::addGroup(Group* group, allowed_t)
|
|
{
|
|
emit groupAdded(group);
|
|
groups.append(group);
|
|
}
|
|
|
|
inline void Workspace::removeGroup(Group* group, allowed_t)
|
|
{
|
|
groups.removeAll(group);
|
|
}
|
|
|
|
inline const ToplevelList& Workspace::stackingOrder() const
|
|
{
|
|
// TODO: Q_ASSERT( block_stacking_updates == 0 );
|
|
return stacking_order;
|
|
}
|
|
|
|
inline void Workspace::showWindowMenu(QPoint pos, Client* cl)
|
|
{
|
|
showWindowMenu(QRect(pos, pos), cl);
|
|
}
|
|
|
|
inline void Workspace::showWindowMenu(int x, int y, Client* cl)
|
|
{
|
|
showWindowMenu(QRect(QPoint(x, y), QPoint(x, y)), cl);
|
|
}
|
|
|
|
inline void Workspace::setWasUserInteraction()
|
|
{
|
|
was_user_interaction = true;
|
|
}
|
|
|
|
inline bool Workspace::wasUserInteraction() const
|
|
{
|
|
return was_user_interaction;
|
|
}
|
|
|
|
inline void Workspace::sessionSaveStarted()
|
|
{
|
|
session_saving = true;
|
|
}
|
|
|
|
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::forceRestacking()
|
|
{
|
|
force_restacking = true;
|
|
StackingUpdatesBlocker blocker(this); // Do restacking if not blocked
|
|
}
|
|
|
|
inline void Workspace::updateFocusMousePosition(const QPoint& pos)
|
|
{
|
|
focusMousePos = pos;
|
|
}
|
|
|
|
inline QPoint Workspace::focusMousePosition() const
|
|
{
|
|
return focusMousePos;
|
|
}
|
|
|
|
template< typename T >
|
|
inline Client* Workspace::findClient(T predicate) const
|
|
{
|
|
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.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 >
|
|
inline void Workspace::forEachClient(T procedure)
|
|
{
|
|
return forEachClient(procedure, TruePredicate());
|
|
}
|
|
|
|
template< typename T >
|
|
inline Unmanaged* Workspace::findUnmanaged(T predicate) const
|
|
{
|
|
return findUnmanagedInList(unmanaged, predicate);
|
|
}
|
|
|
|
template< typename T1, typename T2 >
|
|
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 >
|
|
inline void Workspace::forEachUnmanaged(T procedure)
|
|
{
|
|
return forEachUnmanaged(procedure, TruePredicate());
|
|
}
|
|
|
|
KWIN_COMPARE_PREDICATE(ClientMatchPredicate, Client, const Client*, cl == value);
|
|
|
|
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
|
|
{
|
|
if (!hasDecorationPlugin()) {
|
|
return false;
|
|
}
|
|
return mgr->factory()->supports(AbilityProvidesShadow);
|
|
}
|
|
|
|
inline Qt::Corner Workspace::decorationCloseButtonCorner()
|
|
{
|
|
if (!hasDecorationPlugin()) {
|
|
return Qt::TopRightCorner;
|
|
}
|
|
return mgr->factory()->closeButtonCorner();
|
|
}
|
|
|
|
inline bool Workspace::decorationHasAlpha() const
|
|
{
|
|
if (!hasDecorationPlugin()) {
|
|
return false;
|
|
}
|
|
return mgr->factory()->supports(AbilityUsesAlphaChannel);
|
|
}
|
|
|
|
inline bool Workspace::decorationSupportsTabbing() const
|
|
{
|
|
if (!hasDecorationPlugin()) {
|
|
return false;
|
|
}
|
|
return mgr->factory()->supports(AbilityTabbing);
|
|
}
|
|
|
|
inline bool Workspace::decorationSupportsFrameOverlap() const
|
|
{
|
|
if (!hasDecorationPlugin()) {
|
|
return false;
|
|
}
|
|
return mgr->factory()->supports(AbilityExtendIntoClientArea);
|
|
}
|
|
|
|
inline bool Workspace::decorationSupportsBlurBehind() const
|
|
{
|
|
if (!hasDecorationPlugin()) {
|
|
return false;
|
|
}
|
|
return mgr->factory()->supports(AbilityUsesBlurBehind);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
#endif
|