gimp but for windows: a wayland compositor
git clone https://github.com/m-col/wimp
Files | Refs | Readme

-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