aboutsummaryrefslogtreecommitdiff
path: root/sys/cmd/wm/monitor.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cmd/wm/monitor.c')
-rw-r--r--sys/cmd/wm/monitor.c135
1 files changed, 135 insertions, 0 deletions
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)
{