diff options
Diffstat (limited to 'source/base/base_platform_linux_wayland_input.cpp')
| -rw-r--r-- | source/base/base_platform_linux_wayland_input.cpp | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/source/base/base_platform_linux_wayland_input.cpp b/source/base/base_platform_linux_wayland_input.cpp new file mode 100644 index 0000000..0d66fb4 --- /dev/null +++ b/source/base/base_platform_linux_wayland_input.cpp | |||
| @@ -0,0 +1,159 @@ | |||
| 1 | internal void wayland_keyboard_keymap(void *data, struct wl_keyboard *keyboard, u32 format, s32 fd, u32 size) { | ||
| 2 | Log("<- wl_keyboard.keymap: format=%u fd=%d size=%u\n", format, fd, size); | ||
| 3 | close(fd); | ||
| 4 | } | ||
| 5 | |||
| 6 | internal void wayland_keyboard_enter(void *data, struct wl_keyboard *keyboard, u32 serial, | ||
| 7 | struct wl_surface *surface, struct wl_array *keys) { | ||
| 8 | WaylandState *state = (WaylandState *)data; | ||
| 9 | Log("<- wl_keyboard.enter\n"); | ||
| 10 | |||
| 11 | // wl_array is just { size_t size; size_t alloc; void *data; }. here data is a list of u32. | ||
| 12 | u32 *key = (u32 *)keys->data; | ||
| 13 | u32 key_count = keys->size / sizeof(u32); | ||
| 14 | for (u32 i = 0; i < key_count; ++i) { | ||
| 15 | if (key[i] < sizeof(state->keys_down) / sizeof(state->keys_down[0])) { | ||
| 16 | state->keys_down[key[i]] = true; | ||
| 17 | } | ||
| 18 | } | ||
| 19 | } | ||
| 20 | |||
| 21 | // leave: we lost focus. after this we will NOT receive release events for keys that | ||
| 22 | // are still held, so we release everything ourselves. otherwise keys get "stuck". | ||
| 23 | internal void wayland_keyboard_leave(void *data, struct wl_keyboard *keyboard, u32 serial, | ||
| 24 | struct wl_surface *surface) { | ||
| 25 | WaylandState *state = (WaylandState *)data; | ||
| 26 | Log("<- wl_keyboard.leave\n"); | ||
| 27 | |||
| 28 | MemSetZero(state->keys_down, sizeof(state->keys_down)); | ||
| 29 | } | ||
| 30 | |||
| 31 | internal void wayland_keyboard_key(void *data, struct wl_keyboard *keyboard, u32 serial, | ||
| 32 | u32 time, u32 key, u32 key_state) { | ||
| 33 | WaylandState *state = (WaylandState *)data; | ||
| 34 | b32 pressed = (key_state == WL_KEYBOARD_KEY_STATE_PRESSED); | ||
| 35 | |||
| 36 | Log("<- wl_keyboard.key: key=%u %s\n", key, pressed ? "pressed" : "released"); | ||
| 37 | |||
| 38 | if (key < sizeof(state->keys_down) / sizeof(state->keys_down[0])) { | ||
| 39 | state->keys_down[key] = pressed; | ||
| 40 | } | ||
| 41 | |||
| 42 | if (key == KEY_ESC && pressed) { | ||
| 43 | state->should_close = true; | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | internal void wayland_keyboard_modifiers(void *data, struct wl_keyboard *keyboard, u32 serial, u32 mods_depressed, u32 mods_latched, | ||
| 48 | u32 mods_locked, u32 group) { | ||
| 49 | } | ||
| 50 | |||
| 51 | internal void wayland_keyboard_repeat_info(void *data, struct wl_keyboard *keyboard, | ||
| 52 | s32 rate, s32 delay) { | ||
| 53 | Log("<- wl_keyboard.repeat_info: rate=%d delay=%d\n", rate, delay); | ||
| 54 | } | ||
| 55 | |||
| 56 | // the listener: a struct of function pointers, one per event, in the order the events | ||
| 57 | // are declared in wayland.xml (which is also their opcode). libwayland indexes into this | ||
| 58 | // struct with the opcode it reads from the message header. | ||
| 59 | global_variable const struct wl_keyboard_listener wayland_keyboard_listener = { | ||
| 60 | wayland_keyboard_keymap, // opcode 0 | ||
| 61 | wayland_keyboard_enter, // opcode 1 | ||
| 62 | wayland_keyboard_leave, // opcode 2 | ||
| 63 | wayland_keyboard_key, // opcode 3 | ||
| 64 | wayland_keyboard_modifiers, // opcode 4 | ||
| 65 | wayland_keyboard_repeat_info, // opcode 5 | ||
| 66 | }; | ||
| 67 | |||
| 68 | //- mouse (pointer) input | ||
| 69 | |||
| 70 | enum wayland_mouse_button_pressed: b32 { | ||
| 71 | |||
| 72 | PRESSED, | ||
| 73 | RELEASED, | ||
| 74 | |||
| 75 | }; | ||
| 76 | |||
| 77 | internal void wayland_button_event(void *data, struct wl_pointer *pointer, | ||
| 78 | u32 serial, u32 time, u32 button, u32 state) { | ||
| 79 | |||
| 80 | |||
| 81 | } | ||
| 82 | |||
| 83 | |||
| 84 | internal void wayland_pointer_enter(void *data, struct wl_pointer *pointer, | ||
| 85 | u32 serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) { | ||
| 86 | WaylandState *state = (WaylandState *)data; | ||
| 87 | Log("<- pointer enteirng window"); | ||
| 88 | state->mouse_in_window = true; | ||
| 89 | state->x_offset = surface_x; | ||
| 90 | state->y_offset = surface_y; | ||
| 91 | |||
| 92 | |||
| 93 | } | ||
| 94 | internal void wayland_pointer_motion(void *data, struct wl_pointer *pointer, u32 time, | ||
| 95 | wl_fixed_t surface_x, wl_fixed_t surface_y) { | ||
| 96 | WaylandState *state = (WaylandState *)data; | ||
| 97 | state->x_offset = (f32)wl_fixed_to_double(surface_x); | ||
| 98 | state->y_offset = (f32)wl_fixed_to_double(surface_y); | ||
| 99 | } | ||
| 100 | |||
| 101 | internal void wayland_pointer_leave(void *data, struct wl_pointer *pointer, u32 serial, wl_surface *surface) { | ||
| 102 | WaylandState *state = (WaylandState *)data; | ||
| 103 | state->mouse_in_window = false; | ||
| 104 | Log("<- pointer leaving window"); | ||
| 105 | } | ||
| 106 | |||
| 107 | |||
| 108 | |||
| 109 | global_variable const struct wl_pointer_listener wayland_pointer_listener = { | ||
| 110 | wayland_pointer_enter, | ||
| 111 | wayland_pointer_leave, | ||
| 112 | wayland_pointer_motion, | ||
| 113 | wayland_button_event, | ||
| 114 | }; | ||
| 115 | |||
| 116 | |||
| 117 | |||
| 118 | |||
| 119 | |||
| 120 | //- wl_seat events | ||
| 121 | |||
| 122 | // capabilities: tells us which devices this seat has, as a bitmask: | ||
| 123 | // WL_SEAT_CAPABILITY_POINTER = 1, WL_SEAT_CAPABILITY_KEYBOARD = 2, WL_SEAT_CAPABILITY_TOUCH = 4 | ||
| 124 | // this can be sent again later (keyboard unplugged / plugged in), so we handle both directions. | ||
| 125 | internal void wayland_seat_capabilities(void *data, struct wl_seat *seat, u32 capabilities) { | ||
| 126 | |||
| 127 | WaylandState *state = (WaylandState *)data; | ||
| 128 | b32 has_keyboard = (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) != 0; | ||
| 129 | |||
| 130 | |||
| 131 | Log("<- wl_seat.capabilities: %u\n", capabilities); | ||
| 132 | |||
| 133 | if (has_keyboard && state->keyboard == NULL) { | ||
| 134 | // get_keyboard is a request that creates a new object (a "new_id" argument). | ||
| 135 | // libwayland allocates the id, sends the message, and hands us the proxy. | ||
| 136 | state->keyboard = wl_seat_get_keyboard(seat); | ||
| 137 | wl_keyboard_add_listener(state->keyboard, &wayland_keyboard_listener, state); | ||
| 138 | } else if (!has_keyboard && state->keyboard != NULL) { | ||
| 139 | // keyboard went away: tell the compositor we're done with the object, free the proxy. | ||
| 140 | // the `release` request only exists since wl_seat version 3; before that we can | ||
| 141 | // only free our side of it with destroy. | ||
| 142 | if (wl_keyboard_get_version(state->keyboard) >= WL_KEYBOARD_RELEASE_SINCE_VERSION) { | ||
| 143 | wl_keyboard_release(state->keyboard); | ||
| 144 | } else { | ||
| 145 | wl_keyboard_destroy(state->keyboard); | ||
| 146 | } | ||
| 147 | state->keyboard = NULL; | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 151 | // name: a human readable seat name like "seat0". only useful for multi-seat setups. | ||
| 152 | internal void wayland_seat_name(void *data, struct wl_seat *seat, const char *name) { | ||
| 153 | Log("<- wl_seat.name: %s\n", name); | ||
| 154 | } | ||
| 155 | |||
| 156 | global_variable const struct wl_seat_listener wayland_seat_listener = { | ||
| 157 | wayland_seat_capabilities, // opcode 0 | ||
| 158 | wayland_seat_name, // opcode 1 (since version 2) | ||
| 159 | }; | ||
