diff options
Diffstat (limited to 'wayland')
-rw-r--r-- | wayland/CMakeLists.txt | 2 | ||||
-rw-r--r-- | wayland/registry.c | 71 |
2 files changed, 73 insertions, 0 deletions
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) { |