1 /*
2 * Copyright (C) 2012,2013 Intel Corporation
3 * Copyright (C) 2013-2017 Red Hat, Inc.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18 * 02111-1307, USA.
19 *
20 */
21
22 #include "config.h"
23
24 #include "wayland/meta-wayland-shell-surface.h"
25
26 #include "compositor/meta-surface-actor-wayland.h"
27 #include "compositor/meta-window-actor-private.h"
28 #include "compositor/meta-window-actor-wayland.h"
29 #include "wayland/meta-wayland-actor-surface.h"
30 #include "wayland/meta-wayland-buffer.h"
31 #include "wayland/meta-wayland-subsurface.h"
32 #include "wayland/meta-wayland-surface.h"
33 #include "wayland/meta-window-wayland.h"
34
35 typedef struct _MetaWaylandShellSurfacePrivate
36 {
37 MetaWindow *window;
38
39 gulong unmanaging_handler_id;
40 } MetaWaylandShellSurfacePrivate;
41
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(MetaWaylandShellSurface,meta_wayland_shell_surface,META_TYPE_WAYLAND_ACTOR_SURFACE)42 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaWaylandShellSurface,
43 meta_wayland_shell_surface,
44 META_TYPE_WAYLAND_ACTOR_SURFACE)
45
46 void
47 meta_wayland_shell_surface_calculate_geometry (MetaWaylandShellSurface *shell_surface,
48 MetaRectangle *out_geometry)
49 {
50 MetaWaylandSurfaceRole *surface_role =
51 META_WAYLAND_SURFACE_ROLE (shell_surface);
52 MetaWaylandSurface *surface =
53 meta_wayland_surface_role_get_surface (surface_role);
54 MetaRectangle geometry;
55 MetaWaylandSurface *subsurface_surface;
56
57 geometry = (MetaRectangle) {
58 .width = meta_wayland_surface_get_width (surface),
59 .height = meta_wayland_surface_get_height (surface),
60 };
61
62 META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface)
63 {
64 MetaWaylandSubsurface *subsurface;
65
66 subsurface = META_WAYLAND_SUBSURFACE (subsurface_surface->role);
67 meta_wayland_subsurface_union_geometry (subsurface,
68 0, 0,
69 &geometry);
70 }
71
72 *out_geometry = geometry;
73 }
74
75 void
meta_wayland_shell_surface_determine_geometry(MetaWaylandShellSurface * shell_surface,MetaRectangle * set_geometry,MetaRectangle * out_geometry)76 meta_wayland_shell_surface_determine_geometry (MetaWaylandShellSurface *shell_surface,
77 MetaRectangle *set_geometry,
78 MetaRectangle *out_geometry)
79 {
80 MetaRectangle bounding_geometry = { 0 };
81 MetaRectangle intersected_geometry = { 0 };
82
83 meta_wayland_shell_surface_calculate_geometry (shell_surface,
84 &bounding_geometry);
85
86 meta_rectangle_intersect (set_geometry, &bounding_geometry,
87 &intersected_geometry);
88
89 *out_geometry = intersected_geometry;
90 }
91
92 static void
clear_window(MetaWaylandShellSurface * shell_surface)93 clear_window (MetaWaylandShellSurface *shell_surface)
94 {
95 MetaWaylandShellSurfacePrivate *priv =
96 meta_wayland_shell_surface_get_instance_private (shell_surface);
97 MetaWaylandSurfaceRole *surface_role =
98 META_WAYLAND_SURFACE_ROLE (shell_surface);
99 MetaWaylandSurface *surface =
100 meta_wayland_surface_role_get_surface (surface_role);
101 MetaSurfaceActor *surface_actor;
102
103 if (!priv->window)
104 return;
105
106 g_clear_signal_handler (&priv->unmanaging_handler_id,
107 priv->window);
108 priv->window = NULL;
109
110 surface_actor = meta_wayland_surface_get_actor (surface);
111 if (surface_actor)
112 clutter_actor_set_reactive (CLUTTER_ACTOR (surface_actor), FALSE);
113
114 meta_wayland_surface_notify_unmapped (surface);
115 }
116
117 static void
window_unmanaging(MetaWindow * window,MetaWaylandShellSurface * shell_surface)118 window_unmanaging (MetaWindow *window,
119 MetaWaylandShellSurface *shell_surface)
120 {
121 clear_window (shell_surface);
122 }
123
124 void
meta_wayland_shell_surface_set_window(MetaWaylandShellSurface * shell_surface,MetaWindow * window)125 meta_wayland_shell_surface_set_window (MetaWaylandShellSurface *shell_surface,
126 MetaWindow *window)
127 {
128 MetaWaylandShellSurfacePrivate *priv =
129 meta_wayland_shell_surface_get_instance_private (shell_surface);
130 MetaWaylandSurfaceRole *surface_role =
131 META_WAYLAND_SURFACE_ROLE (shell_surface);
132 MetaWaylandSurface *surface =
133 meta_wayland_surface_role_get_surface (surface_role);
134 MetaSurfaceActor *surface_actor;
135
136 g_assert (!priv->window);
137
138 priv->window = window;
139
140 surface_actor = meta_wayland_surface_get_actor (surface);
141 if (surface_actor)
142 clutter_actor_set_reactive (CLUTTER_ACTOR (surface_actor), TRUE);
143
144 priv->unmanaging_handler_id =
145 g_signal_connect (window,
146 "unmanaging",
147 G_CALLBACK (window_unmanaging),
148 shell_surface);
149
150 meta_window_update_monitor (window, META_WINDOW_UPDATE_MONITOR_FLAGS_NONE);
151 }
152
153 void
meta_wayland_shell_surface_configure(MetaWaylandShellSurface * shell_surface,MetaWaylandWindowConfiguration * configuration)154 meta_wayland_shell_surface_configure (MetaWaylandShellSurface *shell_surface,
155 MetaWaylandWindowConfiguration *configuration)
156 {
157 MetaWaylandShellSurfaceClass *shell_surface_class =
158 META_WAYLAND_SHELL_SURFACE_GET_CLASS (shell_surface);
159
160 shell_surface_class->configure (shell_surface, configuration);
161 }
162
163 void
meta_wayland_shell_surface_ping(MetaWaylandShellSurface * shell_surface,uint32_t serial)164 meta_wayland_shell_surface_ping (MetaWaylandShellSurface *shell_surface,
165 uint32_t serial)
166 {
167 MetaWaylandShellSurfaceClass *shell_surface_class =
168 META_WAYLAND_SHELL_SURFACE_GET_CLASS (shell_surface);
169
170 shell_surface_class->ping (shell_surface, serial);
171 }
172
173 void
meta_wayland_shell_surface_close(MetaWaylandShellSurface * shell_surface)174 meta_wayland_shell_surface_close (MetaWaylandShellSurface *shell_surface)
175 {
176 MetaWaylandShellSurfaceClass *shell_surface_class =
177 META_WAYLAND_SHELL_SURFACE_GET_CLASS (shell_surface);
178
179 shell_surface_class->close (shell_surface);
180 }
181
182 void
meta_wayland_shell_surface_managed(MetaWaylandShellSurface * shell_surface,MetaWindow * window)183 meta_wayland_shell_surface_managed (MetaWaylandShellSurface *shell_surface,
184 MetaWindow *window)
185 {
186 MetaWaylandShellSurfaceClass *shell_surface_class =
187 META_WAYLAND_SHELL_SURFACE_GET_CLASS (shell_surface);
188
189 shell_surface_class->managed (shell_surface, window);
190 }
191
192 static void
meta_wayland_shell_surface_assigned(MetaWaylandSurfaceRole * surface_role)193 meta_wayland_shell_surface_assigned (MetaWaylandSurfaceRole *surface_role)
194 {
195 MetaWaylandSurfaceRoleClass *surface_role_class =
196 META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_shell_surface_parent_class);
197 MetaWaylandSurface *surface =
198 meta_wayland_surface_role_get_surface (surface_role);
199
200 surface->dnd.funcs = meta_wayland_data_device_get_drag_dest_funcs ();
201
202 surface_role_class->assigned (surface_role);
203 }
204
205 static void
meta_wayland_shell_surface_surface_pre_apply_state(MetaWaylandSurfaceRole * surface_role,MetaWaylandSurfaceState * pending)206 meta_wayland_shell_surface_surface_pre_apply_state (MetaWaylandSurfaceRole *surface_role,
207 MetaWaylandSurfaceState *pending)
208 {
209 MetaWaylandShellSurface *shell_surface =
210 META_WAYLAND_SHELL_SURFACE (surface_role);
211 MetaWaylandShellSurfacePrivate *priv =
212 meta_wayland_shell_surface_get_instance_private (shell_surface);
213 MetaWaylandSurface *surface =
214 meta_wayland_surface_role_get_surface (surface_role);
215
216 if (pending->newly_attached &&
217 !surface->buffer_ref->buffer &&
218 priv->window)
219 meta_window_queue (priv->window, META_QUEUE_CALC_SHOWING);
220 }
221
222 static void
meta_wayland_shell_surface_surface_apply_state(MetaWaylandSurfaceRole * surface_role,MetaWaylandSurfaceState * pending)223 meta_wayland_shell_surface_surface_apply_state (MetaWaylandSurfaceRole *surface_role,
224 MetaWaylandSurfaceState *pending)
225 {
226 MetaWaylandShellSurface *shell_surface =
227 META_WAYLAND_SHELL_SURFACE (surface_role);
228 MetaWaylandShellSurfacePrivate *priv =
229 meta_wayland_shell_surface_get_instance_private (shell_surface);
230 MetaWaylandActorSurface *actor_surface =
231 META_WAYLAND_ACTOR_SURFACE (surface_role);
232 MetaWaylandSurface *surface =
233 meta_wayland_surface_role_get_surface (surface_role);
234 MetaWaylandSurfaceRoleClass *surface_role_class;
235 MetaWindow *window;
236 MetaWaylandBuffer *buffer;
237 double geometry_scale;
238
239 surface_role_class =
240 META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_shell_surface_parent_class);
241 surface_role_class->apply_state (surface_role, pending);
242
243 buffer = surface->buffer_ref->buffer;
244 if (!buffer)
245 return;
246
247 window = priv->window;
248 if (!window)
249 return;
250
251 geometry_scale = meta_wayland_actor_surface_get_geometry_scale (actor_surface);
252
253 window->buffer_rect.width =
254 meta_wayland_surface_get_width (surface) * geometry_scale;
255 window->buffer_rect.height =
256 meta_wayland_surface_get_height (surface) * geometry_scale;
257 }
258
259 static MetaWindow *
meta_wayland_shell_surface_get_window(MetaWaylandSurfaceRole * surface_role)260 meta_wayland_shell_surface_get_window (MetaWaylandSurfaceRole *surface_role)
261 {
262 MetaWaylandShellSurface *shell_surface =
263 META_WAYLAND_SHELL_SURFACE (surface_role);
264 MetaWaylandShellSurfacePrivate *priv =
265 meta_wayland_shell_surface_get_instance_private (shell_surface);
266
267 return priv->window;
268 }
269
270 static void
meta_wayland_shell_surface_notify_subsurface_state_changed(MetaWaylandSurfaceRole * surface_role)271 meta_wayland_shell_surface_notify_subsurface_state_changed (MetaWaylandSurfaceRole *surface_role)
272 {
273 MetaWaylandShellSurface *shell_surface =
274 META_WAYLAND_SHELL_SURFACE (surface_role);
275 MetaWaylandShellSurfacePrivate *priv =
276 meta_wayland_shell_surface_get_instance_private (shell_surface);
277 MetaWindow *window;
278 MetaWindowActor *window_actor;
279
280 window = priv->window;
281 if (!window)
282 return;
283
284 window_actor = meta_window_actor_from_window (window);
285 meta_window_actor_wayland_rebuild_surface_tree (window_actor);
286 }
287
288 static double
meta_wayland_shell_surface_get_geometry_scale(MetaWaylandActorSurface * actor_surface)289 meta_wayland_shell_surface_get_geometry_scale (MetaWaylandActorSurface *actor_surface)
290 {
291 MetaWaylandSurfaceRole *surface_role =
292 META_WAYLAND_SURFACE_ROLE (actor_surface);
293 MetaWaylandSurface *surface =
294 meta_wayland_surface_role_get_surface (surface_role);
295 MetaWindow *toplevel_window;
296
297 toplevel_window = meta_wayland_surface_get_toplevel_window (surface);
298 if (meta_is_stage_views_scaled () || !toplevel_window)
299 return 1;
300 else
301 return meta_window_wayland_get_geometry_scale (toplevel_window);
302 }
303
304 static void
meta_wayland_shell_surface_sync_actor_state(MetaWaylandActorSurface * actor_surface)305 meta_wayland_shell_surface_sync_actor_state (MetaWaylandActorSurface *actor_surface)
306 {
307 MetaWaylandSurfaceRole *surface_role =
308 META_WAYLAND_SURFACE_ROLE (actor_surface);
309 MetaWaylandSurface *surface =
310 meta_wayland_surface_role_get_surface (surface_role);
311 MetaWaylandActorSurfaceClass *actor_surface_class =
312 META_WAYLAND_ACTOR_SURFACE_CLASS (meta_wayland_shell_surface_parent_class);
313 MetaWindow *toplevel_window;
314
315 toplevel_window = meta_wayland_surface_get_toplevel_window (surface);
316 if (!toplevel_window)
317 return;
318
319 actor_surface_class->sync_actor_state (actor_surface);
320 }
321
322 void
meta_wayland_shell_surface_destroy_window(MetaWaylandShellSurface * shell_surface)323 meta_wayland_shell_surface_destroy_window (MetaWaylandShellSurface *shell_surface)
324 {
325 MetaWaylandShellSurfacePrivate *priv =
326 meta_wayland_shell_surface_get_instance_private (shell_surface);
327 MetaWindow *window;
328 MetaDisplay *display;
329 uint32_t timestamp;
330
331 window = priv->window;
332 if (!window)
333 return;
334
335 display = meta_window_get_display (window);
336 timestamp = meta_display_get_current_time_roundtrip (display);
337 meta_window_unmanage (window, timestamp);
338 g_assert (!priv->window);
339 }
340
341 static void
meta_wayland_shell_surface_finalize(GObject * object)342 meta_wayland_shell_surface_finalize (GObject *object)
343 {
344 MetaWaylandShellSurface *shell_surface = META_WAYLAND_SHELL_SURFACE (object);
345
346 meta_wayland_shell_surface_destroy_window (shell_surface);
347
348 G_OBJECT_CLASS (meta_wayland_shell_surface_parent_class)->finalize (object);
349 }
350
351 static void
meta_wayland_shell_surface_init(MetaWaylandShellSurface * role)352 meta_wayland_shell_surface_init (MetaWaylandShellSurface *role)
353 {
354 }
355
356 static void
meta_wayland_shell_surface_class_init(MetaWaylandShellSurfaceClass * klass)357 meta_wayland_shell_surface_class_init (MetaWaylandShellSurfaceClass *klass)
358 {
359 GObjectClass *object_class = G_OBJECT_CLASS (klass);
360 MetaWaylandSurfaceRoleClass *surface_role_class =
361 META_WAYLAND_SURFACE_ROLE_CLASS (klass);
362 MetaWaylandActorSurfaceClass *actor_surface_class =
363 META_WAYLAND_ACTOR_SURFACE_CLASS (klass);
364
365 object_class->finalize = meta_wayland_shell_surface_finalize;
366
367 surface_role_class->assigned = meta_wayland_shell_surface_assigned;
368 surface_role_class->pre_apply_state =
369 meta_wayland_shell_surface_surface_pre_apply_state;
370 surface_role_class->apply_state =
371 meta_wayland_shell_surface_surface_apply_state;
372 surface_role_class->notify_subsurface_state_changed =
373 meta_wayland_shell_surface_notify_subsurface_state_changed;
374 surface_role_class->get_window = meta_wayland_shell_surface_get_window;
375
376 actor_surface_class->get_geometry_scale =
377 meta_wayland_shell_surface_get_geometry_scale;
378 actor_surface_class->sync_actor_state =
379 meta_wayland_shell_surface_sync_actor_state;
380 }
381