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