layersurface.c 23 KB
Newer Older
Guido Gunther's avatar
Guido Gunther committed
1
2
/*
 * Copyright (C) 2018 Purism SPC
Zander Brown's avatar
Zander Brown committed
3
4
5
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 *
Guido Gunther's avatar
Guido Gunther committed
6
7
8
9
10
11
12
13
14
15
 * Author: Guido Günther <agx@sigxcpu.org>
 */

#define G_LOG_DOMAIN "phosh-layer-surface"

#include "config.h"
#include "layersurface.h"

#include <gdk/gdkwayland.h>

16
17
18
19
20
21
22
23
24
25
/**
 * SECTION:layersurface
 * @short_description: A #GtkWindow rendered as a LayerSurface by the compositor
 * @Title: PhoshLayerSurface
 *
 * #PhoshLayerSurface allows to use a Wayland surface backed by the
 * layer-shell protocol as #GtkWindow. This allows to render e.g. panels and
 * backgrounds using GTK.
 */

Guido Gunther's avatar
Guido Gunther committed
26
27
28
29
30
31
32
33
enum {
  PHOSH_LAYER_SURFACE_PROP_0,
  PHOSH_LAYER_SURFACE_PROP_LAYER_SHELL,
  PHOSH_LAYER_SURFACE_PROP_WL_OUTPUT,
  PHOSH_LAYER_SURFACE_PROP_ANCHOR,
  PHOSH_LAYER_SURFACE_PROP_LAYER,
  PHOSH_LAYER_SURFACE_PROP_KBD_INTERACTIVITY,
  PHOSH_LAYER_SURFACE_PROP_EXCLUSIVE_ZONE,
34
35
36
37
  PHOSH_LAYER_SURFACE_PROP_MARGIN_TOP,
  PHOSH_LAYER_SURFACE_PROP_MARGIN_BOTTOM,
  PHOSH_LAYER_SURFACE_PROP_MARGIN_LEFT,
  PHOSH_LAYER_SURFACE_PROP_MARGIN_RIGHT,
Guido Gunther's avatar
Guido Gunther committed
38
39
  PHOSH_LAYER_SURFACE_PROP_LAYER_WIDTH,
  PHOSH_LAYER_SURFACE_PROP_LAYER_HEIGHT,
40
41
  PHOSH_LAYER_SURFACE_PROP_CONFIGURED_WIDTH,
  PHOSH_LAYER_SURFACE_PROP_CONFIGURED_HEIGHT,
Guido Gunther's avatar
Guido Gunther committed
42
43
44
45
46
  PHOSH_LAYER_SURFACE_PROP_NAMESPACE,
  PHOSH_LAYER_SURFACE_PROP_LAST_PROP
};
static GParamSpec *props[PHOSH_LAYER_SURFACE_PROP_LAST_PROP];

47
48
49
50
51
52
enum {
  CONFIGURED,
  N_SIGNALS
};
static guint signals [N_SIGNALS];

Guido Gunther's avatar
Guido Gunther committed
53
typedef struct {
Guido Gunther's avatar
Guido Gunther committed
54
  struct wl_surface            *wl_surface;
Guido Gunther's avatar
Guido Gunther committed
55
56
57
  struct zwlr_layer_surface_v1 *layer_surface;

  /* Properties */
Guido Gunther's avatar
Guido Gunther committed
58
59
60
  guint                         anchor;
  guint                         layer;
  gboolean                      kbd_interactivity;
61
62
63
64
65
  int                           exclusive_zone;
  int                           margin_top, margin_bottom;
  int                           margin_left, margin_right;
  int                           width, height;
  int                           configured_width, configured_height;
66
  char                         *namespace;
Guido Gunther's avatar
Guido Gunther committed
67
68
  struct zwlr_layer_shell_v1   *layer_shell;
  struct wl_output             *wl_output;
Guido Gunther's avatar
Guido Gunther committed
69
70
71
72
} PhoshLayerSurfacePrivate;

