#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); }