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 */
|