G_DEFINE_TYPE_WITH_PRIVATE (PhoshLayerSurface, phosh_layer_surface, GTK_TYPE_WINDOW)

73

Guido Gunther's avatar
Guido Gunther committed
74
75
76
77
78
79
static void
layer_surface_configure (void                         *data,
                         struct zwlr_layer_surface_v1 *surface,
                         uint32_t                      serial,
                         uint32_t                      width,
                         uint32_t                      height)
Guido Gunther's avatar
Guido Gunther committed
80
81
{
  PhoshLayerSurface *self = data;
82
  PhoshLayerSurfacePrivate *priv;
83

84
85
  g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
  priv = phosh_layer_surface_get_instance_private (self);
Guido Gunther's avatar
Guido Gunther committed
86
  gtk_window_resize (GTK_WINDOW (self), width, height);
Guido Gunther's avatar
Guido Gunther committed
87
  zwlr_layer_surface_v1_ack_configure (surface, serial);
88

89
90
91
  if (priv->configured_height != height) {
    priv->configured_height = height;
    g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_CONFIGURED_HEIGHT]);
92
93
  }

94
95
96
  if (priv->configured_width != width) {
    priv->configured_width = width;
    g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_CONFIGURED_WIDTH]);
97
98
  }

Guido Gunther's avatar
Guido Gunther committed
99
  g_debug ("Configured %p (%dx%d)", self, width, height);
100
  g_signal_emit (self, signals[CONFIGURED], 0);
Guido Gunther's avatar
Guido Gunther committed
101
102
103
}


Guido Gunther's avatar
Guido Gunther committed
104
105
106
static void
layer_surface_closed (void                         *data,
                      struct zwlr_layer_surface_v1 *surface)
Guido Gunther's avatar
Guido Gunther committed
107
108
109
110
{
  PhoshLayerSurface *self = data;
  PhoshLayerSurfacePrivate *priv = phosh_layer_surface_get_instance_private (self);

111
  g_return_if_fail (priv->layer_surface == surface);
112
  g_debug ("Destroying layer surface '%s'", priv->namespace);
Guido Gunther's avatar
Guido Gunther committed
113
  zwlr_layer_surface_v1_destroy (priv->layer_surface);
Guido Gunther's avatar
Guido Gunther committed
114
115
116
117
  priv->layer_surface = NULL;
  gtk_widget_destroy (GTK_WIDGET (self));
}

118

Guido Gunther's avatar
Guido Gunther committed
119
static struct zwlr_layer_surface_v1_listener layer_surface_listener = {
Guido Gunther's avatar
Guido Gunther committed
120
121
  .configure = layer_surface_configure,
  .closed = layer_surface_closed,
Guido Gunther's avatar
Guido Gunther committed
122
123
};

124

