1 | /******************************************************************** |
2 | KWin - the KDE window manager |
3 | This file is part of the KDE project. |
4 | |
5 | Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org> |
6 | Copyright (C) 2003 Lubos Lunak <l.lunak@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_UTILS_H |
23 | #define KWIN_UTILS_H |
24 | |
25 | // cmake stuff |
26 | #include <config-X11.h> |
27 | #include <config-kwin.h> |
28 | #include <kwinconfig.h> |
29 | // kwin |
30 | #include <kwinglobals.h> |
31 | // KDE |
32 | #include <KDE/NET> |
33 | // Qt |
34 | #include <QList> |
35 | #include <QPoint> |
36 | #include <QRect> |
37 | #include <QScopedPointer> |
38 | // X |
39 | #include <X11/Xlib.h> |
40 | #include <fixx11h.h> |
41 | // system |
42 | #include <limits.h> |
43 | |
44 | namespace KWin |
45 | { |
46 | |
47 | // window types that are supported as normal windows (i.e. KWin actually manages them) |
48 | const int SUPPORTED_MANAGED_WINDOW_TYPES_MASK = NET::NormalMask | NET::DesktopMask | NET::DockMask |
49 | | NET::ToolbarMask | NET::MenuMask | NET::DialogMask /*| NET::OverrideMask*/ | NET::TopMenuMask |
50 | | NET::UtilityMask | NET::SplashMask; |
51 | // window types that are supported as unmanaged (mainly for compositing) |
52 | const int SUPPORTED_UNMANAGED_WINDOW_TYPES_MASK = NET::NormalMask | NET::DesktopMask | NET::DockMask |
53 | | NET::ToolbarMask | NET::MenuMask | NET::DialogMask /*| NET::OverrideMask*/ | NET::TopMenuMask |
54 | | NET::UtilityMask | NET::SplashMask | NET::DropdownMenuMask | NET::PopupMenuMask |
55 | | NET::TooltipMask | NET::NotificationMask | NET::ComboBoxMask | NET::DNDIconMask; |
56 | |
57 | const long ClientWinMask = XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | |
58 | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | |
59 | XCB_EVENT_MASK_KEYMAP_STATE | |
60 | XCB_EVENT_MASK_BUTTON_MOTION | |
61 | XCB_EVENT_MASK_POINTER_MOTION | // need this, too! |
62 | XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | |
63 | XCB_EVENT_MASK_FOCUS_CHANGE | |
64 | XCB_EVENT_MASK_EXPOSURE | |
65 | XCB_EVENT_MASK_STRUCTURE_NOTIFY | |
66 | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT; |
67 | |
68 | const QPoint invalidPoint(INT_MIN, INT_MIN); |
69 | |
70 | class Toplevel; |
71 | class Client; |
72 | class Unmanaged; |
73 | class Deleted; |
74 | class Group; |
75 | class Options; |
76 | |
77 | typedef QList< Toplevel* > ToplevelList; |
78 | typedef QList< Client* > ClientList; |
79 | typedef QList< const Client* > ConstClientList; |
80 | typedef QList< Unmanaged* > UnmanagedList; |
81 | typedef QList< Deleted* > DeletedList; |
82 | |
83 | typedef QList< Group* > GroupList; |
84 | |
85 | extern Options* options; |
86 | |
87 | enum Layer { |
88 | UnknownLayer = -1, |
89 | FirstLayer = 0, |
90 | DesktopLayer = FirstLayer, |
91 | BelowLayer, |
92 | NormalLayer, |
93 | DockLayer, |
94 | AboveLayer, |
95 | ActiveLayer, // active fullscreen, or active dialog |
96 | UnmanagedLayer, // layer for override redirect windows. |
97 | NumLayers // number of layers, must be last |
98 | }; |
99 | |
100 | // yes, I know this is not 100% like standard operator++ |
101 | inline void operator++(Layer& lay) |
102 | { |
103 | lay = static_cast< Layer >(lay + 1); |
104 | } |
105 | |
106 | // for Client::takeActivity() |
107 | enum ActivityFlags { |
108 | ActivityFocus = 1 << 0, // focus the window |
109 | ActivityFocusForce = 1 << 1, // focus even if Dock etc. |
110 | ActivityRaise = 1 << 2 // raise the window |
111 | }; |
112 | |
113 | enum StrutArea { |
114 | StrutAreaInvalid = 0, // Null |
115 | StrutAreaTop = 1 << 0, |
116 | StrutAreaRight = 1 << 1, |
117 | StrutAreaBottom = 1 << 2, |
118 | StrutAreaLeft = 1 << 3, |
119 | StrutAreaAll = StrutAreaTop | StrutAreaRight | StrutAreaBottom | StrutAreaLeft |
120 | }; |
121 | Q_DECLARE_FLAGS(StrutAreas, StrutArea) |
122 | |
123 | class StrutRect : public QRect |
124 | { |
125 | public: |
126 | explicit StrutRect(QRect rect = QRect(), StrutArea area = StrutAreaInvalid); |
127 | StrutRect(const StrutRect& other); |
128 | inline StrutArea area() const { |
129 | return m_area; |
130 | }; |
131 | private: |
132 | StrutArea m_area; |
133 | }; |
134 | typedef QVector<StrutRect> StrutRects; |
135 | |
136 | // some enums to have more readable code, instead of using bools |
137 | enum ForceGeometry_t { NormalGeometrySet, ForceGeometrySet }; |
138 | |
139 | |
140 | |
141 | enum ShadeMode { |
142 | ShadeNone, // not shaded |
143 | ShadeNormal, // normally shaded - isShade() is true only here |
144 | ShadeHover, // "shaded", but visible due to hover unshade |
145 | ShadeActivated // "shaded", but visible due to alt+tab to the window |
146 | }; |
147 | |
148 | // Whether to keep all windows mapped when compositing (i.e. whether to have |
149 | // actively updated window pixmaps). |
150 | enum HiddenPreviews { |
151 | // The normal mode with regard to mapped windows. Hidden (minimized, etc.) |
152 | // and windows on inactive virtual desktops are not mapped, their pixmaps |
153 | // are only their icons. |
154 | HiddenPreviewsNever, |
155 | // Like normal mode, but shown windows (i.e. on inactive virtual desktops) |
156 | // are kept mapped, only hidden windows are unmapped. |
157 | HiddenPreviewsShown, |
158 | // All windows are kept mapped regardless of their state. |
159 | HiddenPreviewsAlways |
160 | }; |
161 | |
162 | class Motif |
163 | { |
164 | public: |
165 | // Read a window's current settings from its _MOTIF_WM_HINTS |
166 | // property. If it explicitly requests that decorations be shown |
167 | // or hidden, 'got_noborder' is set to true and 'noborder' is set |
168 | // appropriately. |
169 | static void readFlags(xcb_window_t w, bool& got_noborder, bool& noborder, |
170 | bool& resize, bool& move, bool& minimize, bool& maximize, |
171 | bool& close); |
172 | struct MwmHints { |
173 | ulong flags; |
174 | ulong functions; |
175 | ulong decorations; |
176 | long input_mode; |
177 | ulong status; |
178 | }; |
179 | enum { |
180 | MWM_HINTS_FUNCTIONS = (1L << 0), |
181 | MWM_HINTS_DECORATIONS = (1L << 1), |
182 | |
183 | MWM_FUNC_ALL = (1L << 0), |
184 | MWM_FUNC_RESIZE = (1L << 1), |
185 | MWM_FUNC_MOVE = (1L << 2), |
186 | MWM_FUNC_MINIMIZE = (1L << 3), |
187 | MWM_FUNC_MAXIMIZE = (1L << 4), |
188 | MWM_FUNC_CLOSE = (1L << 5) |
189 | }; |
190 | }; |
191 | |
192 | // Class which saves original value of the variable, assigns the new value |
193 | // to it, and in the destructor restores the value. |
194 | // Used in Client::isMaximizable() and so on. |
195 | // It also casts away contness and generally this looks like a hack. |
196 | template< typename T > |
197 | class TemporaryAssign |
198 | { |
199 | public: |
200 | TemporaryAssign(const T& var, const T& value) |
201 | : variable(var), orig(var) { |
202 | const_cast< T& >(variable) = value; |
203 | } |
204 | ~TemporaryAssign() { |
205 | const_cast< T& >(variable) = orig; |
206 | } |
207 | private: |
208 | const T& variable; |
209 | T orig; |
210 | }; |
211 | |
212 | template <typename T> |
213 | class ScopedCPointer : public QScopedPointer<T, QScopedPointerPodDeleter> |
214 | { |
215 | public: |
216 | ScopedCPointer(T *p = 0) : QScopedPointer<T, QScopedPointerPodDeleter>(p) {} |
217 | }; |
218 | |
219 | QByteArray getStringProperty(xcb_window_t w, xcb_atom_t prop, char separator = 0); |
220 | void updateXTime(); |
221 | void grabXServer(); |
222 | void ungrabXServer(); |
223 | bool grabbedXServer(); |
224 | bool grabXKeyboard(xcb_window_t w = rootWindow()); |
225 | void ungrabXKeyboard(); |
226 | |
227 | /** |
228 | * Small helper class which performs @link grabXServer in the ctor and |
229 | * @link ungrabXServer in the dtor. Use this class to ensure that grab and |
230 | * ungrab are matched. |
231 | **/ |
232 | class XServerGrabber |
233 | { |
234 | public: |
235 | XServerGrabber() { |
236 | grabXServer(); |
237 | } |
238 | ~XServerGrabber() { |
239 | ungrabXServer(); |
240 | } |
241 | }; |
242 | |
243 | // the docs say it's UrgencyHint, but it's often #defined as XUrgencyHint |
244 | #ifndef UrgencyHint |
245 | #define UrgencyHint XUrgencyHint |
246 | #endif |
247 | |
248 | // for STL-like algo's |
249 | #define KWIN_CHECK_PREDICATE( name, cls, check ) \ |
250 | struct name \ |
251 | { \ |
252 | inline bool operator()( const cls* cl ) { return check; } \ |
253 | } |
254 | |
255 | #define KWIN_COMPARE_PREDICATE( name, cls, type, check ) \ |
256 | struct name \ |
257 | { \ |
258 | typedef type type_helper; /* in order to work also with type being 'const Client*' etc. */ \ |
259 | inline name( const type_helper& compare_value ) : value( compare_value ) {} \ |
260 | inline bool operator()( const cls* cl ) { return check; } \ |
261 | const type_helper& value; \ |
262 | } |
263 | |
264 | #define KWIN_PROCEDURE( name, cls, action ) \ |
265 | struct name \ |
266 | { \ |
267 | inline void operator()( cls* cl ) { action; } \ |
268 | } |
269 | |
270 | KWIN_CHECK_PREDICATE(TruePredicate, Client, cl == cl /*true, avoid warning about 'cl' */); |
271 | |
272 | template< typename T > |
273 | Client* findClientInList(const ClientList& list, T predicate) |
274 | { |
275 | for (ClientList::ConstIterator it = list.begin(); it != list.end(); ++it) { |
276 | if (predicate(const_cast< const Client* >(*it))) |
277 | return *it; |
278 | } |
279 | return NULL; |
280 | } |
281 | |
282 | template< typename T > |
283 | Unmanaged* findUnmanagedInList(const UnmanagedList& list, T predicate) |
284 | { |
285 | for (UnmanagedList::ConstIterator it = list.begin(); it != list.end(); ++it) { |
286 | if (predicate(const_cast< const Unmanaged* >(*it))) |
287 | return *it; |
288 | } |
289 | return NULL; |
290 | } |
291 | |
292 | inline |
293 | int timestampCompare(xcb_timestamp_t time1, xcb_timestamp_t time2) // like strcmp() |
294 | { |
295 | return NET::timestampCompare(time1, time2); |
296 | } |
297 | |
298 | inline |
299 | xcb_timestamp_t timestampDiff(xcb_timestamp_t time1, xcb_timestamp_t time2) // returns time2 - time1 |
300 | { |
301 | return NET::timestampDiff(time1, time2); |
302 | } |
303 | |
304 | QPoint cursorPos(); |
305 | |
306 | // converting between X11 mouse/keyboard state mask and Qt button/keyboard states |
307 | int qtToX11Button(Qt::MouseButton button); |
308 | Qt::MouseButton x11ToQtMouseButton(int button); |
309 | int qtToX11State(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers); |
310 | Qt::MouseButtons x11ToQtMouseButtons(int state); |
311 | Qt::KeyboardModifiers x11ToQtKeyboardModifiers(int state); |
312 | |
313 | void checkNonExistentClients(); |
314 | |
315 | } // namespace |
316 | |
317 | // Must be outside namespace |
318 | Q_DECLARE_OPERATORS_FOR_FLAGS(KWin::StrutAreas) |
319 | |
320 | #endif |
321 | |