background-manager.c 6.15 KB
Newer Older
1 2
/*
 * Copyright (C) 2018 Purism SPC
3 4 5
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 *
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 * Author: Guido Günther <agx@sigxcpu.org>
 */

#define G_LOG_DOMAIN "phosh-background-manager"

#include "background-manager.h"
#include "background.h"
#include "monitor/monitor.h"
#include "phosh-wayland.h"
#include "shell.h"
#include "util.h"

#include <gdk/gdkwayland.h>

/**
21
 * SECTION:background-manager
22 23 24 25 26 27 28
 * @short_description: Tracks screen related events and updates
 * backgrounds accordingly.
 * @Title: PhoshBackgroundManager
 */

struct _PhoshBackgroundManager {
  GObject parent;
29 30 31

  PhoshMonitor *primary_monitor;
  GHashTable   *backgrounds;
32 33
};

34

35 36 37 38 39 40 41 42 43 44 45 46
G_DEFINE_TYPE (PhoshBackgroundManager, phosh_background_manager, G_TYPE_OBJECT);


static PhoshBackground *
create_background_for_monitor (PhoshBackgroundManager *self, PhoshMonitor *monitor)
{
  PhoshWayland *wl = phosh_wayland_get_default();
  PhoshBackground *background;

  background = g_object_ref_sink(PHOSH_BACKGROUND (phosh_background_new (
                                                     phosh_wayland_get_zwlr_layer_shell_v1(wl),
                                                     monitor->wl_output,
47
                                                     MAX(1, monitor->scale),
48
                                                     monitor == self->primary_monitor)));
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
  g_hash_table_insert (self->backgrounds,
                       g_object_ref (monitor),
                       background);
  return background;
}


static void
on_monitor_removed (PhoshBackgroundManager *self,
                    PhoshMonitor           *monitor,
                    PhoshMonitorManager    *monitormanager)
{
  g_return_if_fail (PHOSH_IS_BACKGROUND_MANAGER (self));
  g_return_if_fail (PHOSH_IS_MONITOR (monitor));

  g_debug ("Monitor %p removed", monitor);
  g_return_if_fail (g_hash_table_remove (self->backgrounds, monitor));
}


static void
on_monitor_configured (PhoshBackgroundManager *self,
71
                       PhoshMonitor           *monitor)
72
{
73 74
  PhoshBackground *background;

75
  g_return_if_fail (PHOSH_IS_MONITOR (monitor));
76 77 78 79 80
  g_debug ("Monitor %p (%s) configured", monitor, monitor->name);

  background = g_hash_table_lookup (self->backgrounds, monitor);
  g_return_if_fail (background);

81
  phosh_background_set_scale (background, monitor->scale);
82
  gtk_widget_show (GTK_WIDGET (background));
83 84
}

85

86 87 88 89 90 91 92 93 94 95
static void
on_monitor_added (PhoshBackgroundManager *self,
                  PhoshMonitor           *monitor,
                  PhoshMonitorManager    *unused)
{
  g_return_if_fail (PHOSH_IS_BACKGROUND_MANAGER (self));
  g_return_if_fail (PHOSH_IS_MONITOR (monitor));

  g_debug ("Monitor %p added", monitor);

96
  create_background_for_monitor (self, monitor);
97

98 99 100 101
  g_signal_connect_object (monitor, "configured",
                           G_CALLBACK (on_monitor_configured),
                           self,
                           G_CONNECT_SWAPPED);
102 103
  if (phosh_monitor_is_configured (monitor))
    on_monitor_configured (self, monitor);
104 105 106 107 108 109 110 111
}


static void
on_primary_monitor_changed (PhoshBackgroundManager *self,
                            GParamSpec *pspec,
                            PhoshShell *shell)
{
112 113 114
  PhoshBackground *background;
  PhoshMonitor *monitor;

115 116 117
  g_return_if_fail (PHOSH_IS_BACKGROUND_MANAGER (self));
  g_return_if_fail (PHOSH_IS_SHELL (shell));

118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
  monitor = phosh_shell_get_primary_monitor (shell);
  if (monitor == self->primary_monitor)
    return;

  if (self->primary_monitor) {
    background = g_hash_table_lookup (self->backgrounds, self->primary_monitor);
    if (background)
      phosh_background_set_primary (background, FALSE);
  }

  if (monitor) {
    g_clear_object (&self->primary_monitor);
    self->primary_monitor = g_object_ref (monitor);
    background = g_hash_table_lookup (self->backgrounds, monitor);
    if (background)
      phosh_background_set_primary (background, TRUE);
  }
135 136 137 138 139 140 141 142 143
}


static void
phosh_background_manager_dispose (GObject *object)
{
  PhoshBackgroundManager *self = PHOSH_BACKGROUND_MANAGER (object);

  g_hash_table_destroy (self->backgrounds);
144
  g_clear_object (&self->primary_monitor);
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
  G_OBJECT_CLASS (phosh_background_manager_parent_class)->dispose (object);
}


static void
phosh_background_manager_constructed (GObject *object)
{
  PhoshBackgroundManager *self = PHOSH_BACKGROUND_MANAGER (object);
  PhoshShell *shell = phosh_shell_get_default ();
  PhoshMonitorManager *monitor_manager = phosh_shell_get_monitor_manager (shell);

  G_OBJECT_CLASS (phosh_background_manager_parent_class)->constructed (object);

  /* Listen for monitor changes */
  g_signal_connect_object (monitor_manager, "monitor-added",
                           G_CALLBACK (on_monitor_added),
                           self,
                           G_CONNECT_SWAPPED);
  g_signal_connect_object (monitor_manager, "monitor-removed",
                           G_CALLBACK (on_monitor_removed),
                           self,
                           G_CONNECT_SWAPPED);
  g_signal_connect_object (shell, "notify::primary-monitor",
                           G_CALLBACK (on_primary_monitor_changed),
                           self,
                           G_CONNECT_SWAPPED);
171
  self->primary_monitor = g_object_ref (phosh_shell_get_primary_monitor (shell));
172

173 174 175 176
  /* catch up with monitors already present */
  for (int i = 0; i < phosh_monitor_manager_get_num_monitors (monitor_manager); i++) {
    PhoshMonitor *monitor = phosh_monitor_manager_get_monitor (monitor_manager, i);

177 178
    on_monitor_added (self, monitor, NULL);
  }
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
}


static void
phosh_background_manager_class_init (PhoshBackgroundManagerClass *klass)
{
  GObjectClass *object_class = G_OBJECT_CLASS (klass);

  object_class->constructed = phosh_background_manager_constructed;
  object_class->dispose = phosh_background_manager_dispose;
}


static void
phosh_background_manager_init (PhoshBackgroundManager *self)
{
  self->backgrounds = g_hash_table_new_full (g_direct_hash,
                                             g_direct_equal,
                                             g_object_unref,
                                             (GDestroyNotify)gtk_widget_destroy);
}


PhoshBackgroundManager *
phosh_background_manager_new (void)
{
  return g_object_new (PHOSH_TYPE_BACKGROUND_MANAGER, NULL);
}