File: view.h

package info (click to toggle)
labwc 0.9.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,980 kB
  • sloc: ansic: 34,416; perl: 5,836; xml: 875; sh: 162; python: 131; makefile: 12
file content (601 lines) | stat: -rw-r--r-- 20,302 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_VIEW_H
#define LABWC_VIEW_H

#include <stdbool.h>
#include <stdint.h>
#include <wayland-util.h>
#include <wlr/util/box.h>
#include <xkbcommon/xkbcommon.h>
#include "common/edge.h"
#include "config.h"
#include "config/types.h"

/*
 * Default minimal window size. Clients can explicitly set smaller values via
 * e.g. xdg_toplevel::set_min_size.
 */
#define LAB_MIN_VIEW_WIDTH 100
#define LAB_MIN_VIEW_HEIGHT 60

/*
 * Fallback view geometry used in some cases where a better position
 * and/or size can't be determined. Try to avoid using these except as
 * a last resort.
 */
#define VIEW_FALLBACK_X 100
#define VIEW_FALLBACK_Y 100
#define VIEW_FALLBACK_WIDTH  640
#define VIEW_FALLBACK_HEIGHT 480

/*
 * In labwc, a view is a container for surfaces which can be moved around by
 * the user. In practice this means XDG toplevel and XWayland windows.
 */
enum view_type {
	LAB_XDG_SHELL_VIEW,
#if HAVE_XWAYLAND
	LAB_XWAYLAND_VIEW,
#endif
};

enum ssd_preference {
	LAB_SSD_PREF_UNSPEC = 0,
	LAB_SSD_PREF_CLIENT,
	LAB_SSD_PREF_SERVER,
};

/**
 * Directions in which a view can be maximized. "None" is used
 * internally to mean "not maximized" but is not valid in rc.xml.
 * Therefore when parsing rc.xml, "None" means "Invalid".
 */
enum view_axis {
	VIEW_AXIS_NONE = 0,
	VIEW_AXIS_HORIZONTAL = (1 << 0),
	VIEW_AXIS_VERTICAL = (1 << 1),
	VIEW_AXIS_BOTH = (VIEW_AXIS_HORIZONTAL | VIEW_AXIS_VERTICAL),
	/*
	 * If view_axis is treated as a bitfield, INVALID should never
	 * set the HORIZONTAL or VERTICAL bits.
	 */
	VIEW_AXIS_INVALID = (1 << 2),
};

enum view_wants_focus {
	/* View does not want focus */
	VIEW_WANTS_FOCUS_NEVER = 0,
	/* View wants focus */
	VIEW_WANTS_FOCUS_ALWAYS,
	/*
	 * The following values apply only to XWayland views using the
	 * Globally Active input model per the ICCCM. These views are
	 * offered focus and will voluntarily accept or decline it.
	 *
	 * In some cases, labwc needs to decide in advance whether to
	 * focus the view. For this purpose, these views are classified
	 * (by a heuristic) as likely or unlikely to want focus. However,
	 * it is still ultimately up to the client whether the view gets
	 * focus or not.
	 */
	VIEW_WANTS_FOCUS_LIKELY,
	VIEW_WANTS_FOCUS_UNLIKELY,
};

struct view;
struct wlr_surface;
struct foreign_toplevel;

/* Common to struct view and struct xwayland_unmanaged */
struct mappable {
	bool connected;
	struct wl_listener map;
	struct wl_listener unmap;
};

/* Basic size hints (subset of XSizeHints from X11) */
struct view_size_hints {
	int min_width;
	int min_height;
	int width_inc;
	int height_inc;
	int base_width;
	int base_height;
};

