1 | /******************************************************************** |
2 | KWin - the KDE window manager |
3 | This file is part of the KDE project. |
4 | |
5 | Copyright (C) 2011 Arthur Arlt <a.arlt@stud.uni-heidelberg.de> |
6 | Copyright (C) 2012 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_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 | |
35 | namespace KWin { |
36 | |
37 | class Client; |
38 | class Scene; |
39 | |
40 | class CompositorSelectionOwner : public KSelectionOwner |
41 | { |
42 | Q_OBJECT |
43 | public: |
44 | CompositorSelectionOwner(const char *selection); |
45 | private: |
46 | friend class Compositor; |
47 | bool owning; |
48 | private slots: |
49 | void looseOwnership(); |
50 | }; |
51 | |
52 | class 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) |
82 | public: |
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 | |
155 | public 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 | |
248 | Q_SIGNALS: |
249 | Q_SCRIPTABLE void compositingToggled(bool active); |
250 | |
251 | protected: |
252 | void timerEvent(QTimerEvent *te); |
253 | |
254 | private 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 | |
273 | private: |
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 | |