Guido Gunther's avatar
Guido Gunther committed
125
126
127
128
129
130
131
132
static void
phosh_layer_surface_set_property (GObject      *object,
                                  guint         property_id,
                                  const GValue *value,
                                  GParamSpec   *pspec)
{
  PhoshLayerSurface *self = PHOSH_LAYER_SURFACE (object);
  PhoshLayerSurfacePrivate *priv = phosh_layer_surface_get_instance_private (self);
133
  int width, height;
Guido Gunther's avatar
Guido Gunther committed
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148

  switch (property_id) {
  case PHOSH_LAYER_SURFACE_PROP_LAYER_SHELL:
    priv->layer_shell = g_value_get_pointer (value);
    break;
  case PHOSH_LAYER_SURFACE_PROP_WL_OUTPUT:
    priv->wl_output = g_value_get_pointer (value);
    break;
  case PHOSH_LAYER_SURFACE_PROP_ANCHOR:
    priv->anchor = g_value_get_uint (value);
    break;
  case PHOSH_LAYER_SURFACE_PROP_LAYER:
    priv->layer = g_value_get_uint (value);
    break;
  case PHOSH_LAYER_SURFACE_PROP_KBD_INTERACTIVITY:
149
    phosh_layer_surface_set_kbd_interactivity (self, g_value_get_boolean (value));
Guido Gunther's avatar
Guido Gunther committed
150
151
    break;
  case PHOSH_LAYER_SURFACE_PROP_EXCLUSIVE_ZONE:
152
    phosh_layer_surface_set_exclusive_zone (self, g_value_get_int (value));
Guido Gunther's avatar
Guido Gunther committed
153
    break;
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
  case PHOSH_LAYER_SURFACE_PROP_MARGIN_TOP:
    phosh_layer_surface_set_margins (self,
                                     g_value_get_int (value),
                                     priv->margin_right,
                                     priv->margin_bottom,
                                     priv->margin_left);
    break;
  case PHOSH_LAYER_SURFACE_PROP_MARGIN_BOTTOM:
    phosh_layer_surface_set_margins (self,
                                     priv->margin_top,
                                     priv->margin_right,
                                     g_value_get_int (value),
                                     priv->margin_left);
    break;
  case PHOSH_LAYER_SURFACE_PROP_MARGIN_LEFT:
    phosh_layer_surface_set_margins (self,
                                     priv->margin_top,
                                     priv->margin_right,
                                     priv->margin_bottom,
                                     g_value_get_int (value));
    break;
  case PHOSH_LAYER_SURFACE_PROP_MARGIN_RIGHT:
    phosh_layer_surface_set_margins (self,
                                     priv->margin_top,
                                     g_value_get_int (value),
                                     priv->margin_bottom,
                                     priv->margin_left);
    break;
Guido Gunther's avatar
Guido Gunther committed
182
  case PHOSH_LAYER_SURFACE_PROP_LAYER_WIDTH:
183
    width = g_value_get_uint (value);
Guido Gunther's avatar
Guido Gunther committed
184
    phosh_layer_surface_set_size (self, width, priv->height);
Guido Gunther's avatar
Guido Gunther committed
185
186
    break;
  case PHOSH_LAYER_SURFACE_PROP_LAYER_HEIGHT:
187
    height = g_value_get_uint (value);
Guido Gunther's avatar
Guido Gunther committed
188
    phosh_layer_surface_set_size (self, priv->width, height);
Guido Gunther's avatar
Guido Gunther committed
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
    break;
  case PHOSH_LAYER_SURFACE_PROP_NAMESPACE:
    g_free (priv->namespace);
    priv->namespace = g_value_dup_string (value);
    break;
  default:
    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
    break;
  }
}


static void
phosh_layer_surface_get_property (GObject    *object,
                                  guint       property_id,
                                  GValue     *value,
                                  GParamSpec *pspec)
{
  PhoshLayerSurface *self = PHOSH_LAYER_SURFACE (object);
  PhoshLayerSurfacePrivate *priv = phosh_layer_surface_get_instance_private (self);

  switch (property_id) {
  case PHOSH_LAYER_SURFACE_PROP_LAYER_SHELL:
    g_value_set_pointer (value, priv->layer_shell);
    break;
  case PHOSH_LAYER_SURFACE_PROP_WL_OUTPUT:
    g_value_set_pointer (value, priv->wl_output);
    break;
  case PHOSH_LAYER_SURFACE_PROP_ANCHOR:
    g_value_set_uint (value, priv->anchor);
    break;
  case PHOSH_LAYER_SURFACE_PROP_LAYER:
    g_value_set_uint (value, priv->layer);
    break;
  case PHOSH_LAYER_SURFACE_PROP_KBD_INTERACTIVITY:
    g_value_set_boolean (value, priv->kbd_interactivity);
    break;
  case PHOSH_LAYER_SURFACE_PROP_EXCLUSIVE_ZONE:
227
    g_value_set_int (value, priv->exclusive_zone);
Guido Gunther's avatar
Guido Gunther committed
228
    break;
229
230
231
232
233
234
235
236
237
238
239
240
  case PHOSH_LAYER_SURFACE_PROP_MARGIN_TOP:
    g_value_set_int (value, priv->margin_top);
    break;
  case PHOSH_LAYER_SURFACE_PROP_MARGIN_BOTTOM:
    g_value_set_int (value, priv->margin_bottom);
    break;
  case PHOSH_LAYER_SURFACE_PROP_MARGIN_LEFT:
    g_value_set_int (value, priv->margin_left);
    break;
  case PHOSH_LAYER_SURFACE_PROP_MARGIN_RIGHT:
    g_value_set_int (value, priv->margin_right);
    break;
Guido Gunther's avatar
Guido Gunther committed
241
242
243
244
245
246
  case PHOSH_LAYER_SURFACE_PROP_LAYER_WIDTH:
    g_value_set_uint (value, priv->width);
    break;
  case PHOSH_LAYER_SURFACE_PROP_LAYER_HEIGHT:
    g_value_set_uint (value, priv->height);
    break;
247
248
249
250
251
252
  case PHOSH_LAYER_SURFACE_PROP_CONFIGURED_WIDTH:
    g_value_set_uint (value, priv->configured_width);
    break;
  case PHOSH_LAYER_SURFACE_PROP_CONFIGURED_HEIGHT:
    g_value_set_uint (value, priv->configured_height);
    break;
Guido Gunther's avatar
Guido Gunther committed
253
254
255
256
257
258
259
260
261
262
263
  case PHOSH_LAYER_SURFACE_PROP_NAMESPACE:
    g_value_set_string (value, priv->namespace);
    break;
  default:
    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
    break;
  }
}


