-rw-r--r-- src/input.c
1 #include <inttypes.h> 2 #include <unistd.h> 3 #include <wayland-server-protocol.h> 4 #include <wlr/backend/libinput.h> 5 #include <wlr/types/wlr_keyboard.h> 6 #include <wlr/types/wlr_data_device.h> 7 #include <wlr/types/wlr_primary_selection_v1.h> 8 #include <wlr/types/wlr_virtual_keyboard_v1.h> 9 10 #include "action.h" 11 #include "cursor.h" 12 #include "output.h" 13 #include "shell.h" 14 #include "types.h" 15 16 17 static void on_modifier(struct wl_listener *listener, void *data) { 18 struct keyboard *keyboard = wl_container_of(listener, keyboard, modifier_listener); 19 wlr_seat_keyboard_notify_modifiers( 20 wimp.seat, &keyboard->device->keyboard->modifiers 21 ); 22 23 uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard); 24 bool handled = false; 25 struct binding *kb; 26 if ((modifiers & wimp.mod)) { 27 modifiers &= ~wimp.mod; 28 wl_list_for_each(kb, &wimp.mouse_bindings, link) { 29 if (modifiers == kb->mods) { 30 switch (kb->key) { 31 case MOTION: 32 wimp.on_mouse_motion = kb->action; 33 break; 34 case SCROLL: 35 wimp.on_mouse_scroll = kb->action; 36 break; 37 case DRAG1: 38 wimp.on_drag1 = kb->action; 39 break; 40 case DRAG2: 41 wimp.on_drag2 = kb->action; 42 break; 43 case DRAG3: 44 wimp.on_drag3 = kb->action; 45 break; 46 case PINCH: 47 wimp.on_pinch = kb->action; 48 wimp.on_pinch_begin = *(action* )kb->data; 49 break; 50 } 51 wimp.cursor_mode = CURSOR_MOD; 52 handled = true; 53 } 54 } 55 } 56 57 if (!handled){ 58 wimp.cursor_mode = CURSOR_PASSTHROUGH; 59 } 60 } 61 62 63 static void on_key(struct wl_listener *listener, void *data) { 64 struct wlr_event_keyboard_key *event = data; 65 66 if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { 67 const xkb_keysym_t *syms; 68 xkb_keycode_t keycode = event->keycode + 8; 69 struct keyboard *keyboard = wl_container_of(listener, keyboard, key_listener); 70 struct wlr_keyboard *wlr_kb = keyboard->device->keyboard; 71 72 if (wimp.mark_waiting) { 73 struct mark *mark; 74 wimp.mark_waiting = false; 75 damage_mark_indicator(); 76 xkb_state_key_get_syms(wlr_kb->xkb_state, keycode, &syms); 77 mark = wl_container_of(wimp.marks.next, mark, link); 78 if (mark->key) { 79 actually_go_to_mark((void *)&syms[0]); 80 } else { 81 actually_set_mark(syms[0]); 82 } 83 return; 84 } 85 86 uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard); 87 struct binding *kb; 88 if ((modifiers & wimp.mod)) { 89 xkb_layout_index_t layout_index = xkb_state_key_get_layout(wlr_kb->xkb_state, keycode); 90 int nsyms = xkb_keymap_key_get_syms_by_level( 91 wlr_kb->keymap, keycode, layout_index, 0, &syms 92 ); 93 94 modifiers &= ~wimp.mod; 95 for (int i = 0; i < nsyms; i++) { 96 wl_list_for_each(kb, &wimp.key_bindings, link) { 97 if (syms[i] == kb->key && modifiers == kb->mods) { 98 kb->action(kb->data); 99 return; 100 } 101 } 102 } 103 } 104 } 105 106 // forward to client 107 wlr_seat_keyboard_notify_key( 108 wimp.seat, event->time_msec, event->keycode, event->state 109 ); 110 } 111 112 113 static void on_keyboard_destroy(struct wl_listener *listener, void *data) { 114 struct keyboard *keyboard = wl_container_of(listener, keyboard, destroy_listener); 115 116 wl_list_remove(&keyboard->link); 117 wl_list_remove(&keyboard->modifier_listener.link); 118 wl_list_remove(&keyboard->key_listener.link); 119 wl_list_remove(&keyboard->destroy_listener.link); 120 free(keyboard); 121 122 if (!wl_list_empty(&wimp.keyboards)) { 123 keyboard = wl_container_of(wimp.keyboards.next, keyboard, link); 124 wlr_seat_set_keyboard(wimp.seat, keyboard->device); 125 } 126 } 127 128 129 static void add_new_pointer(struct wlr_input_device *device) { 130 if (wlr_input_device_is_libinput(device)) { 131 struct libinput_device *ldev = wlr_libinput_get_device_handle(device); 132 if (libinput_device_config_tap_get_finger_count(ldev) > 1) { 133 libinput_device_config_tap_set_enabled(ldev, LIBINPUT_CONFIG_TAP_ENABLED); 134 } 135 } 136 wlr_cursor_attach_input_device(wimp.cursor, device); 137 } 138 139 140 static void add_new_keyboard(struct wlr_input_device *device) { 141 struct keyboard *keyboard = calloc(1, sizeof(struct keyboard)); 142 keyboard->device = device; 143 144 // currently assumes default "us" 145 struct xkb_rule_names rules = { 0 }; 146 struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); 147 struct xkb_keymap *keymap = xkb_map_new_from_names(context, &rules, 148 XKB_KEYMAP_COMPILE_NO_FLAGS); 149 150 wlr_keyboard_set_keymap(device->keyboard, keymap); 151 xkb_keymap_unref(keymap); 152 xkb_context_unref(context); 153 wlr_keyboard_set_repeat_info(device->keyboard, 25, 600); 154 155 keyboard->key_listener.notify = on_key; 156 keyboard->destroy_listener.notify = on_keyboard_destroy; 157 keyboard->modifier_listener.notify = on_modifier; 158 wl_signal_add(&device->keyboard->events.key, &keyboard->key_listener); 159 wl_signal_add(&device->keyboard->events.destroy, &keyboard->destroy_listener); 160 wl_signal_add(&device->keyboard->events.modifiers, &keyboard->modifier_listener); 161 162 wlr_seat_set_keyboard(wimp.seat, device); 163 wl_list_insert(&wimp.keyboards, &keyboard->link); 164 } 165 166 167 static void on_request_set_selection(struct wl_listener *listener, void *data) { 168 struct wlr_seat_request_set_selection_event *event = data; 169 wlr_seat_set_selection(wimp.seat, event->source, event->serial); 170 } 171 172 173 static void on_new_input(struct wl_listener *listener, void *data) { 174 struct wlr_input_device *device = data; 175 switch (device->type) { 176 case WLR_INPUT_DEVICE_KEYBOARD: 177 add_new_keyboard(device); 178 break; 179 case WLR_INPUT_DEVICE_POINTER: 180 add_new_pointer(device); 181 break; 182 default: 183 break; 184 } 185 186 uint32_t capabilities = WL_SEAT_CAPABILITY_POINTER; 187 if (!wl_list_empty(&wimp.keyboards)) 188 capabilities |= WL_SEAT_CAPABILITY_KEYBOARD; 189 wlr_seat_set_capabilities(wimp.seat, capabilities); 190 } 191 192 193 static void on_new_virtual_keyboard(struct wl_listener *listener, void *data) { 194 struct wlr_virtual_keyboard_v1 *keyboard = data; 195 struct wlr_input_device *device = &keyboard->input_device; 196 add_new_keyboard(device); 197 } 198 199 200 void set_up_inputs() { 201 wimp.seat = wlr_seat_create(wimp.display, "seat0"); 202 wlr_data_device_manager_create(wimp.display); 203 wlr_primary_selection_v1_device_manager_create(wimp.display); 204 wl_list_init(&wimp.keyboards); 205 206 wimp.new_input_listener.notify = on_new_input; 207 wl_signal_add(&wimp.backend->events.new_input, &wimp.new_input_listener); 208 209 wimp.request_set_selection_listener.notify = on_request_set_selection; 210 wl_signal_add(&wimp.seat->events.request_set_selection, 211 &wimp.request_set_selection_listener); 212 213 wimp.virtual_keyboard = wlr_virtual_keyboard_manager_v1_create(wimp.display); 214 wimp.new_virtual_keyboard_listener.notify = on_new_virtual_keyboard; 215 wl_signal_add(&wimp.virtual_keyboard->events.new_virtual_keyboard, 216 &wimp.new_virtual_keyboard_listener); 217 } 218