diff options
Diffstat (limited to 'sway/input/seat.c')
-rw-r--r-- | sway/input/seat.c | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/sway/input/seat.c b/sway/input/seat.c new file mode 100644 index 00000000..1b25419b --- /dev/null +++ b/sway/input/seat.c | |||
@@ -0,0 +1,242 @@ | |||
1 | #define _XOPEN_SOURCE 700 | ||
2 | #include <wlr/types/wlr_cursor.h> | ||
3 | #include <wlr/types/wlr_xcursor_manager.h> | ||
4 | #include "sway/input/seat.h" | ||
5 | #include "sway/input/cursor.h" | ||
6 | #include "sway/input/input-manager.h" | ||
7 | #include "sway/input/keyboard.h" | ||
8 | #include "sway/output.h" | ||
9 | #include "sway/view.h" | ||
10 | #include "log.h" | ||
11 | |||
12 | static void seat_device_destroy(struct sway_seat_device *seat_device) { | ||
13 | if (!seat_device) { | ||
14 | return; | ||
15 | } | ||
16 | |||
17 | sway_keyboard_destroy(seat_device->keyboard); | ||
18 | wlr_cursor_detach_input_device(seat_device->sway_seat->cursor->cursor, | ||
19 | seat_device->input_device->wlr_device); | ||
20 | wl_list_remove(&seat_device->link); | ||
21 | free(seat_device); | ||
22 | } | ||
23 | |||
24 | struct sway_seat *sway_seat_create(struct sway_input_manager *input, | ||
25 | const char *seat_name) { | ||
26 | struct sway_seat *seat = calloc(1, sizeof(struct sway_seat)); | ||
27 | if (!seat) { | ||
28 | return NULL; | ||
29 | } | ||
30 | |||
31 | seat->wlr_seat = wlr_seat_create(input->server->wl_display, seat_name); | ||
32 | if (!sway_assert(seat->wlr_seat, "could not allocate seat")) { | ||
33 | return NULL; | ||
34 | } | ||
35 | |||
36 | seat->cursor = sway_cursor_create(seat); | ||
37 | if (!seat->cursor) { | ||
38 | wlr_seat_destroy(seat->wlr_seat); | ||
39 | free(seat); | ||
40 | return NULL; | ||
41 | } | ||
42 | |||
43 | seat->input = input; | ||
44 | wl_list_init(&seat->devices); | ||
45 | |||
46 | wlr_seat_set_capabilities(seat->wlr_seat, | ||
47 | WL_SEAT_CAPABILITY_KEYBOARD | | ||
48 | WL_SEAT_CAPABILITY_POINTER | | ||
49 | WL_SEAT_CAPABILITY_TOUCH); | ||
50 | |||
51 | sway_seat_configure_xcursor(seat); | ||
52 | |||
53 | wl_list_insert(&input->seats, &seat->link); | ||
54 | |||
55 | return seat; | ||
56 | } | ||
57 | |||
58 | static void seat_configure_pointer(struct sway_seat *seat, | ||
59 | struct sway_seat_device *sway_device) { | ||
60 | // TODO pointer configuration | ||
61 | wlr_cursor_attach_input_device(seat->cursor->cursor, | ||
62 | sway_device->input_device->wlr_device); | ||
63 | } | ||
64 | |||
65 | static void seat_configure_keyboard(struct sway_seat *seat, | ||
66 | struct sway_seat_device *seat_device) { | ||
67 | if (!seat_device->keyboard) { | ||
68 | sway_keyboard_create(seat, seat_device); | ||
69 | } | ||
70 | sway_keyboard_configure(seat_device->keyboard); | ||
71 | } | ||
72 | |||
73 | static struct sway_seat_device *sway_seat_get_device(struct sway_seat *seat, | ||
74 | struct sway_input_device *input_device) { | ||
75 | struct sway_seat_device *seat_device = NULL; | ||
76 | wl_list_for_each(seat_device, &seat->devices, link) { | ||
77 | if (seat_device->input_device == input_device) { | ||
78 | return seat_device; | ||
79 | } | ||
80 | } | ||
81 | |||
82 | return NULL; | ||
83 | } | ||
84 | |||
85 | void sway_seat_configure_device(struct sway_seat *seat, | ||
86 | struct sway_input_device *input_device) { | ||
87 | struct sway_seat_device *seat_device = | ||
88 | sway_seat_get_device(seat, input_device); | ||
89 | if (!seat_device) { | ||
90 | return; | ||
91 | } | ||
92 | |||
93 | if (seat->config) { | ||
94 | seat_device->attachment_config = | ||
95 | seat_config_get_attachment(seat->config, input_device->identifier); | ||
96 | } | ||
97 | |||
98 | switch (input_device->wlr_device->type) { | ||
99 | case WLR_INPUT_DEVICE_POINTER: | ||
100 | seat_configure_pointer(seat, seat_device); | ||
101 | break; | ||
102 | case WLR_INPUT_DEVICE_KEYBOARD: | ||
103 | seat_configure_keyboard(seat, seat_device); | ||
104 | wlr_seat_set_keyboard(seat->wlr_seat, | ||
105 | seat_device->input_device->wlr_device); | ||
106 | break; | ||
107 | case WLR_INPUT_DEVICE_TOUCH: | ||
108 | case WLR_INPUT_DEVICE_TABLET_PAD: | ||
109 | case WLR_INPUT_DEVICE_TABLET_TOOL: | ||
110 | sway_log(L_DEBUG, "TODO: configure other devices"); | ||
111 | break; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | void sway_seat_add_device(struct sway_seat *seat, | ||
116 | struct sway_input_device *input_device) { | ||
117 | if (sway_seat_get_device(seat, input_device)) { | ||
118 | return; | ||
119 | } | ||
120 | |||
121 | struct sway_seat_device *seat_device = | ||
122 | calloc(1, sizeof(struct sway_seat_device)); | ||
123 | if (!seat_device) { | ||
124 | sway_log(L_DEBUG, "could not allocate seat device"); | ||
125 | return; | ||
126 | } | ||
127 | |||
128 | seat_device->sway_seat = seat; | ||
129 | seat_device->input_device = input_device; | ||
130 | wl_list_insert(&seat->devices, &seat_device->link); | ||
131 | |||
132 | sway_seat_configure_device(seat, input_device); | ||
133 | } | ||
134 | |||
135 | void sway_seat_remove_device(struct sway_seat *seat, | ||
136 | struct sway_input_device *input_device) { | ||
137 | sway_log(L_DEBUG, "input remove: %s", input_device->identifier); | ||
138 | struct sway_seat_device *seat_device = | ||
139 | sway_seat_get_device(seat, input_device); | ||
140 | |||
141 | if (!seat_device) { | ||
142 | return; | ||
143 | } | ||
144 | |||
145 | seat_device_destroy(seat_device); | ||
146 | } | ||
147 | |||
148 | void sway_seat_configure_xcursor(struct sway_seat *seat) { | ||
149 | // TODO configure theme and size | ||
150 | const char *cursor_theme = "default"; | ||
151 | |||
152 | if (!seat->cursor->xcursor_manager) { | ||
153 | seat->cursor->xcursor_manager = | ||
154 | wlr_xcursor_manager_create("default", 24); | ||
155 | if (sway_assert(seat->cursor->xcursor_manager, | ||
156 | "Cannot create XCursor manager for theme %s", | ||
157 | cursor_theme)) { | ||
158 | return; | ||
159 | } | ||
160 | } | ||
161 | |||
162 | for (int i = 0; i < root_container.children->length; ++i) { | ||
163 | swayc_t *output_container = root_container.children->items[i]; | ||
164 | struct wlr_output *output = | ||
165 | output_container->sway_output->wlr_output; | ||
166 | bool result = | ||
167 | wlr_xcursor_manager_load(seat->cursor->xcursor_manager, | ||
168 | output->scale); | ||
169 | |||
170 | sway_assert(!result, | ||
171 | "Cannot load xcursor theme for output '%s' with scale %d", | ||
172 | output->name, output->scale); | ||
173 | } | ||
174 | |||
175 | wlr_xcursor_manager_set_cursor_image(seat->cursor->xcursor_manager, | ||
176 | "left_ptr", seat->cursor->cursor); | ||
177 | wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x, | ||
178 | seat->cursor->cursor->y); | ||
179 | } | ||
180 | |||
181 | static void handle_focus_destroy(struct wl_listener *listener, void *data) { | ||
182 | struct sway_seat *seat = wl_container_of(listener, seat, focus_destroy); | ||
183 | //swayc_t *container = data; | ||
184 | |||
185 | // TODO set new focus based on the state of the tree | ||
186 | sway_seat_set_focus(seat, NULL); | ||
187 | } | ||
188 | |||
189 | void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { | ||
190 | swayc_t *last_focus = seat->focus; | ||
191 | |||
192 | if (last_focus == container) { | ||
193 | return; | ||
194 | } | ||
195 | |||
196 | if (last_focus) { | ||
197 | wl_list_remove(&seat->focus_destroy.link); | ||
198 | } | ||
199 | |||
200 | if (container) { | ||
201 | struct sway_view *view = container->sway_view; | ||
202 | view->iface.set_activated(view, true); | ||
203 | wl_signal_add(&container->events.destroy, &seat->focus_destroy); | ||
204 | seat->focus_destroy.notify = handle_focus_destroy; | ||
205 | wlr_seat_keyboard_notify_enter(seat->wlr_seat, view->surface); | ||
206 | } | ||
207 | |||
208 | seat->focus = container; | ||
209 | |||
210 | if (last_focus && | ||
211 | !sway_input_manager_has_focus(seat->input, last_focus)) { | ||
212 | struct sway_view *view = last_focus->sway_view; | ||
213 | view->iface.set_activated(view, false); | ||
214 | |||
215 | } | ||
216 | } | ||
217 | |||
218 | void sway_seat_set_config(struct sway_seat *seat, | ||
219 | struct seat_config *seat_config) { | ||
220 | // clear configs | ||
221 | seat->config = NULL; | ||
222 | |||
223 | struct sway_seat_device *seat_device = NULL; | ||
224 | wl_list_for_each(seat_device, &seat->devices, link) { | ||
225 | seat_device->attachment_config = NULL; | ||
226 | } | ||
227 | |||
228 | if (!seat_config) { | ||
229 | return; | ||
230 | } | ||
231 | |||
232 | // add configs | ||
233 | seat->config = seat_config; | ||
234 | |||
235 | wl_list_for_each(seat_device, &seat->devices, link) { | ||
236 | seat_device->attachment_config = | ||
237 | seat_config_get_attachment(seat_config, | ||
238 | seat_device->input_device->identifier); | ||
239 | sway_seat_configure_device(seat, seat_device->input_device); | ||
240 | } | ||
241 | |||
242 | } | ||