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/client.c | 274 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 274 insertions(+) create mode 100644 src/cmd/wm/client.c (limited to 'src/cmd/wm/client.c') diff --git a/src/cmd/wm/client.c b/src/cmd/wm/client.c new file mode 100644 index 0000000..5e0927a --- /dev/null +++ b/src/cmd/wm/client.c @@ -0,0 +1,274 @@ +#include "wm.h" + +static char broken[] = "broken"; + +// ----------------------------------------------------------------------- +// scripts + +static inline +void +grab_client(void) +{ + if(server.cursor.mode != CursorNormal) + return; + if(!(server.grab.client = client_at(server.cursor.dot->x, server.cursor.dot->y))) + return; + + floating(server.grab.client, 1); +} + +void +move_client(Arg *arg) +{ + grab_client(); + server.cursor.mode = CursorMove; + + server.grab.x = server.cursor.dot->x - server.grab.client->geometry.x; + server.grab.y = server.cursor.dot->y - server.grab.client->geometry.y; + wlr_xcursor_manager_set_cursor_image(server.cursor.manager, "fleur", server.cursor.dot); +} + +void +float_client(Arg *arg) +{ + Client *client = selected_client(); + wlr_log(WLR_DEBUG, "client selected = %lx", (uintptr)client); + if(!client) + return; + + floating(client, client->isfloating ? 0 : 1); +} + +void +resize_client(Arg *arg) +{ + double x, y; + struct wlr_box geometry; + + grab_client(); + server.cursor.mode = CursorResize; + + wlr_xdg_surface_get_geometry(server.grab.client->xdg, &geometry); + + x = server.grab.client->geometry.x + geometry.x + geometry.width; + y = server.grab.client->geometry.y + geometry.y + geometry.height; + + server.grab.x = server.cursor.dot->x - x; + server.grab.y = server.cursor.dot->y - y; + + server.grab.box = geometry; + server.grab.box.x += server.grab.client->geometry.x; + server.grab.box.y += server.grab.client->geometry.y; +} + +// ----------------------------------------------------------------------- +// core + +static inline +void +activate(struct wlr_surface *surface, int state) +{ +} + +void +focus(Client *client, int lift) +{ + struct wlr_xdg_surface *xdg; + struct wlr_surface *old, *new; + struct wlr_keyboard *keyboard; + + if(!client) { + wlr_seat_keyboard_notify_clear_focus(server.input.seat); + return; + } + + old = server.input.seat->keyboard_state.focused_surface; + + if(lift) { + wl_list_remove(&client->stack); + wl_list_insert(&server.client.stack, &client->stack); + } + + new = client->xdg->surface; + if(old==new) + return; + + wl_list_remove(&client->focus); + wl_list_insert(&server.client.focus, &client->focus); + server.monitor.selected = client->monitor; + client->isurgent = 0; + + if(old) { + if(wlr_surface_is_xdg_surface(old)) { + xdg = wlr_xdg_surface_from_wlr_surface(old); + wlr_xdg_toplevel_set_activated(xdg, false); + } + } + + keyboard = wlr_seat_get_keyboard(server.input.seat); + + wlr_seat_keyboard_notify_enter(server.input.seat, new, + keyboard->keycodes, + keyboard->num_keycodes, + &keyboard->modifiers + ); + + wlr_xdg_toplevel_set_activated(client->xdg, true); +} + +Client* +client_at(double x, double y) +{ + Client *client; + wl_list_for_each(client, &server.client.stack, stack) + if(VISIBLE_ON(client, client->monitor) && wlr_box_contains_point(&client->geometry, x, y)) + return client; + return nil; +} + +static +int +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; + + find = wlr_xdg_surface_surface_at(client->xdg, vsx, vsy, &x, &y); + if(find) { + *sx = x; + *sy = y; + *surface = find; + return true; + } + + return false; +} + +struct wlr_surface * +client_surface_at(Client *client, double cx, double cy, double *sx, double *sy) +{ + return wlr_xdg_surface_surface_at(client->xdg, cx, cy, sx, sy); +} + + +static +void +constrain(Client *client, struct wlr_box *box) +{ + client->geometry.width = MAX(1, client->geometry.width); + client->geometry.height = MAX(1, client->geometry.height); + + if(client->geometry.x >= box->x + box->width) + client->geometry.x = box->x + box->width - client->geometry.width; + if(client->geometry.y >= box->y + box->height) + client->geometry.y = box->y + box->height - client->geometry.height; + if(client->geometry.x + client->geometry.width + 2*client->border <= box->x) + client->geometry.x = box->x; + if(client->geometry.y + client->geometry.height + 2*client->border <= box->y) + client->geometry.y = box->y; +} + +void +resize(Client *client, int x, int y, int w, int h, int interact) +{ + struct wlr_box *box = interact ? &server.monitor.geometry : &client->monitor->window; + + client->geometry.x = x; + client->geometry.y = y; + client->geometry.width = w; + client->geometry.height = h; + + constrain(client, box); + + client->resize = wlr_xdg_toplevel_set_size(client->xdg, + client->geometry.width - 2*client->border, + client->geometry.height - 2*client->border + ); +} + +void +attach(Client *client, Monitor *monitor, uint tags) +{ + Monitor *old = client->monitor; + if(old == monitor) + return; + + client->monitor = monitor; + + if(old) { + wlr_surface_send_leave(client->xdg->surface, old->output); + arrange(old); + } + + if(monitor) { + /* make sure window actually overlaps with the monitor */ + constrain(client, &monitor->geometry); + wlr_surface_send_enter(client->xdg->surface, monitor->output); + client->tags = tags ? tags : monitor->tag.set[monitor->tag.selected]; + arrange(monitor); + } + + focus(focused_client(server.monitor.selected), 1); +} + +void +rules(Client *client) +{ + /* rule matching */ + Rule *rule; + uint i, tags; + char *id, *title; + Monitor *monitor, *it; + + monitor = server.monitor.selected; + + if (!(id=client->xdg->toplevel->app_id)) + id = broken; + if (!(title=client->xdg->toplevel->title)) + title = broken; + + for(tags=0, rule=cfg·rule; rule != cfg·endrule; ++rule) { + if ((!rule->title || strstr(title, rule->title)) + && (!rule->id || strstr(id, rule->id))) { + client->isfloating = rule->isfloating; + tags |= rule->tags; + i = 0; + wl_list_for_each(it, &server.monitor.list, link) + if(rule->monitor == i++) + monitor = it; + } + } + + attach(client, monitor, tags); +} + +void +floating(Client *client, int state) +{ + wlr_log(WLR_DEBUG, "client %lx, floating = %d", (uintptr)client, state); + client->isfloating = state; + arrange(client->monitor); +} + +Client * +selected_client(void) +{ + Client *client = wl_container_of(server.client.focus.next, client, focus); + if(wl_list_empty(&server.client.focus) || !VISIBLE_ON(client, server.monitor.selected)) + return nil; + return client; +} + +void +request_activate(struct wl_listener *l, void *data) +{ + struct wlr_xdg_activation_v1_request_activate_event *event = data; + Client *client; + + if (!wlr_surface_is_xdg_surface(event->surface)) + return; + + client = wlr_xdg_surface_from_wlr_surface(event->surface)->data; + if(client != selected_client()) + client->isurgent = 1; +} -- cgit v1.2.1