1 /*
2  * Copyright (C) 2018 Purism SPC
3  * SPDX-License-Identifier: GPL-3.0+
4  * Author: Guido Günther <agx@sigxcpu.org>
5  */
6 /*
7 
8 WARNING: this file is taken directly from phosh, with no modificaions apart from this message. Please update phosh instead of changing this file. Please copy the file back here afterwards, with the same notice.
9 
10 */
11 
12 #define G_LOG_DOMAIN "phosh-layer-surface"
13 
14 #include "config.h"
15 #include "layersurface.h"
16 
17 #include <gdk/gdkwayland.h>
18 
19 enum {
20   PHOSH_LAYER_SURFACE_PROP_0,
21   PHOSH_LAYER_SURFACE_PROP_LAYER_SHELL,
22   PHOSH_LAYER_SURFACE_PROP_WL_OUTPUT,
23   PHOSH_LAYER_SURFACE_PROP_ANCHOR,
24   PHOSH_LAYER_SURFACE_PROP_LAYER,
25   PHOSH_LAYER_SURFACE_PROP_KBD_INTERACTIVITY,
26   PHOSH_LAYER_SURFACE_PROP_EXCLUSIVE_ZONE,
27   PHOSH_LAYER_SURFACE_PROP_MARGIN_TOP,
28   PHOSH_LAYER_SURFACE_PROP_MARGIN_BOTTOM,
29   PHOSH_LAYER_SURFACE_PROP_MARGIN_LEFT,
30   PHOSH_LAYER_SURFACE_PROP_MARGIN_RIGHT,
31   PHOSH_LAYER_SURFACE_PROP_LAYER_WIDTH,
32   PHOSH_LAYER_SURFACE_PROP_LAYER_HEIGHT,
33   PHOSH_LAYER_SURFACE_PROP_CONFIGURED_WIDTH,
34   PHOSH_LAYER_SURFACE_PROP_CONFIGURED_HEIGHT,
35   PHOSH_LAYER_SURFACE_PROP_NAMESPACE,
36   PHOSH_LAYER_SURFACE_PROP_LAST_PROP
37 };
38 static GParamSpec *props[PHOSH_LAYER_SURFACE_PROP_LAST_PROP];
39 
40 enum {
41   CONFIGURED,
42   N_SIGNALS
43 };
44 static guint signals [N_SIGNALS];
45 
46 
47 typedef struct {
48   struct wl_surface *wl_surface;
49   struct zwlr_layer_surface_v1 *layer_surface;
50 
51   /* Properties */
52   guint anchor;
53   guint layer;
54   gboolean kbd_interactivity;
55   gint exclusive_zone;
56   gint margin_top, margin_bottom;
57   gint margin_left, margin_right;
58   gint width, height;
59   gint configured_width, configured_height;
60   gchar *namespace;
61   struct zwlr_layer_shell_v1 *layer_shell;
62   struct wl_output *wl_output;
63 } PhoshLayerSurfacePrivate;
64 
G_DEFINE_TYPE_WITH_PRIVATE(PhoshLayerSurface,phosh_layer_surface,GTK_TYPE_WINDOW)65 G_DEFINE_TYPE_WITH_PRIVATE (PhoshLayerSurface, phosh_layer_surface, GTK_TYPE_WINDOW)
66 
67 static void layer_surface_configure(void                         *data,
68                                     struct zwlr_layer_surface_v1 *surface,
69                                     uint32_t                      serial,
70                                     uint32_t                      width,
71                                     uint32_t                      height)
72 {
73   PhoshLayerSurface *self = data;
74   PhoshLayerSurfacePrivate *priv;
75 
76   g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
77   priv = phosh_layer_surface_get_instance_private (self);
78   gtk_window_resize (GTK_WINDOW (self), width, height);
79   zwlr_layer_surface_v1_ack_configure(surface, serial);
80 
81   if (priv->configured_height != height) {
82     priv->configured_height = height;
83     g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_CONFIGURED_HEIGHT]);
84   }
85 
86   if (priv->configured_width != width) {
87     priv->configured_width = width;
88     g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_CONFIGURED_WIDTH]);
89   }
90 
91   g_debug("Configured %p", self);
92   g_signal_emit (self, signals[CONFIGURED], 0);
93 }
94 
95 
layer_surface_closed(void * data,struct zwlr_layer_surface_v1 * surface)96 static void layer_surface_closed (void                         *data,
97                                   struct zwlr_layer_surface_v1 *surface)
98 {
99   PhoshLayerSurface *self = data;
100   PhoshLayerSurfacePrivate *priv = phosh_layer_surface_get_instance_private (self);
101 
102   g_return_if_fail (priv->layer_surface == surface);
103   zwlr_layer_surface_v1_destroy(priv->layer_surface);
104   priv->layer_surface = NULL;
105   gtk_widget_destroy (GTK_WIDGET (self));
106 }
107 
108 static struct zwlr_layer_surface_v1_listener layer_surface_listener = {
109     .configure = layer_surface_configure,
110     .closed = layer_surface_closed,
111 };
112 
113 static void
phosh_layer_surface_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)114 phosh_layer_surface_set_property (GObject      *object,
115                                   guint         property_id,
116                                   const GValue *value,
117                                   GParamSpec   *pspec)
118 {
119   PhoshLayerSurface *self = PHOSH_LAYER_SURFACE (object);
120   PhoshLayerSurfacePrivate *priv = phosh_layer_surface_get_instance_private (self);
121   gint width, height;
122 
123   switch (property_id) {
124   case PHOSH_LAYER_SURFACE_PROP_LAYER_SHELL:
125     priv->layer_shell = g_value_get_pointer (value);
126     break;
127   case PHOSH_LAYER_SURFACE_PROP_WL_OUTPUT:
128     priv->wl_output = g_value_get_pointer (value);
129     break;
130   case PHOSH_LAYER_SURFACE_PROP_ANCHOR:
131     priv->anchor = g_value_get_uint (value);
132     break;
133   case PHOSH_LAYER_SURFACE_PROP_LAYER:
134     priv->layer = g_value_get_uint (value);
135     break;
136   case PHOSH_LAYER_SURFACE_PROP_KBD_INTERACTIVITY:
137     phosh_layer_surface_set_kbd_interactivity (self, g_value_get_boolean (value));
138     break;
139   case PHOSH_LAYER_SURFACE_PROP_EXCLUSIVE_ZONE:
140     phosh_layer_surface_set_exclusive_zone (self, g_value_get_int (value));
141     break;
142   case PHOSH_LAYER_SURFACE_PROP_MARGIN_TOP:
143     phosh_layer_surface_set_margins (self,
144                                      g_value_get_int (value),
145                                      priv->margin_right,
146                                      priv->margin_bottom,
147                                      priv->margin_left);
148     break;
149   case PHOSH_LAYER_SURFACE_PROP_MARGIN_BOTTOM:
150     phosh_layer_surface_set_margins (self,
151                                      priv->margin_top,
152                                      priv->margin_right,
153                                      g_value_get_int (value),
154                                      priv->margin_left);
155     break;
156   case PHOSH_LAYER_SURFACE_PROP_MARGIN_LEFT:
157     phosh_layer_surface_set_margins (self,
158                                      priv->margin_top,
159                                      priv->margin_right,
160                                      priv->margin_bottom,
161                                      g_value_get_int (value));
162     break;
163   case PHOSH_LAYER_SURFACE_PROP_MARGIN_RIGHT:
164     phosh_layer_surface_set_margins (self,
165                                      priv->margin_top,
166                                      g_value_get_int (value),
167                                      priv->margin_bottom,
168                                      priv->margin_left);
169     break;
170   case PHOSH_LAYER_SURFACE_PROP_LAYER_WIDTH:
171     width = g_value_get_uint (value);
172     phosh_layer_surface_set_size(self, width, priv->height);
173     break;
174   case PHOSH_LAYER_SURFACE_PROP_LAYER_HEIGHT:
175     height = g_value_get_uint (value);
176     phosh_layer_surface_set_size(self, priv->width, height);
177     break;
178   case PHOSH_LAYER_SURFACE_PROP_NAMESPACE:
179     g_free (priv->namespace);
180     priv->namespace = g_value_dup_string (value);
181     break;
182   default:
183     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
184     break;
185   }
186 }
187 
188 
189 static void
phosh_layer_surface_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)190 phosh_layer_surface_get_property (GObject    *object,
191                                   guint       property_id,
192                                   GValue     *value,
193                                   GParamSpec *pspec)
194 {
195   PhoshLayerSurface *self = PHOSH_LAYER_SURFACE (object);
196   PhoshLayerSurfacePrivate *priv = phosh_layer_surface_get_instance_private (self);
197 
198   switch (property_id) {
199   case PHOSH_LAYER_SURFACE_PROP_LAYER_SHELL:
200     g_value_set_pointer (value, priv->layer_shell);
201     break;
202   case PHOSH_LAYER_SURFACE_PROP_WL_OUTPUT:
203     g_value_set_pointer (value, priv->wl_output);
204     break;
205   case PHOSH_LAYER_SURFACE_PROP_ANCHOR:
206     g_value_set_uint (value, priv->anchor);
207     break;
208   case PHOSH_LAYER_SURFACE_PROP_LAYER:
209     g_value_set_uint (value, priv->layer);
210     break;
211   case PHOSH_LAYER_SURFACE_PROP_KBD_INTERACTIVITY:
212     g_value_set_boolean (value, priv->kbd_interactivity);
213     break;
214   case PHOSH_LAYER_SURFACE_PROP_EXCLUSIVE_ZONE:
215     g_value_set_int (value, priv->exclusive_zone);
216     break;
217   case PHOSH_LAYER_SURFACE_PROP_MARGIN_TOP:
218     g_value_set_int (value, priv->margin_top);
219     break;
220   case PHOSH_LAYER_SURFACE_PROP_MARGIN_BOTTOM:
221     g_value_set_int (value, priv->margin_bottom);
222     break;
223   case PHOSH_LAYER_SURFACE_PROP_MARGIN_LEFT:
224     g_value_set_int (value, priv->margin_left);
225     break;
226   case PHOSH_LAYER_SURFACE_PROP_MARGIN_RIGHT:
227     g_value_set_int (value, priv->margin_right);
228     break;
229   case PHOSH_LAYER_SURFACE_PROP_LAYER_WIDTH:
230     g_value_set_uint (value, priv->width);
231     break;
232   case PHOSH_LAYER_SURFACE_PROP_LAYER_HEIGHT:
233     g_value_set_uint (value, priv->height);
234     break;
235   case PHOSH_LAYER_SURFACE_PROP_CONFIGURED_WIDTH:
236     g_value_set_uint (value, priv->configured_width);
237     break;
238   case PHOSH_LAYER_SURFACE_PROP_CONFIGURED_HEIGHT:
239     g_value_set_uint (value, priv->configured_height);
240     break;
241   case PHOSH_LAYER_SURFACE_PROP_NAMESPACE:
242     g_value_set_string (value, priv->namespace);
243     break;
244   default:
245     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
246     break;
247   }
248 }
249 
250 
251 static void
on_phosh_layer_surface_realized(PhoshLayerSurface * self,gpointer unused)252 on_phosh_layer_surface_realized (PhoshLayerSurface *self, gpointer unused)
253 {
254   PhoshLayerSurfacePrivate *priv;
255   GdkWindow *gdk_window;
256 
257   g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
258 
259   priv = phosh_layer_surface_get_instance_private (self);
260 
261   gdk_window = gtk_widget_get_window (GTK_WIDGET (self));
262   gdk_wayland_window_set_use_custom_surface (gdk_window);
263   priv->wl_surface = gdk_wayland_window_get_wl_surface (gdk_window);
264 
265   gtk_window_set_decorated (GTK_WINDOW (self), FALSE);
266 }
267 
268 
269 static void
on_phosh_layer_surface_mapped(PhoshLayerSurface * self,gpointer unused)270 on_phosh_layer_surface_mapped (PhoshLayerSurface *self, gpointer unused)
271 {
272   PhoshLayerSurfacePrivate *priv;
273   GdkWindow *gdk_window;
274 
275   g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
276   priv = phosh_layer_surface_get_instance_private (self);
277 
278   if (!priv->wl_surface) {
279       gdk_window = gtk_widget_get_window (GTK_WIDGET (self));
280       gdk_wayland_window_set_use_custom_surface (gdk_window);
281       priv->wl_surface = gdk_wayland_window_get_wl_surface (gdk_window);
282   }
283   g_debug ("Mapped %p", priv->wl_surface);
284 
285   priv->layer_surface = zwlr_layer_shell_v1_get_layer_surface(priv->layer_shell,
286                                                               priv->wl_surface,
287                                                               priv->wl_output,
288                                                               priv->layer,
289                                                               priv->namespace);
290   zwlr_layer_surface_v1_set_exclusive_zone(priv->layer_surface, priv->exclusive_zone);
291   zwlr_layer_surface_v1_set_size(priv->layer_surface, priv->width, priv->height);
292   zwlr_layer_surface_v1_set_anchor(priv->layer_surface, priv->anchor);
293   zwlr_layer_surface_v1_set_margin(priv->layer_surface,
294                                    priv->margin_top,
295                                    priv->margin_right,
296                                    priv->margin_bottom,
297                                    priv->margin_left);
298   zwlr_layer_surface_v1_set_keyboard_interactivity(priv->layer_surface, priv->kbd_interactivity);
299   zwlr_layer_surface_v1_add_listener(priv->layer_surface,
300                                      &layer_surface_listener,
301                                      self);
302   wl_surface_commit(priv->wl_surface);
303 
304   /* Process all pending events, otherwise we end up sending ack configure
305    * to a not yet configured surface */
306   wl_display_roundtrip (gdk_wayland_display_get_wl_display (gdk_display_get_default ()));
307 }
308 
309 static void
on_phosh_layer_surface_unmapped(PhoshLayerSurface * self,gpointer unused)310 on_phosh_layer_surface_unmapped (PhoshLayerSurface *self, gpointer unused)
311 {
312   PhoshLayerSurfacePrivate *priv;
313 
314   g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
315 
316   priv = phosh_layer_surface_get_instance_private (self);
317   if (priv->layer_surface) {
318     zwlr_layer_surface_v1_destroy(priv->layer_surface);
319     priv->layer_surface = NULL;
320   }
321   priv->wl_surface = NULL;
322 }
323 
324 static void
phosh_layer_surface_constructed(GObject * object)325 phosh_layer_surface_constructed (GObject *object)
326 {
327   PhoshLayerSurface *self = PHOSH_LAYER_SURFACE (object);
328 
329   g_signal_connect (self, "realize",
330                     G_CALLBACK (on_phosh_layer_surface_realized),
331                     NULL);
332   g_signal_connect (self, "map",
333                     G_CALLBACK (on_phosh_layer_surface_mapped),
334                     NULL);
335   g_signal_connect (self, "unmap",
336                     G_CALLBACK (on_phosh_layer_surface_unmapped),
337                     NULL);
338 
339   G_OBJECT_CLASS (phosh_layer_surface_parent_class)->constructed (object);
340 }
341 
342 
343 static void
phosh_layer_surface_dispose(GObject * object)344 phosh_layer_surface_dispose (GObject *object)
345 {
346   PhoshLayerSurface *self = PHOSH_LAYER_SURFACE (object);
347   PhoshLayerSurfacePrivate *priv = phosh_layer_surface_get_instance_private (self);
348 
349   if (priv->layer_surface) {
350     zwlr_layer_surface_v1_destroy(priv->layer_surface);
351     priv->layer_surface = NULL;
352   }
353   g_clear_pointer (&priv->namespace, g_free);
354 
355   G_OBJECT_CLASS (phosh_layer_surface_parent_class)->dispose (object);
356 }
357 
358 
359 static void
phosh_layer_surface_class_init(PhoshLayerSurfaceClass * klass)360 phosh_layer_surface_class_init (PhoshLayerSurfaceClass *klass)
361 {
362   GObjectClass *object_class = (GObjectClass *)klass;
363 
364   object_class->constructed = phosh_layer_surface_constructed;
365   object_class->dispose = phosh_layer_surface_dispose;
366 
367   object_class->set_property = phosh_layer_surface_set_property;
368   object_class->get_property = phosh_layer_surface_get_property;
369 
370   props[PHOSH_LAYER_SURFACE_PROP_LAYER_SHELL] =
371     g_param_spec_pointer (
372       "layer-shell",
373       "Wayland Layer Shell Global",
374       "The layer shell wayland global",
375       G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
376 
377   props[PHOSH_LAYER_SURFACE_PROP_WL_OUTPUT] =
378     g_param_spec_pointer (
379       "wl-output",
380       "Wayland Output",
381       "The wl_output associated with this surface",
382       G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
383 
384   props[PHOSH_LAYER_SURFACE_PROP_ANCHOR] =
385     g_param_spec_uint (
386       "anchor",
387       "Anchor edges",
388       "The edges to anchor the surface to",
389       0,
390       G_MAXUINT,
391       0,
392       G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
393 
394   props[PHOSH_LAYER_SURFACE_PROP_LAYER] =
395     g_param_spec_uint (
396       "layer",
397       "Layer",
398       "The layer the surface should be attached to",
399       0,
400       G_MAXUINT,
401       0,
402       G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
403 
404   props[PHOSH_LAYER_SURFACE_PROP_KBD_INTERACTIVITY] =
405     g_param_spec_boolean (
406       "kbd-interactivity",
407       "Keyboard interactivity",
408       "Whether the surface interacts with the keyboard",
409       FALSE,
410       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
411 
412   props[PHOSH_LAYER_SURFACE_PROP_EXCLUSIVE_ZONE] =
413     g_param_spec_int (
414       "exclusive-zone",
415       "Exclusive Zone",
416       "Set area that is not occluded with other surfaces",
417       -1,
418       G_MAXINT,
419       0,
420       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
421 
422   props[PHOSH_LAYER_SURFACE_PROP_MARGIN_LEFT] =
423     g_param_spec_int (
424       "margin-left",
425       "Left margin",
426       "Distance away from the left anchor point",
427       G_MININT,
428       G_MAXINT,
429       0,
430       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
431 
432   props[PHOSH_LAYER_SURFACE_PROP_MARGIN_RIGHT] =
433     g_param_spec_int (
434       "margin-right",
435       "Right margin",
436       "Distance away from the right anchor point",
437       G_MININT,
438       G_MAXINT,
439       0,
440       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
441 
442   props[PHOSH_LAYER_SURFACE_PROP_MARGIN_TOP] =
443     g_param_spec_int (
444       "margin-top",
445       "Top margin",
446       "Distance away from the top anchor point",
447       G_MININT,
448       G_MAXINT,
449       0,
450       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
451 
452   props[PHOSH_LAYER_SURFACE_PROP_MARGIN_BOTTOM] =
453     g_param_spec_int (
454       "margin-bottom",
455       "Bottom margin",
456       "Distance away from the bottom anchor point",
457       G_MININT,
458       G_MAXINT,
459       0,
460       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
461 
462   props[PHOSH_LAYER_SURFACE_PROP_LAYER_WIDTH] =
463     g_param_spec_uint (
464       "width",
465       "Width",
466       "The width of the layer surface",
467       0,
468       G_MAXUINT,
469       0,
470       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
471 
472   props[PHOSH_LAYER_SURFACE_PROP_LAYER_HEIGHT] =
473     g_param_spec_uint (
474       "height",
475       "Height",
476       "The height of the layer surface",
477       0,
478       G_MAXUINT,
479       0,
480       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
481 
482 
483   props[PHOSH_LAYER_SURFACE_PROP_CONFIGURED_WIDTH] =
484     g_param_spec_uint (
485       "configured-width",
486       "Configured width",
487       "The width of the layer surface set by the compositor",
488       0,
489       G_MAXUINT,
490       0,
491       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
492 
493   props[PHOSH_LAYER_SURFACE_PROP_CONFIGURED_HEIGHT] =
494     g_param_spec_uint (
495       "configured-height",
496       "Configured height",
497       "The height of the layer surface set by the compositor",
498       0,
499       G_MAXUINT,
500       0,
501       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
502 
503   props[PHOSH_LAYER_SURFACE_PROP_NAMESPACE] =
504     g_param_spec_string (
505       "namespace",
506       "Namespace",
507       "Namespace of the layer surface",
508       "",
509       G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
510 
511   g_object_class_install_properties (object_class, PHOSH_LAYER_SURFACE_PROP_LAST_PROP, props);
512 
513   /**
514    * PhoshLayersurface::configured
515    * @self: The #PhoshLayersurface instance.
516    *
517    * This signal is emitted once we received the configure event from the
518    * compositor.
519    */
520   signals[CONFIGURED] =
521     g_signal_new ("configured",
522                   G_TYPE_FROM_CLASS (klass),
523                   G_SIGNAL_RUN_LAST,
524                   G_STRUCT_OFFSET (PhoshLayerSurfaceClass, configured),
525                   NULL, NULL, NULL,
526                   G_TYPE_NONE, 0);
527 }
528 
529 
530 static void
phosh_layer_surface_init(PhoshLayerSurface * self)531 phosh_layer_surface_init (PhoshLayerSurface *self)
532 {
533 }
534 
535 
536 GtkWidget *
phosh_layer_surface_new(gpointer layer_shell,gpointer wl_output)537 phosh_layer_surface_new (gpointer layer_shell,
538                          gpointer wl_output)
539 {
540   return g_object_new (PHOSH_TYPE_LAYER_SURFACE,
541                        "layer-shell", layer_shell,
542                        "wl-output", wl_output);
543 }
544 
545 /**
546  * phosh_layer_surface_get_surface:
547  *
548  * Get the layer layer surface or #NULL if the window
549  * is not yet realized.
550  */
551 struct zwlr_layer_surface_v1 *
phosh_layer_surface_get_layer_surface(PhoshLayerSurface * self)552 phosh_layer_surface_get_layer_surface(PhoshLayerSurface *self)
553 {
554   PhoshLayerSurfacePrivate *priv;
555 
556   g_return_val_if_fail (PHOSH_IS_LAYER_SURFACE (self), NULL);
557   priv = phosh_layer_surface_get_instance_private (self);
558   return priv->layer_surface;
559 }
560 
561 
562 /**
563  * phosh_layer_surface_get_wl_surface:
564  *
565  * Get the layer wayland surface or #NULL if the window
566  * is not yet realized.
567  */
568 struct wl_surface *
phosh_layer_surface_get_wl_surface(PhoshLayerSurface * self)569 phosh_layer_surface_get_wl_surface(PhoshLayerSurface *self)
570 {
571   PhoshLayerSurfacePrivate *priv;
572 
573   g_return_val_if_fail (PHOSH_IS_LAYER_SURFACE (self), NULL);
574   priv = phosh_layer_surface_get_instance_private (self);
575   return priv->wl_surface;
576 }
577 
578 /**
579  * phosh_layer_surface_set_size:
580  *
581  * Set the size of a layer surface. A value of '-1' indicates 'use old value'
582  */
583 void
phosh_layer_surface_set_size(PhoshLayerSurface * self,gint width,gint height)584 phosh_layer_surface_set_size(PhoshLayerSurface *self, gint width, gint height)
585 {
586   PhoshLayerSurfacePrivate *priv;
587   gint old_width, old_height;
588 
589   g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
590   priv = phosh_layer_surface_get_instance_private (self);
591 
592   if (priv->height == height && priv->width == width) {
593     return;
594   }
595 
596   old_width = priv->width;
597   old_height = priv->height;
598 
599   if (width != -1) {
600     priv->width = width;
601   }
602 
603   if (height != -1) {
604     priv->height = height;
605   }
606 
607   if (gtk_widget_get_mapped (GTK_WIDGET (self))) {
608     zwlr_layer_surface_v1_set_size(priv->layer_surface, priv->width, priv->height);
609   }
610 
611   if (priv->height != old_height) {
612     g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_LAYER_HEIGHT]);
613   }
614 
615   if (priv->width != old_width) {
616     g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_LAYER_WIDTH]);
617   }
618 }
619 
620 /**
621  * phosh_layer_surface_set_margins:
622  *
623  * Set anchor margins of a layer surface.
624  */
625 void
phosh_layer_surface_set_margins(PhoshLayerSurface * self,gint top,gint right,gint bottom,gint left)626 phosh_layer_surface_set_margins(PhoshLayerSurface *self, gint top, gint right, gint bottom, gint left)
627 {
628   PhoshLayerSurfacePrivate *priv;
629   gint old_top, old_bottom, old_left, old_right;
630 
631   g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
632   priv = phosh_layer_surface_get_instance_private (self);
633 
634   old_top = priv->margin_top;
635   old_left = priv->margin_left;
636   old_right = priv->margin_right;
637   old_bottom = priv->margin_bottom;
638 
639   if (old_top == top && old_left == left && old_right == right && old_bottom == bottom) {
640     return;
641   }
642 
643   priv->margin_top = top;
644   priv->margin_left = left;
645   priv->margin_right = right;
646   priv->margin_bottom = bottom;
647 
648   if (priv->layer_surface) {
649     zwlr_layer_surface_v1_set_margin(priv->layer_surface, top, right, bottom, left);
650   }
651 
652   if (old_top != top) {
653     g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_MARGIN_TOP]);
654   }
655   if (old_bottom != bottom) {
656     g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_MARGIN_BOTTOM]);
657   }
658   if (old_left != left) {
659     g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_MARGIN_LEFT]);
660   }
661   if (old_right != right) {
662     g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_MARGIN_RIGHT]);
663   }
664 }
665 
666 /**
667  * phosh_layer_surface_set_exclusive_zone:
668  *
669  * Set exclusive zone of a layer surface.
670  */
671 void
phosh_layer_surface_set_exclusive_zone(PhoshLayerSurface * self,gint zone)672 phosh_layer_surface_set_exclusive_zone(PhoshLayerSurface *self, gint zone)
673 {
674   PhoshLayerSurfacePrivate *priv;
675   gint old_zone;
676 
677   g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
678   priv = phosh_layer_surface_get_instance_private (self);
679 
680   old_zone = priv->exclusive_zone;
681 
682   if (old_zone == zone) {
683     return;
684   }
685 
686   priv->exclusive_zone = zone;
687 
688   if (priv->layer_surface) {
689     zwlr_layer_surface_v1_set_exclusive_zone(priv->layer_surface, zone);
690   }
691 
692   g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_EXCLUSIVE_ZONE]);
693 }
694 
695 /**
696  * phosh_layer_surface_set_keyboard_interactivity:
697  *
698  * Set keyboard ineractivity a layer surface.
699  */
700 void
phosh_layer_surface_set_kbd_interactivity(PhoshLayerSurface * self,gboolean interactivity)701 phosh_layer_surface_set_kbd_interactivity (PhoshLayerSurface *self, gboolean interactivity)
702 {
703   PhoshLayerSurfacePrivate *priv;
704 
705   g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
706   priv = phosh_layer_surface_get_instance_private (self);
707 
708   if (priv->kbd_interactivity == interactivity) {
709     return;
710   }
711   priv->kbd_interactivity = interactivity;
712 
713   if (priv->layer_surface) {
714     zwlr_layer_surface_v1_set_keyboard_interactivity (priv->layer_surface, interactivity);
715   }
716 
717   g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_KBD_INTERACTIVITY]);
718 }
719 
720 /**
721  * phosh_layer_surface_wl_surface_commit:
722  *
723  * Forces a commit of layer surface's state.
724  */
725 void
phosh_layer_surface_wl_surface_commit(PhoshLayerSurface * self)726 phosh_layer_surface_wl_surface_commit (PhoshLayerSurface *self)
727 {
728   PhoshLayerSurfacePrivate *priv;
729 
730   g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
731   priv = phosh_layer_surface_get_instance_private (self);
732 
733   if (priv->wl_surface) {
734     wl_surface_commit (priv->wl_surface);
735   }
736 }
737