static void
264
on_phosh_layer_surface_realized (PhoshLayerSurface *self, gpointer unused)
Guido Gunther's avatar
Guido Gunther committed
265
{
266
  PhoshLayerSurfacePrivate *priv;
Guido Gunther's avatar
Guido Gunther committed
267
268
  GdkWindow *gdk_window;

269
  g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
Guido Gunther's avatar
Guido Gunther committed
270

271
  priv = phosh_layer_surface_get_instance_private (self);
Guido Gunther's avatar
Guido Gunther committed
272
273
274

  gdk_window = gtk_widget_get_window (GTK_WIDGET (self));
  gdk_wayland_window_set_use_custom_surface (gdk_window);
275
  priv->wl_surface = gdk_wayland_window_get_wl_surface (gdk_window);
276

277
278
  gtk_window_set_decorated (GTK_WINDOW (self), FALSE);
}
279

280
281
282
283
284
285
286
287
288
289
290

static void
on_phosh_layer_surface_mapped (PhoshLayerSurface *self, gpointer unused)
{
  PhoshLayerSurfacePrivate *priv;
  GdkWindow *gdk_window;

  g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
  priv = phosh_layer_surface_get_instance_private (self);

  if (!priv->wl_surface) {
Guido Gunther's avatar
Guido Gunther committed
291
292
293
    gdk_window = gtk_widget_get_window (GTK_WIDGET (self));
    gdk_wayland_window_set_use_custom_surface (gdk_window);
    priv->wl_surface = gdk_wayland_window_get_wl_surface (gdk_window);
294
295
  }
  g_debug ("Mapped %p", priv->wl_surface);
Guido Gunther's avatar
Guido Gunther committed
296

Guido Gunther's avatar
Guido Gunther committed
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
  priv->layer_surface = zwlr_layer_shell_v1_get_layer_surface (priv->layer_shell,
                                                               priv->wl_surface,
                                                               priv->wl_output,
                                                               priv->layer,
                                                               priv->namespace);
  zwlr_layer_surface_v1_set_exclusive_zone (priv->layer_surface, priv->exclusive_zone);
  zwlr_layer_surface_v1_set_size (priv->layer_surface, priv->width, priv->height);
  zwlr_layer_surface_v1_set_anchor (priv->layer_surface, priv->anchor);
  zwlr_layer_surface_v1_set_margin (priv->layer_surface,
                                    priv->margin_top,
                                    priv->margin_right,
                                    priv->margin_bottom,
                                    priv->margin_left);
  zwlr_layer_surface_v1_set_keyboard_interactivity (priv->layer_surface, priv->kbd_interactivity);
  zwlr_layer_surface_v1_add_listener (priv->layer_surface,
                                      &layer_surface_listener,
                                      self);
  wl_surface_commit (priv->wl_surface);
315

316
317
318
  /* Process all pending events, otherwise we end up sending ack configure
   * to a not yet configured surface */
  wl_display_roundtrip (gdk_wayland_display_get_wl_display (gdk_display_get_default ()));
Guido Gunther's avatar
Guido Gunther committed
319
320
}