struct view_impl {
	void (*configure)(struct view *view, struct wlr_box geo);
	void (*close)(struct view *view);
	const char *(*get_string_prop)(struct view *view, const char *prop);
	void (*map)(struct view *view);
	void (*set_activated)(struct view *view, bool activated);
	void (*set_fullscreen)(struct view *view, bool fullscreen);
	void (*notify_tiled)(struct view *view);
	/*
	 * client_request is true if the client unmapped its own
	 * surface; false if we are just minimizing the view. The two
	 * cases are similar but have subtle differences (e.g., when
	 * minimizing we don't destroy the foreign toplevel handle).
	 */
	void (*unmap)(struct view *view, bool client_request);
	void (*maximize)(struct view *view, enum view_axis maximized);
	void (*minimize)(struct view *view, bool minimize);
	struct view *(*get_root)(struct view *self);
	void (*append_children)(struct view *self, struct wl_array *children);
	bool (*is_modal_dialog)(struct view *self);
	struct view_size_hints (*get_size_hints)(struct view *self);
	/* if not implemented, VIEW_WANTS_FOCUS_ALWAYS is assumed */
	enum view_wants_focus (*wants_focus)(struct view *self);
	void (*offer_focus)(struct view *self);
	/* returns true if view reserves space at screen edge */
	bool (*has_strut_partial)(struct view *self);
	/* returns true if view declared itself a window type */
	bool (*contains_window_type)(struct view *view,
		enum lab_window_type window_type);
	/* returns the client pid that this view belongs to */
	pid_t (*get_pid)(struct view *view);
};

struct view {
	struct server *server;
	enum view_type type;
	const struct view_impl *impl;
	struct wl_list link;

	/*
	 * The primary output that the view is displayed on. Specifically:
	 *
	 *  - For floating views, this is the output nearest to the
	 *    center of the view. It is computed automatically when the
	 *    view is moved or the output layout changes.
	 *
	 *  - For fullscreen/maximized/tiled views, this is the output
	 *    used to compute the view's geometry. The view remains on
	 *    the same output unless it is disabled or disconnected.
	 *
	 * Many view functions (e.g. view_center(), view_fullscreen(),
	 * view_maximize(), etc.) allow specifying a particular output
	 * by calling view_set_output() beforehand.
	 */
	struct output *output;

	/*
	 * The outputs that the view is displayed on.
	 * This is used to notify the foreign toplevel
	 * implementation and to update the SSD invisible
	 * resize area.
	 * It is a bitset of output->scene_output->index.
	 */
	uint64_t outputs;

	struct workspace *workspace;
	struct wlr_surface *surface;
	struct wlr_scene_tree *scene_tree;
	struct wlr_scene_tree *content_tree;

	bool mapped;
	bool been_mapped;
	enum lab_ssd_mode ssd_mode;
	enum ssd_preference ssd_preference;
	bool shaded;
	bool minimized;
	enum view_axis maximized;
	bool fullscreen;
	bool tearing_hint;
	enum lab_tristate force_tearing;
	bool visible_on_all_workspaces;
	enum lab_edge tiled;
	enum lab_edge edges_visible;
	bool inhibits_keybinds; /* also inhibits mousebinds */
	xkb_layout_index_t keyboard_layout;

	/* Pointer to an output owned struct region, may be NULL */
	struct region *tiled_region;
	/* Set to region->name when tiled_region is free'd by a destroying output */
	char *tiled_region_evacuate;

	/*
	 * Geometry of the wlr_surface contained within the view, as
	 * currently displayed. Should be kept in sync with the
	 * scene-graph at all times.
	 */
	struct wlr_box current;
	/*
	 * Expected geometry after any pending move/resize requests
	 * have been processed. Should match current geometry when no
	 * move/resize requests are pending.
	 */
	struct wlr_box pending;
	/*
	 * Saved geometry which will be restored when the view returns
	 * to normal/floating state after being maximized/fullscreen/
	 * tiled. Values are undefined/out-of-date when the view is not
	 * maximized/fullscreen/tiled.
	 */
	struct wlr_box natural_geometry;
	/*
	 * Whenever an output layout change triggers a view relocation, the
	 * last pending position (or natural geometry) will be saved so the
	 * view may be restored to its original location on a subsequent layout
	 * change.
	 */
	struct wlr_box last_layout_geometry;

	/* used by xdg-shell views */
	uint32_t pending_configure_serial;
	struct wl_event_source *pending_configure_timeout;

	struct ssd *ssd;
	struct resize_indicator {
		int width, height;
		struct wlr_scene_tree *tree;
		struct wlr_scene_rect *border;
		struct wlr_scene_rect *background;
		struct scaled_font_buffer *text;
	} resize_indicator;
	struct resize_outlines {
		struct wlr_box view_geo;
		struct lab_scene_rect *rect;
	} resize_outlines;

	struct mappable mappable;

