diff options
Diffstat (limited to 'wayland/registry.c')
-rw-r--r-- | wayland/registry.c | 293 |
1 files changed, 0 insertions, 293 deletions
diff --git a/wayland/registry.c b/wayland/registry.c deleted file mode 100644 index bbb43ad9..00000000 --- a/wayland/registry.c +++ /dev/null | |||
@@ -1,293 +0,0 @@ | |||
1 | #include <wayland-client.h> | ||
2 | #include <xkbcommon/xkbcommon.h> | ||
3 | #include <stdlib.h> | ||
4 | #include <string.h> | ||
5 | #include <unistd.h> | ||
6 | #include <sys/mman.h> | ||
7 | #include <sys/types.h> | ||
8 | #include <sys/timerfd.h> | ||
9 | #include "wayland-desktop-shell-client-protocol.h" | ||
10 | #include "wayland-swaylock-client-protocol.h" | ||
11 | #include "client/registry.h" | ||
12 | #include "stringop.h" | ||
13 | #include "log.h" | ||
14 | |||
15 | static void display_handle_mode(void *data, struct wl_output *wl_output, | ||
16 | uint32_t flags, int32_t width, int32_t height, int32_t refresh) { | ||
17 | struct output_state *state = data; | ||
18 | if (flags & WL_OUTPUT_MODE_CURRENT) { | ||
19 | state->flags = flags; | ||
20 | state->width = width; | ||
21 | state->height = height; | ||
22 | sway_log(L_DEBUG, "Got mode %dx%d:0x%X for output %p", | ||
23 | width, height, flags, data); | ||
24 | } | ||
25 | } | ||
26 | |||
27 | static void display_handle_geometry(void *data, struct wl_output *wl_output, | ||
28 | int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, | ||
29 | int32_t subpixel, const char *make, const char *model, int32_t transform) { | ||
30 | // this space intentionally left blank | ||
31 | } | ||
32 | |||
33 | static void display_handle_done(void *data, struct wl_output *wl_output) { | ||
34 | // this space intentionally left blank | ||
35 | } | ||
36 | |||
37 | static void display_handle_scale(void *data, struct wl_output *wl_output, int32_t factor) { | ||
38 | struct output_state *state = data; | ||
39 | state->scale = factor; | ||
40 | sway_log(L_DEBUG, "Got scale factor %d for output %p", factor, data); | ||
41 | } | ||
42 | |||
43 | static const struct wl_output_listener output_listener = { | ||
44 | .mode = display_handle_mode, | ||
45 | .geometry = display_handle_geometry, | ||
46 | .done = display_handle_done, | ||
47 | .scale = display_handle_scale | ||
48 | }; | ||
49 | |||
50 | const char *XKB_MASK_NAMES[MASK_LAST] = { | ||
51 | XKB_MOD_NAME_SHIFT, | ||
52 | XKB_MOD_NAME_CAPS, | ||
53 | XKB_MOD_NAME_CTRL, | ||
54 | XKB_MOD_NAME_ALT, | ||
55 | "Mod2", | ||
56 | "Mod3", | ||
57 | XKB_MOD_NAME_LOGO, | ||
58 | "Mod5", | ||
59 | }; | ||
60 | |||
61 | const enum mod_bit XKB_MODS[MASK_LAST] = { | ||
62 | MOD_SHIFT, | ||
63 | MOD_CAPS, | ||
64 | MOD_CTRL, | ||
65 | MOD_ALT, | ||
66 | MOD_MOD2, | ||
67 | MOD_MOD3, | ||
68 | MOD_LOGO, | ||
69 | MOD_MOD5 | ||
70 | }; | ||
71 | |||
72 | static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, | ||
73 | uint32_t format, int fd, uint32_t size) { | ||
74 | // Keyboard errors are abort-worthy because you wouldn't be able to unlock your screen otherwise. | ||
75 | |||
76 | struct registry *registry = data; | ||
77 | if (!data) { | ||
78 | close(fd); | ||
79 | return; | ||
80 | } | ||
81 | |||
82 | if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { | ||
83 | close(fd); | ||
84 | sway_abort("Unknown keymap format %d, aborting", format); | ||
85 | } | ||
86 | |||
87 | char *map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); | ||
88 | if (map_str == MAP_FAILED) { | ||
89 | close(fd); | ||
90 | sway_abort("Unable to initialized shared keyboard memory, aborting"); | ||
91 | } | ||
92 | |||
93 | struct xkb_keymap *keymap = xkb_keymap_new_from_string(registry->input->xkb.context, | ||
94 | map_str, XKB_KEYMAP_FORMAT_TEXT_V1, 0); | ||
95 | munmap(map_str, size); | ||
96 | close(fd); | ||
97 | |||
98 | if (!keymap) { | ||
99 | sway_abort("Failed to compile keymap, aborting"); | ||
100 | } | ||
101 | |||
102 | struct xkb_state *state = xkb_state_new(keymap); | ||
103 | if (!state) { | ||
104 | xkb_keymap_unref(keymap); | ||
105 | sway_abort("Failed to create xkb state, aborting"); | ||
106 | } | ||
107 | |||
108 | xkb_keymap_unref(registry->input->xkb.keymap); | ||
109 | xkb_state_unref(registry->input->xkb.state); | ||
110 | registry->input->xkb.keymap = keymap; | ||
111 | registry->input->xkb.state = state; | ||
112 | |||
113 | int i; | ||
114 | for (i = 0; i < MASK_LAST; ++i) { | ||
115 | registry->input->xkb.masks[i] = 1 << xkb_keymap_mod_get_index(registry->input->xkb.keymap, XKB_MASK_NAMES[i]); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | static void keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, | ||
120 | uint32_t serial, struct wl_surface *surface, struct wl_array *keys) { | ||
121 | // this space intentionally left blank | ||
122 | } | ||
123 | |||
124 | static void keyboard_handle_leave(void *data, struct wl_keyboard *keyboard, | ||
125 | uint32_t serial, struct wl_surface *surface) { | ||
126 | // this space intentionally left blank | ||
127 | } | ||
128 | |||
129 | static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard, | ||
130 | uint32_t serial, uint32_t time, uint32_t key, uint32_t state_w) { | ||
131 | struct registry *registry = data; | ||
132 | enum wl_keyboard_key_state state = state_w; | ||
133 | |||
134 | if (!registry->input->xkb.state) { | ||
135 | return; | ||
136 | } | ||
137 | |||
138 | xkb_keysym_t sym = xkb_state_key_get_one_sym(registry->input->xkb.state, key + 8); | ||
139 | registry->input->sym = (state == WL_KEYBOARD_KEY_STATE_PRESSED ? sym : XKB_KEY_NoSymbol); | ||
140 | registry->input->code = (state == WL_KEYBOARD_KEY_STATE_PRESSED ? key + 8 : 0); | ||
141 | uint32_t codepoint = xkb_state_key_get_utf32(registry->input->xkb.state, registry->input->code); | ||
142 | if (registry->input->notify) { | ||
143 | registry->input->notify(state, sym, key, codepoint); | ||
144 | } | ||
145 | } | ||
146 | |||
147 | static void keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard, | ||
148 | uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, | ||
149 | uint32_t mods_locked, uint32_t group) { | ||
150 | struct registry *registry = data; | ||
151 | |||
152 | if (!registry->input->xkb.keymap) { | ||
153 | return; | ||
154 | } | ||
155 | |||
156 | xkb_state_update_mask(registry->input->xkb.state, mods_depressed, mods_latched, mods_locked, 0, 0, group); | ||
157 | xkb_mod_mask_t mask = xkb_state_serialize_mods(registry->input->xkb.state, | ||
158 | XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED); | ||
159 | |||
160 | registry->input->modifiers = 0; | ||
161 | for (uint32_t i = 0; i < MASK_LAST; ++i) { | ||
162 | if (mask & registry->input->xkb.masks[i]) { | ||
163 | registry->input->modifiers |= XKB_MODS[i]; | ||
164 | } | ||
165 | } | ||
166 | } | ||
167 | |||
168 | static void keyboard_handle_repeat_info(void *data, struct wl_keyboard *keyboard, | ||
169 | int32_t rate, int32_t delay) { | ||
170 | // this space intentionally left blank | ||
171 | } | ||
172 | |||
173 | static const struct wl_keyboard_listener keyboard_listener = { | ||
174 | .keymap = keyboard_handle_keymap, | ||
175 | .enter = keyboard_handle_enter, | ||
176 | .leave = keyboard_handle_leave, | ||
177 | .key = keyboard_handle_key, | ||
178 | .modifiers = keyboard_handle_modifiers, | ||
179 | .repeat_info = keyboard_handle_repeat_info | ||
180 | }; | ||
181 | |||
182 | static void seat_handle_capabilities(void *data, struct wl_seat *seat, | ||
183 | enum wl_seat_capability caps) { | ||
184 | struct registry *reg = data; | ||
185 | |||
186 | if ((caps & WL_SEAT_CAPABILITY_POINTER) && !reg->pointer) { | ||
187 | reg->pointer = wl_seat_get_pointer(reg->seat); | ||
188 | } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && reg->pointer) { | ||
189 | wl_pointer_destroy(reg->pointer); | ||
190 | reg->pointer = NULL; | ||
191 | } | ||
192 | |||
193 | if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !reg->keyboard) { | ||
194 | reg->keyboard = wl_seat_get_keyboard(reg->seat); | ||
195 | wl_keyboard_add_listener(reg->keyboard, &keyboard_listener, reg); | ||
196 | } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && reg->keyboard) { | ||
197 | wl_keyboard_destroy(reg->keyboard); | ||
198 | reg->keyboard = NULL; | ||
199 | } | ||
200 | } | ||
201 | |||
202 | static void seat_handle_name(void *data, struct wl_seat *seat, const char *name) { | ||
203 | // this space intentionally left blank | ||
204 | } | ||
205 | |||
206 | static const struct wl_seat_listener seat_listener = { | ||
207 | .capabilities = seat_handle_capabilities, | ||
208 | .name = seat_handle_name, | ||
209 | }; | ||
210 | |||
211 | static void registry_global(void *data, struct wl_registry *registry, | ||
212 | uint32_t name, const char *interface, uint32_t version) { | ||
213 | struct registry *reg = data; | ||
214 | |||
215 | if (strcmp(interface, wl_compositor_interface.name) == 0) { | ||
216 | reg->compositor = wl_registry_bind(registry, name, &wl_compositor_interface, version); | ||
217 | } else if (strcmp(interface, wl_shm_interface.name) == 0) { | ||
218 | reg->shm = wl_registry_bind(registry, name, &wl_shm_interface, version); | ||
219 | } else if (strcmp(interface, wl_shell_interface.name) == 0) { | ||
220 | reg->shell = wl_registry_bind(registry, name, &wl_shell_interface, version); | ||
221 | } else if (strcmp(interface, wl_seat_interface.name) == 0) { | ||
222 | reg->seat = wl_registry_bind(registry, name, &wl_seat_interface, version); | ||
223 | wl_seat_add_listener(reg->seat, &seat_listener, reg); | ||
224 | } else if (strcmp(interface, wl_output_interface.name) == 0) { | ||
225 | struct wl_output *output = wl_registry_bind(registry, name, &wl_output_interface, version); | ||
226 | struct output_state *ostate = malloc(sizeof(struct output_state)); | ||
227 | ostate->output = output; | ||
228 | ostate->scale = 1; | ||
229 | wl_output_add_listener(output, &output_listener, ostate); | ||
230 | list_add(reg->outputs, ostate); | ||
231 | } else if (strcmp(interface, desktop_shell_interface.name) == 0) { | ||
232 | reg->desktop_shell = wl_registry_bind(registry, name, &desktop_shell_interface, version); | ||
233 | } else if (strcmp(interface, lock_interface.name) == 0) { | ||
234 | reg->swaylock = wl_registry_bind(registry, name, &lock_interface, version); | ||
235 | } | ||
236 | } | ||
237 | |||
238 | static void registry_global_remove(void *data, struct wl_registry *registry, uint32_t name) { | ||
239 | // this space intentionally left blank | ||
240 | } | ||
241 | |||
242 | static const struct wl_registry_listener registry_listener = { | ||
243 | .global = registry_global, | ||
244 | .global_remove = registry_global_remove | ||
245 | }; | ||
246 | |||
247 | struct registry *registry_poll(void) { | ||
248 | struct registry *registry = malloc(sizeof(struct registry)); | ||
249 | memset(registry, 0, sizeof(struct registry)); | ||
250 | registry->outputs = create_list(); | ||
251 | registry->input = calloc(sizeof(struct input), 1); | ||
252 | registry->input->xkb.context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); | ||
253 | |||
254 | registry->display = wl_display_connect(NULL); | ||
255 | if (!registry->display) { | ||
256 | sway_log(L_ERROR, "Error opening display"); | ||
257 | registry_teardown(registry); | ||
258 | return NULL; | ||
259 | } | ||
260 | |||
261 | struct wl_registry *reg = wl_display_get_registry(registry->display); | ||
262 | wl_registry_add_listener(reg, ®istry_listener, registry); | ||
263 | wl_display_dispatch(registry->display); | ||
264 | wl_display_roundtrip(registry->display); | ||
265 | wl_registry_destroy(reg); | ||
266 | |||
267 | return registry; | ||
268 | } | ||
269 | |||
270 | void registry_teardown(struct registry *registry) { | ||
271 | if (registry->pointer) { | ||
272 | wl_pointer_destroy(registry->pointer); | ||
273 | } | ||
274 | if (registry->seat) { | ||
275 | wl_seat_destroy(registry->seat); | ||
276 | } | ||
277 | if (registry->shell) { | ||
278 | wl_shell_destroy(registry->shell); | ||
279 | } | ||
280 | if (registry->shm) { | ||
281 | wl_shm_destroy(registry->shm); | ||
282 | } | ||
283 | if (registry->compositor) { | ||
284 | wl_compositor_destroy(registry->compositor); | ||
285 | } | ||
286 | if (registry->display) { | ||
287 | wl_display_disconnect(registry->display); | ||
288 | } | ||
289 | if (registry->outputs) { | ||
290 | free_flat_list(registry->outputs); | ||
291 | } | ||
292 | free(registry); | ||
293 | } | ||