321

322
static void
323
on_phosh_layer_surface_unmapped (PhoshLayerSurface *self, gpointer unused)
324
{
325
  PhoshLayerSurfacePrivate *priv;
326

327
328
329
330
  g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
  priv = phosh_layer_surface_get_instance_private (self);

  if (priv->layer_surface) {
Guido Gunther's avatar
Guido Gunther committed
331
    zwlr_layer_surface_v1_destroy (priv->layer_surface);
332
333
334
335
    priv->layer_surface = NULL;
  }
  priv->wl_surface = NULL;
}
336

337

338
339
340
341
342
343
344
345
346
347
348
static void
phosh_layer_surface_constructed (GObject *object)
{
  PhoshLayerSurface *self = PHOSH_LAYER_SURFACE (object);

  g_signal_connect (self, "realize",
                    G_CALLBACK (on_phosh_layer_surface_realized),
                    NULL);
  g_signal_connect (self, "map",
                    G_CALLBACK (on_phosh_layer_surface_mapped),
                    NULL);
349
350
351
  g_signal_connect (self, "unmap",
                    G_CALLBACK (on_phosh_layer_surface_unmapped),
                    NULL);
352
353

  G_OBJECT_CLASS (phosh_layer_surface_parent_class)->constructed (object);
354
355
356
}


Guido Gunther's avatar
Guido Gunther committed
357
358
359
360
361
362
363
static void
phosh_layer_surface_dispose (GObject *object)
{
  PhoshLayerSurface *self = PHOSH_LAYER_SURFACE (object);
  PhoshLayerSurfacePrivate *priv = phosh_layer_surface_get_instance_private (self);

  if (priv->layer_surface) {
Guido Gunther's avatar
Guido Gunther committed
364
    zwlr_layer_surface_v1_destroy (priv->layer_surface);
Guido Gunther's avatar
Guido Gunther committed
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
    priv->layer_surface = NULL;
  }
  g_clear_pointer (&priv->namespace, g_free);

  G_OBJECT_CLASS (phosh_layer_surface_parent_class)->dispose (object);
}


