1/********************************************************************
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5Copyright (C) 2011 Arthur Arlt <a.arlt@stud.uni-heidelberg.de>
6Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org>
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 2 of the License, or
11(at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with this program. If not, see <http://www.gnu.org/licenses/>.
20*********************************************************************/
21
22#ifndef KWIN_COMPOSITE_H
23#define KWIN_COMPOSITE_H
24// KWin
25#include <kwinglobals.h>
26// KDE
27#include <KDE/KSelectionOwner>
28// Qt
29#include <QObject>
30#include <QElapsedTimer>
31#include <QTimer>
32#include <QBasicTimer>
33#include <QRegion>
34
35namespace KWin {
36
37class Client;
38class Scene;
39
40class CompositorSelectionOwner : public KSelectionOwner
41{
42 Q_OBJECT
43public:
44 CompositorSelectionOwner(const char *selection);
45private:
46 friend class Compositor;
47 bool owning;
48private slots:
49 void looseOwnership();
50};
51
52class Compositor : public QObject {
53 Q_OBJECT
54 Q_CLASSINFO("D-Bus Interface", "org.kde.kwin.Compositing")
55 /**
56 * @brief Whether the Compositor is active. That is a Scene is present and the Compositor is
57 * not shutting down itself.
58 **/
59 Q_PROPERTY(bool active READ isActive)
60 /**
61 * @brief Whether compositing is possible. Mostly means whether the required X extensions
62 * are available.
63 **/
64 Q_PROPERTY(bool compositingPossible READ isCompositingPossible)
65 /**
66 * @brief The reason why compositing is not possible. Empty String if compositing is possible.
67 **/
68 Q_PROPERTY(QString compositingNotPossibleReason READ compositingNotPossibleReason)
69 /**
70 * @brief Whether OpenGL has failed badly in the past (crash) and is considered as broken.
71 **/
72 Q_PROPERTY(bool openGLIsBroken READ isOpenGLBroken)
73 /**
74 * The type of the currently used Scene:
75 * @li @c none No Compositing
76 * @li @c xrender XRender
77 * @li @c gl1 OpenGL 1
78 * @li @c gl2 OpenGL 2
79 * @li @c gles OpenGL ES 2
80 **/
81 Q_PROPERTY(QString compositingType READ compositingType)
82public:
83 enum SuspendReason { NoReasonSuspend = 0, UserSuspend = 1<<0, BlockRuleSuspend = 1<<1, ScriptSuspend = 1<<2, AllReasonSuspend = 0xff };
84 Q_DECLARE_FLAGS(SuspendReasons, SuspendReason)
85 ~Compositor();
86 // when adding repaints caused by a window, you probably want to use
87 // either Toplevel::addRepaint() or Toplevel::addWorkspaceRepaint()
88 void addRepaint(const QRect& r);
89 void addRepaint(const QRegion& r);
90 void addRepaint(int x, int y, int w, int h);
91 /**
92 * Whether the Compositor is active. That is a Scene is present and the Compositor is
93 * not shutting down itself.
94 **/
95 bool isActive();
96 int xrrRefreshRate() const {
97 return m_xrrRefreshRate;
98 }
99 void setCompositeResetTimer(int msecs);
100
101 bool hasScene() const {
102 return m_scene != NULL;
103 }
104
105 /**
106 * Checks whether @p w is the Scene's overlay window.
107 **/
108 bool checkForOverlayWindow(WId w) const;
109 /**
110 * @returns The Scene's Overlay X Window.
111 **/
112 WId overlayWindow() const;
113 /**
114 * @returns Whether the Scene's Overlay X Window is visible.
115 **/
116 bool isOverlayWindowVisible() const;
117 /**
118 * Set's the Scene's Overlay X Window visibility to @p visible.
119 **/
120 void setOverlayWindowVisibility(bool visible);
121
122 Scene *scene() {
123 return m_scene;
124 }
125
126 /**
127 * @brief Checks whether the Compositor has already been created by the Workspace.
128 *
129 * This method can be used to check whether self will return the Compositor instance or @c null.
130 *
131 * @return bool @c true if the Compositor has been created, @c false otherwise
132 **/
133 static bool isCreated() {
134 return s_compositor != NULL;
135 }
136 /**
137 * @brief Static check to test whether the Compositor is available and active.
138 *
139 * @return bool @c true if there is a Compositor and it is active, @c false otherwise
140 **/
141 static bool compositing() {
142 return s_compositor != NULL && s_compositor->isActive();
143 }
144
145 // for delayed supportproperty management of effects
146 void keepSupportProperty(xcb_atom_t atom);
147 void removeSupportProperty(xcb_atom_t atom);
148
149 // D-Bus: getters for Properties, see documentation on the property
150 bool isCompositingPossible() const;
151 QString compositingNotPossibleReason() const;
152 bool isOpenGLBroken() const;
153 QString compositingType() const;
154
155public Q_SLOTS:
156 void addRepaintFull();
157 /**
158 * Called from the D-Bus interface. Does the same as slotToggleCompositing with the
159 * addition to show a notification on how to revert the compositing state.
160 * @see resume
161 * @see suspend
162 * @deprecated Use suspend or resume instead
163 **/
164 Q_SCRIPTABLE void toggleCompositing();
165 /**
166 * @brief Suspends the Compositor if it is currently active.
167 *
168 * Note: it is possible that the Compositor is not able to suspend. Use @link isActive to check
169 * whether the Compositor has been suspended.
170 *
171 * @return void
172 * @see resume
173 * @see isActive
174 **/
175 Q_SCRIPTABLE inline void suspend() { suspend(ScriptSuspend); }
176 void suspend(Compositor::SuspendReason reason);
177 /**
178 * @brief Resumes the Compositor if it is currently suspended.
179 *
180 * Note: it is possible that the Compositor cannot be resumed, that is there might be Clients
181 * blocking the usage of Compositing or the Scene might be broken. Use @link isActive to check
182 * whether the Compositor has been resumed. Also check @link isCompositingPossible and
183 * @link isOpenGLBroken.
184 *
185 * Note: The starting of the Compositor can require some time and is partially done threaded.
186 * After this method returns the setup may not have been completed.
187 *
188 * @return void
189 * @see suspend
190 * @see isActive
191 * @see isCompositingPossible
192 * @see isOpenGLBroken
193 **/
194 Q_SCRIPTABLE inline void resume() { resume(ScriptSuspend); }
195 void resume(Compositor::SuspendReason reason);
196 /**
197 * @brief Tries to suspend or resume the Compositor based on @p active.
198 *
199 * In case the Compositor is already in the asked for state this method is doing nothing. In
200 * case it does not match it is tried to either resume or suspend the Compositor.
201 *
202 * Note: these operations may fail. There is no guarantee that after calling this method to
203 * enable/disable the Compositor, it actually changes to the state. Use @link isActive to check
204 * the actual state of the Compositor.
205 *
206 * Note: The starting of the Compositor can require some time and is partially done threaded.
207 * After this method returns the setup may not have been completed.
208 *
209 * Note: This function only impacts whether compositing is suspended or resumed by scripts
210 * or dbus calls. Compositing may be suspended for user will or a window rule - no matter how
211 * often you call this function!
212 *
213 * @param active Whether the Compositor should be resumed (@c true) or suspended (@c false)
214 * @return void
215 * @see suspend
216 * @see resume
217 * @see isActive
218 * @see isCompositingPossible
219 * @see isOpenGLBroken
220 **/
221 // NOTICE this is atm. for script usage *ONLY* and needs to be extended like resume / suspend are
222 // if intended to be used from within KWin code!
223 Q_SCRIPTABLE void setCompositing(bool active);
224 /**
225 * Actual slot to perform the toggling compositing.
226 * That is if the Compositor is suspended it will be resumed and if the Compositor is active
227 * it will be suspended.
228 * Invoked primarily by the keybinding.
229 * TODO: make private slot
230 **/
231 void slotToggleCompositing();
232 /**
233 * Re-initializes the Compositor completely.
234 * Connected to the D-Bus signal org.kde.KWin /KWin reinitCompositing
235 **/
236 void slotReinitialize();
237 /**
238 * Schedules a new repaint if no repaint is currently scheduled.
239 **/
240 void scheduleRepaint();
241 void checkUnredirect();
242 void checkUnredirect(bool force);
243 void updateCompositeBlocking();
244 void updateCompositeBlocking(KWin::Client* c);
245
246 // For the D-Bus interface
247
248Q_SIGNALS:
249 Q_SCRIPTABLE void compositingToggled(bool active);
250
251protected:
252 void timerEvent(QTimerEvent *te);
253
254private Q_SLOTS:
255 void setup();
256 /**
257 * Called from setupCompositing() when the CompositingPrefs are ready.
258 **/
259 void slotCompositingOptionsInitialized();
260 void finish();
261 /**
262 * Restarts the Compositor if running.
263 * That is the Compositor will be stopped and started again.
264 **/
265 void restart();
266 void fallbackToXRenderCompositing();
267 void performCompositing();
268 void delayedCheckUnredirect();
269 void slotConfigChanged();
270 void releaseCompositorSelection();
271 void deleteUnusedSupportProperties();
272
273private:
274 void setCompositeTimer();
275 bool windowRepaintsPending() const;
276
277 /**
278 * Restarts the Window Manager in case that the Qt's GraphicsSystem need to be changed
279 * for the chosen Compositing backend.
280 * @param reason The reason why the Window Manager is being restarted, this is logged
281 **/
282 void restartKWin(const QString &reason);
283
284 /**
285 * Whether the Compositor is currently suspended, 8 bits encoding the reason
286 **/
287 SuspendReasons m_suspended;
288
289 QBasicTimer compositeTimer;
290 CompositorSelectionOwner* cm_selection;
291 QTimer m_releaseSelectionTimer;
292 QList<xcb_atom_t> m_unusedSupportProperties;
293 QTimer m_unusedSupportPropertyTimer;
294 qint64 vBlankInterval, fpsInterval;
295 int m_xrrRefreshRate;
296 QElapsedTimer nextPaintReference;
297 QRegion repaints_region;
298
299 QTimer unredirectTimer;
300 bool forceUnredirectCheck;
301 QTimer compositeResetTimer; // for compressing composite resets
302 bool m_finishing; // finish() sets this variable while shutting down
303 bool m_starting; // start() sets this variable while starting
304 qint64 m_timeSinceLastVBlank;
305 Scene *m_scene;
306
307 KWIN_SINGLETON_VARIABLE(Compositor, s_compositor)
308};
309}
310
311# endif // KWIN_COMPOSITE_H
312