49e734f743
With the removal of BoxSwitch all effects which want mouse events use the fullscreen input window. The available functionality is too complex both in EffectsHandler and in the Effects. With this change only fullscreen input windows are supported and all effects share the input window. This means there is at maximum one input window. This simplifies the code in the Effects as they don't have to keep track of the window they created any more. In EffectsHandler it means that only one window needs to be created, destroyed and raised. Also it means that we can properly react on screen size changes which had been ignored in the past. Also quite some roundtrips to X are no longer needed as we do not need to query the window geometry when creating the input window. REVIEW: 110156
488 lines
17 KiB
C++
488 lines
17 KiB
C++
/********************************************************************
|
|
KWin - the KDE window manager
|
|
This file is part of the KDE project.
|
|
|
|
Copyright (C) 2006 Lubos Lunak <l.lunak@kde.org>
|
|
Copyright (C) 2010, 2011 Martin Gräßlin <mgraesslin@kde.org>
|
|
|
|
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_EFFECTSIMPL_H
|
|
#define KWIN_EFFECTSIMPL_H
|
|
|
|
#include "kwineffects.h"
|
|
|
|
#include "scene.h"
|
|
#include "xcbutils.h"
|
|
|
|
#include <QStack>
|
|
#include <QHash>
|
|
#include <Plasma/FrameSvg>
|
|
|
|
class QDBusPendingCallWatcher;
|
|
class QDBusServiceWatcher;
|
|
class KService;
|
|
class OrgFreedesktopScreenSaverInterface;
|
|
|
|
|
|
namespace KWin
|
|
{
|
|
|
|
class AbstractThumbnailItem;
|
|
class DesktopThumbnailItem;
|
|
class WindowThumbnailItem;
|
|
|
|
class Client;
|
|
class Compositor;
|
|
class Deleted;
|
|
class Unmanaged;
|
|
class ScreenLockerWatcher;
|
|
|
|
class EffectsHandlerImpl : public EffectsHandler
|
|
{
|
|
Q_OBJECT
|
|
Q_CLASSINFO("D-Bus Interface", "org.kde.kwin.Effects")
|
|
Q_PROPERTY(QStringList activeEffects READ activeEffects)
|
|
Q_PROPERTY(QStringList loadedEffects READ loadedEffects)
|
|
Q_PROPERTY(QStringList listOfEffects READ listOfEffects)
|
|
public:
|
|
EffectsHandlerImpl(Compositor *compositor, Scene *scene);
|
|
virtual ~EffectsHandlerImpl();
|
|
virtual void prePaintScreen(ScreenPrePaintData& data, int time);
|
|
virtual void paintScreen(int mask, QRegion region, ScreenPaintData& data);
|
|
/**
|
|
* Special hook to perform a paintScreen but just with the windows on @p desktop.
|
|
**/
|
|
void paintDesktop(int desktop, int mask, QRegion region, ScreenPaintData& data);
|
|
virtual void postPaintScreen();
|
|
virtual void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time);
|
|
virtual void paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data);
|
|
virtual void postPaintWindow(EffectWindow* w);
|
|
virtual void paintEffectFrame(EffectFrame* frame, QRegion region, double opacity, double frameOpacity);
|
|
|
|
Effect *provides(Effect::Feature ef);
|
|
|
|
virtual void drawWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data);
|
|
|
|
virtual void buildQuads(EffectWindow* w, WindowQuadList& quadList);
|
|
|
|
virtual void activateWindow(EffectWindow* c);
|
|
virtual EffectWindow* activeWindow() const;
|
|
virtual void moveWindow(EffectWindow* w, const QPoint& pos, bool snap = false, double snapAdjust = 1.0);
|
|
virtual void windowToDesktop(EffectWindow* w, int desktop);
|
|
virtual void windowToScreen(EffectWindow* w, int screen);
|
|
virtual void setShowingDesktop(bool showing);
|
|
|
|
virtual QString currentActivity() const;
|
|
virtual int currentDesktop() const;
|
|
virtual int numberOfDesktops() const;
|
|
virtual void setCurrentDesktop(int desktop);
|
|
virtual void setNumberOfDesktops(int desktops);
|
|
virtual QSize desktopGridSize() const;
|
|
virtual int desktopGridWidth() const;
|
|
virtual int desktopGridHeight() const;
|
|
virtual int workspaceWidth() const;
|
|
virtual int workspaceHeight() const;
|
|
virtual int desktopAtCoords(QPoint coords) const;
|
|
virtual QPoint desktopGridCoords(int id) const;
|
|
virtual QPoint desktopCoords(int id) const;
|
|
virtual int desktopAbove(int desktop = 0, bool wrap = true) const;
|
|
virtual int desktopToRight(int desktop = 0, bool wrap = true) const;
|
|
virtual int desktopBelow(int desktop = 0, bool wrap = true) const;
|
|
virtual int desktopToLeft(int desktop = 0, bool wrap = true) const;
|
|
virtual QString desktopName(int desktop) const;
|
|
virtual bool optionRollOverDesktops() const;
|
|
|
|
virtual int displayWidth() const;
|
|
virtual int displayHeight() const;
|
|
virtual QPoint cursorPos() const;
|
|
virtual bool grabKeyboard(Effect* effect);
|
|
virtual void ungrabKeyboard();
|
|
// not performing XGrabPointer
|
|
virtual void startMouseInterception(Effect *effect, Qt::CursorShape shape);
|
|
virtual void stopMouseInterception(Effect *effect);
|
|
virtual void* getProxy(QString name);
|
|
virtual void startMousePolling();
|
|
virtual void stopMousePolling();
|
|
virtual EffectWindow* findWindow(WId id) const;
|
|
virtual EffectWindowList stackingOrder() const;
|
|
virtual void setElevatedWindow(EffectWindow* w, bool set);
|
|
|
|
virtual void setTabBoxWindow(EffectWindow*);
|
|
virtual void setTabBoxDesktop(int);
|
|
virtual EffectWindowList currentTabBoxWindowList() const;
|
|
virtual void refTabBox();
|
|
virtual void unrefTabBox();
|
|
virtual void closeTabBox();
|
|
virtual QList< int > currentTabBoxDesktopList() const;
|
|
virtual int currentTabBoxDesktop() const;
|
|
virtual EffectWindow* currentTabBoxWindow() const;
|
|
|
|
virtual void setActiveFullScreenEffect(Effect* e);
|
|
virtual Effect* activeFullScreenEffect() const;
|
|
|
|
virtual void addRepaintFull();
|
|
virtual void addRepaint(const QRect& r);
|
|
virtual void addRepaint(const QRegion& r);
|
|
virtual void addRepaint(int x, int y, int w, int h);
|
|
virtual int activeScreen() const;
|
|
virtual int numScreens() const;
|
|
virtual int screenNumber(const QPoint& pos) const;
|
|
virtual QRect clientArea(clientAreaOption, int screen, int desktop) const;
|
|
virtual QRect clientArea(clientAreaOption, const EffectWindow* c) const;
|
|
virtual QRect clientArea(clientAreaOption, const QPoint& p, int desktop) const;
|
|
virtual double animationTimeFactor() const;
|
|
virtual WindowQuadType newWindowQuadType();
|
|
|
|
virtual void defineCursor(Qt::CursorShape shape);
|
|
virtual bool checkInputWindowEvent(XEvent* e);
|
|
virtual void checkInputWindowStacking();
|
|
|
|
virtual void reserveElectricBorder(ElectricBorder border, Effect *effect);
|
|
virtual void unreserveElectricBorder(ElectricBorder border, Effect *effect);
|
|
|
|
virtual unsigned long xrenderBufferPicture();
|
|
virtual void reconfigure();
|
|
virtual void registerPropertyType(long atom, bool reg);
|
|
virtual QByteArray readRootProperty(long atom, long type, int format) const;
|
|
virtual void deleteRootProperty(long atom) const;
|
|
virtual xcb_atom_t announceSupportProperty(const QByteArray& propertyName, Effect* effect);
|
|
virtual void removeSupportProperty(const QByteArray& propertyName, Effect* effect);
|
|
|
|
virtual bool hasDecorationShadows() const;
|
|
|
|
virtual bool decorationsHaveAlpha() const;
|
|
|
|
virtual bool decorationSupportsBlurBehind() const;
|
|
|
|
virtual EffectFrame* effectFrame(EffectFrameStyle style, bool staticSize, const QPoint& position, Qt::Alignment alignment) const;
|
|
|
|
virtual QVariant kwinOption(KWinOption kwopt);
|
|
virtual bool isScreenLocked() const;
|
|
|
|
// internal (used by kwin core or compositing code)
|
|
void startPaint();
|
|
void grabbedKeyboardEvent(QKeyEvent* e);
|
|
bool hasKeyboardGrab() const;
|
|
void desktopResized(const QSize &size);
|
|
|
|
virtual void reloadEffect(Effect *effect);
|
|
QStringList loadedEffects() const;
|
|
QStringList listOfEffects() const;
|
|
|
|
QList<EffectWindow*> elevatedWindows() const;
|
|
QStringList activeEffects() const;
|
|
|
|
/**
|
|
* @returns Whether we are currently in a desktop rendering process triggered by paintDesktop hook
|
|
**/
|
|
bool isDesktopRendering() const {
|
|
return m_desktopRendering;
|
|
}
|
|
/**
|
|
* @returns the desktop currently being rendered in the paintDesktop hook.
|
|
**/
|
|
int currentRenderedDesktop() const {
|
|
return m_currentRenderedDesktop;
|
|
}
|
|
|
|
public Q_SLOTS:
|
|
void slotCurrentTabAboutToChange(EffectWindow* from, EffectWindow* to);
|
|
void slotTabAdded(EffectWindow* from, EffectWindow* to);
|
|
void slotTabRemoved(EffectWindow* c, EffectWindow* newActiveWindow);
|
|
|
|
// slots for D-Bus interface
|
|
Q_SCRIPTABLE void reconfigureEffect(const QString& name);
|
|
Q_SCRIPTABLE bool loadEffect(const QString& name, bool checkDefault = false);
|
|
Q_SCRIPTABLE void toggleEffect(const QString& name);
|
|
Q_SCRIPTABLE void unloadEffect(const QString& name);
|
|
Q_SCRIPTABLE bool isEffectLoaded(const QString& name) const;
|
|
Q_SCRIPTABLE QString supportInformation(const QString& name) const;
|
|
Q_SCRIPTABLE QString debug(const QString& name, const QString& parameter = QString()) const;
|
|
|
|
protected Q_SLOTS:
|
|
void slotDesktopChanged(int old, KWin::Client *withClient);
|
|
void slotClientAdded(KWin::Client *c);
|
|
void slotClientShown(KWin::Toplevel*);
|
|
void slotUnmanagedAdded(KWin::Unmanaged *u);
|
|
void slotWindowClosed(KWin::Toplevel *c);
|
|
void slotClientActivated(KWin::Client *c);
|
|
void slotDeletedRemoved(KWin::Deleted *d);
|
|
void slotClientMaximized(KWin::Client *c, KDecorationDefines::MaximizeMode maxMode);
|
|
void slotClientStartUserMovedResized(KWin::Client *c);
|
|
void slotClientStepUserMovedResized(KWin::Client *c, const QRect &geometry);
|
|
void slotClientFinishUserMovedResized(KWin::Client *c);
|
|
void slotOpacityChanged(KWin::Toplevel *t, qreal oldOpacity);
|
|
void slotClientMinimized(KWin::Client *c, bool animate);
|
|
void slotClientUnminimized(KWin::Client *c, bool animate);
|
|
void slotGeometryShapeChanged(KWin::Toplevel *t, const QRect &old);
|
|
void slotPaddingChanged(KWin::Toplevel *t, const QRect &old);
|
|
void slotWindowDamaged(KWin::Toplevel *t, const QRect& r);
|
|
void slotPropertyNotify(KWin::Toplevel *t, long atom);
|
|
void slotPropertyNotify(long atom);
|
|
|
|
protected:
|
|
bool loadScriptedEffect(const QString &name, KService *service);
|
|
KLibrary* findEffectLibrary(KService* service);
|
|
void effectsChanged();
|
|
void setupClientConnections(KWin::Client *c);
|
|
void setupUnmanagedConnections(KWin::Unmanaged *u);
|
|
|
|
Effect* keyboard_grab_effect;
|
|
Effect* fullscreen_effect;
|
|
QList<EffectWindow*> elevated_windows;
|
|
QMultiMap< int, EffectPair > effect_order;
|
|
QHash< long, int > registered_atoms;
|
|
int next_window_quad_type;
|
|
|
|
private Q_SLOTS:
|
|
void slotEffectsQueried();
|
|
|
|
private:
|
|
QList< Effect* > m_activeEffects;
|
|
QList< Effect* >::iterator m_currentDrawWindowIterator;
|
|
QList< Effect* >::iterator m_currentPaintWindowIterator;
|
|
QList< Effect* >::iterator m_currentPaintEffectFrameIterator;
|
|
QList< Effect* >::iterator m_currentPaintScreenIterator;
|
|
QList< Effect* >::iterator m_currentBuildQuadsIterator;
|
|
typedef QHash< QByteArray, QList< Effect*> > PropertyEffectMap;
|
|
PropertyEffectMap m_propertiesForEffects;
|
|
QHash<QByteArray, qulonglong> m_managedProperties;
|
|
Compositor *m_compositor;
|
|
Scene *m_scene;
|
|
ScreenLockerWatcher *m_screenLockerWatcher;
|
|
bool m_desktopRendering;
|
|
int m_currentRenderedDesktop;
|
|
Xcb::Window m_mouseInterceptionWindow;
|
|
QList<Effect*> m_grabbedMouseEffects;
|
|
};
|
|
|
|
class EffectWindowImpl : public EffectWindow
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
explicit EffectWindowImpl(Toplevel *toplevel);
|
|
virtual ~EffectWindowImpl();
|
|
|
|
virtual void enablePainting(int reason);
|
|
virtual void disablePainting(int reason);
|
|
virtual bool isPaintingEnabled();
|
|
|
|
virtual void refWindow();
|
|
virtual void unrefWindow();
|
|
|
|
virtual const EffectWindowGroup* group() const;
|
|
|
|
virtual QRegion shape() const;
|
|
virtual QRect decorationInnerRect() const;
|
|
virtual QByteArray readProperty(long atom, long type, int format) const;
|
|
virtual void deleteProperty(long atom) const;
|
|
|
|
virtual EffectWindow* findModal();
|
|
virtual EffectWindowList mainWindows() const;
|
|
|
|
virtual WindowQuadList buildQuads(bool force = false) const;
|
|
|
|
const Toplevel* window() const;
|
|
Toplevel* window();
|
|
|
|
void setWindow(Toplevel* w); // internal
|
|
void setSceneWindow(Scene::Window* w); // internal
|
|
const Scene::Window* sceneWindow() const; // internal
|
|
Scene::Window* sceneWindow(); // internal
|
|
|
|
void elevate(bool elevate);
|
|
|
|
void setData(int role, const QVariant &data);
|
|
QVariant data(int role) const;
|
|
|
|
void registerThumbnail(AbstractThumbnailItem *item);
|
|
QHash<WindowThumbnailItem*, QWeakPointer<EffectWindowImpl> > const &thumbnails() const {
|
|
return m_thumbnails;
|
|
}
|
|
QList<DesktopThumbnailItem*> const &desktopThumbnails() const {
|
|
return m_desktopThumbnails;
|
|
}
|
|
private Q_SLOTS:
|
|
void thumbnailDestroyed(QObject *object);
|
|
void thumbnailTargetChanged();
|
|
void desktopThumbnailDestroyed(QObject *object);
|
|
private:
|
|
void insertThumbnail(WindowThumbnailItem *item);
|
|
Toplevel* toplevel;
|
|
Scene::Window* sw; // This one is used only during paint pass.
|
|
QHash<int, QVariant> dataMap;
|
|
QHash<WindowThumbnailItem*, QWeakPointer<EffectWindowImpl> > m_thumbnails;
|
|
QList<DesktopThumbnailItem*> m_desktopThumbnails;
|
|
};
|
|
|
|
class EffectWindowGroupImpl
|
|
: public EffectWindowGroup
|
|
{
|
|
public:
|
|
explicit EffectWindowGroupImpl(Group* g);
|
|
virtual EffectWindowList members() const;
|
|
private:
|
|
Group* group;
|
|
};
|
|
|
|
class EffectFrameImpl
|
|
: public QObject, public EffectFrame
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
explicit EffectFrameImpl(EffectFrameStyle style, bool staticSize = true, QPoint position = QPoint(-1, -1),
|
|
Qt::Alignment alignment = Qt::AlignCenter);
|
|
virtual ~EffectFrameImpl();
|
|
|
|
virtual void free();
|
|
virtual void render(QRegion region = infiniteRegion(), double opacity = 1.0, double frameOpacity = 1.0);
|
|
virtual Qt::Alignment alignment() const;
|
|
virtual void setAlignment(Qt::Alignment alignment);
|
|
virtual const QFont& font() const;
|
|
virtual void setFont(const QFont& font);
|
|
virtual const QRect& geometry() const;
|
|
virtual void setGeometry(const QRect& geometry, bool force = false);
|
|
virtual const QPixmap& icon() const;
|
|
virtual void setIcon(const QPixmap& icon);
|
|
virtual const QSize& iconSize() const;
|
|
virtual void setIconSize(const QSize& size);
|
|
virtual void setPosition(const QPoint& point);
|
|
virtual const QString& text() const;
|
|
virtual void setText(const QString& text);
|
|
virtual EffectFrameStyle style() const {
|
|
return m_style;
|
|
};
|
|
Plasma::FrameSvg& frame() {
|
|
return m_frame;
|
|
}
|
|
bool isStatic() const {
|
|
return m_static;
|
|
};
|
|
void finalRender(QRegion region, double opacity, double frameOpacity) const;
|
|
virtual void setShader(GLShader* shader) {
|
|
m_shader = shader;
|
|
}
|
|
virtual GLShader* shader() const {
|
|
return m_shader;
|
|
}
|
|
virtual void setSelection(const QRect& selection);
|
|
const QRect& selection() const {
|
|
return m_selectionGeometry;
|
|
}
|
|
Plasma::FrameSvg& selectionFrame() {
|
|
return m_selection;
|
|
}
|
|
/**
|
|
* The foreground text color as specified by the default Plasma theme.
|
|
*/
|
|
static QColor styledTextColor();
|
|
|
|
private Q_SLOTS:
|
|
void plasmaThemeChanged();
|
|
|
|
private:
|
|
Q_DISABLE_COPY(EffectFrameImpl) // As we need to use Qt slots we cannot copy this class
|
|
void align(QRect &geometry); // positions geometry around m_point respecting m_alignment
|
|
void autoResize(); // Auto-resize if not a static size
|
|
|
|
EffectFrameStyle m_style;
|
|
Plasma::FrameSvg m_frame; // TODO: share between all EffectFrames
|
|
Plasma::FrameSvg m_selection;
|
|
|
|
// Position
|
|
bool m_static;
|
|
QPoint m_point;
|
|
Qt::Alignment m_alignment;
|
|
QRect m_geometry;
|
|
|
|
// Contents
|
|
QString m_text;
|
|
QFont m_font;
|
|
QPixmap m_icon;
|
|
QSize m_iconSize;
|
|
QRect m_selectionGeometry;
|
|
|
|
Scene::EffectFrame* m_sceneFrame;
|
|
GLShader* m_shader;
|
|
};
|
|
|
|
class ScreenLockerWatcher : public QObject
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
explicit ScreenLockerWatcher(QObject *parent = 0);
|
|
virtual ~ScreenLockerWatcher();
|
|
bool isLocked() const {
|
|
return m_locked;
|
|
}
|
|
Q_SIGNALS:
|
|
void locked(bool locked);
|
|
private Q_SLOTS:
|
|
void setLocked(bool activated);
|
|
void activeQueried(QDBusPendingCallWatcher *watcher);
|
|
void serviceOwnerChanged(const QString &serviceName, const QString &oldOwner, const QString &newOwner);
|
|
void serviceRegisteredQueried();
|
|
void serviceOwnerQueried();
|
|
private:
|
|
OrgFreedesktopScreenSaverInterface *m_interface;
|
|
QDBusServiceWatcher *m_serviceWatcher;
|
|
bool m_locked;
|
|
};
|
|
|
|
inline
|
|
QList<EffectWindow*> EffectsHandlerImpl::elevatedWindows() const
|
|
{
|
|
return elevated_windows;
|
|
}
|
|
|
|
|
|
inline
|
|
EffectWindowGroupImpl::EffectWindowGroupImpl(Group* g)
|
|
: group(g)
|
|
{
|
|
}
|
|
|
|
EffectWindow* effectWindow(Toplevel* w);
|
|
EffectWindow* effectWindow(Scene::Window* w);
|
|
|
|
inline
|
|
const Scene::Window* EffectWindowImpl::sceneWindow() const
|
|
{
|
|
return sw;
|
|
}
|
|
|
|
inline
|
|
Scene::Window* EffectWindowImpl::sceneWindow()
|
|
{
|
|
return sw;
|
|
}
|
|
|
|
inline
|
|
const Toplevel* EffectWindowImpl::window() const
|
|
{
|
|
return toplevel;
|
|
}
|
|
|
|
inline
|
|
Toplevel* EffectWindowImpl::window()
|
|
{
|
|
return toplevel;
|
|
}
|
|
|
|
|
|
} // namespace
|
|
|
|
#endif
|