static void
phosh_layer_surface_class_init (PhoshLayerSurfaceClass *klass)
{
  GObjectClass *object_class = (GObjectClass *)klass;

  object_class->constructed = phosh_layer_surface_constructed;
  object_class->dispose = phosh_layer_surface_dispose;

  object_class->set_property = phosh_layer_surface_set_property;
  object_class->get_property = phosh_layer_surface_get_property;

  props[PHOSH_LAYER_SURFACE_PROP_LAYER_SHELL] =
    g_param_spec_pointer (
      "layer-shell",
      "Wayland Layer Shell Global",
      "The layer shell wayland global",
389
      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
Guido Gunther's avatar
Guido Gunther committed
390
391
392
393
394
395

  props[PHOSH_LAYER_SURFACE_PROP_WL_OUTPUT] =
    g_param_spec_pointer (
      "wl-output",
      "Wayland Output",
      "The wl_output associated with this surface",
396
      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
Guido Gunther's avatar
Guido Gunther committed
397
398
399
400
401

  props[PHOSH_LAYER_SURFACE_PROP_ANCHOR] =
    g_param_spec_uint (
      "anchor",
      "Anchor edges",
Guido Gunther's avatar
Guido Gunther committed
402
      "The edges to anchor the surface to",
Guido Gunther's avatar
Guido Gunther committed
403
404
405
      0,
      G_MAXUINT,
      0,
406
      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
Guido Gunther's avatar
Guido Gunther committed
407
408
409
410
411
412
413
414
415

  props[PHOSH_LAYER_SURFACE_PROP_LAYER] =
    g_param_spec_uint (
      "layer",
      "Layer",
      "The layer the surface should be attached to",
      0,
      G_MAXUINT,
      0,
416
      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
Guido Gunther's avatar
Guido Gunther committed
417
418
419
420
421

  props[PHOSH_LAYER_SURFACE_PROP_KBD_INTERACTIVITY] =
    g_param_spec_boolean (
      "kbd-interactivity",
      "Keyboard interactivity",
Guido Gunther's avatar
Guido Gunther committed
422
      "Whether the surface interacts with the keyboard",
Guido Gunther's avatar
Guido Gunther committed
423
      FALSE,
424
      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
Guido Gunther's avatar
Guido Gunther committed
425
426
427
428
429
430
431
432
433

  props[PHOSH_LAYER_SURFACE_PROP_EXCLUSIVE_ZONE] =
    g_param_spec_int (
      "exclusive-zone",
      "Exclusive Zone",
      "Set area that is not occluded with other surfaces",
      -1,
      G_MAXINT,
      0,
434
      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
Guido Gunther's avatar
Guido Gunther committed
435

436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
  props[PHOSH_LAYER_SURFACE_PROP_MARGIN_LEFT] =
    g_param_spec_int (
      "margin-left",
      "Left margin",
      "Distance away from the left anchor point",
      G_MININT,
      G_MAXINT,
      0,
      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);

  props[PHOSH_LAYER_SURFACE_PROP_MARGIN_RIGHT] =
    g_param_spec_int (
      "margin-right",
      "Right margin",
      "Distance away from the right anchor point",
      G_MININT,
      G_MAXINT,
      0,
      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);

  props[PHOSH_LAYER_SURFACE_PROP_MARGIN_TOP] =
    g_param_spec_int (
      "margin-top",
      "Top margin",
      "Distance away from the top anchor point",
      G_MININT,
      G_MAXINT,
      0,
      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);

  props[PHOSH_LAYER_SURFACE_PROP_MARGIN_BOTTOM] =
    g_param_spec_int (
      "margin-bottom",
      "Bottom margin",
      "Distance away from the bottom anchor point",
      G_MININT,
      G_MAXINT,
      0,
      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);

Guido Gunther's avatar
Guido Gunther committed
476
477
478
479
480
481
482
483
  props[PHOSH_LAYER_SURFACE_PROP_LAYER_WIDTH] =
    g_param_spec_uint (
      "width",
      "Width",
      "The width of the layer surface",
      0,
      G_MAXUINT,
      0,
484
      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
Guido Gunther's avatar
Guido Gunther committed
485
486
487
488
489
490
491
492
493

  props[PHOSH_LAYER_SURFACE_PROP_LAYER_HEIGHT] =
    g_param_spec_uint (
      "height",
      "Height",
      "The height of the layer surface",
      0,
      G_MAXUINT,
      0,
494
      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
Guido Gunther's avatar
Guido Gunther committed
495

496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516

  props[PHOSH_LAYER_SURFACE_PROP_CONFIGURED_WIDTH] =
    g_param_spec_uint (
      "configured-width",
      "Configured width",
      "The width of the layer surface set by the compositor",
      0,
      G_MAXUINT,
      0,
      G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);

  props[PHOSH_LAYER_SURFACE_PROP_CONFIGURED_HEIGHT] =
    g_param_spec_uint (
      "configured-height",
      "Configured height",
      "The height of the layer surface set by the compositor",
      0,
      G_MAXUINT,
      0,
      G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);

Guido Gunther's avatar
Guido Gunther committed
517
518
519
520
521
522
  props[PHOSH_LAYER_SURFACE_PROP_NAMESPACE] =
    g_param_spec_string (
      "namespace",
      "Namespace",
      "Namespace of the layer surface",
      "",
523
      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
Guido Gunther's avatar
Guido Gunther committed
524
525

  g_object_class_install_properties (object_class, PHOSH_LAYER_SURFACE_PROP_LAST_PROP, props);
526
527

  /**
528
529
   * PhoshLayerSurface::configured
   * @self: The #PhoshLayerSurface instance.
530
531
532
533
534
535
536
537
538
539
540
   *
   * This signal is emitted once we received the configure event from the
   * compositor.
   */
  signals[CONFIGURED] =
    g_signal_new ("configured",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (PhoshLayerSurfaceClass, configured),
                  NULL, NULL, NULL,
                  G_TYPE_NONE, 0);
Guido Gunther's avatar
Guido Gunther committed
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
}


static void
phosh_layer_surface_init (PhoshLayerSurface *self)
{
}


GtkWidget *
phosh_layer_surface_new (gpointer layer_shell,
                         gpointer wl_output)
{
  return g_object_new (PHOSH_TYPE_LAYER_SURFACE,
                       "layer-shell", layer_shell,
556
557
                       "wl-output", wl_output,
                       NULL);
Guido Gunther's avatar
Guido Gunther committed
558
}
559

560

561
562
/**
 * phosh_layer_surface_get_surface:
563
 * @self: The #PhoshLayerSurface
564
565
566
567
 *
 * Get the layer layer surface or #NULL if the window
 * is not yet realized.
 */
568
struct zwlr_layer_surface_v1 *
Guido Gunther's avatar
Guido Gunther committed
569
phosh_layer_surface_get_layer_surface (PhoshLayerSurface *self)
570
571
572
573
574
575
576
577
578
{
  PhoshLayerSurfacePrivate *priv;

  g_return_val_if_fail (PHOSH_IS_LAYER_SURFACE (self), NULL);
  priv = phosh_layer_surface_get_instance_private (self);
  return priv->layer_surface;
}


579
580
/**
 * phosh_layer_surface_get_wl_surface:
581
 * @self: The #PhoshLayerSurface
582
583
584
585
 *
 * Get the layer wayland surface or #NULL if the window
 * is not yet realized.
 */
586
struct wl_surface *
Guido Gunther's avatar
Guido Gunther committed
587
phosh_layer_surface_get_wl_surface (PhoshLayerSurface *self)
588
589
590
591
592
593
594
{
  PhoshLayerSurfacePrivate *priv;

  g_return_val_if_fail (PHOSH_IS_LAYER_SURFACE (self), NULL);
  priv = phosh_layer_surface_get_instance_private (self);
  return priv->wl_surface;
}
595

596

597
598
/**
 * phosh_layer_surface_set_size:
599
600
601
 * @self: The #PhoshLayerSurface
 * @width: the height in pixels
 * @height: the width in pixels
602
603
604
605
 *
 * Set the size of a layer surface. A value of '-1' indicates 'use old value'
 */
void
606
phosh_layer_surface_set_size (PhoshLayerSurface *self, int width, int height)
607
608
{
  PhoshLayerSurfacePrivate *priv;
609
  int old_width, old_height;
610
611
612
613
614
615
616

  g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
  priv = phosh_layer_surface_get_instance_private (self);

  if (priv->height == height && priv->width == width)
    return;

617
618
619
  old_width = priv->width;
  old_height = priv->height;

620
621
622
623
624
625
  if (width != -1)
    priv->width = width;

  if (height != -1)
    priv->height = height;

626
  if (gtk_widget_get_mapped (GTK_WIDGET (self))) {
Guido Gunther's avatar
Guido Gunther committed
627
    zwlr_layer_surface_v1_set_size (priv->layer_surface, priv->width, priv->height);
628
  }
629
630
631
632
633
634

  if (priv->height != old_height)
    g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_LAYER_HEIGHT]);

  if (priv->width != old_width)
    g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_LAYER_WIDTH]);
635
}
636

637

638
639
/**
 * phosh_layer_surface_set_margins:
640
641
642
643
644
 * @self: The #PhoshLayerSurface
 * @top: the top margin in pixels
 * @right: the right margin in pixels
 * @bottom: the bottom margin in pixels
 * @left: the left margin in pixels
645
646
647
648
 *
 * Set anchor margins of a layer surface.
 */
void
649
phosh_layer_surface_set_margins (PhoshLayerSurface *self, int top, int right, int bottom, int left)
650
651
{
  PhoshLayerSurfacePrivate *priv;
652
  int old_top, old_bottom, old_left, old_right;
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670

  g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
  priv = phosh_layer_surface_get_instance_private (self);

  old_top = priv->margin_top;
  old_left = priv->margin_left;
  old_right = priv->margin_right;
  old_bottom = priv->margin_bottom;

  if (old_top == top && old_left == left && old_right == right && old_bottom == bottom)
    return;

  priv->margin_top = top;
  priv->margin_left = left;
  priv->margin_right = right;
  priv->margin_bottom = bottom;

  if (priv->layer_surface)
Guido Gunther's avatar
Guido Gunther committed
671
    zwlr_layer_surface_v1_set_margin (priv->layer_surface, top, right, bottom, left);
672
673
674
675
676
677
678
679
680
681

  if (old_top != top)
    g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_MARGIN_TOP]);
  if (old_bottom != bottom)
    g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_MARGIN_BOTTOM]);
  if (old_left != left)
    g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_MARGIN_LEFT]);
  if (old_right != right)
    g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_MARGIN_RIGHT]);
}
682

