From 08a6da05412961ddf629415a92749b02d875fa62 Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Mon, 4 Oct 2021 17:25:48 -0700 Subject: feat(wm): layer shell --- sys/cmd/wm/monitor.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) (limited to 'sys/cmd/wm/monitor.c') diff --git a/sys/cmd/wm/monitor.c b/sys/cmd/wm/monitor.c index 9287bfc..93073f3 100644 --- a/sys/cmd/wm/monitor.c +++ b/sys/cmd/wm/monitor.c @@ -15,6 +15,8 @@ monitor_change(struct wl_listener *l, void *data) wlr_output_configuration_head_v1_create(config, monitor->output); monitor->geometry = monitor->window = *wlr_output_layout_get_box(server.monitor.layout, monitor->output); + + stratify(monitor); arrange(monitor); head->state.enabled = monitor->output->enabled; @@ -89,6 +91,7 @@ monitor_test(struct wl_listener *l, void *data) void make_monitor(struct wl_listener *l, void *data) { + int i; Client *client; Monitor *monitor; MonitorRule *rule; @@ -103,6 +106,9 @@ make_monitor(struct wl_listener *l, void *data) monitor = output->data = calloc(1, sizeof(*monitor)); monitor->output = output; + + for(i=0; i < arrlen(monitor->layer); i++) + wl_list_init(&monitor->layer[i]); monitor->tag.set[0] = monitor->tag.set[1] = 1; for(rule=cfg·monitorrule; rule != cfg·endmonitorrule; ++rule) { @@ -196,6 +202,135 @@ arrange(Monitor *monitor) monitor->layout->arrange(monitor); } +void +stratum(Monitor *monitor, struct wl_list *list, struct wlr_box *area, int exclusive) +{ + Layer *layer; + struct wlr_box full = monitor->geometry; + + wl_list_for_each(layer, list, link) { + struct wlr_layer_surface_v1 *surface = layer->surface; + struct wlr_layer_surface_v1_state *state = &surface->current; + struct wlr_box bounds; + struct wlr_box box = { + .width = state->desired_width, + .height = state->desired_height + }; + const uint32 horizontal = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT + | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; + const uint32 vertical = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP + | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; + + if (exclusive != (state->exclusive_zone > 0)) + continue; + + bounds = state->exclusive_zone == -1 ? full : *area; + + // horizontal axis + if((state->anchor & horizontal) && box.width == 0) { + box.x = bounds.x; + box.width = bounds.width; + } else if((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { + box.x = bounds.x; + } else if((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { + box.x = bounds.x + (bounds.width - box.width); + } else { + box.x = bounds.x + ((bounds.width / 2) - (box.width / 2)); + } + + // vertical axis + if((state->anchor & vertical) && box.height == 0) { + box.y = bounds.y; + box.height = bounds.height; + } else if((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { + box.y = bounds.y; + } else if((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { + box.y = bounds.y + (bounds.height - box.height); + } else { + box.y = bounds.y + ((bounds.height / 2) - (box.height / 2)); + } + + // margin + if((state->anchor & horizontal) == horizontal) { + box.x += state->margin.left; + box.width -= state->margin.left + state->margin.right; + } else if((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { + box.x += state->margin.left; + } else if((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { + box.x -= state->margin.right; + } + + if((state->anchor & vertical) == vertical) { + box.y += state->margin.top; + box.height -= state->margin.top + state->margin.bottom; + } else if((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { + box.y += state->margin.top; + } else if((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { + box.y -= state->margin.bottom; + } + if(box.width < 0 || box.height < 0) { + wlr_layer_surface_v1_close(surface); + continue; + } + layer->geometry = box; + + if (state->exclusive_zone > 0) + exclude(area, + state->anchor, state->exclusive_zone, + state->margin.top, state->margin.right, + state->margin.bottom, state->margin.left); + wlr_layer_surface_v1_configure(surface, box.width, box.height); + } +} + +void +stratify(Monitor *monitor) +{ + int i; + Layer *layer; + struct wlr_box area = monitor->geometry; + uint32_t overlays[] = { + ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, + ZWLR_LAYER_SHELL_V1_LAYER_TOP, + }; + struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(server.input.seat); + + // arrange exclusive surfaces from top->bottom + stratum(monitor, &monitor->layer[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &area, 1); + stratum(monitor, &monitor->layer[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &area, 1); + stratum(monitor, &monitor->layer[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &area, 1); + stratum(monitor, &monitor->layer[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &area, 1); + + if(memcmp(&area, &monitor->window, sizeof(area))) { + monitor->window = area; + arrange(monitor); + } + + // arrange non-exlusive surfaces from top->bottom + stratum(monitor, &monitor->layer[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &area, 0); + stratum(monitor, &monitor->layer[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &area, 0); + stratum(monitor, &monitor->layer[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &area, 0); + stratum(monitor, &monitor->layer[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &area, 0); + + // find topmost keyboard interactive layer, if such a layer exists + for(i = 0; i < arrlen(overlays); i++) { + wl_list_for_each_reverse(layer, &monitor->layer[overlays[i]], link) { + if (layer->surface->current.keyboard_interactive && layer->surface->mapped) { + // Deactivate the focused client. + focus(nil, 0); + wlr_seat_keyboard_notify_enter( + server.input.seat, + layer->surface->surface, + keyboard->keycodes, + keyboard->num_keycodes, + &keyboard->modifiers + ); + return; + } + } + } +} + Client * focused_client(Monitor *monitor) { -- cgit v1.2.1