2021-11-26 19:27:50 +00:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
2023-05-13 16:10:33 +03:00
|
|
|
#ifndef LABWC_H
|
|
|
|
|
#define LABWC_H
|
2020-12-30 10:29:21 +00:00
|
|
|
#include "config.h"
|
2019-11-19 21:00:26 +00:00
|
|
|
#include <wlr/util/log.h>
|
2024-10-07 09:20:58 +09:00
|
|
|
#include "common/set.h"
|
2023-09-03 17:39:48 +02:00
|
|
|
#include "input/cursor.h"
|
2024-04-05 11:35:31 +09:00
|
|
|
#include "overlay.h"
|
2022-05-01 14:38:45 +10:00
|
|
|
#if HAVE_NLS
|
|
|
|
|
#include <libintl.h>
|
|
|
|
|
#include <locale.h>
|
|
|
|
|
#define _ gettext
|
|
|
|
|
#else
|
|
|
|
|
#define _(s) (s)
|
|
|
|
|
#endif
|
2020-06-18 20:18:01 +01:00
|
|
|
|
2019-11-19 21:00:26 +00:00
|
|
|
#define XCURSOR_DEFAULT "left_ptr"
|
|
|
|
|
#define XCURSOR_SIZE 24
|
|
|
|
|
|
2025-07-28 01:22:10 -04:00
|
|
|
struct wlr_xdg_popup;
|
|
|
|
|
|
2020-10-21 20:30:06 +01:00
|
|
|
enum input_mode {
|
|
|
|
|
LAB_INPUT_STATE_PASSTHROUGH = 0,
|
|
|
|
|
LAB_INPUT_STATE_MOVE,
|
|
|
|
|
LAB_INPUT_STATE_RESIZE,
|
2020-10-19 22:14:17 +01:00
|
|
|
LAB_INPUT_STATE_MENU,
|
2024-12-28 16:09:05 +09:00
|
|
|
LAB_INPUT_STATE_WINDOW_SWITCHER,
|
2019-11-19 21:00:26 +00:00
|
|
|
};
|
|
|
|
|
|
2020-10-02 21:19:56 +01:00
|
|
|
struct seat {
|
|
|
|
|
struct wlr_seat *seat;
|
|
|
|
|
struct server *server;
|
|
|
|
|
struct wlr_keyboard_group *keyboard_group;
|
2021-11-28 21:47:24 +00:00
|
|
|
|
2023-08-26 17:01:42 +00:00
|
|
|
struct wl_list touch_points; /* struct touch_point.link */
|
|
|
|
|
|
2022-09-12 13:14:18 -04:00
|
|
|
/*
|
2022-09-16 02:23:44 +02:00
|
|
|
* Enum of most recent server-side cursor image. Set by
|
2022-09-12 13:14:18 -04:00
|
|
|
* cursor_set(). Cleared when a client surface is entered
|
2022-09-16 02:23:44 +02:00
|
|
|
* (in that case the client is expected to set its own cursor image).
|
2022-09-12 13:14:18 -04:00
|
|
|
*/
|
2022-09-16 02:23:44 +02:00
|
|
|
enum lab_cursors server_cursor;
|
2024-11-02 15:59:33 +01:00
|
|
|
bool cursor_visible;
|
2020-10-02 21:19:56 +01:00
|
|
|
struct wlr_cursor *cursor;
|
|
|
|
|
struct wlr_xcursor_manager *xcursor_manager;
|
2025-07-22 00:19:22 +09:00
|
|
|
struct accumulated_scroll {
|
|
|
|
|
double delta;
|
|
|
|
|
double delta_discrete;
|
|
|
|
|
} accumulated_scrolls[2]; /* indexed by wl_pointer_axis */
|
2025-04-16 19:16:06 +02:00
|
|
|
bool cursor_scroll_wheel_emulation;
|
2021-11-28 21:47:24 +00:00
|
|
|
|
Clear keyboard/pointer focus on Move/Resize, window switcher and menu
The previous revert fixed the problem of stuck modifier keys with
keybinds in Blender, but made Firefox show its menu bar with Alt-*
keybinds. This is fundamentally inevitable due to the limitation of
wayland protocol, but at least for the default Alt-Tab keybind for
window switcher, we can mitigate this problem by clearing the keyboard
focus when the window switcher is activated. This is what KWin does, and
we decided to follow that.
So in this commit, keyboard and pointer focus are temporarily cleared
while Move/Resize, window switcher and menu interactions and restored
after them. We slightly deviate from KWin as KWin doesn't clear the
keyboard focus while Move/Resize, but it solves our existing problem
that Firefox shows its menu bar after dragging it with default Alt-Drag
mousebind, and this is what Mutter does.
We considered other solutions, but they don't work well:
1. Send wl_keyboard.{leave,enter} every time keybinds/mousebinds are
triggered. This solves the Firefox's menu bar problem, but that
sounds like a workaround and sending unnecessary events every time is
not desirable.
2. Send release events for both modifiers and keys even when they are
bound to keybinds. This is what Mutter is doing, but it looks like an
implementation issue and violates wayland protocol.
2024-12-29 00:48:55 +09:00
|
|
|
/*
|
|
|
|
|
* The surface whose keyboard focus is temporarily cleared with
|
|
|
|
|
* seat_focus_override_begin() and restored with
|
|
|
|
|
* seat_focus_override_end().
|
|
|
|
|
*/
|
|
|
|
|
struct {
|
|
|
|
|
struct wlr_surface *surface;
|
|
|
|
|
struct wl_listener surface_destroy;
|
|
|
|
|
} focus_override;
|
|
|
|
|
|
2021-10-17 16:54:35 -04:00
|
|
|
struct wlr_pointer_constraint_v1 *current_constraint;
|
2020-10-02 21:19:56 +01:00
|
|
|
|
2022-06-15 01:07:45 +02:00
|
|
|
/* Used to hide the workspace OSD after switching workspaces */
|
|
|
|
|
struct wl_event_source *workspace_osd_timer;
|
|
|
|
|
bool workspace_osd_shown_by_modifier;
|
|
|
|
|
|
2020-10-31 15:09:13 +00:00
|
|
|
/* if set, views cannot receive focus */
|
|
|
|
|
struct wlr_layer_surface_v1 *focused_layer;
|
|
|
|
|
|
2024-02-09 16:52:37 +09:00
|
|
|
struct input_method_relay *input_method_relay;
|
|
|
|
|
|
2022-02-26 01:21:39 +01:00
|
|
|
/**
|
2024-09-21 01:11:27 +09:00
|
|
|
* This is usually zeroed and is only set on button press while the
|
|
|
|
|
* mouse is over a view or surface, and zeroed on button release.
|
2022-02-26 01:21:39 +01:00
|
|
|
* It is used to send cursor motion events to a surface even though
|
|
|
|
|
* the cursor has left the surface in the meantime.
|
|
|
|
|
*
|
|
|
|
|
* This allows to keep dragging a scrollbar or selecting text even
|
|
|
|
|
* when moving outside of the window.
|
2022-09-14 23:09:36 -04:00
|
|
|
*
|
2024-03-08 00:53:39 +09:00
|
|
|
* It is also used to:
|
|
|
|
|
* - determine the target view for action in "Drag" mousebind
|
|
|
|
|
* - validate view move/resize requests from CSD clients
|
|
|
|
|
*
|
2022-09-14 23:09:36 -04:00
|
|
|
* Both (view && !surface) and (surface && !view) are possible.
|
2022-02-26 01:21:39 +01:00
|
|
|
*/
|
2024-09-21 01:11:27 +09:00
|
|
|
struct cursor_context pressed;
|
2022-02-26 01:21:39 +01:00
|
|
|
|
2024-10-07 09:20:58 +09:00
|
|
|
struct lab_set bound_buttons;
|
|
|
|
|
|
2022-09-18 05:40:52 +02:00
|
|
|
struct {
|
|
|
|
|
bool active;
|
|
|
|
|
struct {
|
|
|
|
|
struct wl_listener request;
|
|
|
|
|
struct wl_listener start;
|
|
|
|
|
struct wl_listener destroy;
|
|
|
|
|
} events;
|
|
|
|
|
struct wlr_scene_tree *icons;
|
|
|
|
|
} drag;
|
|
|
|
|
|
2024-04-05 11:35:31 +09:00
|
|
|
struct overlay overlay;
|
2023-03-07 17:51:28 +01:00
|
|
|
/* Used to prevent region snapping when starting a move with A-Left */
|
|
|
|
|
bool region_prevent_snap;
|
2022-07-06 07:19:28 +02:00
|
|
|
|
2020-10-02 21:19:56 +01:00
|
|
|
struct wl_list inputs;
|
|
|
|
|
struct wl_listener new_input;
|
2023-09-27 18:24:35 -04:00
|
|
|
struct wl_listener focus_change;
|
2020-10-02 21:19:56 +01:00
|
|
|
|
2025-04-15 21:43:00 +02:00
|
|
|
struct {
|
|
|
|
|
struct wl_listener motion;
|
|
|
|
|
struct wl_listener motion_absolute;
|
|
|
|
|
struct wl_listener button;
|
|
|
|
|
struct wl_listener axis;
|
|
|
|
|
struct wl_listener frame;
|
|
|
|
|
} on_cursor;
|
2020-10-02 21:19:56 +01:00
|
|
|
|
2021-12-31 23:34:08 +00:00
|
|
|
struct wlr_pointer_gestures_v1 *pointer_gestures;
|
|
|
|
|
struct wl_listener pinch_begin;
|
|
|
|
|
struct wl_listener pinch_update;
|
|
|
|
|
struct wl_listener pinch_end;
|
|
|
|
|
struct wl_listener swipe_begin;
|
|
|
|
|
struct wl_listener swipe_update;
|
|
|
|
|
struct wl_listener swipe_end;
|
2024-11-10 19:22:22 +01:00
|
|
|
struct wl_listener hold_begin;
|
|
|
|
|
struct wl_listener hold_end;
|
2021-12-31 23:34:08 +00:00
|
|
|
|
2025-04-15 21:43:00 +02:00
|
|
|
struct wl_listener request_set_cursor;
|
2023-12-02 17:56:32 +03:00
|
|
|
struct wl_listener request_set_shape;
|
2020-10-02 21:19:56 +01:00
|
|
|
struct wl_listener request_set_selection;
|
2021-08-18 23:41:07 +01:00
|
|
|
struct wl_listener request_set_primary_selection;
|
2020-10-02 21:19:56 +01:00
|
|
|
|
2021-12-31 23:50:31 +00:00
|
|
|
struct wl_listener touch_down;
|
|
|
|
|
struct wl_listener touch_up;
|
|
|
|
|
struct wl_listener touch_motion;
|
|
|
|
|
struct wl_listener touch_frame;
|
|
|
|
|
|
2024-08-09 09:25:00 +02:00
|
|
|
struct wl_listener tablet_tool_proximity;
|
|
|
|
|
struct wl_listener tablet_tool_axis;
|
|
|
|
|
struct wl_listener tablet_tool_tip;
|
|
|
|
|
struct wl_listener tablet_tool_button;
|
|
|
|
|
|
2024-06-04 20:14:30 +02:00
|
|
|
struct wl_list tablets;
|
2024-05-28 20:50:05 +02:00
|
|
|
struct wl_list tablet_tools;
|
2024-06-04 20:14:30 +02:00
|
|
|
struct wl_list tablet_pads;
|
2024-05-28 20:50:05 +02:00
|
|
|
|
2021-10-17 16:54:35 -04:00
|
|
|
struct wl_listener constraint_commit;
|
2022-09-13 10:55:59 -04:00
|
|
|
struct wl_listener pressed_surface_destroy;
|
2022-08-17 18:17:21 +00:00
|
|
|
|
|
|
|
|
struct wlr_virtual_pointer_manager_v1 *virtual_pointer;
|
|
|
|
|
struct wl_listener virtual_pointer_new;
|
2022-08-17 18:23:06 +00:00
|
|
|
|
|
|
|
|
struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard;
|
2025-06-26 18:23:09 +09:00
|
|
|
struct wl_listener new_virtual_keyboard;
|
2020-10-02 21:19:56 +01:00
|
|
|
};
|
|
|
|
|
|
2019-12-27 20:48:58 +00:00
|
|
|
struct server {
|
2019-11-19 21:00:26 +00:00
|
|
|
struct wl_display *wl_display;
|
2022-06-15 01:07:45 +02:00
|
|
|
struct wl_event_loop *wl_event_loop; /* Can be used for timer events */
|
2019-11-19 21:00:26 +00:00
|
|
|
struct wlr_renderer *renderer;
|
2021-11-21 07:01:16 +00:00
|
|
|
struct wlr_allocator *allocator;
|
2020-09-29 19:53:46 +01:00
|
|
|
struct wlr_backend *backend;
|
2023-12-09 12:01:11 +03:00
|
|
|
struct headless {
|
|
|
|
|
struct wlr_backend *backend;
|
|
|
|
|
} headless;
|
2023-01-24 04:12:02 +01:00
|
|
|
struct wlr_session *session;
|
2024-10-13 14:13:01 +02:00
|
|
|
struct wlr_linux_dmabuf_v1 *linux_dmabuf;
|
2025-06-10 05:13:07 +09:00
|
|
|
struct wlr_compositor *compositor;
|
|
|
|
|
|
|
|
|
|
struct wl_event_source *sighup_source;
|
|
|
|
|
struct wl_event_source *sigint_source;
|
|
|
|
|
struct wl_event_source *sigterm_source;
|
|
|
|
|
struct wl_event_source *sigchld_source;
|
2019-11-19 21:00:26 +00:00
|
|
|
|
|
|
|
|
struct wlr_xdg_shell *xdg_shell;
|
2020-09-30 17:18:20 +01:00
|
|
|
struct wlr_layer_shell_v1 *layer_shell;
|
|
|
|
|
|
2024-03-19 02:38:09 +01:00
|
|
|
struct wl_listener new_xdg_toplevel;
|
2020-09-30 17:18:20 +01:00
|
|
|
struct wl_listener new_layer_surface;
|
|
|
|
|
|
2023-03-22 19:56:59 +00:00
|
|
|
struct wl_listener kde_server_decoration;
|
2020-05-13 20:51:13 +01:00
|
|
|
struct wl_listener xdg_toplevel_decoration;
|
2020-12-30 10:29:21 +00:00
|
|
|
#if HAVE_XWAYLAND
|
2019-11-19 21:00:26 +00:00
|
|
|
struct wlr_xwayland *xwayland;
|
2024-01-24 18:06:57 +01:00
|
|
|
struct wl_listener xwayland_server_ready;
|
|
|
|
|
struct wl_listener xwayland_xwm_ready;
|
2023-01-07 17:50:33 -05:00
|
|
|
struct wl_listener xwayland_new_surface;
|
2020-12-30 10:29:21 +00:00
|
|
|
#endif
|
2020-10-02 21:19:56 +01:00
|
|
|
|
2023-02-04 10:07:46 +01:00
|
|
|
struct wlr_xdg_activation_v1 *xdg_activation;
|
|
|
|
|
struct wl_listener xdg_activation_request;
|
2024-07-10 20:22:52 +02:00
|
|
|
struct wl_listener xdg_activation_new_token;
|
2023-02-04 10:07:46 +01:00
|
|
|
|
2025-05-30 20:58:48 +09:00
|
|
|
struct wlr_xdg_toplevel_icon_manager_v1 *xdg_toplevel_icon_manager;
|
|
|
|
|
struct wl_listener xdg_toplevel_icon_set_icon;
|
|
|
|
|
|
2019-11-19 21:00:26 +00:00
|
|
|
struct wl_list views;
|
2020-09-04 20:25:20 +01:00
|
|
|
struct wl_list unmanaged_surfaces;
|
2019-11-19 21:00:26 +00:00
|
|
|
|
2020-10-02 21:19:56 +01:00
|
|
|
struct seat seat;
|
2022-02-11 23:12:45 +00:00
|
|
|
struct wlr_scene *scene;
|
2023-09-21 21:33:12 -04:00
|
|
|
struct wlr_scene_output_layout *scene_layout;
|
2024-07-16 20:39:48 +02:00
|
|
|
bool direct_scanout_enabled;
|
2022-02-11 23:12:45 +00:00
|
|
|
|
2020-05-18 20:54:25 +01:00
|
|
|
/* cursor interactive */
|
2020-10-21 20:30:06 +01:00
|
|
|
enum input_mode input_mode;
|
2019-12-27 20:48:58 +00:00
|
|
|
struct view *grabbed_view;
|
2024-07-20 16:58:39 +09:00
|
|
|
/* Cursor position when interactive move/resize is requested */
|
2019-11-19 21:00:26 +00:00
|
|
|
double grab_x, grab_y;
|
2024-07-20 16:58:39 +09:00
|
|
|
/* View geometry when interactive move/resize is requested */
|
2020-05-12 20:37:05 +01:00
|
|
|
struct wlr_box grab_box;
|
2019-11-19 21:00:26 +00:00
|
|
|
uint32_t resize_edges;
|
|
|
|
|
|
2023-09-26 01:35:36 -04:00
|
|
|
/*
|
2023-12-19 17:45:11 +00:00
|
|
|
* 'active_view' is generally the view with keyboard-focus, updated with
|
|
|
|
|
* each "focus change". This view is drawn with "active" SSD coloring.
|
|
|
|
|
*
|
Clear keyboard/pointer focus on Move/Resize, window switcher and menu
The previous revert fixed the problem of stuck modifier keys with
keybinds in Blender, but made Firefox show its menu bar with Alt-*
keybinds. This is fundamentally inevitable due to the limitation of
wayland protocol, but at least for the default Alt-Tab keybind for
window switcher, we can mitigate this problem by clearing the keyboard
focus when the window switcher is activated. This is what KWin does, and
we decided to follow that.
So in this commit, keyboard and pointer focus are temporarily cleared
while Move/Resize, window switcher and menu interactions and restored
after them. We slightly deviate from KWin as KWin doesn't clear the
keyboard focus while Move/Resize, but it solves our existing problem
that Firefox shows its menu bar after dragging it with default Alt-Drag
mousebind, and this is what Mutter does.
We considered other solutions, but they don't work well:
1. Send wl_keyboard.{leave,enter} every time keybinds/mousebinds are
triggered. This solves the Firefox's menu bar problem, but that
sounds like a workaround and sending unnecessary events every time is
not desirable.
2. Send release events for both modifiers and keys even when they are
bound to keybinds. This is what Mutter is doing, but it looks like an
implementation issue and violates wayland protocol.
2024-12-29 00:48:55 +09:00
|
|
|
* The exceptions are:
|
|
|
|
|
* - when a layer-shell client takes keyboard-focus in which case the
|
|
|
|
|
* currently active view stays active
|
|
|
|
|
* - when keyboard focus is temporarily cleared for server-side
|
|
|
|
|
* interactions like Move/Resize, window switcher and menus.
|
|
|
|
|
*
|
|
|
|
|
* Note that active_view is synced with foreign-toplevel clients.
|
2023-09-26 01:35:36 -04:00
|
|
|
*/
|
2023-12-19 17:45:11 +00:00
|
|
|
struct view *active_view;
|
2023-10-21 11:28:00 -04:00
|
|
|
|
2022-11-26 16:46:28 -05:00
|
|
|
struct ssd_hover_state *ssd_hover_state;
|
2022-02-21 03:18:38 +01:00
|
|
|
|
2022-02-22 07:57:17 +01:00
|
|
|
/* Tree for all non-layer xdg/xwayland-shell surfaces */
|
|
|
|
|
struct wlr_scene_tree *view_tree;
|
2023-05-20 08:58:42 +01:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Popups need to be rendered above always-on-top views, so we reparent
|
|
|
|
|
* them to this dedicated tree
|
|
|
|
|
*/
|
|
|
|
|
struct wlr_scene_tree *xdg_popup_tree;
|
|
|
|
|
|
|
|
|
|
/* Tree for all non-layer xdg/xwayland-shell surfaces with always-on-top/below */
|
2022-04-09 01:16:09 +02:00
|
|
|
struct wlr_scene_tree *view_tree_always_on_top;
|
2023-05-11 22:26:41 +01:00
|
|
|
struct wlr_scene_tree *view_tree_always_on_bottom;
|
2022-02-22 07:57:17 +01:00
|
|
|
#if HAVE_XWAYLAND
|
|
|
|
|
/* Tree for unmanaged xsurfaces without initialized view (usually popups) */
|
|
|
|
|
struct wlr_scene_tree *unmanaged_tree;
|
|
|
|
|
#endif
|
|
|
|
|
/* Tree for built in menu */
|
2022-02-19 02:05:38 +01:00
|
|
|
struct wlr_scene_tree *menu_tree;
|
2022-02-11 23:12:45 +00:00
|
|
|
|
2022-06-15 01:07:45 +02:00
|
|
|
/* Workspaces */
|
2024-07-25 21:56:05 +02:00
|
|
|
struct {
|
|
|
|
|
struct wl_list all; /* struct workspace.link */
|
|
|
|
|
struct workspace *current;
|
|
|
|
|
struct workspace *last;
|
2024-07-24 01:04:44 +02:00
|
|
|
struct lab_cosmic_workspace_manager *cosmic_manager;
|
|
|
|
|
struct lab_cosmic_workspace_group *cosmic_group;
|
2024-12-10 06:26:19 +01:00
|
|
|
struct lab_ext_workspace_manager *ext_manager;
|
|
|
|
|
struct lab_ext_workspace_group *ext_group;
|
2024-07-24 01:04:44 +02:00
|
|
|
struct {
|
|
|
|
|
struct wl_listener layout_output_added;
|
|
|
|
|
} on;
|
2024-07-25 21:56:05 +02:00
|
|
|
} workspaces;
|
2022-06-15 01:07:45 +02:00
|
|
|
|
2019-11-19 21:00:26 +00:00
|
|
|
struct wl_list outputs;
|
|
|
|
|
struct wl_listener new_output;
|
2020-10-02 21:19:56 +01:00
|
|
|
struct wlr_output_layout *output_layout;
|
2020-05-25 13:42:40 +01:00
|
|
|
|
2021-02-27 23:15:02 -05:00
|
|
|
struct wl_listener output_layout_change;
|
|
|
|
|
struct wlr_output_manager_v1 *output_manager;
|
2024-01-22 15:22:26 +01:00
|
|
|
struct wl_listener output_manager_test;
|
2021-02-27 23:15:02 -05:00
|
|
|
struct wl_listener output_manager_apply;
|
2022-09-20 01:17:22 -04:00
|
|
|
/*
|
|
|
|
|
* While an output layout change is in process, this counter is
|
|
|
|
|
* non-zero and causes change-events from the wlr_output_layout
|
|
|
|
|
* to be ignored (to prevent, for example, moving views in a
|
|
|
|
|
* transitory layout state). Once the counter reaches zero,
|
|
|
|
|
* do_output_layout_change() must be called explicitly.
|
|
|
|
|
*/
|
|
|
|
|
int pending_output_layout_change;
|
2021-02-27 23:15:02 -05:00
|
|
|
|
2024-07-17 17:13:51 -07:00
|
|
|
struct wl_listener renderer_lost;
|
|
|
|
|
|
2023-12-01 17:07:05 +00:00
|
|
|
struct wlr_gamma_control_manager_v1 *gamma_control_manager_v1;
|
|
|
|
|
struct wl_listener gamma_control_set_gamma;
|
|
|
|
|
|
2024-05-30 00:13:34 +09:00
|
|
|
struct session_lock_manager *session_lock_manager;
|
2023-03-30 22:19:05 +01:00
|
|
|
|
2021-08-05 12:18:10 +01:00
|
|
|
struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager;
|
2024-08-12 20:34:25 +02:00
|
|
|
struct wlr_ext_foreign_toplevel_list_v1 *foreign_toplevel_list;
|
2021-08-05 12:18:10 +01:00
|
|
|
|
2022-03-26 04:51:54 +00:00
|
|
|
struct wlr_drm_lease_v1_manager *drm_lease_manager;
|
|
|
|
|
struct wl_listener drm_lease_request;
|
|
|
|
|
|
2022-03-06 04:46:11 +00:00
|
|
|
struct wlr_output_power_manager_v1 *output_power_manager_v1;
|
|
|
|
|
struct wl_listener output_power_manager_set_mode;
|
|
|
|
|
|
2021-10-17 16:54:35 -04:00
|
|
|
struct wlr_relative_pointer_manager_v1 *relative_pointer_manager;
|
|
|
|
|
struct wlr_pointer_constraints_v1 *constraints;
|
|
|
|
|
struct wl_listener new_constraint;
|
|
|
|
|
|
2024-01-08 22:58:58 +02:00
|
|
|
struct wlr_tearing_control_manager_v1 *tearing_control;
|
|
|
|
|
struct wl_listener tearing_new_object;
|
|
|
|
|
|
2024-02-09 16:52:37 +09:00
|
|
|
struct wlr_input_method_manager_v2 *input_method_manager;
|
|
|
|
|
struct wlr_text_input_manager_v3 *text_input_manager;
|
|
|
|
|
|
2024-04-11 23:48:00 +02:00
|
|
|
struct wlr_tablet_manager_v2 *tablet_manager;
|
2024-05-16 12:52:47 +03:00
|
|
|
struct wlr_security_context_manager_v1 *security_context_manager_v1;
|
2024-04-11 23:48:00 +02:00
|
|
|
|
2020-09-04 20:25:20 +01:00
|
|
|
/* Set when in cycle (alt-tab) mode */
|
2022-04-26 22:06:22 +02:00
|
|
|
struct osd_state {
|
|
|
|
|
struct view *cycle_view;
|
2022-04-26 23:56:27 +02:00
|
|
|
bool preview_was_enabled;
|
2022-04-26 22:06:22 +02:00
|
|
|
struct wlr_scene_node *preview_node;
|
2024-03-05 21:01:39 +00:00
|
|
|
struct wlr_scene_tree *preview_parent;
|
2022-04-26 22:06:22 +02:00
|
|
|
struct wlr_scene_node *preview_anchor;
|
2025-06-09 16:27:17 +09:00
|
|
|
struct lab_scene_rect *preview_outline;
|
2022-04-26 22:06:22 +02:00
|
|
|
} osd_state;
|
2020-10-19 22:14:17 +01:00
|
|
|
|
2021-02-21 21:54:40 +00:00
|
|
|
struct theme *theme;
|
2022-02-12 19:43:32 +00:00
|
|
|
|
2022-02-19 02:05:38 +01:00
|
|
|
struct menu *menu_current;
|
2023-10-09 20:59:04 +01:00
|
|
|
struct wl_list menus;
|
2024-03-09 17:12:54 +00:00
|
|
|
|
2024-11-18 18:59:49 +01:00
|
|
|
struct sfdo *sfdo;
|
2024-09-06 17:00:40 +09:00
|
|
|
|
2024-03-09 17:12:54 +00:00
|
|
|
pid_t primary_client_pid;
|
2019-11-19 21:00:26 +00:00
|
|
|
};
|
|
|
|
|
|
2021-03-02 20:37:23 +00:00
|
|
|
void xdg_popup_create(struct view *view, struct wlr_xdg_popup *wlr_popup);
|
2023-10-20 22:04:08 +01:00
|
|
|
void xdg_shell_init(struct server *server);
|
2025-02-08 15:48:50 +01:00
|
|
|
void xdg_shell_finish(struct server *server);
|
2019-12-26 21:37:31 +00:00
|
|
|
|
2021-10-16 19:44:54 +01:00
|
|
|
/*
|
|
|
|
|
* desktop.c routines deal with a collection of views
|
|
|
|
|
*
|
|
|
|
|
* Definition of a few keywords used in desktop.c
|
|
|
|
|
* raise - Bring view to front.
|
|
|
|
|
* focus - Give keyboard focus to view.
|
|
|
|
|
* activate - Set view surface as active so that client window decorations
|
|
|
|
|
* are painted to show that the window is active,typically by
|
|
|
|
|
* using a different color. Although xdg-shell protocol says you
|
|
|
|
|
* cannot assume this means that the window actually has keyboard
|
|
|
|
|
* or pointer focus, in this compositor are they called together.
|
|
|
|
|
*/
|
2023-10-02 22:37:12 -04:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* desktop_focus_view() - do multiple things to make a view "active" and
|
|
|
|
|
* ready to use:
|
|
|
|
|
* - unminimize
|
|
|
|
|
* - switch to the workspace it's on
|
|
|
|
|
* - give input (keyboard) focus
|
|
|
|
|
* - optionally raise above other views
|
|
|
|
|
*
|
|
|
|
|
* It's okay to call this function even if the view isn't mapped or the
|
2024-03-19 00:32:47 +01:00
|
|
|
* session is locked; it will simply do nothing.
|
2023-10-02 22:37:12 -04:00
|
|
|
*/
|
2023-09-27 18:37:28 -04:00
|
|
|
void desktop_focus_view(struct view *view, bool raise);
|
2023-11-01 23:01:19 -04:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* desktop_focus_view_or_surface() - like desktop_focus_view() but can
|
|
|
|
|
* also focus other (e.g. xwayland-unmanaged) surfaces
|
|
|
|
|
*/
|
|
|
|
|
void desktop_focus_view_or_surface(struct seat *seat, struct view *view,
|
|
|
|
|
struct wlr_surface *surface, bool raise);
|
|
|
|
|
|
2022-06-30 20:02:24 +02:00
|
|
|
void desktop_arrange_all_views(struct server *server);
|
2023-03-05 17:16:23 +01:00
|
|
|
void desktop_focus_output(struct output *output);
|
2023-09-23 11:51:47 -04:00
|
|
|
struct view *desktop_topmost_focusable_view(struct server *server);
|
2020-09-11 20:48:28 +01:00
|
|
|
|
2023-11-10 23:58:25 +01:00
|
|
|
/**
|
|
|
|
|
* Toggles the (output local) visibility of the layershell top layer
|
|
|
|
|
* based on the existence of a fullscreen window on the current workspace.
|
|
|
|
|
*/
|
2025-01-08 23:35:23 -04:00
|
|
|
void desktop_update_top_layer_visibility(struct server *server);
|
2023-11-10 23:58:25 +01:00
|
|
|
|
2023-10-02 22:37:12 -04:00
|
|
|
/**
|
|
|
|
|
* desktop_focus_topmost_view() - focus the topmost view on the current
|
|
|
|
|
* workspace, skipping views that claim not to want focus (those can
|
|
|
|
|
* still be focused by explicit request, e.g. by clicking in them).
|
|
|
|
|
*
|
|
|
|
|
* This function is typically called when the focused view is hidden
|
|
|
|
|
* (closes, is minimized, etc.) to focus the "next" view underneath.
|
|
|
|
|
*/
|
2023-09-23 11:51:47 -04:00
|
|
|
void desktop_focus_topmost_view(struct server *server);
|
2021-07-12 16:44:30 +01:00
|
|
|
|
2020-10-02 21:19:56 +01:00
|
|
|
void seat_init(struct server *server);
|
|
|
|
|
void seat_finish(struct server *server);
|
2021-10-10 12:03:18 -04:00
|
|
|
void seat_reconfigure(struct server *server);
|
2020-10-08 20:22:52 +01:00
|
|
|
void seat_focus_surface(struct seat *seat, struct wlr_surface *surface);
|
2023-10-15 02:59:58 -04:00
|
|
|
|
2024-11-01 09:11:33 +01:00
|
|
|
void seat_pointer_end_grab(struct seat *seat, struct wlr_surface *surface);
|
|
|
|
|
|
2023-10-15 02:59:58 -04:00
|
|
|
/**
|
|
|
|
|
* seat_focus_lock_surface() - ONLY to be called from session-lock.c to
|
|
|
|
|
* focus lock screen surfaces. Use seat_focus_surface() otherwise.
|
|
|
|
|
*/
|
|
|
|
|
void seat_focus_lock_surface(struct seat *seat, struct wlr_surface *surface);
|
|
|
|
|
|
2020-10-31 15:09:13 +00:00
|
|
|
void seat_set_focus_layer(struct seat *seat, struct wlr_layer_surface_v1 *layer);
|
2024-09-21 01:11:27 +09:00
|
|
|
void seat_set_pressed(struct seat *seat, struct cursor_context *ctx);
|
2022-09-01 17:50:28 -04:00
|
|
|
void seat_reset_pressed(struct seat *seat);
|
2024-01-09 06:58:35 +01:00
|
|
|
void seat_output_layout_changed(struct seat *seat);
|
2020-09-04 20:25:20 +01:00
|
|
|
|
Clear keyboard/pointer focus on Move/Resize, window switcher and menu
The previous revert fixed the problem of stuck modifier keys with
keybinds in Blender, but made Firefox show its menu bar with Alt-*
keybinds. This is fundamentally inevitable due to the limitation of
wayland protocol, but at least for the default Alt-Tab keybind for
window switcher, we can mitigate this problem by clearing the keyboard
focus when the window switcher is activated. This is what KWin does, and
we decided to follow that.
So in this commit, keyboard and pointer focus are temporarily cleared
while Move/Resize, window switcher and menu interactions and restored
after them. We slightly deviate from KWin as KWin doesn't clear the
keyboard focus while Move/Resize, but it solves our existing problem
that Firefox shows its menu bar after dragging it with default Alt-Drag
mousebind, and this is what Mutter does.
We considered other solutions, but they don't work well:
1. Send wl_keyboard.{leave,enter} every time keybinds/mousebinds are
triggered. This solves the Firefox's menu bar problem, but that
sounds like a workaround and sending unnecessary events every time is
not desirable.
2. Send release events for both modifiers and keys even when they are
bound to keybinds. This is what Mutter is doing, but it looks like an
implementation issue and violates wayland protocol.
2024-12-29 00:48:55 +09:00
|
|
|
/*
|
|
|
|
|
* Temporarily clear the pointer/keyboard focus from the client at the
|
|
|
|
|
* beginning of interactive move/resize, window switcher or menu interactions.
|
|
|
|
|
* The focus is kept cleared until seat_focus_override_end() is called or
|
|
|
|
|
* layer-shell/session-lock surfaces are mapped.
|
|
|
|
|
*/
|
|
|
|
|
void seat_focus_override_begin(struct seat *seat, enum input_mode input_mode,
|
|
|
|
|
enum lab_cursors cursor_shape);
|
|
|
|
|
/*
|
|
|
|
|
* Restore the pointer/keyboard focus which was cleared in
|
|
|
|
|
* seat_focus_override_begin().
|
|
|
|
|
*/
|
|
|
|
|
void seat_focus_override_end(struct seat *seat);
|
|
|
|
|
|
xdg: handle initially maximized xdg-shell views better
Currently, initially maximized (or fullscreen) xdg-shell views exhibit
one of two issues:
- some (e.g. GTK and Qt apps) paint an initial frame un-maximized
(before the "map" event) and only maximize in a later commit
- others (e.g. foot) maximize immediately without flicker, but never
store a valid natural size, so we end up using a fallback (640x480)
Under KWin, neither of these issues occur, so I looked into what labwc
is doing wrong. It seems that:
- wlroots internally sends an initial configure event with a size of
0x0 to all xdg-shell views. This requests the client to set its own
preferred (a.k.a. natural) size.
- For an initially maximized/fullscreen view, the initial configure
event should contain the maximized/fullscreen size rather than 0x0.
In labwc, this means we have to call wlr_xdg_toplevel_set_size()
earlier, i.e. from the new_surface event. Tracing with WAYLAND_DEBUG
shows that the initial configure event now has the correct geometry,
matching KWin behavior. With this change, GTK and Qt apps no longer
paint an incorrect un-maximized frame.
- However, this means that all xdg-shell views now suffer from the same
issue as foot, where we never receive a commit with the un-maximized
(natural) geometry. The correct way to get the natural geometry seems
to be to wait until we want to un-maximize, and send a configure
event of 0x0 at that point.
Sending a configure event of 0x0 when un-maximizing is a bit annoying as
it breaks some assumptions in labwc code. In particular:
- view->natural_geometry may now be unknown (0x0), requiring various
wlr_box_empty() checks sprinkled around. I added these in all the
obvious places, but there could be some code paths that I missed.
- Positioning the newly un-maximized view within view_maximize() no
longer works since we don't know the natural size. Instead we have to
run the positioning logic from the surface commit handler. This
results in some extra complexity, especially for interactive move.
See the new do_late_positioning() function in xdg.c.
Some TODOs/FIXMEs (non-blocking in my opinion):
- The view_wants_decorations() check is now duplicated in both the
new_surface and map event handlers. I'm not sure if this is necessary
but it seemed like the safest approach for now. More testing would be
nice, particularly with various combinations of config and client SSD
preferences.
- Aside from the interactive move case, the "late positioning" logic
always centers the view when un-maximizing, and does not invoke any
of the smart placement logic. If we want to invoke smart placement
here, I'd appreciate someone with more knowledge of that code to take
a look and figure out how to do that correctly.
2024-07-02 07:24:29 -04:00
|
|
|
/**
|
2024-08-07 09:17:25 +09:00
|
|
|
* interactive_anchor_to_cursor() - repositions the geometry to remain
|
xdg: handle initially maximized xdg-shell views better
Currently, initially maximized (or fullscreen) xdg-shell views exhibit
one of two issues:
- some (e.g. GTK and Qt apps) paint an initial frame un-maximized
(before the "map" event) and only maximize in a later commit
- others (e.g. foot) maximize immediately without flicker, but never
store a valid natural size, so we end up using a fallback (640x480)
Under KWin, neither of these issues occur, so I looked into what labwc
is doing wrong. It seems that:
- wlroots internally sends an initial configure event with a size of
0x0 to all xdg-shell views. This requests the client to set its own
preferred (a.k.a. natural) size.
- For an initially maximized/fullscreen view, the initial configure
event should contain the maximized/fullscreen size rather than 0x0.
In labwc, this means we have to call wlr_xdg_toplevel_set_size()
earlier, i.e. from the new_surface event. Tracing with WAYLAND_DEBUG
shows that the initial configure event now has the correct geometry,
matching KWin behavior. With this change, GTK and Qt apps no longer
paint an incorrect un-maximized frame.
- However, this means that all xdg-shell views now suffer from the same
issue as foot, where we never receive a commit with the un-maximized
(natural) geometry. The correct way to get the natural geometry seems
to be to wait until we want to un-maximize, and send a configure
event of 0x0 at that point.
Sending a configure event of 0x0 when un-maximizing is a bit annoying as
it breaks some assumptions in labwc code. In particular:
- view->natural_geometry may now be unknown (0x0), requiring various
wlr_box_empty() checks sprinkled around. I added these in all the
obvious places, but there could be some code paths that I missed.
- Positioning the newly un-maximized view within view_maximize() no
longer works since we don't know the natural size. Instead we have to
run the positioning logic from the surface commit handler. This
results in some extra complexity, especially for interactive move.
See the new do_late_positioning() function in xdg.c.
Some TODOs/FIXMEs (non-blocking in my opinion):
- The view_wants_decorations() check is now duplicated in both the
new_surface and map event handlers. I'm not sure if this is necessary
but it seemed like the safest approach for now. More testing would be
nice, particularly with various combinations of config and client SSD
preferences.
- Aside from the interactive move case, the "late positioning" logic
always centers the view when un-maximizing, and does not invoke any
of the smart placement logic. If we want to invoke smart placement
here, I'd appreciate someone with more knowledge of that code to take
a look and figure out how to do that correctly.
2024-07-02 07:24:29 -04:00
|
|
|
* underneath the cursor when its size changes during interactive move.
|
2024-08-07 09:17:25 +09:00
|
|
|
* This function also resizes server->grab_box and repositions it to remain
|
|
|
|
|
* underneath server->grab_{x,y}.
|
xdg: handle initially maximized xdg-shell views better
Currently, initially maximized (or fullscreen) xdg-shell views exhibit
one of two issues:
- some (e.g. GTK and Qt apps) paint an initial frame un-maximized
(before the "map" event) and only maximize in a later commit
- others (e.g. foot) maximize immediately without flicker, but never
store a valid natural size, so we end up using a fallback (640x480)
Under KWin, neither of these issues occur, so I looked into what labwc
is doing wrong. It seems that:
- wlroots internally sends an initial configure event with a size of
0x0 to all xdg-shell views. This requests the client to set its own
preferred (a.k.a. natural) size.
- For an initially maximized/fullscreen view, the initial configure
event should contain the maximized/fullscreen size rather than 0x0.
In labwc, this means we have to call wlr_xdg_toplevel_set_size()
earlier, i.e. from the new_surface event. Tracing with WAYLAND_DEBUG
shows that the initial configure event now has the correct geometry,
matching KWin behavior. With this change, GTK and Qt apps no longer
paint an incorrect un-maximized frame.
- However, this means that all xdg-shell views now suffer from the same
issue as foot, where we never receive a commit with the un-maximized
(natural) geometry. The correct way to get the natural geometry seems
to be to wait until we want to un-maximize, and send a configure
event of 0x0 at that point.
Sending a configure event of 0x0 when un-maximizing is a bit annoying as
it breaks some assumptions in labwc code. In particular:
- view->natural_geometry may now be unknown (0x0), requiring various
wlr_box_empty() checks sprinkled around. I added these in all the
obvious places, but there could be some code paths that I missed.
- Positioning the newly un-maximized view within view_maximize() no
longer works since we don't know the natural size. Instead we have to
run the positioning logic from the surface commit handler. This
results in some extra complexity, especially for interactive move.
See the new do_late_positioning() function in xdg.c.
Some TODOs/FIXMEs (non-blocking in my opinion):
- The view_wants_decorations() check is now duplicated in both the
new_surface and map event handlers. I'm not sure if this is necessary
but it seemed like the safest approach for now. More testing would be
nice, particularly with various combinations of config and client SSD
preferences.
- Aside from the interactive move case, the "late positioning" logic
always centers the view when un-maximizing, and does not invoke any
of the smart placement logic. If we want to invoke smart placement
here, I'd appreciate someone with more knowledge of that code to take
a look and figure out how to do that correctly.
2024-07-02 07:24:29 -04:00
|
|
|
*
|
2024-08-07 09:17:25 +09:00
|
|
|
* geo->{width,height} are provided by the caller.
|
|
|
|
|
* geo->{x,y} are computed by this function.
|
2024-07-20 16:58:39 +09:00
|
|
|
*/
|
2024-08-07 09:17:25 +09:00
|
|
|
void interactive_anchor_to_cursor(struct server *server, struct wlr_box *geo);
|
2024-07-20 16:58:39 +09:00
|
|
|
|
2023-01-31 11:43:45 +01:00
|
|
|
void interactive_begin(struct view *view, enum input_mode mode, uint32_t edges);
|
2022-11-19 12:58:52 -05:00
|
|
|
void interactive_finish(struct view *view);
|
|
|
|
|
void interactive_cancel(struct view *view);
|
2025-08-02 21:35:51 +09:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the edge to snap a window to.
|
|
|
|
|
* For example, if the output-relative cursor position (x,y) fulfills
|
|
|
|
|
* x <= (<snapping><cornerRange>) and y <= (<snapping><range>),
|
|
|
|
|
* then edge1=VIEW_EDGE_UP and edge2=VIEW_EDGE_LEFT.
|
|
|
|
|
* The value of (edge1|edge2) can be passed to view_snap_to_edge().
|
|
|
|
|
*/
|
|
|
|
|
bool edge_from_cursor(struct seat *seat, struct output **dest_output,
|
|
|
|
|
enum view_edge *edge1, enum view_edge *edge2);
|
2020-05-29 21:27:34 +01:00
|
|
|
|
2025-06-26 18:23:09 +09:00
|
|
|
void handle_tearing_new_object(struct wl_listener *listener, void *data);
|
2021-02-27 23:15:02 -05:00
|
|
|
|
2020-06-03 18:39:46 +01:00
|
|
|
void server_init(struct server *server);
|
|
|
|
|
void server_start(struct server *server);
|
|
|
|
|
void server_finish(struct server *server);
|
2019-12-26 21:37:31 +00:00
|
|
|
|
2021-10-17 16:54:35 -04:00
|
|
|
void create_constraint(struct wl_listener *listener, void *data);
|
|
|
|
|
void constrain_cursor(struct server *server, struct wlr_pointer_constraint_v1
|
|
|
|
|
*constraint);
|
|
|
|
|
|
2023-05-13 16:10:33 +03:00
|
|
|
#endif /* LABWC_H */
|