683

684
685
/**
 * phosh_layer_surface_set_exclusive_zone:
686
687
 * @self: The #PhoshLayerSurface
 * @zone: Size of the exclusive zone.
688
689
690
691
 *
 * Set exclusive zone of a layer surface.
 */
void
692
phosh_layer_surface_set_exclusive_zone (PhoshLayerSurface *self, int zone)
693
694
{
  PhoshLayerSurfacePrivate *priv;
695
  int old_zone;
696
697
698
699
700
701
702
703
704
705
706
707

  g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
  priv = phosh_layer_surface_get_instance_private (self);

  old_zone = priv->exclusive_zone;

  if (old_zone == zone)
    return;

  priv->exclusive_zone = zone;

  if (priv->layer_surface)
Guido Gunther's avatar
Guido Gunther committed
708
    zwlr_layer_surface_v1_set_exclusive_zone (priv->layer_surface, zone);
709
710
711

  g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_EXCLUSIVE_ZONE]);
}
712

713

714
715
/**
 * phosh_layer_surface_set_keyboard_interactivity:
716
717
 * @self: The #PhoshLayerSurface
 * @interactivity: %TRUE if the #PhoshLayerSurface should receive keyboard input.
718
719
720
721
722
723
724
725
726
727
728
 *
 * Set keyboard ineractivity a layer surface.
 */
