6
6
* See the LICENSE file accompanying this file.
7
7
*/
8
8
9
+ #include <assert.h>
9
10
#include <stdbool.h>
10
11
#include <stdlib.h>
11
12
#include <wayland-server-core.h>
@@ -41,67 +42,32 @@ xdg_decoration_handle_request_mode(struct wl_listener *listener, void *data)
41
42
wlr_xdg_toplevel_decoration_v1_set_mode (xdg_decoration -> wlr_decoration , mode );
42
43
}
43
44
44
- static void
45
- xdg_popup_destroy (struct cg_view_child * child )
45
+ static struct cg_view *
46
+ popup_get_view (struct wlr_xdg_popup * popup )
46
47
{
47
- if (!child ) {
48
- return ;
49
- }
50
-
51
- struct cg_xdg_popup * popup = (struct cg_xdg_popup * ) child ;
52
- wl_list_remove (& popup -> destroy .link );
53
- wl_list_remove (& popup -> map .link );
54
- wl_list_remove (& popup -> unmap .link );
55
- wl_list_remove (& popup -> new_popup .link );
56
- view_child_finish (& popup -> view_child );
57
- free (popup );
58
- }
48
+ while (true) {
49
+ if (popup -> parent == NULL || !wlr_surface_is_xdg_surface (popup -> parent )) {
50
+ return NULL ;
51
+ }
59
52
60
- static void
61
- handle_xdg_popup_map (struct wl_listener * listener , void * data )
62
- {
63
- struct cg_xdg_popup * popup = wl_container_of (listener , popup , map );
64
- struct wlr_scene_node * parent_node = popup -> view_child .view -> scene_node ;
65
- popup -> scene_surface = wlr_scene_surface_create (parent_node , popup -> view_child .wlr_surface );
66
- if (!popup -> scene_surface ) {
67
- return ;
53
+ struct wlr_xdg_surface * xdg_surface = wlr_xdg_surface_from_wlr_surface (popup -> parent );
54
+ switch (xdg_surface -> role ) {
55
+ case WLR_XDG_SURFACE_ROLE_TOPLEVEL :
56
+ return xdg_surface -> data ;
57
+ case WLR_XDG_SURFACE_ROLE_POPUP :
58
+ popup = xdg_surface -> popup ;
59
+ break ;
60
+ case WLR_XDG_SURFACE_ROLE_NONE :
61
+ return NULL ;
62
+ }
68
63
}
69
- double sx , sy ;
70
- wlr_xdg_popup_get_position (popup -> wlr_popup , & sx , & sy );
71
- wlr_scene_node_set_position (& popup -> scene_surface -> node , sx , sy );
72
- }
73
-
74
- static void
75
- handle_xdg_popup_unmap (struct wl_listener * listener , void * data )
76
- {
77
- struct cg_xdg_popup * popup = wl_container_of (listener , popup , unmap );
78
- wlr_scene_node_destroy (& popup -> scene_surface -> node );
79
- }
80
-
81
- static void
82
- handle_xdg_popup_destroy (struct wl_listener * listener , void * data )
83
- {
84
- struct cg_xdg_popup * popup = wl_container_of (listener , popup , destroy );
85
- struct cg_view_child * view_child = (struct cg_view_child * ) popup ;
86
- xdg_popup_destroy (view_child );
87
- }
88
-
89
- static void xdg_popup_create (struct cg_view * view , struct wlr_xdg_popup * wlr_popup );
90
-
91
- static void
92
- popup_handle_new_xdg_popup (struct wl_listener * listener , void * data )
93
- {
94
- struct cg_xdg_popup * popup = wl_container_of (listener , popup , new_popup );
95
- struct wlr_xdg_popup * wlr_popup = data ;
96
- xdg_popup_create (popup -> view_child .view , wlr_popup );
97
64
}
98
65
99
66
static void
100
- popup_unconstrain (struct cg_xdg_popup * popup )
67
+ popup_unconstrain (struct cg_view * view , struct wlr_xdg_popup * popup )
101
68
{
102
- struct cg_view * view = popup -> view_child .view ;
103
69
struct cg_server * server = view -> server ;
104
- struct wlr_box * popup_box = & popup -> wlr_popup -> geometry ;
70
+ struct wlr_box * popup_box = & popup -> geometry ;
105
71
106
72
struct wlr_output_layout * output_layout = server -> output_layout ;
107
73
struct wlr_output * wlr_output =
@@ -115,38 +81,7 @@ popup_unconstrain(struct cg_xdg_popup *popup)
115
81
.height = output_box -> height ,
116
82
};
117
83
118
- wlr_xdg_popup_unconstrain_from_box (popup -> wlr_popup , & output_toplevel_box );
119
- }
120
-
121
- static void
122
- xdg_popup_create (struct cg_view * view , struct wlr_xdg_popup * wlr_popup )
123
- {
124
- struct cg_xdg_popup * popup = calloc (1 , sizeof (struct cg_xdg_popup ));
125
- if (!popup ) {
126
- return ;
127
- }
128
-
129
- popup -> wlr_popup = wlr_popup ;
130
- view_child_init (& popup -> view_child , view , wlr_popup -> base -> surface );
131
- popup -> view_child .destroy = xdg_popup_destroy ;
132
- popup -> destroy .notify = handle_xdg_popup_destroy ;
133
- wl_signal_add (& wlr_popup -> base -> events .destroy , & popup -> destroy );
134
- popup -> map .notify = handle_xdg_popup_map ;
135
- wl_signal_add (& wlr_popup -> base -> events .map , & popup -> map );
136
- popup -> unmap .notify = handle_xdg_popup_unmap ;
137
- wl_signal_add (& wlr_popup -> base -> events .unmap , & popup -> unmap );
138
- popup -> new_popup .notify = popup_handle_new_xdg_popup ;
139
- wl_signal_add (& wlr_popup -> base -> events .new_popup , & popup -> new_popup );
140
-
141
- popup_unconstrain (popup );
142
- }
143
-
144
- static void
145
- handle_new_xdg_popup (struct wl_listener * listener , void * data )
146
- {
147
- struct cg_xdg_shell_view * xdg_shell_view = wl_container_of (listener , xdg_shell_view , new_popup );
148
- struct wlr_xdg_popup * wlr_popup = data ;
149
- xdg_popup_create (& xdg_shell_view -> view , wlr_popup );
84
+ wlr_xdg_popup_unconstrain_from_box (popup , & output_toplevel_box );
150
85
}
151
86
152
87
static struct cg_xdg_shell_view *
@@ -261,7 +196,6 @@ handle_xdg_shell_surface_destroy(struct wl_listener *listener, void *data)
261
196
wl_list_remove (& xdg_shell_view -> unmap .link );
262
197
wl_list_remove (& xdg_shell_view -> destroy .link );
263
198
wl_list_remove (& xdg_shell_view -> request_fullscreen .link );
264
- wl_list_remove (& xdg_shell_view -> new_popup .link );
265
199
xdg_shell_view -> xdg_surface = NULL ;
266
200
267
201
view_destroy (view );
@@ -283,29 +217,64 @@ handle_xdg_shell_surface_new(struct wl_listener *listener, void *data)
283
217
struct cg_server * server = wl_container_of (listener , server , new_xdg_shell_surface );
284
218
struct wlr_xdg_surface * xdg_surface = data ;
285
219
286
- if (xdg_surface -> role != WLR_XDG_SURFACE_ROLE_TOPLEVEL ) {
287
- return ;
288
- }
220
+ switch (xdg_surface -> role ) {
221
+ case WLR_XDG_SURFACE_ROLE_TOPLEVEL :;
222
+ struct cg_xdg_shell_view * xdg_shell_view = calloc (1 , sizeof (struct cg_xdg_shell_view ));
223
+ if (!xdg_shell_view ) {
224
+ wlr_log (WLR_ERROR , "Failed to allocate XDG Shell view" );
225
+ return ;
226
+ }
289
227
290
- struct cg_xdg_shell_view * xdg_shell_view = calloc (1 , sizeof (struct cg_xdg_shell_view ));
291
- if (!xdg_shell_view ) {
292
- wlr_log (WLR_ERROR , "Failed to allocate XDG Shell view" );
293
- return ;
294
- }
228
+ view_init (& xdg_shell_view -> view , server , CAGE_XDG_SHELL_VIEW , & xdg_shell_view_impl );
229
+ xdg_shell_view -> xdg_surface = xdg_surface ;
230
+
231
+ xdg_shell_view -> map .notify = handle_xdg_shell_surface_map ;
232
+ wl_signal_add (& xdg_surface -> events .map , & xdg_shell_view -> map );
233
+ xdg_shell_view -> unmap .notify = handle_xdg_shell_surface_unmap ;
234
+ wl_signal_add (& xdg_surface -> events .unmap , & xdg_shell_view -> unmap );
235
+ xdg_shell_view -> destroy .notify = handle_xdg_shell_surface_destroy ;
236
+ wl_signal_add (& xdg_surface -> events .destroy , & xdg_shell_view -> destroy );
237
+ xdg_shell_view -> request_fullscreen .notify = handle_xdg_shell_surface_request_fullscreen ;
238
+ wl_signal_add (& xdg_surface -> toplevel -> events .request_fullscreen , & xdg_shell_view -> request_fullscreen );
239
+
240
+ xdg_surface -> data = xdg_shell_view ;
241
+ break ;
242
+ case WLR_XDG_SURFACE_ROLE_POPUP :;
243
+ struct wlr_xdg_popup * popup = xdg_surface -> popup ;
244
+ struct cg_view * view = popup_get_view (popup );
245
+ if (view == NULL ) {
246
+ return ;
247
+ }
295
248
296
- view_init (& xdg_shell_view -> view , server , CAGE_XDG_SHELL_VIEW , & xdg_shell_view_impl );
297
- xdg_shell_view -> xdg_surface = xdg_surface ;
298
-
299
- xdg_shell_view -> map .notify = handle_xdg_shell_surface_map ;
300
- wl_signal_add (& xdg_surface -> events .map , & xdg_shell_view -> map );
301
- xdg_shell_view -> unmap .notify = handle_xdg_shell_surface_unmap ;
302
- wl_signal_add (& xdg_surface -> events .unmap , & xdg_shell_view -> unmap );
303
- xdg_shell_view -> destroy .notify = handle_xdg_shell_surface_destroy ;
304
- wl_signal_add (& xdg_surface -> events .destroy , & xdg_shell_view -> destroy );
305
- xdg_shell_view -> request_fullscreen .notify = handle_xdg_shell_surface_request_fullscreen ;
306
- wl_signal_add (& xdg_surface -> toplevel -> events .request_fullscreen , & xdg_shell_view -> request_fullscreen );
307
- xdg_shell_view -> new_popup .notify = handle_new_xdg_popup ;
308
- wl_signal_add (& xdg_surface -> events .new_popup , & xdg_shell_view -> new_popup );
249
+ struct wlr_scene_node * parent_scene_node = NULL ;
250
+ struct wlr_xdg_surface * parent = wlr_xdg_surface_from_wlr_surface (popup -> parent );
251
+ switch (parent -> role ) {
252
+ case WLR_XDG_SURFACE_ROLE_TOPLEVEL :;
253
+ parent_scene_node = view -> scene_node ;
254
+ break ;
255
+ case WLR_XDG_SURFACE_ROLE_POPUP :
256
+ parent_scene_node = parent -> data ;
257
+ break ;
258
+ case WLR_XDG_SURFACE_ROLE_NONE :
259
+ break ;
260
+ }
261
+ if (parent_scene_node == NULL ) {
262
+ return ;
263
+ }
264
+
265
+ struct wlr_scene_node * popup_scene_node = wlr_scene_xdg_popup_create (parent_scene_node , popup );
266
+ if (popup_scene_node == NULL ) {
267
+ wlr_log (WLR_ERROR , "Failed to allocate scene-graph node for XDG popup" );
268
+ return ;
269
+ }
270
+
271
+ popup_unconstrain (view , popup );
272
+
273
+ xdg_surface -> data = popup_scene_node ;
274
+ break ;
275
+ case WLR_XDG_SURFACE_ROLE_NONE :
276
+ assert (false); // unreachable
277
+ }
309
278
}
310
279
311
280
void
0 commit comments