	struct wl_listener destroy;
	struct wl_listener surface_destroy;
	struct wl_listener commit;
	struct wl_listener request_move;
	struct wl_listener request_resize;
	struct wl_listener request_minimize;
	struct wl_listener request_maximize;
	struct wl_listener request_fullscreen;
	struct wl_listener set_title;

	struct foreign_toplevel *foreign_toplevel;

	/* used by scaled_icon_buffer */
	struct {
		char *name;
		struct wl_array buffers; /* struct lab_data_buffer * */
	} icon;

	struct {
		struct wl_signal new_app_id;
		struct wl_signal new_title;
		struct wl_signal new_outputs;
		struct wl_signal maximized;
		struct wl_signal minimized;
		struct wl_signal fullscreened;
		struct wl_signal activated;     /* bool *activated */
		/*
		 * This is emitted when app_id, or icon set via xdg_toplevel_icon
		 * is updated. This is listened by scaled_icon_buffer.
		 */
		struct wl_signal set_icon;
		struct wl_signal destroy;
	} events;
};

struct view_query {
	struct wl_list link;
	char *identifier;
	char *title;
	enum lab_window_type window_type;
	char *sandbox_engine;
	char *sandbox_app_id;
	enum lab_tristate shaded;
	enum view_axis maximized;
	enum lab_tristate iconified;
	enum lab_tristate focused;
	enum lab_tristate omnipresent;
	enum lab_edge tiled;
	char *tiled_region;
	char *desktop;
	enum lab_ssd_mode decoration;
	char *monitor;
};

struct xdg_toplevel_view {
	struct view base;
	struct wlr_xdg_surface *xdg_surface;

	/* Events unique to xdg-toplevel views */
	struct wl_listener set_app_id;
	struct wl_listener request_show_window_menu;
	struct wl_listener new_popup;
};

/**
 * view_from_wlr_surface() - returns the view associated with a
 * wlr_surface, or NULL if the surface has no associated view.
 */
struct view *view_from_wlr_surface(struct wlr_surface *surface);

/**
 * view_query_create() - Create a new heap allocated view query with
 * all members initialized to their default values (window_type = -1,
 * NULL for strings)
 */
struct view_query *view_query_create(void);

/**
 * view_query_free() - Free a given view query
 * @query: Query to be freed.
 */
void view_query_free(struct view_query *view);

/**
 * view_matches_query() - Check if view matches the given criteria
 * @view: View to checked.
 * @query: Criteria to match against.
 *
 * Returns true if %view matches all of the criteria given in %query, false
 * otherwise.
 */
bool view_matches_query(struct view *view, struct view_query *query);

/**
 * for_each_view() - iterate over all views which match criteria
 * @view: Iterator.
 * @head: Head of list to iterate over.
 * @criteria: Criteria to match against.
 * Example:
 *	struct view *view;
 *	for_each_view(view, &server->views, LAB_VIEW_CRITERIA_NONE) {
 *		printf("%s\n", view_get_string_prop(view, "app_id"));
 *	}
 */
#define for_each_view(view, head, criteria)           \
	for (view = view_next(head, NULL, criteria);  \
	     view;                                    \
	     view = view_next(head, view, criteria))

/**
 * for_each_view_reverse() - iterate over all views which match criteria
 * @view: Iterator.
 * @head: Head of list to iterate over.
 * @criteria: Criteria to match against.
 * Example:
 *	struct view *view;
 *	for_each_view_reverse(view, &server->views, LAB_VIEW_CRITERIA_NONE) {
 *		printf("%s\n", view_get_string_prop(view, "app_id"));
 *	}
 */
#define for_each_view_reverse(view, head, criteria)   \
	for (view = view_prev(head, NULL, criteria);  \
	     view;                                    \
	     view = view_prev(head, view, criteria))

/**
 * view_next() - Get next view which matches criteria.
 * @head: Head of list to iterate over.
 * @view: Current view from which to find the next one. If NULL is provided as
 *	  the view argument, the start of the list will be used.
 * @criteria: Criteria to match against.
 *
 * Returns NULL if there are no views matching the criteria.
 */
struct view *view_next(struct wl_list *head, struct view *view,
	enum lab_view_criteria criteria);

