From ce05175372a9ddca1a225db0765ace1127a39293 Mon Sep 17 00:00:00 2001 From: Nicholas Date: Fri, 12 Nov 2021 09:22:01 -0800 Subject: chore: simplified organizational structure --- src/cmd/wm/input.c | 316 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 316 insertions(+) create mode 100644 src/cmd/wm/input.c (limited to 'src/cmd/wm/input.c') diff --git a/src/cmd/wm/input.c b/src/cmd/wm/input.c new file mode 100644 index 0000000..4c6bfd4 --- /dev/null +++ b/src/cmd/wm/input.c @@ -0,0 +1,316 @@ +#include "wm.h" + +// ----------------------------------------------------------------------- +// keyboard + +static +void +keymodifier(struct wl_listener *l, void *data) +{ + Keyboard *keyboard = wl_container_of(l, keyboard, event.modify); + + wlr_seat_set_keyboard(server.input.seat, keyboard->device); + wlr_seat_keyboard_notify_modifiers(server.input.seat, &keyboard->device->keyboard->modifiers); +} + +static +int +keybinding(uint32 modifier, xkb_keysym_t sym) +{ + Key *key; + + for(key=cfg·binding; key!=cfg·endbinding; ++key) { + if(modifier == key->modifier && sym == key->sym && key->action){ + key->action(&key->arg); + return 1; + } + } + return 0; +} + +static +void +keypress(struct wl_listener *l, void *data) +{ + int i,h,n; + uint32 keycode, modifier; + const xkb_keysym_t *syms; + struct Keyboard *keyboard = wl_container_of(l, keyboard, event.press); + struct wlr_event_keyboard_key *event = data; + + keycode = event->keycode + 8; + + h = 0; + n = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state, keycode, &syms); + + modifier = wlr_keyboard_get_modifiers(keyboard->device->keyboard); + if(event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { + for(i=0; idevice); + wlr_seat_keyboard_notify_key(server.input.seat, event->time_msec, event->keycode, event->state); + } +} + +static +void +free_keyboard(struct wl_listener *l, void *data) +{ + struct wlr_input_device *device = data; + Keyboard *keyboard = device->data; + + /* XXX: debug + wl_list_remove(&keyboard->link); + wl_list_remove(&keyboard->event.modify.link); + wl_list_remove(&keyboard->event.press.link); + wl_list_remove(&keyboard->event.destroy.link); + + free(keyboard); + */ +} + +static +void +make_keyboard(struct wlr_input_device *device) +{ + Keyboard *keyboard; + struct xkb_context *context; + struct xkb_keymap *keymap; + + keyboard = device->data = calloc(1, sizeof(*keyboard)); + keyboard->device = device; + + context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + keymap = xkb_keymap_new_from_names(context, nil, XKB_KEYMAP_COMPILE_NO_FLAGS); + + wlr_keyboard_set_keymap(device->keyboard, keymap); + + xkb_keymap_unref(keymap); + xkb_context_unref(context); + + wlr_keyboard_set_repeat_info(device->keyboard, cfg·repeat_rate, cfg·repeat_delay); + + keyboard->event.modify.notify = keymodifier; + wl_signal_add(&device->keyboard->events.modifiers, &keyboard->event.modify); + + keyboard->event.press.notify = keypress; + wl_signal_add(&device->keyboard->events.key, &keyboard->event.press); + + keyboard->event.destroy.notify = free_keyboard; + wl_signal_add(&device->keyboard->events.destroy, &keyboard->event.destroy); + + wlr_seat_set_keyboard(server.input.seat, device); + + wl_list_insert(&server.input.keyboards, &keyboard->link); +} + +// ----------------------------------------------------------------------- +// cursor + +static +void +focus_surface(Client *client, struct wlr_surface *surface, double sx, double sy, uint32 time) +{ + struct timespec now; + int lift = time; + + if(client && !surface) + surface = client->xdg->surface; + + if(!surface){ + wlr_seat_pointer_notify_clear_focus(server.input.seat); + return; + } + + if(!time) { + clock_gettime(CLOCK_MONOTONIC, &now); + time = now.tv_sec * 1000 + now.tv_nsec / 1000000; + } + + if(surface == server.input.seat->pointer_state.focused_surface) { + wlr_seat_pointer_notify_motion(server.input.seat, time, sx, sy); + return; + } + + wlr_seat_pointer_notify_enter(server.input.seat, surface, sx, sy); + + if(cfg·sloppyfocus && lift) + focus(client, 0); +} + +void +notify_move(uint32 time) +{ + double sx, sy; + Client *client; + struct wlr_box box; + struct wlr_surface *surface; + + if(time) { + wlr_idle_notify_activity(server.input.idle, server.input.seat); + if(cfg·sloppyfocus) + server.monitor.selected = monitor_at(server.cursor.dot->x, server.cursor.dot->y); + } + + if(server.cursor.mode == CursorMove) { + resize(server.grab.client, + server.cursor.dot->x - server.grab.x, + server.cursor.dot->y - server.grab.y, + server.grab.client->geometry.width, + server.grab.client->geometry.height, + 1 + ); + return; + } + + if(server.cursor.mode == CursorResize) { + wlr_xdg_surface_get_geometry(server.grab.client->xdg, &box); + resize(server.grab.client, + server.grab.box.x - box.x, + server.grab.box.y - box.y, + server.cursor.dot->x - server.grab.x - server.grab.box.x, + server.cursor.dot->y - server.grab.y - server.grab.box.y, + 1 + ); + return; + } + + /* otherwise, find the client under the pointer and send the event along. */ + client = client_at(server.cursor.dot->x, server.cursor.dot->y); + if(!client) { + wlr_xcursor_manager_set_cursor_image(server.cursor.manager, "left_ptr", server.cursor.dot); + return; + } + + surface = client_surface_at( + client, + server.cursor.dot->x - client->geometry.x - client->border, + server.cursor.dot->y - client->geometry.y - client->border, + &sx, &sy + ); + + focus_surface(client, surface, sx, sy, time); +} + +void +cursor_move(struct wl_listener *l, void *data) +{ + struct wlr_event_pointer_motion *event = data; + wlr_cursor_move(server.cursor.dot, event->device, event->delta_x, event->delta_y); + notify_move(event->time_msec); +} + +void +cursor_move_abs(struct wl_listener *l, void *data) +{ + struct wlr_event_pointer_motion_absolute *event = data; + wlr_cursor_warp_absolute(server.cursor.dot, event->device, event->x, event->y); + notify_move(event->time_msec); +} + +void +cursor_button(struct wl_listener *l, void *data) +{ + Client *client; + uint32 modifier; + Button *button; + struct wlr_keyboard *keyboard; + struct wlr_event_pointer_button *event = data; + + wlr_idle_notify_activity(server.input.idle, server.input.seat); + + switch(event->state) { + case WLR_BUTTON_PRESSED: + if((client=client_at(server.cursor.dot->x, server.cursor.dot->y))) + focus(client,1); + + keyboard = wlr_seat_get_keyboard(server.input.seat); + modifier = wlr_keyboard_get_modifiers(keyboard); + for(button=cfg·button; button != cfg·endbutton; ++button) { + if(modifier == button->modifier && event->button == button->code && button->function) { + button->function(&button->arg); + return; + } + } + break; + case WLR_BUTTON_RELEASED: + if(server.cursor.mode != CursorNormal) { + wlr_xcursor_manager_set_cursor_image(server.cursor.manager, "left_ptr", server.cursor.dot); + server.cursor.mode = CursorNormal; + /* Drop the window off on its new monitor */ + server.monitor.selected = monitor_at(server.cursor.dot->x, server.cursor.dot->y); + attach(server.grab.client, server.monitor.selected, 0); + return; + } + } + + wlr_seat_pointer_notify_button(server.input.seat, event->time_msec, event->button, event->state); +} + +void +cursor_axis(struct wl_listener *l, void *data) +{ + struct wlr_event_pointer_axis *event = data; + /* Notify the client with pointer focus of the axis event. */ + wlr_seat_pointer_notify_axis(server.input.seat, + event->time_msec, event->orientation, event->delta, + event->delta_discrete, event->source); +} + +void +cursor_frame(struct wl_listener *l, void *data) +{ + wlr_seat_pointer_notify_frame(server.input.seat); +} + +void +request_cursor(struct wl_listener *l, void *data) +{ + struct wlr_seat_pointer_request_set_cursor_event *event = data; + struct wlr_seat_client *focused = server.input.seat->pointer_state.focused_client; + if(focused == event->seat_client) + wlr_cursor_set_surface(server.cursor.dot, event->surface, event->hotspot_x, event->hotspot_y); +} + +void +request_set_selection(struct wl_listener *l, void *data) +{ + struct wlr_seat_request_set_selection_event *event = data; + wlr_seat_set_selection(server.input.seat, event->source, event->serial); +} + +static +void +make_pointer(struct wlr_input_device *device) +{ + wlr_cursor_attach_input_device(server.cursor.dot, device); +} + +// ----------------------------------------------------------------------- +// generic input + +void +make_input(struct wl_listener *l, void *data) +{ + uint32 capability; + struct wlr_input_device *device = data; + + switch(device->type) { + case WLR_INPUT_DEVICE_KEYBOARD: + make_keyboard(device); + break; + case WLR_INPUT_DEVICE_POINTER: + make_pointer(device); + /* fallthrough */ + default: + break; + } + + capability = WL_SEAT_CAPABILITY_POINTER; + if(!wl_list_empty(&server.input.keyboards)) + capability |= WL_SEAT_CAPABILITY_KEYBOARD; + wlr_seat_set_capabilities(server.input.seat, capability); +} -- cgit v1.2.1