aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Noll <nbnoll@eml.cc>2021-10-04 11:33:07 -0700
committerNicholas Noll <nbnoll@eml.cc>2021-10-04 11:33:07 -0700
commit93e9672953d849288f27ff3d977cc1c1ff111da8 (patch)
tree64c431f8bf6d4e842da6bcd76a259434045197e0
parent8f224149f176fb8de90a82b44f4dd1c6a1b89a4f (diff)
feat(wm): keyboard focus corrected
-rw-r--r--sys/cmd/dwm/dwm.h4
-rw-r--r--sys/cmd/wm/client.c116
-rw-r--r--sys/cmd/wm/config.h13
-rw-r--r--sys/cmd/wm/input.c127
-rw-r--r--sys/cmd/wm/main.c1
-rw-r--r--sys/cmd/wm/wm.h24
-rw-r--r--sys/cmd/wm/xdg.c2
7 files changed, 153 insertions, 134 deletions
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 <u.h>
#include <libn.h>
#include <wayland-server-core.h>
+#include <linux/input-event-codes.h>
#define WLR_USE_UNSTABLE
#include <wlr/backend.h>
@@ -15,6 +16,7 @@
#include <wlr/types/wlr_export_dmabuf_v1.h>
#include <wlr/types/wlr_gamma_control_v1.h>
#include <wlr/types/wlr_input_device.h>
+#include <wlr/types/wlr_idle.h>
#include <wlr/types/wlr_keyboard.h>
#include <wlr/types/wlr_matrix.h>
#include <wlr/types/wlr_output.h>
@@ -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);
}