commit fc92a02
shrub
·
2025-12-16 01:03:48 +0000 UTC
parent b8d53ba
scroll/axis bindings this adds bindings for the pointer axis. it also adds a swc_pointer_send-axis helper for compositors that want to sometimes intercept axis events. various window stacking helpers were also added
5 files changed,
+238,
-1
+65,
-1
1@@ -40,6 +40,13 @@ struct binding {
2 void *data;
3 };
4
5+struct axis_binding {
6+ uint32_t axis;
7+ uint32_t modifiers;
8+ swc_axis_binding_handler handler;
9+ void *data;
10+};
11+
12 static bool handle_key(struct keyboard *keyboard, uint32_t time, struct key *key, uint32_t state);
13
14 static struct keyboard_handler key_binding_handler = {
15@@ -47,12 +54,15 @@ static struct keyboard_handler key_binding_handler = {
16 };
17
18 static bool handle_button(struct pointer_handler *handler, uint32_t time, struct button *button, uint32_t state);
19+static bool handle_axis(struct pointer_handler *handler, uint32_t time, enum wl_pointer_axis axis,
20+ enum wl_pointer_axis_source source, wl_fixed_t value, int value120);
21
22 static struct pointer_handler button_binding_handler = {
23 .button = handle_button,
24+ .axis = handle_axis,
25 };
26
27-static struct wl_array key_bindings, button_bindings;
28+static struct wl_array key_bindings, button_bindings, axis_bindings;
29
30 const struct swc_bindings swc_bindings = {
31 .keyboard_handler = &key_binding_handler,
32@@ -107,6 +117,19 @@ find_button_binding(uint32_t modifiers, uint32_t value)
33 return find_binding(&button_bindings, modifiers, value);
34 }
35
36+static struct axis_binding *
37+find_axis_binding(uint32_t modifiers, uint32_t axis)
38+{
39+ struct axis_binding *binding;
40+
41+ wl_array_for_each (binding, &axis_bindings) {
42+ if (binding->axis == axis && (binding->modifiers == modifiers || binding->modifiers == SWC_MOD_ANY))
43+ return binding;
44+ }
45+
46+ return NULL;
47+}
48+
49 static bool
50 handle_binding(uint32_t time, struct press *press, uint32_t state, struct binding *(*find_binding)(uint32_t, uint32_t))
51 {
52@@ -140,11 +163,35 @@ handle_button(struct pointer_handler *handler, uint32_t time, struct button *but
53 return handle_binding(time, &button->press, state, &find_button_binding);
54 }
55
56+bool
57+handle_axis(struct pointer_handler *handler, uint32_t time, enum wl_pointer_axis axis,
58+ enum wl_pointer_axis_source source, wl_fixed_t value, int value120)
59+{
60+ (void)handler;
61+ (void)source;
62+
63+ struct axis_binding *binding = find_axis_binding(swc.seat->keyboard->modifiers, axis);
64+ int32_t delta120 = value120;
65+
66+ if (!binding)
67+ return false;
68+
69+ if (!delta120 && value) {
70+ delta120 = (int32_t)(wl_fixed_to_double(value) * 120.0);
71+ if (!delta120)
72+ delta120 = value > 0 ? 1 : -1;
73+ }
74+
75+ binding->handler(binding->data, time, axis, delta120);
76+ return true;
77+}
78+
79 bool
80 bindings_initialize(void)
81 {
82 wl_array_init(&key_bindings);
83 wl_array_init(&button_bindings);
84+ wl_array_init(&axis_bindings);
85
86 return true;
87 }
88@@ -154,6 +201,7 @@ bindings_finalize(void)
89 {
90 wl_array_release(&key_bindings);
91 wl_array_release(&button_bindings);
92+ wl_array_release(&axis_bindings);
93 }
94
95 EXPORT int
96@@ -183,3 +231,19 @@ swc_add_binding(enum swc_binding_type type, uint32_t modifiers, uint32_t value,
97
98 return 0;
99 }
100+
101+EXPORT int
102+swc_add_axis_binding(uint32_t modifiers, uint32_t axis, swc_axis_binding_handler handler, void *data)
103+{
104+ struct axis_binding *binding;
105+
106+ if (!(binding = wl_array_add(&axis_bindings, sizeof(*binding))))
107+ return -ENOMEM;
108+
109+ binding->axis = axis;
110+ binding->modifiers = modifiers;
111+ binding->handler = handler;
112+ binding->data = data;
113+
114+ return 0;
115+}
+92,
-0
1@@ -634,6 +634,98 @@ swc_window_at(int32_t x, int32_t y)
2 return view ? &view->window->base : NULL;
3 }
4
5+static struct compositor_view *
6+view_for_window(struct swc_window *base)
7+{
8+ struct window *window;
9+
10+ if (!base)
11+ return NULL;
12+
13+ window = (struct window *)base;
14+ return window->view;
15+}
16+
17+static struct compositor_view *
18+prev_window_view(struct compositor_view *view)
19+{
20+ struct wl_list *link;
21+ struct compositor_view *other;
22+
23+ for (link = view->link.prev; link != &compositor.views; link = link->prev) {
24+ other = wl_container_of(link, other, link);
25+
26+ if (other->visible && other->window)
27+ return other;
28+ }
29+
30+ return NULL;
31+}
32+
33+static struct compositor_view *
34+next_window_view(struct compositor_view *view)
35+{
36+ struct wl_list *link;
37+ struct compositor_view *other;
38+
39+ for (link = view->link.next; link != &compositor.views; link = link->next) {
40+ other = wl_container_of(link, other, link);
41+
42+ if (other->visible && other->window)
43+ return other;
44+ }
45+
46+ return NULL;
47+}
48+
49+static void
50+damage_views(struct compositor_view *a, struct compositor_view *b)
51+{
52+ uint32_t screens = a->base.screens | (b ? b->base.screens : 0);
53+
54+ a->border.damaged = true;
55+ pixman_region32_union_rect(&compositor.damage, &compositor.damage,
56+ a->extents.x1, a->extents.y1,
57+ (uint32_t)(a->extents.x2 - a->extents.x1),
58+ (uint32_t)(a->extents.y2 - a->extents.y1));
59+
60+ if (b) {
61+ b->border.damaged = true;
62+ pixman_region32_union_rect(&compositor.damage, &compositor.damage,
63+ b->extents.x1, b->extents.y1,
64+ (uint32_t)(b->extents.x2 - b->extents.x1),
65+ (uint32_t)(b->extents.y2 - b->extents.y1));
66+ }
67+
68+ schedule_updates(screens);
69+}
70+
71+EXPORT void
72+swc_window_stack(struct swc_window *window, int32_t direction)
73+{
74+ struct compositor_view *view = view_for_window(window);
75+ struct compositor_view *other = NULL;
76+
77+ if (!view || !view->visible || direction == 0)
78+ return;
79+
80+ if (direction < 0) {
81+ other = prev_window_view(view);
82+ if (!other)
83+ return;
84+ wl_list_remove(&view->link);
85+ wl_list_insert(other->link.prev, &view->link);
86+ } else {
87+ other = next_window_view(view);
88+ if (!other)
89+ return;
90+ wl_list_remove(&view->link);
91+ wl_list_insert(&other->link, &view->link);
92+ }
93+
94+ damage_views(view, other);
95+}
96+
97 struct compositor_view *
98 compositor_create_view(struct surface *surface)
99 {
+37,
-0
1@@ -57,6 +57,43 @@ swc_pointer_send_button(uint32_t time, uint32_t button, uint32_t state)
2 pointer->client_axis_source = -1;
3 }
4
5+EXPORT void
6+swc_pointer_send_axis(uint32_t time, uint32_t axis, int32_t value120)
7+{
8+ struct pointer *pointer = swc.seat ? swc.seat->pointer : NULL;
9+ struct wl_resource *resource;
10+ wl_fixed_t value;
11+
12+ if (!pointer || wl_list_empty(&pointer->focus.active))
13+ return;
14+
15+ value = wl_fixed_from_double((double)value120 / 120.0);
16+
17+ wl_resource_for_each (resource, &pointer->focus.active) {
18+ int ver = wl_resource_get_version(resource);
19+
20+ if (ver >= WL_POINTER_AXIS_SOURCE_SINCE_VERSION)
21+ wl_pointer_send_axis_source(resource, WL_POINTER_AXIS_SOURCE_WHEEL);
22+ if (value120) {
23+ if (ver >= WL_POINTER_AXIS_VALUE120_SINCE_VERSION)
24+ wl_pointer_send_axis_value120(resource, axis, value120);
25+ else if (ver >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION)
26+ wl_pointer_send_axis_discrete(resource, axis, value120 / 120);
27+ }
28+
29+ if (value)
30+ wl_pointer_send_axis(resource, time, axis, value);
31+ else if (ver >= WL_POINTER_AXIS_STOP_SINCE_VERSION)
32+ wl_pointer_send_axis_stop(resource, time, axis);
33+ }
34+
35+ wl_resource_for_each (resource, &pointer->focus.active) {
36+ if (wl_resource_get_version(resource) >= WL_POINTER_FRAME_SINCE_VERSION)
37+ wl_pointer_send_frame(resource);
38+ }
39+ pointer->client_axis_source = -1;
40+}
41+
42 static void
43 enter(struct input_focus_handler *handler, struct wl_list *resources, struct compositor_view *view)
44 {
+32,
-0
1@@ -53,6 +53,16 @@ bool swc_cursor_position(int32_t *x, int32_t *y);
2 */
3 void swc_pointer_send_button(uint32_t time, uint32_t button, uint32_t state);
4
5+/**
6+ * Send a pointer axis event to the currently focused client.
7+ *
8+ * This is intended for window managers which intercept axis events (for
9+ * example for mouse chords) but want normal scrolling to still reach clients.
10+ *
11+ * value120 uses the wl_pointer "120 units" convention.
12+ */
13+void swc_pointer_send_axis(uint32_t time, uint32_t axis, int32_t value120);
14+
15 /**
16 * draw [or update] a simple box overlay
17 *
18@@ -262,6 +272,11 @@ void swc_window_set_size(struct swc_window *window, uint32_t width, uint32_t hei
19 */
20 void swc_window_set_geometry(struct swc_window *window, const struct swc_rectangle *geometry);
21
22+/**
23+ * Get the window's current geometry in compositor-global coordinates.
24+ */
25+bool swc_window_get_geometry(const struct swc_window *window, struct swc_rectangle *geometry);
26+
27 /**
28 * Set the window's border color and width.
29 *
30@@ -307,6 +322,14 @@ void swc_window_end_resize(struct swc_window *window);
31 */
32 struct swc_window *swc_window_at(int32_t x, int32_t y);
33
34+/**
35+ * move a window in the stacking order by one step
36+ *
37+ * direction < 0 moves the window towards the front (higher)
38+ * direction > 0 moves the window towards the back (lower)
39+ */
40+void swc_window_stack(struct swc_window *window, int32_t direction);
41+
42 /* }}} */
43
44 /* Bindings {{{ */
45@@ -325,6 +348,7 @@ enum swc_binding_type {
46 };
47
48 typedef void (*swc_binding_handler)(void *data, uint32_t time, uint32_t value, uint32_t state);
49+typedef void (*swc_axis_binding_handler)(void *data, uint32_t time, uint32_t axis, int32_t value120);
50
51 /**
52 * Register a new input binding.
53@@ -333,6 +357,14 @@ typedef void (*swc_binding_handler)(void *data, uint32_t time, uint32_t value, u
54 */
55 int swc_add_binding(enum swc_binding_type type, uint32_t modifiers, uint32_t value, swc_binding_handler handler, void *data);
56
57+/**
58+ * register a new pointer axis binding
59+ *
60+ * this will intercept axis events from clients; use swc_pointer_send_axis()
61+ * from the handler to forward events when appropriate
62+ */
63+int swc_add_axis_binding(uint32_t modifiers, uint32_t axis, swc_axis_binding_handler handler, void *data);
64+
65 /* }}} */
66
67 /**
+12,
-0
1@@ -248,6 +248,18 @@ swc_window_set_geometry(struct swc_window *window, const struct swc_rectangle *g
2 swc_window_set_position(window, geometry->x, geometry->y);
3 }
4
5+EXPORT bool
6+swc_window_get_geometry(const struct swc_window *base, struct swc_rectangle *geometry)
7+{
8+ struct window *window = INTERNAL((struct swc_window *)base);
9+
10+ if (!window || !geometry)
11+ return false;
12+
13+ *geometry = window->view->base.geometry;
14+ return true;
15+}
16+
17 EXPORT void
18 swc_window_set_border(struct swc_window *window, uint32_t inner_border_color, uint32_t inner_border_width,
19 uint32_t outer_border_color, uint32_t outer_border_width)