step 5: extract protocol init to wl_extensions.c (protocol globals + 5 handler relocations)
This commit is contained in:
parent
b5aa99542c
commit
e78cef743e
|
|
@ -132,6 +132,8 @@ void W_UnregisterBacking(unsigned long id);
|
|||
/* Forward declarations */
|
||||
|
||||
#include "wl_types.h"
|
||||
|
||||
extern void wl_protocols_init(void);
|
||||
extern void wm_dock_app_add(struct wl_toplevel_view *v);
|
||||
extern void wm_dock_app_remove(WNativeWindow id);
|
||||
|
||||
|
|
@ -196,9 +198,9 @@ extern void handle_pointer_motion(struct wl_listener *listener, void *data);
|
|||
extern struct wlr_surface *view_surface_at(int px, int py, double *sx_out,
|
||||
double *sy_out, struct wl_toplevel_view **view_out);
|
||||
extern void handle_seat_request_cursor(struct wl_listener *listener, void *data);
|
||||
static void handle_seat_request_set_selection(struct wl_listener *listener, void *data);
|
||||
void handle_seat_request_set_selection(struct wl_listener *listener, void *data);
|
||||
void handle_seat_request_start_drag(struct wl_listener *listener, void *data);
|
||||
static void handle_seat_request_primary_selection(struct wl_listener *listener, void *data);
|
||||
void handle_seat_request_primary_selection(struct wl_listener *listener, void *data);
|
||||
/* Compositor-internal clipboard hooks for WINGs. */
|
||||
void wl_clipboard_store_to_seat(const char *text, int len);
|
||||
char *wl_clipboard_fetch_from_seat(int *len_out);
|
||||
|
|
@ -208,10 +210,10 @@ void wl_drag_icon_show(struct W_View *view, int x, int y);
|
|||
void wl_drag_icon_move(int x, int y);
|
||||
void wl_drag_icon_hide(void);
|
||||
void wl_drag_cursor_feedback(Bool accepted);
|
||||
static void handle_idle_new_inhibitor(struct wl_listener *listener, void *data);
|
||||
void handle_idle_new_inhibitor(struct wl_listener *listener, void *data);
|
||||
extern void handle_pointer_axis(struct wl_listener *listener, void *data);
|
||||
static void handle_new_pointer_constraint(struct wl_listener *listener, void *data);
|
||||
static void handle_new_shortcuts_inhibitor(struct wl_listener *listener, void *data);
|
||||
void handle_new_pointer_constraint(struct wl_listener *listener, void *data);
|
||||
void handle_new_shortcuts_inhibitor(struct wl_listener *listener, void *data);
|
||||
extern void handle_output_mgr_apply(struct wl_listener *listener, void *data);
|
||||
extern void handle_output_mgr_test(struct wl_listener *listener, void *data);
|
||||
extern void handle_output_power_set_mode(struct wl_listener *listener, void *data);
|
||||
|
|
@ -524,250 +526,7 @@ wl_display_open(const char *name)
|
|||
wl_state.socket_name,
|
||||
getenv("DISPLAY") ? getenv("DISPLAY") : "(unset)");
|
||||
|
||||
wl_state.compositor =
|
||||
wlr_compositor_create(wl_state.display, 6, wl_state.renderer);
|
||||
wlr_subcompositor_create(wl_state.display);
|
||||
wl_state.seat = wlr_seat_create(wl_state.display, "seat0");
|
||||
wl_state.data_device_mgr =
|
||||
wlr_data_device_manager_create(wl_state.display);
|
||||
|
||||
if (wl_state.seat) {
|
||||
wl_state.seat_request_cursor_listener.notify = handle_seat_request_cursor;
|
||||
wl_signal_add(&wl_state.seat->events.request_set_cursor,
|
||||
&wl_state.seat_request_cursor_listener);
|
||||
}
|
||||
/* handle clipboard set-selection requests on the seat so
|
||||
* Ctrl-C / copy operations from clients propagate to the seat selection
|
||||
* and become available for paste in other clients. */
|
||||
if (wl_state.seat) {
|
||||
wl_state.seat_request_set_selection_listener.notify =
|
||||
handle_seat_request_set_selection;
|
||||
wl_signal_add(&wl_state.seat->events.request_set_selection,
|
||||
&wl_state.seat_request_set_selection_listener);
|
||||
wwarning("wl_backend: clipboard selection wired");
|
||||
|
||||
wl_state.seat_request_start_drag_listener.notify =
|
||||
handle_seat_request_start_drag;
|
||||
wl_signal_add(&wl_state.seat->events.request_start_drag,
|
||||
&wl_state.seat_request_start_drag_listener);
|
||||
wwarning("wl_backend: DND start_drag wired");
|
||||
}
|
||||
|
||||
/* primary selection (middle-click paste) via
|
||||
* zwp_primary_selection_device_manager_v1. */
|
||||
wl_state.primary_selection_mgr =
|
||||
wlr_primary_selection_v1_device_manager_create(wl_state.display);
|
||||
if (wl_state.primary_selection_mgr && wl_state.seat) {
|
||||
wl_state.seat_request_primary_selection_listener.notify =
|
||||
handle_seat_request_primary_selection;
|
||||
wl_signal_add(&wl_state.seat->events.request_set_primary_selection,
|
||||
&wl_state.seat_request_primary_selection_listener);
|
||||
wwarning("wl_backend: primary selection (middle-click) wired");
|
||||
}
|
||||
|
||||
/* xdg-output — panels and HiDPI apps query logical output
|
||||
* geometry via zxdg_output_manager_v1. Requires output_layout. */
|
||||
if (wl_state.output_layout) {
|
||||
wl_state.xdg_output_mgr =
|
||||
wlr_xdg_output_manager_v1_create(wl_state.display,
|
||||
wl_state.output_layout);
|
||||
if (wl_state.xdg_output_mgr)
|
||||
wwarning("wl_backend: xdg-output-manager created");
|
||||
}
|
||||
|
||||
/* idle-inhibit — video players and games create inhibitor
|
||||
* objects to suppress screen blanking while active. */
|
||||
wl_state.idle_inhibit_mgr =
|
||||
wlr_idle_inhibit_v1_create(wl_state.display);
|
||||
if (wl_state.idle_inhibit_mgr) {
|
||||
wl_state.idle_new_inhibitor_listener.notify = handle_idle_new_inhibitor;
|
||||
wl_signal_add(&wl_state.idle_inhibit_mgr->events.new_inhibitor,
|
||||
&wl_state.idle_new_inhibitor_listener);
|
||||
wwarning("wl_backend: idle-inhibit manager created");
|
||||
}
|
||||
|
||||
/* wp_viewporter — hardware video scaling and subsurface damage
|
||||
* subset used by mpv, Chromium, Firefox, SDL2. */
|
||||
wl_state.viewporter = wlr_viewporter_create(wl_state.display);
|
||||
if (wl_state.viewporter)
|
||||
wwarning("wl_backend: wp_viewporter created");
|
||||
else
|
||||
wwarning("wl_backend: wp_viewporter unavailable");
|
||||
|
||||
wl_state.relative_pointer_mgr =
|
||||
wlr_relative_pointer_manager_v1_create(wl_state.display);
|
||||
if (wl_state.relative_pointer_mgr)
|
||||
wwarning("wl_backend: relative-pointer-manager created");
|
||||
|
||||
wl_state.pointer_constraints =
|
||||
wlr_pointer_constraints_v1_create(wl_state.display);
|
||||
if (wl_state.pointer_constraints) {
|
||||
wl_state.new_constraint_listener.notify = handle_new_pointer_constraint;
|
||||
wl_signal_add(&wl_state.pointer_constraints->events.new_constraint,
|
||||
&wl_state.new_constraint_listener);
|
||||
wwarning("wl_backend: pointer-constraints created");
|
||||
}
|
||||
|
||||
/* keyboard shortcuts inhibitor — fullscreen apps / remote desktop
|
||||
* request to suppress WM keyboard shortcuts. */
|
||||
wl_state.shortcuts_inhibit_mgr =
|
||||
wlr_keyboard_shortcuts_inhibit_v1_create(wl_state.display);
|
||||
if (wl_state.shortcuts_inhibit_mgr) {
|
||||
wl_state.new_shortcuts_inhibitor_listener.notify =
|
||||
handle_new_shortcuts_inhibitor;
|
||||
wl_signal_add(&wl_state.shortcuts_inhibit_mgr->events.new_inhibitor,
|
||||
&wl_state.new_shortcuts_inhibitor_listener);
|
||||
wwarning("wl_backend: keyboard-shortcuts-inhibit created");
|
||||
}
|
||||
/* GPU zero-copy (linux-dmabuf), screencopy, export-dmabuf.
|
||||
* All three are purely passive globals: wlroots handles the protocol
|
||||
* implementation internally; no event listeners are required. */
|
||||
wl_state.linux_dmabuf =
|
||||
wlr_linux_dmabuf_v1_create_with_renderer(wl_state.display, 4, wl_state.renderer);
|
||||
if (wl_state.linux_dmabuf)
|
||||
wwarning("wl_backend: linux-dmabuf created (zwp_linux_dmabuf_v1)");
|
||||
else
|
||||
wwarning("wl_backend: linux-dmabuf unavailable (renderer has no DRM FD)");
|
||||
wl_state.screencopy_mgr =
|
||||
wlr_screencopy_manager_v1_create(wl_state.display);
|
||||
if (wl_state.screencopy_mgr)
|
||||
wwarning("wl_backend: screencopy manager created (zwlr_screencopy_manager_v1)");
|
||||
wl_state.export_dmabuf_mgr =
|
||||
wlr_export_dmabuf_manager_v1_create(wl_state.display);
|
||||
if (wl_state.export_dmabuf_mgr)
|
||||
wwarning("wl_backend: export-dmabuf manager created (zwlr_export_dmabuf_manager_v1)");
|
||||
|
||||
/* output management (wlr-output-management), output power (DPMS),
|
||||
* gamma control (Night Light / redshift), and presentation time feedback. */
|
||||
wl_state.output_mgr = wlr_output_manager_v1_create(wl_state.display);
|
||||
if (wl_state.output_mgr) {
|
||||
wl_state.output_mgr_apply_listener.notify = handle_output_mgr_apply;
|
||||
wl_signal_add(&wl_state.output_mgr->events.apply,
|
||||
&wl_state.output_mgr_apply_listener);
|
||||
wl_state.output_mgr_test_listener.notify = handle_output_mgr_test;
|
||||
wl_signal_add(&wl_state.output_mgr->events.test,
|
||||
&wl_state.output_mgr_test_listener);
|
||||
wwarning("wl_backend: output-management created (zwlr_output_management_v1)");
|
||||
}
|
||||
wl_state.output_power_mgr = wlr_output_power_manager_v1_create(wl_state.display);
|
||||
if (wl_state.output_power_mgr) {
|
||||
wl_state.output_power_set_mode_listener.notify = handle_output_power_set_mode;
|
||||
wl_signal_add(&wl_state.output_power_mgr->events.set_mode,
|
||||
&wl_state.output_power_set_mode_listener);
|
||||
wwarning("wl_backend: output-power-management created (zwlr_output_power_management_v1)");
|
||||
}
|
||||
wl_state.gamma_control_mgr = wlr_gamma_control_manager_v1_create(wl_state.display);
|
||||
if (wl_state.gamma_control_mgr)
|
||||
wwarning("wl_backend: gamma-control created (zwlr_gamma_control_manager_v1)");
|
||||
wl_state.presentation = wlr_presentation_create(wl_state.display, wl_state.backend, 1);
|
||||
if (wl_state.presentation)
|
||||
wwarning("wl_backend: presentation-time created (wp_presentation)");
|
||||
|
||||
/* text input v3, input method v2, virtual keyboard v1.
|
||||
* All three are passive globals for IME / on-screen keyboard support. */
|
||||
wl_state.text_input_mgr =
|
||||
wlr_text_input_manager_v3_create(wl_state.display);
|
||||
if (wl_state.text_input_mgr) {
|
||||
wl_state.text_input_new_listener.notify = handle_text_input_new;
|
||||
wl_signal_add(&wl_state.text_input_mgr->events.text_input,
|
||||
&wl_state.text_input_new_listener);
|
||||
wwarning("wl_backend: text-input-v3 created (zwp_text_input_manager_v3)");
|
||||
}
|
||||
wl_state.input_method_mgr =
|
||||
wlr_input_method_manager_v2_create(wl_state.display);
|
||||
if (wl_state.input_method_mgr) {
|
||||
wl_state.input_method_new_listener.notify = handle_input_method_new;
|
||||
wl_signal_add(&wl_state.input_method_mgr->events.input_method,
|
||||
&wl_state.input_method_new_listener);
|
||||
wwarning("wl_backend: input-method-v2 created (zwp_input_method_manager_v2)");
|
||||
}
|
||||
wl_state.virtual_keyboard_mgr =
|
||||
wlr_virtual_keyboard_manager_v1_create(wl_state.display);
|
||||
if (wl_state.virtual_keyboard_mgr) {
|
||||
wl_state.virtual_keyboard_new_listener.notify = handle_virtual_keyboard_new;
|
||||
wl_signal_add(&wl_state.virtual_keyboard_mgr->events.new_virtual_keyboard,
|
||||
&wl_state.virtual_keyboard_new_listener);
|
||||
wwarning("wl_backend: virtual-keyboard-v1 created (zwp_virtual_keyboard_manager_v1)");
|
||||
}
|
||||
|
||||
/* foreign toplevel management — lets taskbars enumerate windows.
|
||||
* xdg_activation — focus-token protocol replacing _NET_ACTIVE_WINDOW. */
|
||||
wl_state.foreign_toplevel_mgr =
|
||||
wlr_foreign_toplevel_manager_v1_create(wl_state.display);
|
||||
if (wl_state.foreign_toplevel_mgr)
|
||||
wwarning("wl_backend: foreign-toplevel-management created (zwlr_foreign_toplevel_management_v1)");
|
||||
wl_state.xdg_activation = wlr_xdg_activation_v1_create(wl_state.display);
|
||||
if (wl_state.xdg_activation) {
|
||||
wl_state.xdg_activation_request_listener.notify = handle_xdg_activation_request;
|
||||
wl_signal_add(&wl_state.xdg_activation->events.request_activate,
|
||||
&wl_state.xdg_activation_request_listener);
|
||||
wwarning("wl_backend: xdg-activation created (xdg_activation_v1)");
|
||||
}
|
||||
|
||||
wl_state.layer_shell = wlr_layer_shell_v1_create(wl_state.display, 4);
|
||||
if (wl_state.layer_shell) {
|
||||
wl_state.layer_shell_new_surface_listener.notify =
|
||||
handle_layer_shell_new_surface;
|
||||
wl_signal_add(&wl_state.layer_shell->events.new_surface,
|
||||
&wl_state.layer_shell_new_surface_listener);
|
||||
wwarning("wl_backend: layer-shell created (zwlr_layer_shell_v1)");
|
||||
}
|
||||
|
||||
/* clipboard manager (wl-clipboard/cliphist), input inhibitor
|
||||
* (lock screen input gating), virtual pointer (remote desktop / VNC),
|
||||
* KDE idle protocol, xdg-foreign v2 (cross-client window embedding). */
|
||||
wl_state.data_control_mgr =
|
||||
wlr_data_control_manager_v1_create(wl_state.display);
|
||||
if (wl_state.data_control_mgr)
|
||||
wwarning("wl_backend: data-control created (zwlr_data_control_manager_v1)");
|
||||
|
||||
/* zwlr_input_inhibitor_v1 removed from wlroots 0.18 — use ext-session-lock-v1 */
|
||||
|
||||
wl_state.virtual_pointer_mgr =
|
||||
wlr_virtual_pointer_manager_v1_create(wl_state.display);
|
||||
if (wl_state.virtual_pointer_mgr) {
|
||||
wl_state.virtual_pointer_new_listener.notify =
|
||||
handle_virtual_pointer_new;
|
||||
wl_signal_add(&wl_state.virtual_pointer_mgr->events.new_virtual_pointer,
|
||||
&wl_state.virtual_pointer_new_listener);
|
||||
wwarning("wl_backend: virtual-pointer created (zwlr_virtual_pointer_manager_v1)");
|
||||
}
|
||||
|
||||
/* org_kde_kwin_idle (wlr_idle) removed from wlroots 0.18 — use ext-idle-notify-v1 */
|
||||
|
||||
wl_state.xdg_foreign_registry =
|
||||
wlr_xdg_foreign_registry_create(wl_state.display);
|
||||
if (wl_state.xdg_foreign_registry) {
|
||||
wl_state.xdg_foreign_v2 =
|
||||
wlr_xdg_foreign_v2_create(wl_state.display,
|
||||
wl_state.xdg_foreign_registry);
|
||||
if (wl_state.xdg_foreign_v2)
|
||||
wwarning("wl_backend: xdg-foreign-v2 created (zxdg_exporter/importer_v2)");
|
||||
}
|
||||
|
||||
wl_state.xdg_shell = wlr_xdg_shell_create(wl_state.display, 3);
|
||||
|
||||
/* Advertise wmaker-popup-v1 — clients use it to drive popup positioning. */
|
||||
wl_state.wmaker_popup_manager = wl_global_create(wl_state.display,
|
||||
&wmaker_popup_manager_v1_interface, 1, NULL,
|
||||
wmaker_popup_manager_bind);
|
||||
if (wl_state.wmaker_popup_manager)
|
||||
wwarning("wl_backend: wmaker-popup-v1 manager created");
|
||||
|
||||
/* advertise zxdg_decoration_manager_v1 so clients that
|
||||
* support server-side decorations can negotiate; we respond with
|
||||
* CLIENT_SIDE since the Wayland path has no X11 frame rendering. */
|
||||
wl_state.decoration_manager =
|
||||
wlr_xdg_decoration_manager_v1_create(wl_state.display);
|
||||
if (wl_state.decoration_manager) {
|
||||
wl_state.decoration_new_listener.notify = handle_new_toplevel_decoration;
|
||||
wl_signal_add(&wl_state.decoration_manager->events.new_toplevel_decoration,
|
||||
&wl_state.decoration_new_listener);
|
||||
wwarning("wl_backend: xdg-decoration-manager created");
|
||||
}
|
||||
|
||||
wlr_renderer_init_wl_shm(wl_state.renderer, wl_state.display);
|
||||
/* wl_output global is created in handle_backend_new_output. */
|
||||
wl_protocols_init();
|
||||
|
||||
/* 53: In wlroots 0.19, the headless backend has no input devices.
|
||||
* Real keyboard/pointer devices arrive via handle_backend_new_input when
|
||||
|
|
@ -1395,94 +1154,6 @@ wl_event_loop_terminate(void)
|
|||
/*
|
||||
* seat request_set_selection — client calls wl_data_device.set_selection
|
||||
* (i.e. Ctrl-C or other clipboard write). Forward to wlr_seat so the
|
||||
* selection becomes available to the next client that reads it.
|
||||
*/
|
||||
static void
|
||||
handle_seat_request_set_selection(struct wl_listener *listener, void *data)
|
||||
{
|
||||
(void)listener;
|
||||
struct wlr_seat_request_set_selection_event *ev = data;
|
||||
if (!wl_state.seat)
|
||||
return;
|
||||
wlr_seat_set_selection(wl_state.seat, ev->source, ev->serial);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* seat request_set_primary_selection — client writes to the
|
||||
* primary selection buffer (e.g. by selecting text). Forward to
|
||||
* wlr_seat so middle-click paste works in other clients.
|
||||
*/
|
||||
static void
|
||||
handle_seat_request_primary_selection(struct wl_listener *listener, void *data)
|
||||
{
|
||||
(void)listener;
|
||||
struct wlr_seat_request_set_primary_selection_event *ev = data;
|
||||
if (!wl_state.seat)
|
||||
return;
|
||||
wlr_seat_set_primary_selection(wl_state.seat, ev->source, ev->serial);
|
||||
}
|
||||
|
||||
/*
|
||||
* idle_inhibit new_inhibitor — a client (e.g. mpv, a game) created
|
||||
* an idle-inhibit object. wlroots tracks the inhibitor list internally;
|
||||
* the compositor can query wl_state.idle_inhibit_mgr->inhibitors to decide
|
||||
* whether to suppress screen blanking. For now we just log the event so
|
||||
* the capability is advertised and the inhibitor object doesn't error out.
|
||||
*/
|
||||
static void
|
||||
handle_idle_new_inhibitor(struct wl_listener *listener, void *data)
|
||||
{
|
||||
(void)listener;
|
||||
struct wlr_idle_inhibitor_v1 *inhibitor = data;
|
||||
(void)inhibitor;
|
||||
wwarning("wl_backend: idle inhibitor created (client suppressing screen blank)");
|
||||
}
|
||||
|
||||
/*
|
||||
* scroll-wheel axis event handler.
|
||||
* wlr_event_pointer_axis carries orientation (vertical/horizontal), delta,
|
||||
* delta_discrete (notches), and source (wheel vs finger). Forward directly
|
||||
* to the seat so the focused Wayland client receives wl_pointer.axis events.
|
||||
* Without this, scrolling is silently dropped in every Wayland client.
|
||||
*/
|
||||
/*
|
||||
* new pointer constraint — a client requested pointer lock or
|
||||
* pointer confinement (e.g. a game locking the cursor to its window).
|
||||
* We activate the constraint immediately so the client gets confirmed.
|
||||
* In headless mode the pointer is virtual so there is nothing physically
|
||||
* to lock, but activating keeps the client happy.
|
||||
*/
|
||||
static void
|
||||
handle_new_pointer_constraint(struct wl_listener *listener, void *data)
|
||||
{
|
||||
(void)listener;
|
||||
struct wlr_pointer_constraint_v1 *constraint = data;
|
||||
(void)constraint;
|
||||
/* Activate immediately — in nested mode the real pointer is bounded
|
||||
* by the host compositor's window anyway. */
|
||||
wlr_pointer_constraint_v1_send_activated(constraint);
|
||||
wwarning("wl_backend: pointer constraint activated");
|
||||
}
|
||||
|
||||
/*
|
||||
* new keyboard shortcuts inhibitor — a fullscreen app or remote
|
||||
* desktop client wants to suppress WM keyboard shortcuts.
|
||||
* Activate the inhibitor immediately so the client knows it is granted.
|
||||
* The existing wWaylandKeyPress() dispatcher in handle_keyboard_key already
|
||||
* forwards all non-shortcut keys; with the inhibitor active we should skip
|
||||
* the shortcut check for that focused client. For now we simply activate
|
||||
* and log; per-client inhibitor tracking can be refined later.
|
||||
*/
|
||||
static void
|
||||
handle_new_shortcuts_inhibitor(struct wl_listener *listener, void *data)
|
||||
{
|
||||
(void)listener;
|
||||
struct wlr_keyboard_shortcuts_inhibitor_v1 *inhibitor = data;
|
||||
wlr_keyboard_shortcuts_inhibitor_v1_activate(inhibitor);
|
||||
wwarning("wl_backend: keyboard shortcuts inhibitor activated");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,50 @@
|
|||
#include "../../screen.h"
|
||||
#include "wl_types.h"
|
||||
|
||||
#include <wlr/types/wlr_compositor.h>
|
||||
#include <wlr/types/wlr_subcompositor.h>
|
||||
#include <wlr/types/wlr_data_device.h>
|
||||
#include <wlr/types/wlr_output.h>
|
||||
#include <wlr/types/wlr_output_layout.h>
|
||||
#include <wlr/types/wlr_seat.h>
|
||||
#include <wlr/types/wlr_primary_selection.h>
|
||||
#include <wlr/types/wlr_primary_selection_v1.h>
|
||||
#include <wlr/types/wlr_xdg_output_v1.h>
|
||||
#include <wlr/types/wlr_idle_inhibit_v1.h>
|
||||
#include <wlr/types/wlr_viewporter.h>
|
||||
#include <wlr/types/wlr_relative_pointer_v1.h>
|
||||
#include "protocols/pointer-constraints-unstable-v1-protocol.h"
|
||||
#include <wlr/types/wlr_pointer_constraints_v1.h>
|
||||
#include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h>
|
||||
#include <wlr/types/wlr_linux_dmabuf_v1.h>
|
||||
#include <wlr/types/wlr_screencopy_v1.h>
|
||||
#include <wlr/types/wlr_export_dmabuf_v1.h>
|
||||
#include <wlr/types/wlr_output_management_v1.h>
|
||||
#include "protocols/wlr-output-power-management-unstable-v1-protocol.h"
|
||||
#include <wlr/types/wlr_output_power_management_v1.h>
|
||||
#include <wlr/types/wlr_gamma_control_v1.h>
|
||||
#include <wlr/types/wlr_presentation_time.h>
|
||||
#include <wlr/types/wlr_text_input_v3.h>
|
||||
#include <wlr/types/wlr_input_method_v2.h>
|
||||
#include <wlr/types/wlr_virtual_keyboard_v1.h>
|
||||
#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
|
||||
#include <wlr/types/wlr_xdg_activation_v1.h>
|
||||
#include "protocols/wlr-layer-shell-unstable-v1-protocol.h"
|
||||
#include <wlr/types/wlr_layer_shell_v1.h>
|
||||
#include <wlr/types/wlr_data_control_v1.h>
|
||||
#include <wlr/types/wlr_virtual_pointer_v1.h>
|
||||
#include <wlr/types/wlr_xdg_foreign_registry.h>
|
||||
#include <wlr/types/wlr_xdg_foreign_v2.h>
|
||||
#include <wlr/types/wlr_xdg_shell.h>
|
||||
#include <wlr/types/wlr_xdg_decoration_v1.h>
|
||||
#include <wlr/types/wlr_buffer.h>
|
||||
#include <wlr/interfaces/wlr_buffer.h>
|
||||
#include <wlr/render/wlr_renderer.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "wmaker-popup-v1-server-protocol.h"
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Extensions / cursors / error handlers */
|
||||
|
||||
|
|
@ -164,6 +208,286 @@ wl_texture_create_gc(WScreen *scr, unsigned long pixel)
|
|||
(void) scr; (void) pixel;
|
||||
return NULL;
|
||||
}
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Protocol globals — called from wl_display_open() */
|
||||
|
||||
|
||||
/* Forward declarations for handlers defined in other backend modules */
|
||||
extern void handle_seat_request_cursor(struct wl_listener *listener, void *data);
|
||||
extern void handle_seat_request_start_drag(struct wl_listener *listener, void *data);
|
||||
extern void handle_output_mgr_apply(struct wl_listener *listener, void *data);
|
||||
extern void handle_output_mgr_test(struct wl_listener *listener, void *data);
|
||||
extern void handle_output_power_set_mode(struct wl_listener *listener, void *data);
|
||||
extern void handle_text_input_new(struct wl_listener *listener, void *data);
|
||||
extern void handle_input_method_new(struct wl_listener *listener, void *data);
|
||||
extern void handle_virtual_keyboard_new(struct wl_listener *listener, void *data);
|
||||
extern void handle_xdg_activation_request(struct wl_listener *listener, void *data);
|
||||
extern void handle_layer_shell_new_surface(struct wl_listener *listener, void *data);
|
||||
extern void handle_virtual_pointer_new(struct wl_listener *listener, void *data);
|
||||
extern void handle_new_toplevel_decoration(struct wl_listener *listener, void *data);
|
||||
extern void wmaker_popup_manager_bind(struct wl_client *client, void *data,
|
||||
uint32_t version, uint32_t id);
|
||||
|
||||
|
||||
/* Forward declarations for handlers defined in wl_handlers.c */
|
||||
extern void handle_seat_request_set_selection(struct wl_listener *listener, void *data);
|
||||
extern void handle_seat_request_primary_selection(struct wl_listener *listener, void *data);
|
||||
extern void handle_idle_new_inhibitor(struct wl_listener *listener, void *data);
|
||||
extern void handle_new_pointer_constraint(struct wl_listener *listener, void *data);
|
||||
extern void handle_new_shortcuts_inhibitor(struct wl_listener *listener, void *data);
|
||||
|
||||
void
|
||||
wl_protocols_init(void)
|
||||
{
|
||||
wl_state.compositor =
|
||||
wlr_compositor_create(wl_state.display, 6, wl_state.renderer);
|
||||
wlr_subcompositor_create(wl_state.display);
|
||||
wl_state.seat = wlr_seat_create(wl_state.display, "seat0");
|
||||
wl_state.data_device_mgr =
|
||||
wlr_data_device_manager_create(wl_state.display);
|
||||
|
||||
if (wl_state.seat) {
|
||||
wl_state.seat_request_cursor_listener.notify = handle_seat_request_cursor;
|
||||
wl_signal_add(&wl_state.seat->events.request_set_cursor,
|
||||
&wl_state.seat_request_cursor_listener);
|
||||
}
|
||||
/* handle clipboard set-selection requests on the seat so
|
||||
* Ctrl-C / copy operations from clients propagate to the seat selection
|
||||
* and become available for paste in other clients. */
|
||||
if (wl_state.seat) {
|
||||
wl_state.seat_request_set_selection_listener.notify =
|
||||
handle_seat_request_set_selection;
|
||||
wl_signal_add(&wl_state.seat->events.request_set_selection,
|
||||
&wl_state.seat_request_set_selection_listener);
|
||||
wwarning("wl_backend: clipboard selection wired");
|
||||
|
||||
wl_state.seat_request_start_drag_listener.notify =
|
||||
handle_seat_request_start_drag;
|
||||
wl_signal_add(&wl_state.seat->events.request_start_drag,
|
||||
&wl_state.seat_request_start_drag_listener);
|
||||
wwarning("wl_backend: DND start_drag wired");
|
||||
}
|
||||
|
||||
/* primary selection (middle-click paste) via
|
||||
* zwp_primary_selection_device_manager_v1. */
|
||||
wl_state.primary_selection_mgr =
|
||||
wlr_primary_selection_v1_device_manager_create(wl_state.display);
|
||||
if (wl_state.primary_selection_mgr && wl_state.seat) {
|
||||
wl_state.seat_request_primary_selection_listener.notify =
|
||||
handle_seat_request_primary_selection;
|
||||
wl_signal_add(&wl_state.seat->events.request_set_primary_selection,
|
||||
&wl_state.seat_request_primary_selection_listener);
|
||||
wwarning("wl_backend: primary selection (middle-click) wired");
|
||||
}
|
||||
|
||||
/* xdg-output — panels and HiDPI apps query logical output
|
||||
* geometry via zxdg_output_manager_v1. Requires output_layout. */
|
||||
if (wl_state.output_layout) {
|
||||
wl_state.xdg_output_mgr =
|
||||
wlr_xdg_output_manager_v1_create(wl_state.display,
|
||||
wl_state.output_layout);
|
||||
if (wl_state.xdg_output_mgr)
|
||||
wwarning("wl_backend: xdg-output-manager created");
|
||||
}
|
||||
|
||||
/* idle-inhibit — video players and games create inhibitor
|
||||
* objects to suppress screen blanking while active. */
|
||||
wl_state.idle_inhibit_mgr =
|
||||
wlr_idle_inhibit_v1_create(wl_state.display);
|
||||
if (wl_state.idle_inhibit_mgr) {
|
||||
wl_state.idle_new_inhibitor_listener.notify = handle_idle_new_inhibitor;
|
||||
wl_signal_add(&wl_state.idle_inhibit_mgr->events.new_inhibitor,
|
||||
&wl_state.idle_new_inhibitor_listener);
|
||||
wwarning("wl_backend: idle-inhibit manager created");
|
||||
}
|
||||
|
||||
/* wp_viewporter — hardware video scaling and subsurface damage
|
||||
* subset used by mpv, Chromium, Firefox, SDL2. */
|
||||
wl_state.viewporter = wlr_viewporter_create(wl_state.display);
|
||||
if (wl_state.viewporter)
|
||||
wwarning("wl_backend: wp_viewporter created");
|
||||
else
|
||||
wwarning("wl_backend: wp_viewporter unavailable");
|
||||
|
||||
wl_state.relative_pointer_mgr =
|
||||
wlr_relative_pointer_manager_v1_create(wl_state.display);
|
||||
if (wl_state.relative_pointer_mgr)
|
||||
wwarning("wl_backend: relative-pointer-manager created");
|
||||
|
||||
wl_state.pointer_constraints =
|
||||
wlr_pointer_constraints_v1_create(wl_state.display);
|
||||
if (wl_state.pointer_constraints) {
|
||||
wl_state.new_constraint_listener.notify = handle_new_pointer_constraint;
|
||||
wl_signal_add(&wl_state.pointer_constraints->events.new_constraint,
|
||||
&wl_state.new_constraint_listener);
|
||||
wwarning("wl_backend: pointer-constraints created");
|
||||
}
|
||||
|
||||
/* keyboard shortcuts inhibitor — fullscreen apps / remote desktop
|
||||
* request to suppress WM keyboard shortcuts. */
|
||||
wl_state.shortcuts_inhibit_mgr =
|
||||
wlr_keyboard_shortcuts_inhibit_v1_create(wl_state.display);
|
||||
if (wl_state.shortcuts_inhibit_mgr) {
|
||||
wl_state.new_shortcuts_inhibitor_listener.notify =
|
||||
handle_new_shortcuts_inhibitor;
|
||||
wl_signal_add(&wl_state.shortcuts_inhibit_mgr->events.new_inhibitor,
|
||||
&wl_state.new_shortcuts_inhibitor_listener);
|
||||
wwarning("wl_backend: keyboard-shortcuts-inhibit created");
|
||||
}
|
||||
/* GPU zero-copy (linux-dmabuf), screencopy, export-dmabuf.
|
||||
* All three are purely passive globals: wlroots handles the protocol
|
||||
* implementation internally; no event listeners are required. */
|
||||
wl_state.linux_dmabuf =
|
||||
wlr_linux_dmabuf_v1_create_with_renderer(wl_state.display, 4, wl_state.renderer);
|
||||
if (wl_state.linux_dmabuf)
|
||||
wwarning("wl_backend: linux-dmabuf created (zwp_linux_dmabuf_v1)");
|
||||
else
|
||||
wwarning("wl_backend: linux-dmabuf unavailable (renderer has no DRM FD)");
|
||||
wl_state.screencopy_mgr =
|
||||
wlr_screencopy_manager_v1_create(wl_state.display);
|
||||
if (wl_state.screencopy_mgr)
|
||||
wwarning("wl_backend: screencopy manager created (zwlr_screencopy_manager_v1)");
|
||||
wl_state.export_dmabuf_mgr =
|
||||
wlr_export_dmabuf_manager_v1_create(wl_state.display);
|
||||
if (wl_state.export_dmabuf_mgr)
|
||||
wwarning("wl_backend: export-dmabuf manager created (zwlr_export_dmabuf_manager_v1)");
|
||||
|
||||
/* output management (wlr-output-management), output power (DPMS),
|
||||
* gamma control (Night Light / redshift), and presentation time feedback. */
|
||||
wl_state.output_mgr = wlr_output_manager_v1_create(wl_state.display);
|
||||
if (wl_state.output_mgr) {
|
||||
wl_state.output_mgr_apply_listener.notify = handle_output_mgr_apply;
|
||||
wl_signal_add(&wl_state.output_mgr->events.apply,
|
||||
&wl_state.output_mgr_apply_listener);
|
||||
wl_state.output_mgr_test_listener.notify = handle_output_mgr_test;
|
||||
wl_signal_add(&wl_state.output_mgr->events.test,
|
||||
&wl_state.output_mgr_test_listener);
|
||||
wwarning("wl_backend: output-management created (zwlr_output_management_v1)");
|
||||
}
|
||||
wl_state.output_power_mgr = wlr_output_power_manager_v1_create(wl_state.display);
|
||||
if (wl_state.output_power_mgr) {
|
||||
wl_state.output_power_set_mode_listener.notify = handle_output_power_set_mode;
|
||||
wl_signal_add(&wl_state.output_power_mgr->events.set_mode,
|
||||
&wl_state.output_power_set_mode_listener);
|
||||
wwarning("wl_backend: output-power-management created (zwlr_output_power_management_v1)");
|
||||
}
|
||||
wl_state.gamma_control_mgr = wlr_gamma_control_manager_v1_create(wl_state.display);
|
||||
if (wl_state.gamma_control_mgr)
|
||||
wwarning("wl_backend: gamma-control created (zwlr_gamma_control_manager_v1)");
|
||||
wl_state.presentation = wlr_presentation_create(wl_state.display, wl_state.backend, 1);
|
||||
if (wl_state.presentation)
|
||||
wwarning("wl_backend: presentation-time created (wp_presentation)");
|
||||
|
||||
/* text input v3, input method v2, virtual keyboard v1.
|
||||
* All three are passive globals for IME / on-screen keyboard support. */
|
||||
wl_state.text_input_mgr =
|
||||
wlr_text_input_manager_v3_create(wl_state.display);
|
||||
if (wl_state.text_input_mgr) {
|
||||
wl_state.text_input_new_listener.notify = handle_text_input_new;
|
||||
wl_signal_add(&wl_state.text_input_mgr->events.text_input,
|
||||
&wl_state.text_input_new_listener);
|
||||
wwarning("wl_backend: text-input-v3 created (zwp_text_input_manager_v3)");
|
||||
}
|
||||
wl_state.input_method_mgr =
|
||||
wlr_input_method_manager_v2_create(wl_state.display);
|
||||
if (wl_state.input_method_mgr) {
|
||||
wl_state.input_method_new_listener.notify = handle_input_method_new;
|
||||
wl_signal_add(&wl_state.input_method_mgr->events.input_method,
|
||||
&wl_state.input_method_new_listener);
|
||||
wwarning("wl_backend: input-method-v2 created (zwp_input_method_manager_v2)");
|
||||
}
|
||||
wl_state.virtual_keyboard_mgr =
|
||||
wlr_virtual_keyboard_manager_v1_create(wl_state.display);
|
||||
if (wl_state.virtual_keyboard_mgr) {
|
||||
wl_state.virtual_keyboard_new_listener.notify = handle_virtual_keyboard_new;
|
||||
wl_signal_add(&wl_state.virtual_keyboard_mgr->events.new_virtual_keyboard,
|
||||
&wl_state.virtual_keyboard_new_listener);
|
||||
wwarning("wl_backend: virtual-keyboard-v1 created (zwp_virtual_keyboard_manager_v1)");
|
||||
}
|
||||
|
||||
/* foreign toplevel management — lets taskbars enumerate windows.
|
||||
* xdg_activation — focus-token protocol replacing _NET_ACTIVE_WINDOW. */
|
||||
wl_state.foreign_toplevel_mgr =
|
||||
wlr_foreign_toplevel_manager_v1_create(wl_state.display);
|
||||
if (wl_state.foreign_toplevel_mgr)
|
||||
wwarning("wl_backend: foreign-toplevel-management created (zwlr_foreign_toplevel_management_v1)");
|
||||
wl_state.xdg_activation = wlr_xdg_activation_v1_create(wl_state.display);
|
||||
if (wl_state.xdg_activation) {
|
||||
wl_state.xdg_activation_request_listener.notify = handle_xdg_activation_request;
|
||||
wl_signal_add(&wl_state.xdg_activation->events.request_activate,
|
||||
&wl_state.xdg_activation_request_listener);
|
||||
wwarning("wl_backend: xdg-activation created (xdg_activation_v1)");
|
||||
}
|
||||
|
||||
wl_state.layer_shell = wlr_layer_shell_v1_create(wl_state.display, 4);
|
||||
if (wl_state.layer_shell) {
|
||||
wl_state.layer_shell_new_surface_listener.notify =
|
||||
handle_layer_shell_new_surface;
|
||||
wl_signal_add(&wl_state.layer_shell->events.new_surface,
|
||||
&wl_state.layer_shell_new_surface_listener);
|
||||
wwarning("wl_backend: layer-shell created (zwlr_layer_shell_v1)");
|
||||
}
|
||||
|
||||
/* clipboard manager (wl-clipboard/cliphist), input inhibitor
|
||||
* (lock screen input gating), virtual pointer (remote desktop / VNC),
|
||||
* KDE idle protocol, xdg-foreign v2 (cross-client window embedding). */
|
||||
wl_state.data_control_mgr =
|
||||
wlr_data_control_manager_v1_create(wl_state.display);
|
||||
if (wl_state.data_control_mgr)
|
||||
wwarning("wl_backend: data-control created (zwlr_data_control_manager_v1)");
|
||||
|
||||
/* zwlr_input_inhibitor_v1 removed from wlroots 0.18 — use ext-session-lock-v1 */
|
||||
|
||||
wl_state.virtual_pointer_mgr =
|
||||
wlr_virtual_pointer_manager_v1_create(wl_state.display);
|
||||
if (wl_state.virtual_pointer_mgr) {
|
||||
wl_state.virtual_pointer_new_listener.notify =
|
||||
handle_virtual_pointer_new;
|
||||
wl_signal_add(&wl_state.virtual_pointer_mgr->events.new_virtual_pointer,
|
||||
&wl_state.virtual_pointer_new_listener);
|
||||
wwarning("wl_backend: virtual-pointer created (zwlr_virtual_pointer_manager_v1)");
|
||||
}
|
||||
|
||||
/* org_kde_kwin_idle (wlr_idle) removed from wlroots 0.18 — use ext-idle-notify-v1 */
|
||||
|
||||
wl_state.xdg_foreign_registry =
|
||||
wlr_xdg_foreign_registry_create(wl_state.display);
|
||||
if (wl_state.xdg_foreign_registry) {
|
||||
wl_state.xdg_foreign_v2 =
|
||||
wlr_xdg_foreign_v2_create(wl_state.display,
|
||||
wl_state.xdg_foreign_registry);
|
||||
if (wl_state.xdg_foreign_v2)
|
||||
wwarning("wl_backend: xdg-foreign-v2 created (zxdg_exporter/importer_v2)");
|
||||
}
|
||||
|
||||
wl_state.xdg_shell = wlr_xdg_shell_create(wl_state.display, 3);
|
||||
|
||||
/* Advertise wmaker-popup-v1 — clients use it to drive popup positioning. */
|
||||
wl_state.wmaker_popup_manager = wl_global_create(wl_state.display,
|
||||
&wmaker_popup_manager_v1_interface, 1, NULL,
|
||||
wmaker_popup_manager_bind);
|
||||
if (wl_state.wmaker_popup_manager)
|
||||
wwarning("wl_backend: wmaker-popup-v1 manager created");
|
||||
|
||||
/* advertise zxdg_decoration_manager_v1 so clients that
|
||||
* support server-side decorations can negotiate; we respond with
|
||||
* CLIENT_SIDE since the Wayland path has no X11 frame rendering. */
|
||||
wl_state.decoration_manager =
|
||||
wlr_xdg_decoration_manager_v1_create(wl_state.display);
|
||||
if (wl_state.decoration_manager) {
|
||||
wl_state.decoration_new_listener.notify = handle_new_toplevel_decoration;
|
||||
wl_signal_add(&wl_state.decoration_manager->events.new_toplevel_decoration,
|
||||
&wl_state.decoration_new_listener);
|
||||
wwarning("wl_backend: xdg-decoration-manager created");
|
||||
}
|
||||
|
||||
wlr_renderer_init_wl_shm(wl_state.renderer, wl_state.display);
|
||||
/* wl_output global is created in handle_backend_new_output. */
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
wl_texture_free_gc(GC gc)
|
||||
|
|
|
|||
Loading…
Reference in New Issue