layersurface.c 23.1 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 331
  g_return_if_fail (PHOSH_IS_LAYER_SURFACE (self));
  priv = phosh_layer_surface_get_instance_private (self);

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

338

339 340 341 342 343 344 345 346 347 348 349
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);
350 351 352
  g_signal_connect (self, "unmap",
                    G_CALLBACK (on_phosh_layer_surface_unmapped),
                    NULL);
353 354

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


Guido Gunther's avatar
Guido Gunther committed
358 359 360 361 362 363 364
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
365
    zwlr_layer_surface_v1_destroy (priv->layer_surface);
Guido Gunther's avatar
Guido Gunther committed
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
    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",
390
      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
Guido Gunther's avatar
Guido Gunther committed
391 392 393 394 395 396

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

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

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

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

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

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

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

  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
518 519 520 521 522 523
  props[PHOSH_LAYER_SURFACE_PROP_NAMESPACE] =
    g_param_spec_string (
      "namespace",
      "Namespace",
      "Namespace of the layer surface",
      "",
524
      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
Guido Gunther's avatar
Guido Gunther committed
525 526

  g_object_class_install_properties (object_class, PHOSH_LAYER_SURFACE_PROP_LAST_PROP, props);
527 528

  /**
529 530
   * PhoshLayerSurface::configured
   * @self: The #PhoshLayerSurface instance.
531 532 533 534 535 536 537 538 539 540 541
   *
   * 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
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556
}


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,
557 558
                       "wl-output", wl_output,
                       NULL);
Guido Gunther's avatar
Guido Gunther committed
559
}
560

561

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


580 581
/**
 * phosh_layer_surface_get_wl_surface:
582
 * @self: The #PhoshLayerSurface
583 584 585 586
 *
 * Get the layer wayland surface or #NULL if the window
 * is not yet realized.
 */
587
struct wl_surface *
Guido Gunther's avatar
Guido Gunther committed
588
phosh_layer_surface_get_wl_surface (PhoshLayerSurface *self)
589 590 591 592 593 594 595
{
  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;
}
596

597

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

  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;

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

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

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

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

  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]);
636
}
637

638

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

  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
672
    zwlr_layer_surface_v1_set_margin (priv->layer_surface, top, right, bottom, left);
673 674 675 676 677 678 679 680 681 682

  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]);
}
683

684

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

  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
709
    zwlr_layer_surface_v1_set_exclusive_zone (priv->layer_surface, zone);
710 711 712

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

714

715 716
/**
 * phosh_layer_surface_set_keyboard_interactivity:
717 718
 * @self: The #PhoshLayerSurface
 * @interactivity: %TRUE if the #PhoshLayerSurface should receive keyboard input.
719 720 721 722 723 724 725 726 727 728 729
 *
 * 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
730
  if (priv->kbd_interactivity == interactivity)
731 732 733 734 735 736 737 738 739
    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]);
}
740

741

742 743
/**
 * phosh_layer_surface_wl_surface_commit:
744
 * @self: The #PhoshLayerSurface
745 746 747 748 749 750 751 752 753 754 755 756 757 758
 *
 * 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);
}