commit 2b8fb38

dalem  ·  2026-02-23 22:09:52 +0000 UTC
parent 1536be8
Add a protocol for interactive area selection

This adds a new protocol "swc_select" to expose the internal overlay set box function to clients

Behavior wise it sets appropriate cursors for the state of the operation, and starts the overlay box drawing operation after a click
6 files changed,  +155, -0
+6, -0
 1@@ -97,6 +97,7 @@ PROTO_EXTENSIONS= \
 2 	protocol/server-decoration.xml \
 3 	protocol/swc.xml \
 4 	protocol/swc_snap.xml \
 5+	protocol/swc_select.xml \
 6 	protocol/swc_wallpaper.xml \
 7 	protocol/wayland-drm.xml \
 8 	${WAYLAND_PROTOCOLS_DATADIR}/stable/xdg-shell/xdg-shell.xml \
 9@@ -125,6 +126,7 @@ PROTO_GEN_C= \
10 	protocol/server-decoration-protocol.c \
11 	protocol/swc-protocol.c \
12 	protocol/swc_snap-protocol.c \
13+	protocol/swc_select-protocol.c \
14 	protocol/swc_wallpaper-protocol.c \
15 	protocol/wayland-drm-protocol.c \
16 	protocol/xdg-decoration-unstable-v1-protocol.c \
17@@ -139,6 +141,8 @@ PROTO_GEN_H= \
18 	protocol/swc-client-protocol.h \
19 	protocol/swc_snap-server-protocol.h \
20 	protocol/swc_snap-client-protocol.h \
21+	protocol/swc_select-server-protocol.h \
22+	protocol/swc_select-client-protocol.h \
23 	protocol/swc_wallpaper-server-protocol.h \
24 	protocol/swc_wallpaper-client-protocol.h \
25 	protocol/wayland-drm-server-protocol.h \
26@@ -205,6 +209,7 @@ SWC_SOURCES= \
27 	libswc/subcompositor.c \
28 	libswc/subsurface.c \
29 	libswc/surface.c \
30+	libswc/select.c \
31 	libswc/swc.c \
32 	libswc/util.c \
33 	libswc/view.c \
34@@ -217,6 +222,7 @@ SWC_SOURCES= \
35 	protocol/server-decoration-protocol.c \
36 	protocol/swc-protocol.c \
37 	protocol/swc_snap-protocol.c \
38+	protocol/swc_select-protocol.c \
39 	protocol/swc_wallpaper-protocol.c \
40 	protocol/wayland-drm-protocol.c \
41 	protocol/xdg-decoration-unstable-v1-protocol.c \
+1, -0
1@@ -50,6 +50,7 @@ struct swc {
2 	struct wl_global *panel_manager;
3 	struct wl_global *shell;
4 	struct wl_global *snap_manager;
5+	struct wl_global *select_manager;
6 	struct wl_global *subcompositor;
7 	struct wl_global *wallpaper_manager;
8 	struct wl_global *xdg_decoration_manager;
+109, -0
  1@@ -0,0 +1,109 @@
  2+#include <wayland-server.h>
  3+
  4+#include "select.h"
  5+#include "swc_select-server-protocol.h"
  6+
  7+#include "compositor.h"
  8+#include "pointer.h"
  9+#include "seat.h"
 10+#include "util.h"
 11+
 12+static struct wl_list select_resources;
 13+static int32_t start_x, start_y;
 14+static struct pointer_handler select_pointer_handler;
 15+
 16+enum select_state { STATE_WAIT, STATE_DRAG };
 17+static enum select_state select_state;
 18+
 19+static bool
 20+handle_motion(struct pointer_handler *h, uint32_t time, wl_fixed_t fx,
 21+              wl_fixed_t fy)
 22+{
 23+	int32_t x = wl_fixed_to_int(fx);
 24+	int32_t y = wl_fixed_to_int(fy);
 25+	struct wl_resource *resource;
 26+
 27+	if (select_state != STATE_DRAG) {
 28+		return false;
 29+	}
 30+
 31+	/* TODO: customizable color, maybeee, idk idc */
 32+	swc_overlay_set_box(start_x, start_y, x, y, 0xffffffff, 2);
 33+
 34+	wl_resource_for_each(resource, &select_resources)
 35+	    swc_select_send_update(resource, start_x, start_y, x, y);
 36+
 37+	return true;
 38+}
 39+
 40+static bool
 41+handle_button(struct pointer_handler *h, uint32_t time, struct button *button,
 42+              uint32_t state)
 43+{
 44+	int32_t x = wl_fixed_to_int(swc.seat->pointer->x);
 45+	int32_t y = wl_fixed_to_int(swc.seat->pointer->y);
 46+	struct wl_resource *resource;
 47+
 48+	if (state == WL_POINTER_BUTTON_STATE_PRESSED &&
 49+	    select_state == STATE_WAIT) {
 50+		start_x = x;
 51+		start_y = y;
 52+		select_state = STATE_DRAG;
 53+		return true;
 54+	}
 55+
 56+	if (state == WL_POINTER_BUTTON_STATE_RELEASED &&
 57+	    select_state == STATE_DRAG) {
 58+		swc_overlay_clear();
 59+		wl_list_remove(&select_pointer_handler.link);
 60+		select_state = STATE_WAIT;
 61+		swc_set_cursor(SWC_CURSOR_DEFAULT);
 62+
 63+		wl_resource_for_each(resource, &select_resources)
 64+		    swc_select_send_done(resource, start_x, start_y, x, y);
 65+
 66+		return true;
 67+	}
 68+
 69+	return false;
 70+}
 71+
 72+static void
 73+handle_grab(struct wl_client *client, struct wl_resource *resource)
 74+{
 75+	select_state = STATE_WAIT;
 76+	select_pointer_handler.motion = handle_motion;
 77+	select_pointer_handler.button = handle_button;
 78+	wl_list_insert(&swc.seat->pointer->handlers, &select_pointer_handler.link);
 79+	swc_set_cursor(SWC_CURSOR_CROSS);
 80+}
 81+
 82+static const struct swc_select_interface select_impl = {
 83+    .grab = handle_grab,
 84+};
 85+
 86+static void
 87+bind_select(struct wl_client *client, void *data, uint32_t version, uint32_t id)
 88+{
 89+	struct wl_resource *resource;
 90+
 91+	resource = wl_resource_create(client, &swc_select_interface, 1, id);
 92+	if (!resource) {
 93+		wl_client_post_no_memory(client);
 94+		return;
 95+	}
 96+
 97+	wl_resource_set_implementation(resource, &select_impl, NULL,
 98+	                               remove_resource);
 99+	wl_list_insert(&select_resources, wl_resource_get_link(resource));
100+}
101+
102+struct wl_global *
103+select_manager_create(struct wl_display *display)
104+{
105+	wl_list_init(&select_resources);
106+	select_pointer_handler.motion = handle_motion;
107+	select_pointer_handler.button = handle_button;
108+	return wl_global_create(display, &swc_select_interface, 1, NULL,
109+	                        &bind_select);
110+}
+4, -0
1@@ -0,0 +1,4 @@
2+#include <wayland-server.h>
3+
4+struct wl_global *
5+select_manager_create(struct wl_display *display);
+9, -0
 1@@ -35,6 +35,7 @@
 2 #include "pointer.h"
 3 #include "screen.h"
 4 #include "seat.h"
 5+#include "select.h"
 6 #include "shell.h"
 7 #include "shm.h"
 8 #include "snap.h"
 9@@ -251,10 +252,18 @@ swc_initialize(struct wl_display *display, struct wl_event_loop *event_loop,
10 	}
11 #endif
12 
13+	swc.select_manager = select_manager_create(display);
14+	if (!swc.select_manager) {
15+		ERROR("Could not initialize select manager\n");
16+		goto error17;
17+	}
18+
19 	setup_compositor();
20 
21 	return true;
22 
23+error17:
24+	wl_global_destroy(swc.select_manager);
25 #ifdef ENABLE_XWAYLAND
26 error16:
27 	wl_global_destroy(swc.wallpaper_manager);
+26, -0
 1@@ -0,0 +1,26 @@
 2+<?xml version="1.0" encoding="UTF-8"?>
 3+<protocol name="swc_select">
 4+    <interface name="swc_select" version="1">
 5+        <description summary="Get a selection box">
 6+            Allows clients to get an interactive selction box.
 7+        </description>
 8+
 9+        <request name="grab" />
10+				<event name="update" >
11+						<arg name="x1" type="int" />
12+						<arg name="y1" type="int" />
13+						<arg name="x2" type="int" />
14+						<arg name="y2" type="int" />
15+				</event>
16+
17+				<event name="done" >
18+						<arg name="x1" type="int" />
19+						<arg name="y1" type="int" />
20+						<arg name="x2" type="int" />
21+						<arg name="y2" type="int" />
22+				</event>
23+
24+				<event name="cancelled" />
25+				<request name="destroy" type="destructor" />
26+		</interface>
27+</protocol>