1 | /******************************************************************** |
2 | KWin - the KDE window manager |
3 | This file is part of the KDE project. |
4 | |
5 | Copyright (C) 2006 Lubos Lunak <l.lunak@kde.org> |
6 | Copyright (C) 2010, 2011 Martin Gräßlin <mgraesslin@kde.org> |
7 | |
8 | This program is free software; you can redistribute it and/or modify |
9 | it under the terms of the GNU General Public License as published by |
10 | the Free Software Foundation; either version 2 of the License, or |
11 | (at your option) any later version. |
12 | |
13 | This program is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | GNU General Public License for more details. |
17 | |
18 | You should have received a copy of the GNU General Public License |
19 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
20 | *********************************************************************/ |
21 | |
22 | #ifndef KWIN_EFFECTSIMPL_H |
23 | #define KWIN_EFFECTSIMPL_H |
24 | |
25 | #include "kwineffects.h" |
26 | |
27 | #include "scene.h" |
28 | #include "xcbutils.h" |
29 | |
30 | #include <QStack> |
31 | #include <QHash> |
32 | #include <Plasma/FrameSvg> |
33 | |
34 | class QDBusPendingCallWatcher; |
35 | class QDBusServiceWatcher; |
36 | class KService; |
37 | class OrgFreedesktopScreenSaverInterface; |
38 | |
39 | |
40 | namespace KWin |
41 | { |
42 | |
43 | class AbstractThumbnailItem; |
44 | class DesktopThumbnailItem; |
45 | class WindowThumbnailItem; |
46 | |
47 | class Client; |
48 | class Compositor; |
49 | class Deleted; |
50 | class Unmanaged; |
51 | class ScreenLockerWatcher; |
52 | |
53 | class EffectsHandlerImpl : public EffectsHandler |
54 | { |
55 | Q_OBJECT |
56 | Q_CLASSINFO("D-Bus Interface" , "org.kde.kwin.Effects" ) |
57 | Q_PROPERTY(QStringList activeEffects READ activeEffects) |
58 | Q_PROPERTY(QStringList loadedEffects READ loadedEffects) |
59 | Q_PROPERTY(QStringList listOfEffects READ listOfEffects) |
60 | public: |
61 | EffectsHandlerImpl(Compositor *compositor, Scene *scene); |
62 | virtual ~EffectsHandlerImpl(); |
63 | virtual void prePaintScreen(ScreenPrePaintData& data, int time); |
64 | virtual void paintScreen(int mask, QRegion region, ScreenPaintData& data); |
65 | /** |
66 | * Special hook to perform a paintScreen but just with the windows on @p desktop. |
67 | **/ |
68 | void paintDesktop(int desktop, int mask, QRegion region, ScreenPaintData& data); |
69 | virtual void postPaintScreen(); |
70 | virtual void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time); |
71 | virtual void paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data); |
72 | virtual void postPaintWindow(EffectWindow* w); |
73 | virtual void paintEffectFrame(EffectFrame* frame, QRegion region, double opacity, double frameOpacity); |
74 | |
75 | Effect *provides(Effect::Feature ef); |
76 | |
77 | virtual void drawWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data); |
78 | |
79 | virtual void buildQuads(EffectWindow* w, WindowQuadList& quadList); |
80 | |
81 | virtual void activateWindow(EffectWindow* c); |
82 | virtual EffectWindow* activeWindow() const; |
83 | virtual void moveWindow(EffectWindow* w, const QPoint& pos, bool snap = false, double snapAdjust = 1.0); |
84 | virtual void windowToDesktop(EffectWindow* w, int desktop); |
85 | virtual void windowToScreen(EffectWindow* w, int screen); |
86 | virtual void setShowingDesktop(bool showing); |
87 | |
88 | virtual QString currentActivity() const; |
89 | virtual int currentDesktop() const; |
90 | virtual int numberOfDesktops() const; |
91 | virtual void setCurrentDesktop(int desktop); |
92 | virtual void setNumberOfDesktops(int desktops); |
93 | virtual QSize desktopGridSize() const; |
94 | virtual int desktopGridWidth() const; |
95 | virtual int desktopGridHeight() const; |
96 | virtual int workspaceWidth() const; |
97 | virtual int workspaceHeight() const; |
98 | virtual int desktopAtCoords(QPoint coords) const; |
99 | virtual QPoint desktopGridCoords(int id) const; |
100 | virtual QPoint desktopCoords(int id) const; |
101 | virtual int desktopAbove(int desktop = 0, bool wrap = true) const; |
102 | virtual int desktopToRight(int desktop = 0, bool wrap = true) const; |
103 | virtual int desktopBelow(int desktop = 0, bool wrap = true) const; |
104 | virtual int desktopToLeft(int desktop = 0, bool wrap = true) const; |
105 | virtual QString desktopName(int desktop) const; |
106 | virtual bool optionRollOverDesktops() const; |
107 | |
108 | virtual int displayWidth() const; |
109 | virtual int displayHeight() const; |
110 | virtual QPoint cursorPos() const; |
111 | virtual bool grabKeyboard(Effect* effect); |
112 | virtual void ungrabKeyboard(); |
113 | // not performing XGrabPointer |
114 | virtual void startMouseInterception(Effect *effect, Qt::CursorShape shape); |
115 | virtual void stopMouseInterception(Effect *effect); |
116 | virtual void* getProxy(QString name); |
117 | virtual void startMousePolling(); |
118 | virtual void stopMousePolling(); |
119 | virtual EffectWindow* findWindow(WId id) const; |
120 | virtual EffectWindowList stackingOrder() const; |
121 | virtual void setElevatedWindow(EffectWindow* w, bool set); |
122 | |
123 | virtual void setTabBoxWindow(EffectWindow*); |
124 | virtual void setTabBoxDesktop(int); |
125 | virtual EffectWindowList currentTabBoxWindowList() const; |
126 | virtual void refTabBox(); |
127 | virtual void unrefTabBox(); |
128 | virtual void closeTabBox(); |
129 | virtual QList< int > currentTabBoxDesktopList() const; |
130 | virtual int currentTabBoxDesktop() const; |
131 | virtual EffectWindow* currentTabBoxWindow() const; |
132 | |
133 | virtual void setActiveFullScreenEffect(Effect* e); |
134 | virtual Effect* activeFullScreenEffect() const; |
135 | |
136 | virtual void addRepaintFull(); |
137 | virtual void addRepaint(const QRect& r); |
138 | virtual void addRepaint(const QRegion& r); |
139 | virtual void addRepaint(int x, int y, int w, int h); |
140 | virtual int activeScreen() const; |
141 | virtual int numScreens() const; |
142 | virtual int screenNumber(const QPoint& pos) const; |
143 | virtual QRect clientArea(clientAreaOption, int screen, int desktop) const; |
144 | virtual QRect clientArea(clientAreaOption, const EffectWindow* c) const; |
145 | virtual QRect clientArea(clientAreaOption, const QPoint& p, int desktop) const; |
146 | virtual double animationTimeFactor() const; |
147 | virtual WindowQuadType newWindowQuadType(); |
148 | |
149 | virtual void defineCursor(Qt::CursorShape shape); |
150 | virtual bool checkInputWindowEvent(XEvent* e); |
151 | virtual void checkInputWindowStacking(); |
152 | |
153 | virtual void reserveElectricBorder(ElectricBorder border, Effect *effect); |
154 | virtual void unreserveElectricBorder(ElectricBorder border, Effect *effect); |
155 | |
156 | virtual unsigned long xrenderBufferPicture(); |
157 | virtual void reconfigure(); |
158 | virtual void registerPropertyType(long atom, bool reg); |
159 | virtual QByteArray readRootProperty(long atom, long type, int format) const; |
160 | virtual void deleteRootProperty(long atom) const; |
161 | virtual xcb_atom_t announceSupportProperty(const QByteArray& propertyName, Effect* effect); |
162 | virtual void removeSupportProperty(const QByteArray& propertyName, Effect* effect); |
163 | |
164 | virtual bool hasDecorationShadows() const; |
165 | |
166 | virtual bool decorationsHaveAlpha() const; |
167 | |
168 | virtual bool decorationSupportsBlurBehind() const; |
169 | |
170 | virtual EffectFrame* effectFrame(EffectFrameStyle style, bool staticSize, const QPoint& position, Qt::Alignment alignment) const; |
171 | |
172 | virtual QVariant kwinOption(KWinOption kwopt); |
173 | virtual bool isScreenLocked() const; |
174 | |
175 | // internal (used by kwin core or compositing code) |
176 | void startPaint(); |
177 | void grabbedKeyboardEvent(QKeyEvent* e); |
178 | bool hasKeyboardGrab() const; |
179 | void desktopResized(const QSize &size); |
180 | |
181 | virtual void reloadEffect(Effect *effect); |
182 | QStringList loadedEffects() const; |
183 | QStringList listOfEffects() const; |
184 | |
185 | QList<EffectWindow*> elevatedWindows() const; |
186 | QStringList activeEffects() const; |
187 | |
188 | /** |
189 | * @returns Whether we are currently in a desktop rendering process triggered by paintDesktop hook |
190 | **/ |
191 | bool isDesktopRendering() const { |
192 | return m_desktopRendering; |
193 | } |
194 | /** |
195 | * @returns the desktop currently being rendered in the paintDesktop hook. |
196 | **/ |
197 | int currentRenderedDesktop() const { |
198 | return m_currentRenderedDesktop; |
199 | } |
200 | |
201 | public Q_SLOTS: |
202 | void slotCurrentTabAboutToChange(EffectWindow* from, EffectWindow* to); |
203 | void slotTabAdded(EffectWindow* from, EffectWindow* to); |
204 | void slotTabRemoved(EffectWindow* c, EffectWindow* newActiveWindow); |
205 | |
206 | // slots for D-Bus interface |
207 | Q_SCRIPTABLE void reconfigureEffect(const QString& name); |
208 | Q_SCRIPTABLE bool loadEffect(const QString& name, bool checkDefault = false); |
209 | Q_SCRIPTABLE void toggleEffect(const QString& name); |
210 | Q_SCRIPTABLE void unloadEffect(const QString& name); |
211 | Q_SCRIPTABLE bool isEffectLoaded(const QString& name) const; |
212 | Q_SCRIPTABLE QString supportInformation(const QString& name) const; |
213 | Q_SCRIPTABLE QString debug(const QString& name, const QString& parameter = QString()) const; |
214 | |
215 | protected Q_SLOTS: |
216 | void slotDesktopChanged(int old, KWin::Client *withClient); |
217 | void slotDesktopPresenceChanged(KWin::Client *c, int old); |
218 | void slotClientAdded(KWin::Client *c); |
219 | void slotClientShown(KWin::Toplevel*); |
220 | void slotUnmanagedAdded(KWin::Unmanaged *u); |
221 | void slotUnmanagedShown(KWin::Toplevel*); |
222 | void slotWindowClosed(KWin::Toplevel *c); |
223 | void slotClientActivated(KWin::Client *c); |
224 | void slotDeletedRemoved(KWin::Deleted *d); |
225 | void slotClientMaximized(KWin::Client *c, KDecorationDefines::MaximizeMode maxMode); |
226 | void slotClientStartUserMovedResized(KWin::Client *c); |
227 | void slotClientStepUserMovedResized(KWin::Client *c, const QRect &geometry); |
228 | void slotClientFinishUserMovedResized(KWin::Client *c); |
229 | void slotOpacityChanged(KWin::Toplevel *t, qreal oldOpacity); |
230 | void slotClientMinimized(KWin::Client *c, bool animate); |
231 | void slotClientUnminimized(KWin::Client *c, bool animate); |
232 | void slotClientModalityChanged(); |
233 | void slotGeometryShapeChanged(KWin::Toplevel *t, const QRect &old); |
234 | void slotPaddingChanged(KWin::Toplevel *t, const QRect &old); |
235 | void slotWindowDamaged(KWin::Toplevel *t, const QRect& r); |
236 | void slotPropertyNotify(KWin::Toplevel *t, long atom); |
237 | void slotPropertyNotify(long atom); |
238 | |
239 | protected: |
240 | bool loadScriptedEffect(const QString &name, KService *service); |
241 | KLibrary* findEffectLibrary(KService* service); |
242 | void effectsChanged(); |
243 | void setupClientConnections(KWin::Client *c); |
244 | void setupUnmanagedConnections(KWin::Unmanaged *u); |
245 | |
246 | Effect* keyboard_grab_effect; |
247 | Effect* fullscreen_effect; |
248 | QList<EffectWindow*> elevated_windows; |
249 | QMultiMap< int, EffectPair > effect_order; |
250 | QHash< long, int > registered_atoms; |
251 | int next_window_quad_type; |
252 | |
253 | private Q_SLOTS: |
254 | void slotEffectsQueried(); |
255 | |
256 | private: |
257 | typedef QVector< Effect*> EffectsList; |
258 | typedef EffectsList::const_iterator EffectsIterator; |
259 | EffectsList m_activeEffects; |
260 | EffectsIterator m_currentDrawWindowIterator; |
261 | EffectsIterator m_currentPaintWindowIterator; |
262 | EffectsIterator m_currentPaintEffectFrameIterator; |
263 | EffectsIterator m_currentPaintScreenIterator; |
264 | EffectsIterator m_currentBuildQuadsIterator; |
265 | typedef QHash< QByteArray, QList< Effect*> > PropertyEffectMap; |
266 | PropertyEffectMap m_propertiesForEffects; |
267 | QHash<QByteArray, qulonglong> m_managedProperties; |
268 | Compositor *m_compositor; |
269 | Scene *m_scene; |
270 | ScreenLockerWatcher *m_screenLockerWatcher; |
271 | bool m_desktopRendering; |
272 | int m_currentRenderedDesktop; |
273 | Xcb::Window m_mouseInterceptionWindow; |
274 | QList<Effect*> m_grabbedMouseEffects; |
275 | }; |
276 | |
277 | class EffectWindowImpl : public EffectWindow |
278 | { |
279 | Q_OBJECT |
280 | public: |
281 | explicit EffectWindowImpl(Toplevel *toplevel); |
282 | virtual ~EffectWindowImpl(); |
283 | |
284 | virtual void enablePainting(int reason); |
285 | virtual void disablePainting(int reason); |
286 | virtual bool isPaintingEnabled(); |
287 | |
288 | virtual void refWindow(); |
289 | virtual void unrefWindow(); |
290 | |
291 | virtual const EffectWindowGroup* group() const; |
292 | |
293 | virtual QRegion shape() const; |
294 | virtual QRect decorationInnerRect() const; |
295 | virtual QByteArray readProperty(long atom, long type, int format) const; |
296 | virtual void deleteProperty(long atom) const; |
297 | |
298 | virtual EffectWindow* findModal(); |
299 | virtual EffectWindowList mainWindows() const; |
300 | |
301 | virtual WindowQuadList buildQuads(bool force = false) const; |
302 | |
303 | virtual void referencePreviousWindowPixmap(); |
304 | virtual void unreferencePreviousWindowPixmap(); |
305 | |
306 | const Toplevel* window() const; |
307 | Toplevel* window(); |
308 | |
309 | void setWindow(Toplevel* w); // internal |
310 | void setSceneWindow(Scene::Window* w); // internal |
311 | const Scene::Window* sceneWindow() const; // internal |
312 | Scene::Window* sceneWindow(); // internal |
313 | |
314 | void elevate(bool elevate); |
315 | |
316 | void setData(int role, const QVariant &data); |
317 | QVariant data(int role) const; |
318 | |
319 | void registerThumbnail(AbstractThumbnailItem *item); |
320 | QHash<WindowThumbnailItem*, QWeakPointer<EffectWindowImpl> > const &thumbnails() const { |
321 | return m_thumbnails; |
322 | } |
323 | QList<DesktopThumbnailItem*> const &desktopThumbnails() const { |
324 | return m_desktopThumbnails; |
325 | } |
326 | private Q_SLOTS: |
327 | void thumbnailDestroyed(QObject *object); |
328 | void thumbnailTargetChanged(); |
329 | void desktopThumbnailDestroyed(QObject *object); |
330 | private: |
331 | void insertThumbnail(WindowThumbnailItem *item); |
332 | Toplevel* toplevel; |
333 | Scene::Window* sw; // This one is used only during paint pass. |
334 | QHash<int, QVariant> dataMap; |
335 | QHash<WindowThumbnailItem*, QWeakPointer<EffectWindowImpl> > m_thumbnails; |
336 | QList<DesktopThumbnailItem*> m_desktopThumbnails; |
337 | }; |
338 | |
339 | class EffectWindowGroupImpl |
340 | : public EffectWindowGroup |
341 | { |
342 | public: |
343 | explicit EffectWindowGroupImpl(Group* g); |
344 | virtual EffectWindowList members() const; |
345 | private: |
346 | Group* group; |
347 | }; |
348 | |
349 | class EffectFrameImpl |
350 | : public QObject, public EffectFrame |
351 | { |
352 | Q_OBJECT |
353 | public: |
354 | explicit EffectFrameImpl(EffectFrameStyle style, bool staticSize = true, QPoint position = QPoint(-1, -1), |
355 | Qt::Alignment alignment = Qt::AlignCenter); |
356 | virtual ~EffectFrameImpl(); |
357 | |
358 | virtual void free(); |
359 | virtual void render(QRegion region = infiniteRegion(), double opacity = 1.0, double frameOpacity = 1.0); |
360 | virtual Qt::Alignment alignment() const; |
361 | virtual void setAlignment(Qt::Alignment alignment); |
362 | virtual const QFont& font() const; |
363 | virtual void setFont(const QFont& font); |
364 | virtual const QRect& geometry() const; |
365 | virtual void setGeometry(const QRect& geometry, bool force = false); |
366 | virtual const QPixmap& icon() const; |
367 | virtual void setIcon(const QPixmap& icon); |
368 | virtual const QSize& iconSize() const; |
369 | virtual void setIconSize(const QSize& size); |
370 | virtual void setPosition(const QPoint& point); |
371 | virtual const QString& text() const; |
372 | virtual void setText(const QString& text); |
373 | virtual EffectFrameStyle style() const { |
374 | return m_style; |
375 | }; |
376 | Plasma::FrameSvg& frame() { |
377 | return m_frame; |
378 | } |
379 | bool isStatic() const { |
380 | return m_static; |
381 | }; |
382 | void finalRender(QRegion region, double opacity, double frameOpacity) const; |
383 | virtual void setShader(GLShader* shader) { |
384 | m_shader = shader; |
385 | } |
386 | virtual GLShader* shader() const { |
387 | return m_shader; |
388 | } |
389 | virtual void setSelection(const QRect& selection); |
390 | const QRect& selection() const { |
391 | return m_selectionGeometry; |
392 | } |
393 | Plasma::FrameSvg& selectionFrame() { |
394 | return m_selection; |
395 | } |
396 | /** |
397 | * The foreground text color as specified by the default Plasma theme. |
398 | */ |
399 | static QColor styledTextColor(); |
400 | |
401 | private Q_SLOTS: |
402 | void plasmaThemeChanged(); |
403 | |
404 | private: |
405 | Q_DISABLE_COPY(EffectFrameImpl) // As we need to use Qt slots we cannot copy this class |
406 | void align(QRect &geometry); // positions geometry around m_point respecting m_alignment |
407 | void autoResize(); // Auto-resize if not a static size |
408 | |
409 | EffectFrameStyle m_style; |
410 | Plasma::FrameSvg m_frame; // TODO: share between all EffectFrames |
411 | Plasma::FrameSvg m_selection; |
412 | |
413 | // Position |
414 | bool m_static; |
415 | QPoint m_point; |
416 | Qt::Alignment m_alignment; |
417 | QRect m_geometry; |
418 | |
419 | // Contents |
420 | QString m_text; |
421 | QFont m_font; |
422 | QPixmap m_icon; |
423 | QSize m_iconSize; |
424 | QRect m_selectionGeometry; |
425 | |
426 | Scene::EffectFrame* m_sceneFrame; |
427 | GLShader* m_shader; |
428 | }; |
429 | |
430 | class ScreenLockerWatcher : public QObject |
431 | { |
432 | Q_OBJECT |
433 | public: |
434 | explicit ScreenLockerWatcher(QObject *parent = 0); |
435 | virtual ~ScreenLockerWatcher(); |
436 | bool isLocked() const { |
437 | return m_locked; |
438 | } |
439 | Q_SIGNALS: |
440 | void locked(bool locked); |
441 | private Q_SLOTS: |
442 | void setLocked(bool activated); |
443 | void activeQueried(QDBusPendingCallWatcher *watcher); |
444 | void serviceOwnerChanged(const QString &serviceName, const QString &oldOwner, const QString &newOwner); |
445 | void serviceRegisteredQueried(); |
446 | void serviceOwnerQueried(); |
447 | private: |
448 | OrgFreedesktopScreenSaverInterface *m_interface; |
449 | QDBusServiceWatcher *m_serviceWatcher; |
450 | bool m_locked; |
451 | }; |
452 | |
453 | inline |
454 | QList<EffectWindow*> EffectsHandlerImpl::elevatedWindows() const |
455 | { |
456 | return elevated_windows; |
457 | } |
458 | |
459 | |
460 | inline |
461 | EffectWindowGroupImpl::EffectWindowGroupImpl(Group* g) |
462 | : group(g) |
463 | { |
464 | } |
465 | |
466 | EffectWindow* effectWindow(Toplevel* w); |
467 | EffectWindow* effectWindow(Scene::Window* w); |
468 | |
469 | inline |
470 | const Scene::Window* EffectWindowImpl::sceneWindow() const |
471 | { |
472 | return sw; |
473 | } |
474 | |
475 | inline |
476 | Scene::Window* EffectWindowImpl::sceneWindow() |
477 | { |
478 | return sw; |
479 | } |
480 | |
481 | inline |
482 | const Toplevel* EffectWindowImpl::window() const |
483 | { |
484 | return toplevel; |
485 | } |
486 | |
487 | inline |
488 | Toplevel* EffectWindowImpl::window() |
489 | { |
490 | return toplevel; |
491 | } |
492 | |
493 | |
494 | } // namespace |
495 | |
496 | #endif |
497 | |