diff options
-rw-r--r-- | include/client/registry.h | 55 | ||||
-rw-r--r-- | wayland/CMakeLists.txt | 2 | ||||
-rw-r--r-- | wayland/registry.c | 71 |
3 files changed, 128 insertions, 0 deletions
diff --git a/include/client/registry.h b/include/client/registry.h index 5e47b18e..2ab02174 100644 --- a/include/client/registry.h +++ b/include/client/registry.h | |||
@@ -2,16 +2,70 @@ | |||
2 | #define _SWAY_CLIENT_REGISTRY_H | 2 | #define _SWAY_CLIENT_REGISTRY_H |
3 | 3 | ||
4 | #include <wayland-client.h> | 4 | #include <wayland-client.h> |
5 | #include <xkbcommon/xkbcommon.h> | ||
5 | #include "wayland-desktop-shell-client-protocol.h" | 6 | #include "wayland-desktop-shell-client-protocol.h" |
6 | #include "wayland-swaylock-client-protocol.h" | 7 | #include "wayland-swaylock-client-protocol.h" |
7 | #include "list.h" | 8 | #include "list.h" |
8 | 9 | ||
10 | enum mod_bit { | ||
11 | MOD_SHIFT = 1<<0, | ||
12 | MOD_CAPS = 1<<1, | ||
13 | MOD_CTRL = 1<<2, | ||
14 | MOD_ALT = 1<<3, | ||
15 | MOD_MOD2 = 1<<4, | ||
16 | MOD_MOD3 = 1<<5, | ||
17 | MOD_LOGO = 1<<6, | ||
18 | MOD_MOD5 = 1<<7, | ||
19 | }; | ||
20 | |||
21 | enum mask { | ||
22 | MASK_SHIFT, | ||
23 | MASK_CAPS, | ||
24 | MASK_CTRL, | ||
25 | MASK_ALT, | ||
26 | MASK_MOD2, | ||
27 | MASK_MOD3, | ||
28 | MASK_LOGO, | ||
29 | MASK_MOD5, | ||
30 | MASK_LAST | ||
31 | }; | ||
32 | |||
9 | struct output_state { | 33 | struct output_state { |
10 | struct wl_output *output; | 34 | struct wl_output *output; |
11 | uint32_t flags; | 35 | uint32_t flags; |
12 | uint32_t width, height; | 36 | uint32_t width, height; |
13 | }; | 37 | }; |
14 | 38 | ||
39 | struct xkb { | ||
40 | struct xkb_state *state; | ||
41 | struct xkb_context *context; | ||
42 | struct xkb_keymap *keymap; | ||
43 | xkb_mod_mask_t masks[MASK_LAST]; | ||
44 | }; | ||
45 | |||
46 | struct input { | ||
47 | int *repeat_fd; | ||
48 | |||
49 | struct xkb xkb; | ||
50 | |||
51 | xkb_keysym_t sym; | ||
52 | uint32_t code; | ||
53 | uint32_t last_code; | ||
54 | uint32_t modifiers; | ||
55 | |||
56 | xkb_keysym_t repeat_sym; | ||
57 | uint32_t repeat_key; | ||
58 | |||
59 | int32_t repeat_rate_sec; | ||
60 | int32_t repeat_rate_nsec; | ||
61 | int32_t repeat_delay_sec; | ||
62 | int32_t repeat_delay_nsec; | ||
63 | |||
64 | struct { | ||
65 | void (*key)(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t code); | ||
66 | } notify; | ||
67 | }; | ||
68 | |||
15 | struct registry { | 69 | struct registry { |
16 | struct wl_compositor *compositor; | 70 | struct wl_compositor *compositor; |
17 | struct wl_display *display; | 71 | struct wl_display *display; |
@@ -22,6 +76,7 @@ struct registry { | |||
22 | struct wl_shm *shm; | 76 | struct wl_shm *shm; |
23 | struct desktop_shell *desktop_shell; | 77 | struct desktop_shell *desktop_shell; |
24 | struct lock *swaylock; | 78 | struct lock *swaylock; |
79 | struct input *input; | ||
25 | list_t *outputs; | 80 | list_t *outputs; |
26 | }; | 81 | }; |
27 | 82 | ||
diff --git a/wayland/CMakeLists.txt b/wayland/CMakeLists.txt index 8e19fc03..6519cd7d 100644 --- a/wayland/CMakeLists.txt +++ b/wayland/CMakeLists.txt | |||
@@ -2,6 +2,7 @@ include_directories( | |||
2 | ${PROTOCOLS_INCLUDE_DIRS} | 2 | ${PROTOCOLS_INCLUDE_DIRS} |
3 | ${PANGO_INCLUDE_DIRS} | 3 | ${PANGO_INCLUDE_DIRS} |
4 | ${GDK_PIXBUF_INCLUDE_DIRS} | 4 | ${GDK_PIXBUF_INCLUDE_DIRS} |
5 | ${XKBCOMMON_INCLUDE_DIRS} | ||
5 | ) | 6 | ) |
6 | 7 | ||
7 | add_library(sway-wayland | 8 | add_library(sway-wayland |
@@ -17,4 +18,5 @@ target_link_libraries(sway-wayland | |||
17 | sway-protocols | 18 | sway-protocols |
18 | ${PANGO_LIBRARIES} | 19 | ${PANGO_LIBRARIES} |
19 | ${GDK_PIXBUF_LIBRARIES} | 20 | ${GDK_PIXBUF_LIBRARIES} |
21 | ${XKBCOMMON_LIBRARIES} | ||
20 | ) | 22 | ) |
diff --git a/wayland/registry.c b/wayland/registry.c index 883c69d3..45735ccd 100644 --- a/wayland/registry.c +++ b/wayland/registry.c | |||
@@ -1,6 +1,10 @@ | |||
1 | #include <wayland-client.h> | 1 | #include <wayland-client.h> |
2 | #include <xkbcommon/xkbcommon.h> | ||
2 | #include <stdlib.h> | 3 | #include <stdlib.h> |
3 | #include <string.h> | 4 | #include <string.h> |
5 | #include <unistd.h> | ||
6 | #include <sys/mman.h> | ||
7 | #include <sys/timerfd.h> | ||
4 | #include "wayland-desktop-shell-client-protocol.h" | 8 | #include "wayland-desktop-shell-client-protocol.h" |
5 | #include "wayland-swaylock-client-protocol.h" | 9 | #include "wayland-swaylock-client-protocol.h" |
6 | #include "client/registry.h" | 10 | #include "client/registry.h" |
@@ -38,8 +42,73 @@ static const struct wl_output_listener output_listener = { | |||
38 | .scale = display_handle_scale | 42 | .scale = display_handle_scale |
39 | }; | 43 | }; |
40 | 44 | ||
45 | const char *XKB_MASK_NAMES[MASK_LAST] = { | ||
46 | XKB_MOD_NAME_SHIFT, | ||
47 | XKB_MOD_NAME_CAPS, | ||
48 | XKB_MOD_NAME_CTRL, | ||
49 | XKB_MOD_NAME_ALT, | ||
50 | "Mod2", | ||
51 | "Mod3", | ||
52 | XKB_MOD_NAME_LOGO, | ||
53 | "Mod5", | ||
54 | }; | ||
55 | |||
56 | const enum mod_bit XKB_MODS[MASK_LAST] = { | ||
57 | MOD_SHIFT, | ||
58 | MOD_CAPS, | ||
59 | MOD_CTRL, | ||
60 | MOD_ALT, | ||
61 | MOD_MOD2, | ||
62 | MOD_MOD3, | ||
63 | MOD_LOGO, | ||
64 | MOD_MOD5 | ||
65 | }; | ||
66 | |||
41 | static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, | 67 | static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, |
42 | uint32_t format, int fd, uint32_t size) { | 68 | uint32_t format, int fd, uint32_t size) { |
69 | // Keyboard errors are abort-worthy because you wouldn't be able to unlock your screen otherwise. | ||
70 | |||
71 | struct registry *registry = data; | ||
72 | if (!data) { | ||
73 | close(fd); | ||
74 | return; | ||
75 | } | ||
76 | |||
77 | if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { | ||
78 | close(fd); | ||
79 | sway_abort("Unknown keymap format %d, aborting", format); | ||
80 | } | ||
81 | |||
82 | char *map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); | ||
83 | if (map_str == MAP_FAILED) { | ||
84 | close(fd); | ||
85 | sway_abort("Unable to initialized shared keyboard memory, aborting"); | ||
86 | } | ||
87 | |||
88 | struct xkb_keymap *keymap = xkb_keymap_new_from_string(registry->input->xkb.context, | ||
89 | map_str, XKB_KEYMAP_FORMAT_TEXT_V1, 0); | ||
90 | munmap(map_str, size); | ||
91 | close(fd); | ||
92 | |||
93 | if (!keymap) { | ||
94 | sway_abort("Failed to compile keymap, aborting"); | ||
95 | } | ||
96 | |||
97 | struct xkb_state *state = xkb_state_new(keymap); | ||
98 | if (!state) { | ||
99 | xkb_keymap_unref(keymap); | ||
100 | sway_abort("Failed to create xkb state, aborting"); | ||
101 | } | ||
102 | |||
103 | xkb_keymap_unref(registry->input->xkb.keymap); | ||
104 | xkb_state_unref(registry->input->xkb.state); | ||
105 | registry->input->xkb.keymap = keymap; | ||
106 | registry->input->xkb.state = state; | ||
107 | |||
108 | int i; | ||
109 | for (i = 0; i < MASK_LAST; ++i) { | ||
110 | registry->input->xkb.masks[i] = 1 << xkb_keymap_mod_get_index(registry->input->xkb.keymap, XKB_MASK_NAMES[i]); | ||
111 | } | ||
43 | } | 112 | } |
44 | 113 | ||
45 | static void keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, | 114 | static void keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, |
@@ -115,6 +184,8 @@ struct registry *registry_poll(void) { | |||
115 | struct registry *registry = malloc(sizeof(struct registry)); | 184 | struct registry *registry = malloc(sizeof(struct registry)); |
116 | memset(registry, 0, sizeof(struct registry)); | 185 | memset(registry, 0, sizeof(struct registry)); |
117 | registry->outputs = create_list(); | 186 | registry->outputs = create_list(); |
187 | registry->input = calloc(sizeof(struct input), 1); | ||
188 | registry->input->xkb.context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); | ||
118 | 189 | ||
119 | registry->display = wl_display_connect(NULL); | 190 | registry->display = wl_display_connect(NULL); |
120 | if (!registry->display) { | 191 | if (!registry->display) { |