/**
 * view_prev() - Get previous view which matches criteria.
 * @head: Head of list to iterate over.
 * @view: Current view from which to find the previous one. If NULL is provided
 *        as the view argument, the end of the list will be used.
 * @criteria: Criteria to match against.
 *
 * Returns NULL if there are no views matching the criteria.
 */
struct view *view_prev(struct wl_list *head, struct view *view,
	enum lab_view_criteria criteria);

/*
 * Same as `view_next()` except that they iterate one whole cycle rather than
 * stopping at the list-head
 */
struct view *view_next_no_head_stop(struct wl_list *head, struct view *from,
	enum lab_view_criteria criteria);
struct view *view_prev_no_head_stop(struct wl_list *head, struct view *from,
	enum lab_view_criteria criteria);

/**
 * view_array_append() - Append views that match criteria to array
 * @server: server context
 * @views: arrays to append to
 * @criteria: criteria to match against
 *
 * This function is useful in cases where the calling function may change the
 * stacking order or where it needs to iterate over the views multiple times,
 * for example to get the number of views before processing them.
 *
 * Note: This array has a very short shelf-life so it is intended to be used
 *       with a single-use-throw-away approach.
 *
 * Example usage:
 *	struct view **view;
 *	struct wl_array views;
 *	wl_array_init(&views);
 *	view_array_append(server, &views, LAB_VIEW_CRITERIA_CURRENT_WORKSPACE);
 *	wl_array_for_each(view, &views) {
 *		// Do something with *view
 *	}
 *	wl_array_release(&views);
 */
void view_array_append(struct server *server, struct wl_array *views,
	enum lab_view_criteria criteria);

enum view_wants_focus view_wants_focus(struct view *view);

/* If view is NULL, the size of SSD is not considered */
struct wlr_box view_get_edge_snap_box(struct view *view, struct output *output,
	enum lab_edge edge);
struct wlr_box view_get_region_snap_box(struct view *view, struct region *region);

/**
 * view_is_focusable() - Check whether or not a view can be focused
 * @view: view to be checked
 *
 * The purpose of this test is to filter out views (generally Xwayland) which
 * are not meant to be focused such as those with surfaces
 *	a. that have been created but never mapped;
 *	b. set to NULL after client minimize-request.
 *
 * The only views that are allowed to be focused are those that have a surface
 * and have been mapped at some point since creation.
 */
bool view_is_focusable(struct view *view);

/*
 * For use by desktop_focus_view() only - please do not call directly.
 * See the description of VIEW_WANTS_FOCUS_OFFER for more information.
 */
void view_offer_focus(struct view *view);

struct wlr_box view_get_edge_snap_box(struct view *view, struct output *output,
	enum lab_edge edge);

void mappable_connect(struct mappable *mappable, struct wlr_surface *surface,
	wl_notify_func_t notify_map, wl_notify_func_t notify_unmap);
void mappable_disconnect(struct mappable *mappable);

void view_toggle_keybinds(struct view *view);
bool view_inhibits_actions(struct view *view, struct wl_list *actions);

void view_set_activated(struct view *view, bool activated);
void view_set_output(struct view *view, struct output *output);
void view_close(struct view *view);

/**
 * view_move_resize - resize and move view
 * @view: view to be resized and moved
 * @geo: the new geometry
 * NOTE: Only use this when the view actually changes width and/or height
 * otherwise the serials might cause a delay in moving xdg-shell clients.
 * For move only, use view_move()
 */
void view_move_resize(struct view *view, struct wlr_box geo);
void view_resize_relative(struct view *view,
	int left, int right, int top, int bottom);
void view_move_relative(struct view *view, int x, int y);
void view_move(struct view *view, int x, int y);
void view_move_to_cursor(struct view *view);
void view_moved(struct view *view);
void view_minimize(struct view *view, bool minimized);
bool view_compute_centered_position(struct view *view,
	const struct wlr_box *ref, int w, int h, int *x, int *y);
struct wlr_box view_get_fallback_natural_geometry(struct view *view);
void view_store_natural_geometry(struct view *view);

/**
 * view_apply_natural_geometry - adjust view->natural_geometry if it doesn't
 * intersect with view->output and then apply it
 */
void view_apply_natural_geometry(struct view *view);

/**
 * view_effective_height - effective height of view, with respect to shaded state
 * @view: view for which effective height is desired
 * @use_pending: if false, report current height; otherwise, report pending height
 */
