gimp but for windows: a wayland compositor
git clone https://github.com/m-col/wimp
Files | Refs | Readme

Commit a70ba044975c98144424d02b54c2aacfd07a05ca
Parent: 5b791861a1d4f5560401207f9dd44edd598f99b9
Author: mcol <mcol@posteo.net>
Date: 2021-01-30 19:28:43 +0000
Committer: mcol <mcol@posteo.net>
Committed: 2021-01-30 19:28:43 +0000

Arrange layer shell layers (taking code from sway)

src/types.h Modified

@@ -134,6 +134,7 @@
     struct wl_listener unmap_listener;
     struct wl_listener destroy_listener;
     struct output *output;
+    struct wlr_box geo;
 };
 
 struct keyboard {

src/output.c Modified

@@ -87,17 +87,6 @@
     wlr_renderer_begin(renderer, width, height);
     wlr_renderer_clear(renderer, desk->background);
 
-    struct render_data rdata = {
-	.output = output->wlr_output,
-	.renderer = renderer,
-	.bordered = NULL,
-	.when = &now,
-	.zoom = zoom,
-	.is_focussed = false,
-	.x = 0,
-	.y = 0,
-    };
-
     double ox, oy;
     struct wlr_output_layout_output *ol;
     wl_list_for_each(ol, &wimp.output_layout->outputs, link) {
@@ -123,6 +112,17 @@
 	}
     }
 
+    struct render_data rdata = {
+	.output = output->wlr_output,
+	.renderer = renderer,
+	.bordered = NULL,
+	.when = &now,
+	.zoom = 1,
+	.is_focussed = false,
+	.x = 0,
+	.y = 0,
+    };
+
     // paint background and bottom layers
     struct layer_view *lview;
     wl_list_for_each(lview, &output->layer_views[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], link) {
@@ -136,6 +136,8 @@
 	);
     }
 
+    rdata.zoom = zoom;
+
     // paint clients
     struct view *view;
     struct view *focussed = wl_container_of(wimp.current_desk->views.next, focussed, link);
@@ -157,16 +159,19 @@
 
     rdata.bordered = NULL;
     rdata.is_focussed = false;
-    rdata.x = 0;
-    rdata.y = 0;
+    rdata.zoom = 1;
 
     // paint top and overlay layers
     wl_list_for_each(lview, &output->layer_views[ZWLR_LAYER_SHELL_V1_LAYER_TOP], link) {
+	rdata.x = lview->geo.x;
+	rdata.y = lview->geo.y;
 	wlr_surface_for_each_surface(
 	    lview->surface->surface, render_surface, &rdata
 	);
     }
     wl_list_for_each(lview, &output->layer_views[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], link) {
+	rdata.x = lview->geo.x;
+	rdata.y = lview->geo.y;
 	wlr_surface_for_each_surface(
 	    lview->surface->surface, render_surface, &rdata
 	);

src/layer_shell.c Modified

@@ -7,8 +7,10 @@
     struct layer_view *lview;
     struct wlr_layer_surface_v1 *surface;
     struct wlr_layer_surface_v1_state *state;
+    int width, height;
+    wlr_output_effective_resolution(output->wlr_output, &width, &height);
 
-    for (int i = 0; i<4; i++) {
+    for (int i = 0; i < 4; i++) {
 	if (wl_list_empty(&output->layer_views[i])) {
 	    continue;
 	}
@@ -16,7 +18,61 @@
 	wl_list_for_each(lview, &output->layer_views[i], link) {
 	    surface = lview->surface;
 	    state = &surface->current;
-	    wlr_layer_surface_v1_configure(surface, state->desired_width, state->desired_height);
+	    struct wlr_box box = {
+		.width = state->desired_width,
+		.height = state->desired_height
+	    };
+	    // Horizontal axis
+	    const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
+		| ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
+	    if ((state->anchor & both_horiz) && box.width == 0) {
+		box.x = state->margin.left;
+		box.width = 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 = width - box.width - state->margin.right;
+	    } else {
+		box.x = width / 2 - box.width / 2;
+	    }
+	    // Vertical axis
+	    const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP
+		    | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
+	    if ((state->anchor & both_vert) && box.height == 0) {
+		box.y = state->margin.top;
+		box.height = 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 = height - box.height - state->margin.bottom;
+	    } else {
+		box.y = height / 2 - box.height / 2;
+	    }
+	    if (box.width < 0 || box.height < 0) {
+		wlr_layer_surface_v1_close(surface);
+		continue;
+	    }
+	    lview->geo = box;
+	    wlr_layer_surface_v1_configure(surface, box.width, box.height);
+	}
+    }
+
+    // Find topmost keyboard interactive layer, if such a layer exists
+    uint32_t layers_above_shell[] = {
+	ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY,
+	ZWLR_LAYER_SHELL_V1_LAYER_TOP,
+    };
+    size_t nlayers = sizeof(layers_above_shell) / sizeof(layers_above_shell[0]);
+    struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(wimp.seat);
+    for (size_t i = 0; i < nlayers; ++i) {
+	wl_list_for_each_reverse(lview, &output->layer_views[layers_above_shell[i]], link) {
+	    if (lview->surface->current.keyboard_interactive && lview->surface->mapped) {
+		wlr_seat_keyboard_notify_enter(
+		    wimp.seat, lview->surface->surface, keyboard->keycodes,
+		    keyboard->num_keycodes, &keyboard->modifiers
+		);
+		return;
+	    }
 	}
     }
 }
@@ -73,7 +129,12 @@
     lview->output = output;
     wl_list_insert(&output->layer_views[surface->client_pending.layer], &lview->link);
 
+    // Temporarily set the layer's current state to client_pending
+    // So that we can easily arrange it
+    struct wlr_layer_surface_v1_state old_state = surface->current;
+    surface->current = surface->client_pending;
     layer(lview->output);
+    surface->current = old_state;
 }