1 // SPDX-License-Identifier: MIT
2 // Copyright (c) 2011-2013, Christopher Jeffrey
3 // Copyright (c) 2013 Richard Grenville <pyxlcy@gmail.com>
4 #pragma once
5 #include <stdbool.h>
6 #include <xcb/damage.h>
7 #include <xcb/render.h>
8 #include <xcb/xcb.h>
9 
10 #include "uthash_extra.h"
11 
12 // FIXME shouldn't need this
13 #ifdef CONFIG_OPENGL
14 #include <GL/gl.h>
15 #endif
16 
17 #include "c2.h"
18 #include "compiler.h"
19 #include "list.h"
20 #include "region.h"
21 #include "render.h"
22 #include "types.h"
23 #include "utils.h"
24 #include "win_defs.h"
25 #include "x.h"
26 
27 struct backend_base;
28 typedef struct session session_t;
29 typedef struct _glx_texture glx_texture_t;
30 
31 #define win_stack_foreach_managed(w, win_stack)                                          \
32 	list_foreach(struct managed_win, w, win_stack, base.stack_neighbour) if (w->base.managed)
33 
34 #define win_stack_foreach_managed_safe(w, win_stack)                                     \
35 	list_foreach_safe(struct managed_win, w, win_stack,                              \
36 	                  base.stack_neighbour) if (w->base.managed)
37 
38 #ifdef CONFIG_OPENGL
39 // FIXME this type should be in opengl.h
40 //       it is very unideal for it to be here
41 typedef struct {
42 	/// Framebuffer used for blurring.
43 	GLuint fbo;
44 	/// Textures used for blurring.
45 	GLuint textures[2];
46 	/// Width of the textures.
47 	int width;
48 	/// Height of the textures.
49 	int height;
50 } glx_blur_cache_t;
51 #endif
52 
53 /// An entry in the window stack. May or may not correspond to a window we know about.
54 struct window_stack_entry {
55 	struct list_node stack_neighbour;
56 	/// The actual window correspond to this stack entry. NULL if we didn't know about
57 	/// this window (e.g. an InputOnly window, or we haven't handled the window
58 	/// creation yet)
59 	struct win *win;
60 	/// The window id. Might not be unique in the stack, because there might be
61 	/// destroyed window still fading out in the stack.
62 	xcb_window_t id;
63 };
64 
65 /**
66  * About coordinate systems
67  *
68  * In general, X is the horizontal axis, Y is the vertical axis.
69  * X goes from left to right, Y goes downwards.
70  *
71  * Global: the origin is the top left corner of the Xorg screen.
72  * Local: the origin is the top left corner of the window, border is
73  *        considered part of the window.
74  */
75 
76 /// Structure representing a top-level managed window.
77 typedef struct win win;
78 struct win {
79 	UT_hash_handle hh;
80 	struct list_node stack_neighbour;
81 	/// ID of the top-level frame window.
82 	xcb_window_t id;
83 	/// Whether the window is destroyed from Xorg's perspective
84 	bool destroyed : 1;
85 	/// True if we just received CreateNotify, and haven't queried X for any info
86 	/// about the window
87 	bool is_new : 1;
88 	/// True if this window is managed, i.e. this struct is actually a `managed_win`.
89 	/// Always false if `is_new` is true.
90 	bool managed : 1;
91 };
92 struct managed_win {
93 	struct win base;
94 	/// backend data attached to this window. Only available when
95 	/// `state` is not UNMAPPED
96 	void *win_image;
97 	void *shadow_image;
98 	/// Pointer to the next higher window to paint.
99 	struct managed_win *prev_trans;
100 	/// Number of windows above this window
101 	int stacking_rank;
102 	// TODO rethink reg_ignore
103 
104 	// Core members
105 	/// The "mapped state" of this window, doesn't necessary
106 	/// match X mapped state, because of fading.
107 	winstate_t state;
108 	/// Window attributes.
109 	xcb_get_window_attributes_reply_t a;
110 	/// Reply of xcb_get_geometry, which returns the geometry of the window body,
111 	/// excluding the window border.
112 	xcb_get_geometry_reply_t g;
113 	/// Xinerama screen this window is on.
114 	int xinerama_scr;
115 	/// Window visual pict format
116 	const xcb_render_pictforminfo_t *pictfmt;
117 	/// Client window visual pict format
118 	const xcb_render_pictforminfo_t *client_pictfmt;
119 	/// Window painting mode.
120 	winmode_t mode;
121 	/// Whether the window has been damaged at least once.
122 	bool ever_damaged;
123 	/// Whether the window was damaged after last paint.
124 	bool pixmap_damaged;
125 	/// Damage of the window.
126 	xcb_damage_damage_t damage;
127 	/// Paint info of the window.
128 	paint_t paint;
129 
130 	/// Bounding shape of the window. In local coordinates.
131 	/// See above about coordinate systems.
132 	region_t bounding_shape;
133 	/// Window flags. Definitions above.
134 	uint64_t flags;
135 	/// The region of screen that will be obscured when windows above is painted,
136 	/// in global coordinates.
137 	/// We use this to reduce the pixels that needed to be paint when painting
138 	/// this window and anything underneath. Depends on window frame
139 	/// opacity state, window geometry, window mapped/unmapped state,
140 	/// window mode of the windows above. DOES NOT INCLUDE the body of THIS WINDOW.
141 	/// NULL means reg_ignore has not been calculated for this window.
142 	rc_region_t *reg_ignore;
143 	/// Whether the reg_ignore of all windows beneath this window are valid
144 	bool reg_ignore_valid;
145 	/// Cached width/height of the window including border.
146 	int widthb, heightb;
147 	/// Whether the window is bounding-shaped.
148 	bool bounding_shaped;
149 	/// Whether the window just have rounded corners.
150 	bool rounded_corners;
151 	/// Whether this window is to be painted.
152 	bool to_paint;
153 	/// Whether the window is painting excluded.
154 	bool paint_excluded;
155 	/// Whether the window is unredirect-if-possible excluded.
156 	bool unredir_if_possible_excluded;
157 	/// Whether this window is in open/close state.
158 	bool in_openclose;
159 
160 	// Client window related members
161 	/// ID of the top-level client window of the window.
162 	xcb_window_t client_win;
163 	/// Type of the window.
164 	wintype_t window_type;
165 	/// Whether it looks like a WM window. We consider a window WM window if
166 	/// it does not have a decedent with WM_STATE and it is not override-
167 	/// redirected itself.
168 	bool wmwin;
169 	/// Leader window ID of the window.
170 	xcb_window_t leader;
171 	/// Cached topmost window ID of the window.
172 	xcb_window_t cache_leader;
173 
174 	// Focus-related members
175 	/// Whether the window is to be considered focused.
176 	bool focused;
177 	/// Override value of window focus state. Set by D-Bus method calls.
178 	switch_t focused_force;
179 
180 	// Blacklist related members
181 	/// Name of the window.
182 	char *name;
183 	/// Window instance class of the window.
184 	char *class_instance;
185 	/// Window general class of the window.
186 	char *class_general;
187 	/// <code>WM_WINDOW_ROLE</code> value of the window.
188 	char *role;
189 
190 	// Opacity-related members
191 	/// Current window opacity.
192 	double opacity;
193 	/// Target window opacity.
194 	double opacity_target;
195 	/// Previous window opacity.
196 	double opacity_target_old;
197 	/// true if window (or client window, for broken window managers
198 	/// not transferring client window's _NET_WM_OPACITY value) has opacity prop
199 	bool has_opacity_prop;
200 	/// Cached value of opacity window attribute.
201 	opacity_t opacity_prop;
202 	/// true if opacity is set by some rules
203 	bool opacity_is_set;
204 	/// Last window opacity value set by the rules.
205 	double opacity_set;
206 
207 	// Fading-related members
208 	/// Override value of window fade state. Set by D-Bus method calls.
209 	switch_t fade_force;
210 
211 	// Frame-opacity-related members
212 	/// Current window frame opacity. Affected by window opacity.
213 	double frame_opacity;
214 	/// Frame extents. Acquired from _NET_FRAME_EXTENTS.
215 	margin_t frame_extents;
216 
217 	// Shadow-related members
218 	/// Whether a window has shadow. Calculated.
219 	bool shadow;
220 	/// Override value of window shadow state. Set by D-Bus method calls.
221 	switch_t shadow_force;
222 	/// Opacity of the shadow. Affected by window opacity and frame opacity.
223 	double shadow_opacity;
224 	/// X offset of shadow. Affected by commandline argument.
225 	int shadow_dx;
226 	/// Y offset of shadow. Affected by commandline argument.
227 	int shadow_dy;
228 	/// Width of shadow. Affected by window size and commandline argument.
229 	int shadow_width;
230 	/// Height of shadow. Affected by window size and commandline argument.
231 	int shadow_height;
232 	/// Picture to render shadow. Affected by window size.
233 	paint_t shadow_paint;
234 	/// The value of _COMPTON_SHADOW attribute of the window. Below 0 for
235 	/// none.
236 	long prop_shadow;
237 
238 	// Dim-related members
239 	/// Whether the window is to be dimmed.
240 	bool dim;
241 
242 	/// Whether to invert window color.
243 	bool invert_color;
244 	/// Override value of window color inversion state. Set by D-Bus method
245 	/// calls.
246 	switch_t invert_color_force;
247 
248 	/// Whether to blur window background.
249 	bool blur_background;
250 
251 #ifdef CONFIG_OPENGL
252 	/// Textures and FBO background blur use.
253 	glx_blur_cache_t glx_blur_cache;
254 #endif
255 };
256 
257 /// Process pending updates/images flags on a window. Has to be called in X critical
258 /// section
259 void win_process_update_flags(session_t *ps, struct managed_win *w);
260 void win_process_image_flags(session_t *ps, struct managed_win *w);
261 /// Bind a shadow to the window, with color `c` and shadow kernel `kernel`
262 bool win_bind_shadow(struct backend_base *b, struct managed_win *w, struct color c,
263                      struct conv *kernel);
264 
265 /// Start the unmap of a window. We cannot unmap immediately since we might need to fade
266 /// the window out.
267 void unmap_win_start(struct session *, struct managed_win *);
268 
269 /// Start the mapping of a window. We cannot map immediately since we might need to fade
270 /// the window in.
271 void map_win_start(struct session *, struct managed_win *);
272 
273 /// Start the destroying of a window. Windows cannot always be destroyed immediately
274 /// because of fading and such.
275 bool must_use destroy_win_start(session_t *ps, struct win *w);
276 
277 /// Release images bound with a window, set the *_NONE flags on the window. Only to be
278 /// used when de-initializing the backend outside of win.c
279 void win_release_images(struct backend_base *base, struct managed_win *w);
280 int win_update_name(session_t *ps, struct managed_win *w);
281 int win_get_role(session_t *ps, struct managed_win *w);
282 winmode_t attr_pure win_calc_mode(const struct managed_win *w);
283 void win_set_shadow_force(session_t *ps, struct managed_win *w, switch_t val);
284 void win_set_fade_force(struct managed_win *w, switch_t val);
285 void win_set_focused_force(session_t *ps, struct managed_win *w, switch_t val);
286 void win_set_invert_color_force(session_t *ps, struct managed_win *w, switch_t val);
287 /**
288  * Set real focused state of a window.
289  */
290 void win_set_focused(session_t *ps, struct managed_win *w);
291 bool attr_pure win_should_fade(session_t *ps, const struct managed_win *w);
292 void win_update_prop_shadow_raw(session_t *ps, struct managed_win *w);
293 void win_update_prop_shadow(session_t *ps, struct managed_win *w);
294 void win_update_opacity_target(session_t *ps, struct managed_win *w);
295 void win_on_factor_change(session_t *ps, struct managed_win *w);
296 /**
297  * Update cache data in struct _win that depends on window size.
298  */
299 void win_on_win_size_change(session_t *ps, struct managed_win *w);
300 void win_update_wintype(session_t *ps, struct managed_win *w);
301 void win_mark_client(session_t *ps, struct managed_win *w, xcb_window_t client);
302 void win_unmark_client(session_t *ps, struct managed_win *w);
303 void win_recheck_client(session_t *ps, struct managed_win *w);
304 bool win_get_class(session_t *ps, struct managed_win *w);
305 
306 /**
307  * Calculate and return the opacity target of a window.
308  *
309  * The priority of opacity settings are:
310  *
311  * inactive_opacity_override (if set, and unfocused) > _NET_WM_WINDOW_OPACITY (if set) >
312  * opacity-rules (if matched) > window type default opacity > active/inactive opacity
313  *
314  * @param ps           current session
315  * @param w            struct _win object representing the window
316  *
317  * @return target opacity
318  */
319 double attr_pure win_calc_opacity_target(session_t *ps, const struct managed_win *w);
320 bool attr_pure win_should_dim(session_t *ps, const struct managed_win *w);
321 void win_update_screen(session_t *, struct managed_win *);
322 /**
323  * Reread opacity property of a window.
324  */
325 void win_update_opacity_prop(session_t *ps, struct managed_win *w);
326 /**
327  * Update leader of a window.
328  */
329 void win_update_leader(session_t *ps, struct managed_win *w);
330 /**
331  * Retrieve the bounding shape of a window.
332  */
333 // XXX was win_border_size
334 void win_update_bounding_shape(session_t *ps, struct managed_win *w);
335 /**
336  * Check if a window has BYPASS_COMPOSITOR property set
337  */
338 bool win_is_bypassing_compositor(const session_t *ps, const struct managed_win *w);
339 /**
340  * Get a rectangular region in global coordinates a window (and possibly
341  * its shadow) occupies.
342  *
343  * Note w->shadow and shadow geometry must be correct before calling this
344  * function.
345  */
346 void win_extents(const struct managed_win *w, region_t *res);
347 region_t win_extents_by_val(const struct managed_win *w);
348 /**
349  * Add a window to damaged area.
350  *
351  * @param ps current session
352  * @param w struct _win element representing the window
353  */
354 void add_damage_from_win(session_t *ps, const struct managed_win *w);
355 /**
356  * Get a rectangular region a window occupies, excluding frame and shadow.
357  *
358  * Return region in global coordinates.
359  */
360 void win_get_region_noframe_local(const struct managed_win *w, region_t *);
361 
362 /// Get the region for the frame of the window
363 void win_get_region_frame_local(const struct managed_win *w, region_t *res);
364 /// Get the region for the frame of the window, by value
365 region_t win_get_region_frame_local_by_val(const struct managed_win *w);
366 /**
367  * Retrieve frame extents from a window.
368  */
369 void win_update_frame_extents(session_t *ps, struct managed_win *w, xcb_window_t client);
370 /// Insert a new window above window with id `below`, if there is no window, add to top
371 /// New window will be in unmapped state
372 struct win *add_win_above(session_t *ps, xcb_window_t id, xcb_window_t below);
373 /// Insert a new win entry at the top of the stack
374 struct win *add_win_top(session_t *ps, xcb_window_t id);
375 /// Query the Xorg for information about window `win`
376 /// `win` pointer might become invalid after this function returns
377 struct win *fill_win(session_t *ps, struct win *win);
378 /// Move window `w` to be right above `below`
379 void restack_above(session_t *ps, struct win *w, xcb_window_t below);
380 /// Move window `w` to the bottom of the stack
381 void restack_bottom(session_t *ps, struct win *w);
382 /// Move window `w` to the top of the stack
383 void restack_top(session_t *ps, struct win *w);
384 
385 /**
386  * Execute fade callback of a window if fading finished.
387  */
388 bool must_use win_check_fade_finished(session_t *ps, struct managed_win *w);
389 
390 // Stop receiving events (except ConfigureNotify, XXX why?) from a window
391 void win_ev_stop(session_t *ps, const struct win *w);
392 
393 /// Skip the current in progress fading of window,
394 /// transition the window straight to its end state
395 ///
396 /// @return whether the window is destroyed and freed
397 bool must_use win_skip_fading(session_t *ps, struct managed_win *w);
398 /**
399  * Find a managed window from window id in window linked list of the session.
400  */
401 struct managed_win *find_managed_win(session_t *ps, xcb_window_t id);
402 struct win *find_win(session_t *ps, xcb_window_t id);
403 struct managed_win *find_toplevel(session_t *ps, xcb_window_t id);
404 /**
405  * Find a managed window that is, or is a parent of `wid`.
406  *
407  * @param ps current session
408  * @param wid window ID
409  * @return struct _win object of the found window, NULL if not found
410  */
411 struct managed_win *find_managed_window_or_parent(session_t *ps, xcb_window_t wid);
412 
413 /**
414  * Check if a window is a fullscreen window.
415  *
416  * It's not using w->border_size for performance measures.
417  */
418 bool attr_pure win_is_fullscreen(const session_t *ps, const struct managed_win *w);
419 
420 /**
421  * Check if a window is focused, without using any focus rules or forced focus settings
422  */
423 bool attr_pure win_is_focused_raw(const session_t *ps, const struct managed_win *w);
424 
425 /// check if window has ARGB visual
426 bool attr_pure win_has_alpha(const struct managed_win *w);
427 
428 /// check if reg_ignore_valid is true for all windows above us
429 bool attr_pure win_is_region_ignore_valid(session_t *ps, const struct managed_win *w);
430 
431 /// Whether a given window is mapped on the X server side
432 bool win_is_mapped_in_x(const struct managed_win *w);
433 
434 // Find the managed window immediately below `w` in the window stack
435 struct managed_win *attr_pure win_stack_find_next_managed(const session_t *ps,
436                                                           const struct list_node *w);
437 /// Set flags on a window. Some sanity checks are performed
438 void win_set_flags(struct managed_win *w, uint64_t flags);
439 /// Clear flags on a window. Some sanity checks are performed
440 void win_clear_flags(struct managed_win *w, uint64_t flags);
441 /// Returns true if any of the flags in `flags` is set
442 bool win_check_flags_any(struct managed_win *w, uint64_t flags);
443 /// Returns true if all of the flags in `flags` are set
444 bool win_check_flags_all(struct managed_win *w, uint64_t flags);
445 
446 /// Free all resources in a struct win
447 void free_win_res(session_t *ps, struct managed_win *w);
448 
win_get_bounding_shape_global_by_val(struct managed_win * w)449 static inline region_t win_get_bounding_shape_global_by_val(struct managed_win *w) {
450 	region_t ret;
451 	pixman_region32_init(&ret);
452 	pixman_region32_copy(&ret, &w->bounding_shape);
453 	pixman_region32_translate(&ret, w->g.x, w->g.y);
454 	return ret;
455 }
456 
457 /**
458  * Calculate the extents of the frame of the given window based on EWMH
459  * _NET_FRAME_EXTENTS and the X window border width.
460  */
win_calc_frame_extents(const struct managed_win * w)461 static inline margin_t attr_pure win_calc_frame_extents(const struct managed_win *w) {
462 	margin_t result = w->frame_extents;
463 	result.top = max2(result.top, w->g.border_width);
464 	result.left = max2(result.left, w->g.border_width);
465 	result.bottom = max2(result.bottom, w->g.border_width);
466 	result.right = max2(result.right, w->g.border_width);
467 	return result;
468 }
469 
470 /**
471  * Check whether a window has WM frames.
472  */
win_has_frame(const struct managed_win * w)473 static inline bool attr_pure win_has_frame(const struct managed_win *w) {
474 	return w->g.border_width || w->frame_extents.top || w->frame_extents.left ||
475 	       w->frame_extents.right || w->frame_extents.bottom;
476 }
477