void
phosh_layer_surface_set_kbd_interactivity (PhoshLayerSurface *self, gboolean interactivity)
{
  PhoshLayerSurfacePrivate *priv;

  g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
  priv = phosh_layer_surface_get_instance_private (self);

Guido Gunther's avatar
Guido Gunther committed
729
  if (priv->kbd_interactivity == interactivity)
730
731
732
733
734
735
736
737
738
    return;

  priv->kbd_interactivity = interactivity;

  if (priv->layer_surface)
    zwlr_layer_surface_v1_set_keyboard_interactivity (priv->layer_surface, interactivity);

  g_object_notify_by_pspec (G_OBJECT (self), props[PHOSH_LAYER_SURFACE_PROP_KBD_INTERACTIVITY]);
}
739

740

741
742
/**
 * phosh_layer_surface_wl_surface_commit:
743
 * @self: The #PhoshLayerSurface
744
745
746
747
748
749
750
751
752
753
754
755
756
757
 *
 * Forces a commit of layer surface's state.
 */
void
phosh_layer_surface_wl_surface_commit (PhoshLayerSurface *self)
{
  PhoshLayerSurfacePrivate *priv;

  g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
  priv = phosh_layer_surface_get_instance_private (self);

  if (priv->wl_surface)
    wl_surface_commit (priv->wl_surface);
}