-rw-r--r-- src/layer_shell.c
1 #include <wlr/types/wlr_layer_shell_v1.h> 2 #include <wlr/types/wlr_output_damage.h> 3 4 #include "layer_shell.h" 5 #include "output.h" 6 #include "shell.h" 7 8 9 static void layer(struct output *output) { 10 struct layer_view *lview; 11 struct wlr_layer_surface_v1 *surface; 12 struct wlr_layer_surface_v1_state *state; 13 int width, height; 14 wlr_output_effective_resolution(output->wlr_output, &width, &height); 15 16 for (int i = 0; i < 4; i++) { 17 wl_list_for_each(lview, &output->layer_views[i], link) { 18 surface = lview->surface; 19 state = &surface->current; 20 struct wlr_box box = { 21 .width = state->desired_width, 22 .height = state->desired_height 23 }; 24 // Horizontal axis 25 const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT 26 | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; 27 if ((state->anchor & both_horiz) && box.width == 0) { 28 box.x = state->margin.left; 29 box.width = width - state->margin.left - state->margin.right; 30 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { 31 box.x = state->margin.left; 32 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { 33 box.x = width - box.width - state->margin.right; 34 } else { 35 box.x = width / 2 - box.width / 2; 36 } 37 // Vertical axis 38 const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP 39 | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; 40 if ((state->anchor & both_vert) && box.height == 0) { 41 box.y = state->margin.top; 42 box.height = height - state->margin.top - state->margin.bottom; 43 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { 44 box.y = state->margin.top; 45 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { 46 box.y = height - box.height - state->margin.bottom; 47 } else { 48 box.y = height / 2 - box.height / 2; 49 } 50 if (box.width < 0 || box.height < 0) { 51 wlr_layer_surface_v1_close(surface); 52 continue; 53 } 54 memcpy(&lview->geo, &box, sizeof(struct wlr_box)); 55 wlr_layer_surface_v1_configure(surface, box.width, box.height); 56 } 57 } 58 59 // Find topmost keyboard interactive layer, if such a layer exists 60 uint32_t layers_above_shell[] = { 61 ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, 62 ZWLR_LAYER_SHELL_V1_LAYER_TOP, 63 }; 64 size_t nlayers = sizeof(layers_above_shell) / sizeof(layers_above_shell[0]); 65 bool found = false; 66 for (size_t i = 0; i < nlayers; ++i) { 67 wl_list_for_each_reverse(lview, &output->layer_views[layers_above_shell[i]], link) { 68 if (lview->surface->current.keyboard_interactive && lview->surface->mapped) { 69 focus(lview, NULL, true); 70 found = true; 71 break; 72 } 73 } 74 if (found) { 75 break; 76 } 77 } 78 79 wlr_output_damage_add_whole(output->wlr_output_damage); 80 } 81 82 83 static void on_destroy(struct wl_listener *listener, void *data) { 84 struct layer_view *lview = wl_container_of(listener, lview, destroy_listener); 85 struct output *output = lview->output; 86 87 wl_list_remove(&lview->destroy_listener.link); 88 wl_list_remove(&lview->map_listener.link); 89 wl_list_remove(&lview->unmap_listener.link); 90 wl_list_remove(&lview->link); 91 free(lview); 92 layer(output); 93 } 94 95 96 static void on_commit(struct wl_listener *listener, void *data) { 97 struct layer_view *lview = wl_container_of(listener, lview, commit_listener); 98 damage_by_lview(lview); 99 } 100 101 102 static void on_unmap(struct wl_listener *listener, void *data) { 103 struct layer_view *lview = wl_container_of(listener, lview, unmap_listener); 104 lview->surface->mapped = false; 105 layer(lview->output); 106 if (wimp.focussed_layer_view == lview) { 107 wimp.focussed_layer_view = NULL; 108 find_focus(); 109 } 110 } 111 112 113 static void on_map(struct wl_listener *listener, void *data) { 114 struct layer_view *lview = wl_container_of(listener, lview, map_listener); 115 lview->surface->mapped = true; 116 layer(lview->output); 117 wlr_surface_send_enter(lview->surface->surface, lview->surface->output); 118 } 119 120 121 static void on_new_surface(struct wl_listener *listener, void *data) { 122 struct wlr_layer_surface_v1 *surface = data; 123 124 struct layer_view *lview = calloc(1, sizeof(struct view)); 125 lview->surface = surface; 126 surface->data = lview; 127 128 lview->map_listener.notify = on_map; 129 lview->unmap_listener.notify = on_unmap; 130 lview->destroy_listener.notify = on_destroy; 131 lview->commit_listener.notify = on_commit; 132 wl_signal_add(&surface->events.map, &lview->map_listener); 133 wl_signal_add(&surface->events.unmap, &lview->unmap_listener); 134 wl_signal_add(&surface->events.destroy, &lview->destroy_listener); 135 wl_signal_add(&surface->surface->events.commit, &lview->commit_listener); 136 137 if (!surface->output) { 138 surface->output = wlr_output_layout_output_at( 139 wimp.output_layout, wimp.cursor->x, wimp.cursor->y 140 ); 141 } 142 struct output *output = surface->output->data; 143 lview->output = output; 144 wl_list_insert(&output->layer_views[surface->client_pending.layer], &lview->link); 145 layer(lview->output); 146 } 147 148 149 void set_up_layer_shell() { 150 wimp.layer_shell = wlr_layer_shell_v1_create(wimp.display); 151 wimp.layer_shell_surface_listener.notify = on_new_surface; 152 wl_signal_add(&wimp.layer_shell->events.new_surface, &wimp.layer_shell_surface_listener); 153 } 154