-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlayer_shell.c
156 lines (122 loc) · 5.11 KB
/
layer_shell.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include "output.h"
#include "popup.h"
#include "view.h"
#include "wlr-layer-shell-unstable-v1-protocol.h"
#include <assert.h>
#include <includes.h>
#include <layer_shell.h>
#include <server.h>
#include <stdint.h>
#include <stdlib.h>
#include <wayland-server-core.h>
#include <wayland-util.h>
#include <wlr/types/wlr_layer_shell_v1.h>
#include <wlr/util/box.h>
#include <wlr/util/log.h>
void configure_layer(struct simwm_output *output, struct wlr_box *full_area,
struct wlr_box *usable_area, struct wlr_scene_tree *tree) {
struct wlr_scene_node *node;
wl_list_for_each(node, &tree->children, link) {
struct simwm_view *view = node->data;
if (!node) {
continue;
}
assert(view);
if (view->type == SIMWM_VIEW_LAYER) {
wlr_scene_layer_surface_v1_configure(view->layer->scene, full_area,
usable_area);
}
}
}
void configure_all_layers(struct simwm_output *output) {
struct wlr_box full_area;
wlr_output_layout_get_box(server->output_layout, output->wlr_output,
&full_area);
struct wlr_box usable_area = full_area;
configure_layer(output, &full_area, &usable_area, server->layers[LAYER_BG]);
configure_layer(output, &full_area, &usable_area,
server->layers[LAYER_BOTTOM]);
configure_layer(output, &full_area, &usable_area, server->layers[LAYER_TOP]);
configure_layer(output, &full_area, &usable_area,
server->layers[LAYER_OVERLAY]);
}
void on_layer_new_popup(struct wl_listener *listener, void *data) {
struct simwm_layer_surface *layer =
wl_container_of(listener, layer, new_popup);
struct wlr_xdg_popup *xdg_popup = data;
create_popup(xdg_popup, layer->view);
}
void on_layer_surface_map(struct wl_listener *listener, void *data) {
struct simwm_layer_surface *layer = wl_container_of(listener, layer, map);
if (layer->scene->layer_surface->current.keyboard_interactive) {
wlr_seat_keyboard_notify_enter(
server->seat, layer->scene->layer_surface->surface,
server->seat->keyboard_state.keyboard->keycodes,
server->seat->keyboard_state.keyboard->num_keycodes,
&server->seat->keyboard_state.keyboard->modifiers);
configure_all_layers(layer->output);
}
}
void on_layer_surface_unmap(struct wl_listener *listener, void *data) {
struct simwm_layer_surface *layer = wl_container_of(listener, layer, unmap);
configure_all_layers(layer->output);
}
void on_layer_surface_destroy(struct wl_listener *listener, void *data) {
struct simwm_layer_surface *layer = wl_container_of(listener, layer, destroy);
wl_list_remove(&layer->map.link);
wl_list_remove(&layer->unmap.link);
wl_list_remove(&layer->commit.link);
wl_list_remove(&layer->destroy.link);
free(layer->view);
free(layer);
}
void on_layer_surface_commit(struct wl_listener *listener, void *data) {
struct simwm_layer_surface *layer = wl_container_of(listener, layer, commit);
uint32_t commited = layer->scene->layer_surface->current.committed;
// Layer was changed, reparent node to new layer.
if (commited & WLR_LAYER_SURFACE_V1_STATE_LAYER) {
wlr_scene_node_reparent(
&layer->scene->tree->node,
server->layers[layer->scene->layer_surface->current.layer]);
}
// If any other change was detected, or the mapped state changed, we
// reconfigure all the layers.
if (commited || layer->scene->layer_surface->mapped != layer->mapped) {
layer->mapped = layer->scene->layer_surface->mapped;
configure_all_layers(layer->output);
}
int lx, ly;
wlr_scene_node_coords(&layer->scene->tree->node, &lx, &ly);
wlr_scene_node_set_position(&layer->popup_scene->node, lx, ly);
}
void on_new_layer_surface(struct wl_listener *listener, void *data) {
struct wlr_layer_surface_v1 *layer_surface = data;
struct simwm_view *view = calloc(1, sizeof(struct simwm_view));
view->type = SIMWM_VIEW_LAYER;
struct simwm_layer_surface *layer =
calloc(1, sizeof(struct simwm_layer_surface));
view->layer = layer;
layer->view = view;
struct wlr_output *wlr_output = layer_surface->output;
if (wlr_output == NULL) {
wlr_output = wlr_output_layout_get_center_output(server->output_layout);
}
struct simwm_output *output = wlr_output->data;
layer->output = output;
layer->scene = wlr_scene_layer_surface_v1_create(
server->layers[layer_surface->current.layer], layer_surface);
layer->scene->tree->node.data = view;
layer->popup_scene = wlr_scene_tree_create(server->layers[LAYER_TOP]);
layer->popup_scene->node.data = view;
layer->commit.notify = on_layer_surface_commit;
wl_signal_add(&layer_surface->surface->events.commit, &layer->commit);
layer->map.notify = on_layer_surface_map;
wl_signal_add(&layer_surface->events.map, &layer->map);
layer->unmap.notify = on_layer_surface_unmap;
wl_signal_add(&layer_surface->events.unmap, &layer->unmap);
layer->destroy.notify = on_layer_surface_destroy;
wl_signal_add(&layer_surface->events.destroy, &layer->destroy);
layer->new_popup.notify = on_layer_new_popup;
wl_signal_add(&layer_surface->events.new_popup, &layer->new_popup);
configure_all_layers(layer->output);
}