int view_effective_height(struct view *view, bool use_pending);

/**
 * view_center - center view within some region
 * @view: view to be centered
 * @ref: optional reference region (in layout coordinates) to center
 * within; if NULL, view is centered within usable area of its output
 */
void view_center(struct view *view, const struct wlr_box *ref);

/**
 * view_place_by_policy - apply placement strategy to view
 * @view: view to be placed
 * @allow_cursor: set to false to ignore center-on-cursor policy
 * @policy: placement policy to apply
 */
void view_place_by_policy(struct view *view, bool allow_cursor,
	enum lab_placement_policy policy);
void view_constrain_size_to_that_of_usable_area(struct view *view);

void view_set_maximized(struct view *view, enum view_axis maximized);
void view_set_untiled(struct view *view);
void view_maximize(struct view *view, enum view_axis axis,
	bool store_natural_geometry);
void view_set_fullscreen(struct view *view, bool fullscreen);
void view_toggle_maximize(struct view *view, enum view_axis axis);
bool view_wants_decorations(struct view *view);
void view_toggle_decorations(struct view *view);

bool view_is_always_on_top(struct view *view);
bool view_is_always_on_bottom(struct view *view);
bool view_is_omnipresent(struct view *view);
void view_toggle_always_on_top(struct view *view);
void view_toggle_always_on_bottom(struct view *view);
void view_toggle_visible_on_all_workspaces(struct view *view);

bool view_is_tiled(struct view *view);
bool view_is_tiled_and_notify_tiled(struct view *view);
bool view_is_floating(struct view *view);
void view_move_to_workspace(struct view *view, struct workspace *workspace);
bool view_titlebar_visible(struct view *view);
void view_set_ssd_mode(struct view *view, enum lab_ssd_mode mode);
void view_set_decorations(struct view *view, enum lab_ssd_mode mode, bool force_ssd);
void view_toggle_fullscreen(struct view *view);
void view_invalidate_last_layout_geometry(struct view *view);
void view_adjust_for_layout_change(struct view *view);
void view_move_to_edge(struct view *view, enum lab_edge direction, bool snap_to_windows);
void view_grow_to_edge(struct view *view, enum lab_edge direction);
void view_shrink_to_edge(struct view *view, enum lab_edge direction);
void view_snap_to_edge(struct view *view, enum lab_edge direction,
	bool across_outputs, bool combine, bool store_natural_geometry);
void view_snap_to_region(struct view *view, struct region *region, bool store_natural_geometry);
void view_move_to_output(struct view *view, struct output *output);

void view_move_to_front(struct view *view);
void view_move_to_back(struct view *view);

/**
 * view_get_modal_dialog() - returns any modal dialog found among this
 * view's children or siblings (or possibly this view itself). Applies
 * only to xwayland views and always returns NULL for xdg-shell views.
 */
struct view *view_get_modal_dialog(struct view *view);

bool view_on_output(struct view *view, struct output *output);

/**
 * view_has_strut_partial() - returns true for views that reserve space
 * at a screen edge (e.g. panels). These views are treated as if they
 * have the fixedPosition window rule: i.e. they are not restricted to
 * the usable area and cannot be moved/resized interactively.
 */
bool view_has_strut_partial(struct view *view);

const char *view_get_string_prop(struct view *view, const char *prop);
void view_update_title(struct view *view);
void view_update_app_id(struct view *view);
void view_reload_ssd(struct view *view);

void view_set_shade(struct view *view, bool shaded);

/* Icon buffers set with this function are dropped later */
void view_set_icon(struct view *view, const char *icon_name,
	struct wl_array *buffers);

struct view_size_hints view_get_size_hints(struct view *view);
void view_adjust_size(struct view *view, int *w, int *h);

void view_evacuate_region(struct view *view);
void view_on_output_destroy(struct view *view);
void view_connect_map(struct view *view, struct wlr_surface *surface);

void view_init(struct view *view);
void view_destroy(struct view *view);

enum view_axis view_axis_parse(const char *direction);
enum lab_placement_policy view_placement_parse(const char *policy);

/* xdg.c */
struct wlr_xdg_surface *xdg_surface_from_view(struct view *view);

#endif /* LABWC_VIEW_H */