1#include <wayland-server.h>
2
3#include "select.h"
4#include "swc_select-server-protocol.h"
5
6#include "internal.h"
7#include "compositor.h"
8#include "pointer.h"
9#include "seat.h"
10#include "util.h"
11
12static struct wl_list select_resources;
13static int32_t start_x, start_y;
14static struct pointer_handler select_pointer_handler;
15
16enum select_state { STATE_WAIT, STATE_DRAG };
17static enum select_state select_state;
18
19static bool
20handle_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
40static bool
41handle_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
72static void
73handle_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
82static const struct swc_select_interface select_impl = {
83 .grab = handle_grab,
84};
85
86static void
87bind_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
102struct wl_global *
103select_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}