2022-11-21 10:10:39 -05:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
2023-05-13 16:10:33 +03:00
|
|
|
#ifndef LABWC_VIEW_H
|
|
|
|
|
#define LABWC_VIEW_H
|
2022-11-21 10:10:39 -05:00
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
#include <wayland-util.h>
|
|
|
|
|
#include <wlr/util/box.h>
|
|
|
|
|
|
2022-11-22 20:13:06 +00:00
|
|
|
/*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
|
|
|
|
|
2022-11-21 10:10:39 -05:00
|
|
|
enum view_type {
|
|
|
|
|
LAB_XDG_SHELL_VIEW,
|
|
|
|
|
#if HAVE_XWAYLAND
|
|
|
|
|
LAB_XWAYLAND_VIEW,
|
|
|
|
|
#endif
|
|
|
|
|
};
|
|
|
|
|
|
2023-03-22 19:53:17 +01:00
|
|
|
enum ssd_preference {
|
|
|
|
|
LAB_SSD_PREF_UNSPEC = 0,
|
|
|
|
|
LAB_SSD_PREF_CLIENT,
|
|
|
|
|
LAB_SSD_PREF_SERVER,
|
|
|
|
|
};
|
|
|
|
|
|
2023-08-02 04:30:50 +02:00
|
|
|
enum view_edge {
|
|
|
|
|
VIEW_EDGE_INVALID = 0,
|
|
|
|
|
|
|
|
|
|
VIEW_EDGE_LEFT,
|
|
|
|
|
VIEW_EDGE_RIGHT,
|
|
|
|
|
VIEW_EDGE_UP,
|
|
|
|
|
VIEW_EDGE_DOWN,
|
|
|
|
|
VIEW_EDGE_CENTER,
|
|
|
|
|
};
|
|
|
|
|
|
2022-11-26 16:46:28 -05:00
|
|
|
struct view;
|
2023-09-22 01:22:19 -04:00
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
};
|
|
|
|
|
|
2022-11-21 10:10:39 -05:00
|
|
|
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);
|
2023-07-01 12:37:47 -04:00
|
|
|
/*
|
|
|
|
|
* 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);
|
2022-11-21 10:10:39 -05:00
|
|
|
void (*maximize)(struct view *view, bool maximize);
|
2023-06-25 11:37:56 +01:00
|
|
|
void (*minimize)(struct view *view, bool minimize);
|
2023-02-05 19:29:24 +00:00
|
|
|
void (*move_to_front)(struct view *view);
|
2023-03-25 16:38:43 +00:00
|
|
|
void (*move_to_back)(struct view *view);
|
2023-08-02 20:57:39 +01:00
|
|
|
struct view *(*get_root)(struct view *self);
|
|
|
|
|
void (*append_children)(struct view *self, struct wl_array *children);
|
2023-09-22 01:22:19 -04:00
|
|
|
struct view_size_hints (*get_size_hints)(struct view *self);
|
2022-11-21 10:10:39 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct view {
|
|
|
|
|
struct server *server;
|
|
|
|
|
enum view_type type;
|
|
|
|
|
const struct view_impl *impl;
|
|
|
|
|
struct wl_list link;
|
2023-02-21 08:14:11 -05:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The 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
|
2023-02-28 11:46:48 -05:00
|
|
|
* by calling view_set_output() beforehand.
|
2023-02-21 08:14:11 -05:00
|
|
|
*/
|
2022-11-21 10:10:39 -05:00
|
|
|
struct output *output;
|
|
|
|
|
struct workspace *workspace;
|
|
|
|
|
struct wlr_surface *surface;
|
|
|
|
|
struct wlr_scene_tree *scene_tree;
|
|
|
|
|
struct wlr_scene_node *scene_node;
|
|
|
|
|
|
|
|
|
|
bool mapped;
|
|
|
|
|
bool been_mapped;
|
2022-11-21 15:38:20 -05:00
|
|
|
bool ssd_enabled;
|
2023-04-14 09:01:13 +02:00
|
|
|
bool ssd_titlebar_hidden;
|
2023-03-22 19:53:17 +01:00
|
|
|
enum ssd_preference ssd_preference;
|
2022-11-21 10:10:39 -05:00
|
|
|
bool minimized;
|
|
|
|
|
bool maximized;
|
2023-02-15 02:12:22 -05:00
|
|
|
bool fullscreen;
|
2022-11-21 10:10:39 -05:00
|
|
|
uint32_t tiled; /* private, enum view_edge in src/view.c */
|
2023-03-05 10:35:56 +01:00
|
|
|
bool inhibits_keybinds;
|
2022-07-07 19:05:54 +02:00
|
|
|
|
2023-01-01 18:12:20 +01:00
|
|
|
/* Pointer to an output owned struct region, may be NULL */
|
2022-07-06 17:04:21 +02:00
|
|
|
struct region *tiled_region;
|
2022-07-07 19:05:54 +02:00
|
|
|
/* Set to region->name when tiled_region is free'd by a destroying output */
|
|
|
|
|
char *tiled_region_evacuate;
|
|
|
|
|
|
2023-02-08 23:19:14 -05:00
|
|
|
/*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
2022-11-21 10:10:39 -05:00
|
|
|
struct wlr_box natural_geometry;
|
|
|
|
|
|
2023-02-08 23:19:14 -05:00
|
|
|
/* used by xdg-shell views */
|
|
|
|
|
uint32_t pending_configure_serial;
|
2023-02-28 11:30:42 -05:00
|
|
|
struct wl_event_source *pending_configure_timeout;
|
2022-11-21 10:10:39 -05:00
|
|
|
|
2022-11-26 16:46:28 -05:00
|
|
|
struct ssd *ssd;
|
2023-08-17 18:59:29 +02:00
|
|
|
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;
|
2022-11-21 10:10:39 -05:00
|
|
|
|
2023-02-01 09:27:25 +01:00
|
|
|
struct foreign_toplevel {
|
|
|
|
|
struct wlr_foreign_toplevel_handle_v1 *handle;
|
|
|
|
|
struct wl_listener maximize;
|
|
|
|
|
struct wl_listener minimize;
|
|
|
|
|
struct wl_listener fullscreen;
|
|
|
|
|
struct wl_listener activate;
|
|
|
|
|
struct wl_listener close;
|
|
|
|
|
struct wl_listener destroy;
|
|
|
|
|
} toplevel;
|
2022-11-21 10:10:39 -05:00
|
|
|
|
|
|
|
|
struct wl_listener map;
|
|
|
|
|
struct wl_listener unmap;
|
|
|
|
|
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;
|
2022-11-22 20:13:06 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct xdg_toplevel_view {
|
|
|
|
|
struct view base;
|
2022-11-25 13:41:12 -05:00
|
|
|
struct wlr_xdg_surface *xdg_surface;
|
2022-11-22 20:13:06 +00:00
|
|
|
|
|
|
|
|
/* Events unique to xdg-toplevel views */
|
|
|
|
|
struct wl_listener set_app_id;
|
|
|
|
|
struct wl_listener new_popup;
|
|
|
|
|
};
|
|
|
|
|
|
2023-08-10 15:46:00 +01:00
|
|
|
enum lab_view_criteria {
|
2023-08-18 22:18:59 +01:00
|
|
|
LAB_VIEW_CRITERIA_NONE = 0,
|
2023-08-10 15:46:00 +01:00
|
|
|
LAB_VIEW_CRITERIA_CURRENT_WORKSPACE = 1 << 0,
|
|
|
|
|
LAB_VIEW_CRITERIA_NO_ALWAYS_ON_TOP = 1 << 1,
|
|
|
|
|
LAB_VIEW_CRITERIA_NO_SKIP_WINDOW_SWITCHER = 1 << 2,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
2023-08-18 22:18:59 +01:00
|
|
|
* 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))
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 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_array_append() - Append views that match criteria to array
|
2023-08-10 15:46:00 +01:00
|
|
|
* @server: server context
|
|
|
|
|
* @views: arrays to append to
|
|
|
|
|
* @criteria: criteria to match against
|
|
|
|
|
*
|
2023-08-18 22:18:59 +01:00
|
|
|
* 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.
|
|
|
|
|
*
|
2023-08-10 15:46:00 +01:00
|
|
|
* 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);
|
|
|
|
|
|
2023-08-20 16:43:29 +01:00
|
|
|
/**
|
|
|
|
|
* view_isfocusable() - 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 focusd are those that have a surface
|
|
|
|
|
* and have been mapped at some point since creation.
|
|
|
|
|
*/
|
|
|
|
|
bool view_isfocusable(struct view *view);
|
|
|
|
|
|
2023-03-05 10:35:56 +01:00
|
|
|
bool view_inhibits_keybinds(struct view *view);
|
|
|
|
|
void view_toggle_keybinds(struct view *view);
|
|
|
|
|
|
2023-09-26 01:35:36 -04:00
|
|
|
void view_focus(struct view *view);
|
|
|
|
|
void view_defocus(struct view *view);
|
2023-02-28 11:46:48 -05:00
|
|
|
void view_set_output(struct view *view, struct output *output);
|
2022-11-21 10:10:39 -05:00
|
|
|
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);
|
2023-06-27 21:20:04 +03:00
|
|
|
void view_resize_relative(struct view *view,
|
|
|
|
|
int left, int right, int top, int bottom);
|
2023-07-23 12:04:36 +03:00
|
|
|
void view_move_relative(struct view *view, int x, int y);
|
2022-11-21 10:10:39 -05:00
|
|
|
void view_move(struct view *view, int x, int y);
|
|
|
|
|
void view_moved(struct view *view);
|
|
|
|
|
void view_minimize(struct view *view, bool minimized);
|
|
|
|
|
void view_store_natural_geometry(struct view *view);
|
2023-03-05 01:58:24 -05:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 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
|
|
|
|
|
*/
|
2023-02-20 16:23:53 -05:00
|
|
|
void view_center(struct view *view, const struct wlr_box *ref);
|
2022-11-21 10:10:39 -05:00
|
|
|
void view_restore_to(struct view *view, struct wlr_box geometry);
|
2022-11-21 13:17:14 -05:00
|
|
|
void view_set_untiled(struct view *view);
|
2022-11-21 10:10:39 -05:00
|
|
|
void view_maximize(struct view *view, bool maximize,
|
|
|
|
|
bool store_natural_geometry);
|
2023-02-20 13:36:15 -05:00
|
|
|
void view_set_fullscreen(struct view *view, bool fullscreen);
|
2022-11-21 10:10:39 -05:00
|
|
|
void view_toggle_maximize(struct view *view);
|
|
|
|
|
void view_toggle_decorations(struct view *view);
|
2023-05-11 22:26:41 +01:00
|
|
|
|
2022-12-29 04:50:21 +01:00
|
|
|
bool view_is_always_on_top(struct view *view);
|
2023-05-11 22:26:41 +01:00
|
|
|
void view_toggle_always_on_top(struct view *view);
|
|
|
|
|
void view_toggle_always_on_bottom(struct view *view);
|
|
|
|
|
|
2023-01-01 18:12:20 +01:00
|
|
|
bool view_is_tiled(struct view *view);
|
2023-02-11 09:36:42 +01:00
|
|
|
bool view_is_floating(struct view *view);
|
2022-11-21 13:03:49 -05:00
|
|
|
void view_move_to_workspace(struct view *view, struct workspace *workspace);
|
2022-11-21 10:10:39 -05:00
|
|
|
void view_set_decorations(struct view *view, bool decorations);
|
|
|
|
|
void view_toggle_fullscreen(struct view *view);
|
|
|
|
|
void view_adjust_for_layout_change(struct view *view);
|
2023-08-02 04:30:50 +02:00
|
|
|
void view_move_to_edge(struct view *view, enum view_edge direction);
|
|
|
|
|
void view_snap_to_edge(struct view *view, enum view_edge direction, bool store_natural_geometry);
|
|
|
|
|
void view_snap_to_region(struct view *view, struct region *region, bool store_natural_geometry);
|
2023-04-01 14:06:52 -04:00
|
|
|
|
|
|
|
|
void view_move_to_front(struct view *view);
|
|
|
|
|
void view_move_to_back(struct view *view);
|
2023-08-02 20:57:39 +01:00
|
|
|
struct view *view_get_root(struct view *view);
|
|
|
|
|
void view_append_children(struct view *view, struct wl_array *children);
|
2023-04-01 14:06:52 -04:00
|
|
|
|
2022-11-21 10:10:39 -05:00
|
|
|
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);
|
2022-11-26 02:13:42 -05:00
|
|
|
void view_reload_ssd(struct view *view);
|
2022-11-21 10:10:39 -05:00
|
|
|
|
2023-09-22 01:22:19 -04:00
|
|
|
struct view_size_hints view_get_size_hints(struct view *view);
|
2022-11-21 10:10:39 -05:00
|
|
|
void view_adjust_size(struct view *view, int *w, int *h);
|
|
|
|
|
|
2023-02-16 11:54:18 -05:00
|
|
|
void view_evacuate_region(struct view *view);
|
2022-11-21 10:10:39 -05:00
|
|
|
void view_on_output_destroy(struct view *view);
|
|
|
|
|
void view_destroy(struct view *view);
|
|
|
|
|
|
2023-08-02 04:30:50 +02:00
|
|
|
enum view_edge view_edge_parse(const char *direction);
|
|
|
|
|
|
2022-11-25 13:41:12 -05:00
|
|
|
/* xdg.c */
|
|
|
|
|
struct wlr_xdg_surface *xdg_surface_from_view(struct view *view);
|
|
|
|
|
|
2023-05-13 16:10:33 +03:00
|
|
|
#endif /* LABWC_VIEW_H */
|