aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Noll <nbnoll@eml.cc>2021-09-29 12:59:39 -0700
committerNicholas Noll <nbnoll@eml.cc>2021-09-29 12:59:39 -0700
commit7e7fab861a7e5baae9182419f7f320af36ce1ec4 (patch)
treed323b19f009826d437a3216909d38ee1a05f8382
parentd20be3112770c9fd252c91306675717dcb59e28f (diff)
Feat(wm): prepararation for layout mechanism
-rw-r--r--sys/cmd/wm/arg.c2
-rw-r--r--sys/cmd/wm/client.c41
-rw-r--r--sys/cmd/wm/config.h16
-rw-r--r--sys/cmd/wm/input.c3
-rw-r--r--sys/cmd/wm/main.c4
-rw-r--r--sys/cmd/wm/output.c75
-rw-r--r--sys/cmd/wm/rules.mk1
-rw-r--r--sys/cmd/wm/wm.h47
-rw-r--r--sys/cmd/wm/xdg.c29
9 files changed, 178 insertions, 40 deletions
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;
@@ -30,6 +30,15 @@ unmap(struct wl_listener *l, void *data)
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)
{
Client *client = wl_container_of(l, client, event.destroy);
@@ -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);