From 7e7fab861a7e5baae9182419f7f320af36ce1ec4 Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Wed, 29 Sep 2021 12:59:39 -0700 Subject: Feat(wm): prepararation for layout mechanism --- sys/cmd/wm/arg.c | 2 ++ sys/cmd/wm/client.c | 41 ++++++++++++++++++++++++++--- sys/cmd/wm/config.h | 16 ++++++++++++ sys/cmd/wm/input.c | 3 +-- sys/cmd/wm/main.c | 4 +-- sys/cmd/wm/output.c | 75 +++++++++++++++++++++++++++++++++++++++++++---------- sys/cmd/wm/rules.mk | 1 + sys/cmd/wm/wm.h | 47 +++++++++++++++++++++++++-------- sys/cmd/wm/xdg.c | 29 +++++++++++++++------ 9 files changed, 178 insertions(+), 40 deletions(-) (limited to 'sys') diff --git a/sys/cmd/wm/arg.c b/sys/cmd/wm/arg.c index bf58534..060393e 100644 --- a/sys/cmd/wm/arg.c +++ b/sys/cmd/wm/arg.c @@ -1,5 +1,7 @@ #include "wm.h" +void tile(Monitor *m); + void spawn(Arg *arg) { diff --git a/sys/cmd/wm/client.c b/sys/cmd/wm/client.c index 33dfcb1..2a8c0c0 100644 --- a/sys/cmd/wm/client.c +++ b/sys/cmd/wm/client.c @@ -9,8 +9,8 @@ focus(Client *client, struct wlr_surface *new) struct wlr_keyboard *keyboard; if(client) { - wl_list_remove(&client->link); - wl_list_insert(&server.clients, &client->link); + wl_list_remove(&client->stack); + wl_list_insert(&server.client.stack, &client->stack); } seat = server.input.seat; @@ -61,7 +61,7 @@ Client* client_at(double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { Client *it; - wl_list_for_each(it, &server.clients, link) { + wl_list_for_each(it, &server.client.list, link) { if(client_has(it, lx, ly, surface, sx, sy)) return it; } @@ -100,3 +100,38 @@ setinteractive(Client *client, int mode, uint32 edges) { server.resize = edges; } } + +static +void +apply_bounds(Client *client, struct wlr_box *box) +{ + client->geo.width = MAX(1, client->geo.width); + client->geo.height = MAX(1, client->geo.height); + + if(client->geo.x >= box->x + box->width) + client->geo.x = box->x + box->width - client->geo.width; + if(client->geo.y >= box->y + box->height) + client->geo.y = box->y + box->height - client->geo.height; + if(client->geo.x + client->geo.width + 2*client->border <= box->x) + client->geo.x = box->x; + if(client->geo.y + client->geo.height + 2*client->border <= box->y) + client->geo.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->geo.x = x; + client->geo.y = y; + client->geo.width = w; + client->geo.height = h; + + apply_bounds(client, box); + + client->resize = wlr_xdg_toplevel_set_size(client->xdg, + client->geo.width - 2*client->border, + client->geo.height - 2*client->border + ); +} diff --git a/sys/cmd/wm/config.h b/sys/cmd/wm/config.h index dbeeaf6..3c8c4d9 100644 --- a/sys/cmd/wm/config.h +++ b/sys/cmd/wm/config.h @@ -12,6 +12,22 @@ CONFIG(int, repeat_delay, 600); /* commands */ CONFIG(char*, termcommand[], { "alacritty", nil }); +/* layouts */ +CONFIG(Layout, layouts[], { + /* symbol arrange */ + { "[]=", tile }, + { "><>", nil }, /* no layout function means floating behavior */ +}); + +/* monitors + * The order in which monitors are defined determines their position. + * non-configured monitors are always added to the left. */ +CONFIG(MonitorRule, monitorrule[], { + /* name layout, x, y, scale, transform master */ + { nil, &cfg·layouts[0], 0, 0, 1, WL_OUTPUT_TRANSFORM_NORMAL, {0.55, 1} }, +}); +CONFIG(MonitorRule*, endmonitorrule, arrend(cfg·monitorrule)); + /* keybindings */ #define MOD(a) WLR_MODIFIER_##a #define MODKEY WLR_MODIFIER_ALT diff --git a/sys/cmd/wm/input.c b/sys/cmd/wm/input.c index 295f861..7913a9f 100644 --- a/sys/cmd/wm/input.c +++ b/sys/cmd/wm/input.c @@ -115,7 +115,7 @@ cursormove(uint32 time) { } static -void +void cursorresize(uint32 time) { struct wlr_box box; @@ -284,4 +284,3 @@ make_input(struct wl_listener *l, void *data) capability |= WL_SEAT_CAPABILITY_KEYBOARD; wlr_seat_set_capabilities(server.input.seat, capability); } - diff --git a/sys/cmd/wm/main.c b/sys/cmd/wm/main.c index 3dd9903..61f039a 100644 --- a/sys/cmd/wm/main.c +++ b/sys/cmd/wm/main.c @@ -52,8 +52,8 @@ static inline void init_shells(void) { - wl_list_init(&server.clients); - wl_list_init(&server.stack); + wl_list_init(&server.client.list); + wl_list_init(&server.client.stack); server.shell.xdg = wlr_xdg_shell_create(server.display); wl_signal_add(&server.shell.xdg->events.new_surface, &server.event.make_xdg_surface); diff --git a/sys/cmd/wm/output.c b/sys/cmd/wm/output.c index 46e702f..910f57b 100644 --- a/sys/cmd/wm/output.c +++ b/sys/cmd/wm/output.c @@ -64,7 +64,7 @@ render_clients(Monitor *monitor, struct timespec *now) struct wlr_surface *surface; output = monitor->output; - wl_list_for_each_reverse(client, &server.clients, link) { + wl_list_for_each_reverse(client, &server.client.stack, stack) { if(!client->ismapped) continue; @@ -108,11 +108,20 @@ void render_monitor(struct wl_listener *l, void *data) { int w, h; + Client *client; Monitor *monitor; struct timespec now; - monitor = wl_container_of(l, monitor, event.render); clock_gettime(CLOCK_MONOTONIC, &now); + monitor = wl_container_of(l, monitor, event.render); + + /* + wl_list_for_each(client, &server.client.list, link) { + if(client->resize) { + wlr_surface_send_frame_done(client->xdg->surface, &now); + } + } + */ if(!wlr_output_attach_render(monitor->output, nil)) return; @@ -135,6 +144,7 @@ static void free_monitor(struct wl_listener *l, void *data) { + /* int len, i = 0; struct wlr_output *output = data; Monitor *monitor = output->data; @@ -146,6 +156,8 @@ free_monitor(struct wl_listener *l, void *data) wlr_output_layout_remove(server.monitor.layout, monitor->output); len = wl_list_length(&server.monitor.list); + */ + /* do // don't switch to disabled mons selmon = wl_container_of(mons.prev, selmon, link); @@ -160,25 +172,60 @@ free_monitor(struct wl_listener *l, void *data) void make_monitor(struct wl_listener *l, void *data) { + Client *client; + Monitor *monitor; + MonitorRule *rule; struct wlr_output_mode *mode; - struct Monitor *monitor; - struct wlr_output *output = data; - - if (!wl_list_empty(&output->modes)) { - mode = wlr_output_preferred_mode(output); - wlr_output_set_mode(output, mode); - wlr_output_enable(output, true); - if (!wlr_output_commit(output)) { - return; - } - } + struct wlr_output *output = data; + + /* + * XXX: needed? + if (wl_list_empty(&output->modes)) + return; + */ monitor = calloc(1, sizeof(*monitor)); monitor->output = output; + for(rule=cfg·monitorrule; rule != cfg·endmonitorrule; ++rule) { + if(!rule->name || strstr(output->name, rule->name)) { + monitor->master.len = rule->master.len; + monitor->master.frac = rule->master.frac; + + wlr_output_set_scale(output, rule->scale); + wlr_xcursor_manager_load(server.cursor.manager, rule->scale); + monitor->layout[0] = monitor->layout[1] = rule->layout; + + wlr_output_set_transform(output, rule->transform); + break; + } + } + + mode = wlr_output_preferred_mode(output); + wlr_output_set_mode(output, mode); + wlr_output_enable_adaptive_sync(output, true); monitor->event.render.notify = render_monitor; wl_signal_add(&output->events.frame, &monitor->event.render); + monitor->event.destroy.notify = free_monitor; + wl_signal_add(&output->events.destroy, &monitor->event.destroy); + + wlr_output_enable(output, true); + if (!wlr_output_commit(output)) + return; + wl_list_insert(&server.monitor.list, &monitor->link); - wlr_output_layout_add_auto(server.monitor.layout, output); + wlr_output_layout_add(server.monitor.layout, output, rule->x, rule->y); + server.monitor.geometry = *wlr_output_layout_get_box(server.monitor.layout, nil); + + /* update the geometries of all monitors */ + wl_list_for_each(monitor, &server.monitor.list, link) { + /* first monitor in the list = most recently added */ + wl_list_for_each(client, &server.client.list, link) { + if(client->isfloating) + resize(client, client->geo.x+monitor->window.width, client->geo.y, + client->geo.width, client->geo.height, 0); + } + return; + } } diff --git a/sys/cmd/wm/rules.mk b/sys/cmd/wm/rules.mk index 8714aec..82cae06 100644 --- a/sys/cmd/wm/rules.mk +++ b/sys/cmd/wm/rules.mk @@ -6,6 +6,7 @@ SRCS_$(d) := \ $(d)/xdg-shell-protocol.c \ $(d)/util.c \ $(d)/arg.c \ + $(d)/layout.c \ $(d)/input.c \ $(d)/output.c \ $(d)/xdg.c \ diff --git a/sys/cmd/wm/wm.h b/sys/cmd/wm/wm.h index e1d3670..1e9e41e 100644 --- a/sys/cmd/wm/wm.h +++ b/sys/cmd/wm/wm.h @@ -62,6 +62,8 @@ typedef struct Layout Layout; typedef struct Monitor Monitor; typedef struct Server Server; +typedef struct MonitorRule MonitorRule; + struct Rectangle { int x, y; @@ -113,6 +115,7 @@ struct Client struct { struct wl_listener map; struct wl_listener unmap; + struct wl_listener commit; struct wl_listener destroy; struct wl_listener request_move; struct wl_listener request_title; @@ -122,12 +125,16 @@ struct Client struct wlr_box geo, oldgeo; + Monitor *monitor; + uint tags; int border : 4; int ismapped : 1; int isfloating : 1; int isurgent : 1; int isfullscreen : 1; + + uint32 resize; }; struct Layout @@ -144,18 +151,32 @@ struct Monitor struct wl_listener render; struct wl_listener destroy; } event; + + struct wlr_box geometry; + struct wlr_box window; + + Layout *layout[2]; + struct { + uint set[2]; + uint selected; + } tag; + struct { + double frac; + int len; + } master; }; struct MonitorRule { - char *name; - float mfact; - int nmaster; - float scale; - const Layout *lt; - enum wl_output_transform rr; - int x; - int y; + char *name; + Layout *layout; + int x, y; + float scale; + enum wl_output_transform transform; + struct { + double frac; + int len; + } master; }; struct Rule @@ -178,8 +199,10 @@ struct Server struct wlr_xdg_shell *xdg; } shell; - struct wl_list clients; - struct wl_list stack; + struct { + struct wl_list list; + struct wl_list stack; + } client; Client *selected; struct { @@ -192,6 +215,7 @@ struct Server struct { struct wlr_output_layout *layout; struct wl_list list; + struct wlr_box geometry; } monitor; struct { @@ -249,7 +273,8 @@ void request_cursor(struct wl_listener *, void *); void request_set_selection(struct wl_listener *, void *); /* client.c */ -void focus(Client *client, struct wlr_surface *new); +void focus(Client *, struct wlr_surface *); +void resize(Client *, int x, int y, int w, int h, int interact); Client* client_at(double, double, struct wlr_surface **, double *, double *); int client_has(Client *, double, double, struct wlr_surface **, double *, double *); void setinteractive(Client *client, int mode, uint32 edges); diff --git a/sys/cmd/wm/xdg.c b/sys/cmd/wm/xdg.c index 0ff7c0a..07ddf53 100644 --- a/sys/cmd/wm/xdg.c +++ b/sys/cmd/wm/xdg.c @@ -7,8 +7,8 @@ map(struct wl_listener *l, void *data) Client *client = wl_container_of(l, client, event.map); client->ismapped = true; - wl_list_insert(&server.clients, &client->link); - wl_list_insert(&server.stack, &client->stack); + wl_list_insert(&server.client.list, &client->link); + wl_list_insert(&server.client.stack, &client->stack); wlr_xdg_surface_get_geometry(client->xdg, &client->geo); client->geo.width += 2 * client->border; @@ -28,6 +28,15 @@ unmap(struct wl_listener *l, void *data) wl_list_remove(&client->stack); } +static +void +commit(struct wl_listener *l, void *data) +{ + Client *client = wl_container_of(l, client, event.commit); + if(client->resize && client->resize <= client->xdg->configure_serial) + client->resize = 0; +} + static void destroy(struct wl_listener *l, void *data) @@ -46,18 +55,19 @@ request_move(struct wl_listener *l, void *data) static void -request_title(struct wl_listener *l, void *data) +request_resize(struct wl_listener *l, void *data) { - Client *client = wl_container_of(l, client, event.request_title); + struct wlr_xdg_toplevel_resize_event *event = data; + Client *client = wl_container_of(l, client, event.request_resize); + setinteractive(client, CursorResize, event->edges); } + static void -request_resize(struct wl_listener *l, void *data) +request_title(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); + Client *client = wl_container_of(l, client, event.request_title); } static @@ -89,6 +99,9 @@ make_xdg_surface(struct wl_listener *l, void *data) client->event.destroy.notify = destroy; wl_signal_add(&xdg->events.destroy, &client->event.destroy); + client->event.commit.notify = commit; + wl_signal_add(&xdg->surface->events.commit, &client->event.commit); + toplevel = xdg->toplevel; client->event.request_move.notify = request_move; wl_signal_add(&toplevel->events.request_move, &client->event.request_move); -- cgit v1.2.1