From 93e9672953d849288f27ff3d977cc1c1ff111da8 Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Mon, 4 Oct 2021 11:33:07 -0700 Subject: feat(wm): keyboard focus corrected --- sys/cmd/dwm/dwm.h | 4 +- sys/cmd/wm/client.c | 116 +++++++++++++++++++++++------------------------ sys/cmd/wm/config.h | 13 +++++- sys/cmd/wm/input.c | 127 ++++++++++++++++++++++++++++------------------------ sys/cmd/wm/main.c | 1 + sys/cmd/wm/wm.h | 24 ++++++---- sys/cmd/wm/xdg.c | 2 - 7 files changed, 153 insertions(+), 134 deletions(-) (limited to 'sys/cmd') diff --git a/sys/cmd/dwm/dwm.h b/sys/cmd/dwm/dwm.h index 6493093..3a94248 100644 --- a/sys/cmd/dwm/dwm.h +++ b/sys/cmd/dwm/dwm.h @@ -42,11 +42,11 @@ /* enums */ enum -{ +{ MouseNormal, MouseResize, MouseMove, - MouseLast + MouseLast, }; /* mouse states */ enum diff --git a/sys/cmd/wm/client.c b/sys/cmd/wm/client.c index f626cfa..3139367 100644 --- a/sys/cmd/wm/client.c +++ b/sys/cmd/wm/client.c @@ -2,47 +2,67 @@ static char broken[] = "broken"; +// ----------------------------------------------------------------------- +// scripts + +void * +move_client(Arg *arg) +{ + return nil; +} + +void * +float_client(Arg *arg) +{ + return nil; +} + +void * +resize_client(Arg *arg) +{ + return nil; +} + +// ----------------------------------------------------------------------- +// core + void focus(Client *client, int lift) { - struct wlr_seat *seat; struct wlr_surface *old, *new; struct wlr_xdg_surface *xdg; struct wlr_keyboard *keyboard; - new = server.input.seat->keyboard_state.focused_surface; + if(!client) { + wlr_seat_keyboard_notify_clear_focus(server.input.seat); + return; + } + + old = server.input.seat->keyboard_state.focused_surface; - if(client && lift) { + if(lift) { wl_list_remove(&client->stack); wl_list_insert(&server.client.stack, &client->stack); } - seat = server.input.seat; - old = seat->keyboard_state.focused_surface; - + new = client->xdg->surface; if(old==new) return; - if(client) { - wl_list_remove(&client->focus); - wl_list_insert(&server.client.focus, &client->focus); - server.monitor.selected = client->monitor; - client->isurgent = 0; - } + wl_list_remove(&client->focus); + wl_list_insert(&server.client.focus, &client->focus); + server.monitor.selected = client->monitor; + client->isurgent = 0; + // XXX: do we need for non-client case? if(old) { - xdg = wlr_xdg_surface_from_wlr_surface(seat->keyboard_state.focused_surface); + xdg = wlr_xdg_surface_from_wlr_surface(old); wlr_xdg_toplevel_set_activated(xdg, false); } - if(!client) { - wlr_seat_keyboard_notify_clear_focus(seat); - return; - } + keyboard = wlr_seat_get_keyboard(server.input.seat); - keyboard = wlr_seat_get_keyboard(seat); - - wlr_seat_keyboard_notify_enter(seat, client->xdg->surface, + wlr_seat_keyboard_notify_enter(server.input.seat, new, keyboard->keycodes, keyboard->num_keycodes, &keyboard->modifiers @@ -51,8 +71,19 @@ focus(Client *client, int lift) wlr_xdg_toplevel_set_activated(client->xdg, true); } +Client* +client_at(double x, double y) +{ + Client *client; + wl_list_for_each(client, &server.client.list, link) + if(VISIBLE_ON(client, client->monitor) && wlr_box_contains_point(&client->geometry, x, y)) + return client; + return nil; +} + +static int -client_has(Client *client, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) +has(Client *client, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { double x, y, vsx = lx - client->geometry.x, vsy = ly - client->geometry.y; struct wlr_surface *find = nil; @@ -68,49 +99,12 @@ client_has(Client *client, double lx, double ly, struct wlr_surface **surface, d return false; } -Client* -client_at(double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) +struct wlr_surface * +client_surface_at(Client *client, double cx, double cy, double *sx, double *sy) { - Client *it; - wl_list_for_each(it, &server.client.list, link) { - if(client_has(it, lx, ly, surface, sx, sy)) - return it; - } - - return nil; + return wlr_xdg_surface_surface_at(client->xdg, cx, cy, sx, sy); } -void -setinteractive(Client *client, int mode, uint32 edges) { - double bx, by; - struct wlr_box box; - struct wlr_surface *focused = server.input.seat->pointer_state.focused_surface; - - if(client->xdg->surface != focused) - return; - - server.grab.client = client; - server.cursor.mode = mode; - - if(mode == CursorMove) { - server.grab.x = server.cursor.dot->x - client->geometry.x; - server.grab.y = server.cursor.dot->y - client->geometry.y; - } else { - wlr_xdg_surface_get_geometry(client->xdg, &box); - - bx = (client->geometry.x + box.x) + ((edges & WLR_EDGE_RIGHT) ? box.width : 0); - by = (client->geometry.y + box.y) + ((edges & WLR_EDGE_BOTTOM) ? box.height : 0); - - server.grab.x = server.cursor.dot->x - bx; - server.grab.y = server.cursor.dot->y - by; - - server.grab.box = box; - server.grab.box.x += client->geometry.x; - server.grab.box.y += client->geometry.y; - - server.resize = edges; - } -} static void diff --git a/sys/cmd/wm/config.h b/sys/cmd/wm/config.h index 517c78d..d44b45f 100644 --- a/sys/cmd/wm/config.h +++ b/sys/cmd/wm/config.h @@ -43,8 +43,8 @@ CONFIG(MonitorRule, monitorrule[], { CONFIG(MonitorRule*, endmonitorrule, arrend(cfg·monitorrule)); /* keybindings */ -#define MOD(a) WLR_MODIFIER_##a #define MODKEY WLR_MODIFIER_ALT +#define MOD(a) WLR_MODIFIER_##a #define KEY(a) XKB_KEY_##a CONFIG(Key, binding[], { @@ -55,5 +55,14 @@ CONFIG(Key, binding[], { CONFIG(Key*, endbinding, arrend(cfg·binding)); #undef MOD -#undef MODKEY #undef KEY + +/* mouse buttons */ +CONFIG(Button, button[], { + { MODKEY, BTN_LEFT, move_client, {.ui = CursorMove} }, + { MODKEY, BTN_MIDDLE, float_client, {0} }, + { MODKEY, BTN_RIGHT, resize_client, {.ui = CursorResize} }, +}); +CONFIG(Button*, endbutton, arrend(cfg·button)); + +#undef MODKEY diff --git a/sys/cmd/wm/input.c b/sys/cmd/wm/input.c index d9e6285..eb5fdd1 100644 --- a/sys/cmd/wm/input.c +++ b/sys/cmd/wm/input.c @@ -109,52 +109,33 @@ make_keyboard(struct wlr_input_device *device) static void -cursormove(uint32 time) { - server.grab.x = server.cursor.dot->x - server.grab.x; - server.grab.y = server.cursor.dot->y - server.grab.y; -} - -static -void -cursorresize(uint32 time) +focus_surface(Client *client, struct wlr_surface *surface, double sx, double sy, uint32 time) { - struct wlr_box box; - Client *client = server.grab.client; - double bx = server.cursor.dot->x - server.grab.x; - double by = server.cursor.dot->y - server.grab.y; - int new_left = server.grab.box.x; - int new_right = server.grab.box.x + server.grab.box.width; - int new_top = server.grab.box.y; - int new_bottom = server.grab.box.y + server.grab.box.height; - int new_width, new_height; - - if(server.resize & WLR_EDGE_TOP) { - new_top = by; - if (new_top >= new_bottom) - new_top = new_bottom - 1; - }else if (server.resize & WLR_EDGE_BOTTOM) { - new_bottom = by; - if (new_bottom <= new_top) - new_bottom = new_top + 1; + 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(server.resize & WLR_EDGE_LEFT) { - new_left = bx; - if (new_left >= new_right) - new_left = new_right - 1; - } else if(server.resize & WLR_EDGE_RIGHT) { - new_right = bx; - if (new_right <= new_left) - new_right = new_left + 1; + if(!time) { + clock_gettime(CLOCK_MONOTONIC, &now); + time = now.tv_sec * 1000 + now.tv_nsec / 1000000; } - wlr_xdg_surface_get_geometry(client->xdg, &box); - client->geometry.x = new_left - box.x; - client->geometry.y = new_top - box.y; + 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); - new_width = new_right - new_left; - new_height = new_bottom - new_top; - wlr_xdg_toplevel_set_size(client->xdg, new_width, new_height); + if(cfg·sloppyfocus && lift) + focus(client, 0); } static @@ -163,9 +144,14 @@ move(uint32 time) { double sx, sy; Client *client; - struct wlr_seat *seat; 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, @@ -189,18 +175,20 @@ move(uint32 time) } /* Otherwise, find the client under the pointer and send the event along. */ - seat = server.input.seat; - surface = nil; - client = client_at(server.cursor.dot->x, server.cursor.dot->y, &surface, &sx, &sy); - if(!client) + 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); - - if(surface) { - wlr_seat_pointer_notify_enter(seat, surface, sx, sy); - wlr_seat_pointer_notify_motion(seat, time, sx, sy); - } else { - wlr_seat_pointer_clear_focus(seat); + 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 @@ -223,16 +211,39 @@ void cursor_button(struct wl_listener *l, void *data) { Client *client; - double sx, sy; - struct wlr_surface *surface; + 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); - client = client_at(server.cursor.dot->x, server.cursor.dot->y, &surface, &sx, &sy); - if (event->state == WLR_BUTTON_RELEASED) - server.cursor.mode = CursorPassthrough; - else - focus(client, 1); } void diff --git a/sys/cmd/wm/main.c b/sys/cmd/wm/main.c index 25981ca..9d18b01 100644 --- a/sys/cmd/wm/main.c +++ b/sys/cmd/wm/main.c @@ -95,6 +95,7 @@ init_inputs(void) wl_list_init(&server.input.keyboards); wl_signal_add(&server.backend->events.new_input, &server.event.make_input); + server.input.idle = wlr_idle_create(server.display); server.input.seat = wlr_seat_create(server.display, "seat0"); wl_signal_add(&server.input.seat->events.request_set_cursor, &server.event.request_cursor); diff --git a/sys/cmd/wm/wm.h b/sys/cmd/wm/wm.h index f6ff752..2e9ea9f 100644 --- a/sys/cmd/wm/wm.h +++ b/sys/cmd/wm/wm.h @@ -3,6 +3,7 @@ #include #include #include +#include #define WLR_USE_UNSTABLE #include @@ -15,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -49,7 +51,7 @@ enum { - CursorPassthrough, + CursorNormal, CursorMove, CursorResize, }; @@ -88,12 +90,12 @@ struct Key Arg arg; }; -struct Button +struct Button { - uint mod; - uint button; - void (*func)(const Arg *); - const Arg arg; + uint modifier; + uint code; + void (*function)(Arg *); + Arg arg; }; struct Keyboard @@ -233,6 +235,7 @@ struct Server struct { struct wlr_seat *seat; struct wl_list keyboards; + struct wlr_idle *idle; } input; struct { @@ -288,10 +291,13 @@ void focus(Client *, int lift); void resize(Client *, int x, int y, int w, int h, int interact); void attach(Client *, Monitor *, uint tags); -Client* client_at(double, double, struct wlr_surface **, double *, double *); -int client_has(Client *, double, double, struct wlr_surface **, double *, double *); +Client *client_at(double x, double y); +struct wlr_surface *client_surface_at(Client *, double cx, double cy, double *sx, double *sy); +struct wlr_surface *top_surface(Client *); -void setinteractive(Client *client, int mode, uint32 edges); // XXX: deprecate +void *move_client(Arg *arg); +void *float_client(Arg *arg); +void *resize_client(Arg *arg); /* monitor.c */ void tile(Monitor *); diff --git a/sys/cmd/wm/xdg.c b/sys/cmd/wm/xdg.c index 1d5ae68..6a0c2c8 100644 --- a/sys/cmd/wm/xdg.c +++ b/sys/cmd/wm/xdg.c @@ -56,7 +56,6 @@ void request_move(struct wl_listener *l, void *data) { Client *client = wl_container_of(l, client, event.request_move); - setinteractive(client, CursorMove, 0); } static @@ -65,7 +64,6 @@ request_resize(struct wl_listener *l, void *data) { struct wlr_xdg_toplevel_resize_event *event = data; Client *client = wl_container_of(l, client, event.request_resize); - setinteractive(client, CursorResize, event->edges); } -- cgit v1.2.1