Commit 8b10355f authored by Guido Gunther's avatar Guido Gunther Committed by Guido Gunther
Browse files

PhoshBackgroundManager: Add manager to handle multiple outputs



This handles multiple output making sure we update the backgrounds
on output changes.

Closes: #113
Signed-off-by: Guido Gunther's avatarGuido Günther <guido.gunther@puri.sm>
parent da8734ff
/*
* Copyright (C) 2018 Purism SPC
* SPDX-License-Identifier: GPL-3.0+
* 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>
/**
* SECTION:phosh-background-manager
* @short_description: Tracks screen related events and updates
* backgrounds accordingly.
* @Title: PhoshBackgroundManager
*/
struct _PhoshBackgroundManager {
GObject parent;
GHashTable *backgrounds;
};
G_DEFINE_TYPE (PhoshBackgroundManager, phosh_background_manager, G_TYPE_OBJECT);
static PhoshBackground *
create_background_for_monitor (PhoshBackgroundManager *self, PhoshMonitor *monitor)
{
PhoshShell *shell = phosh_shell_get_default ();
PhoshWayland *wl = phosh_wayland_get_default();
PhoshMonitor *primary_monitor;
PhoshBackground *background;
primary_monitor = phosh_shell_get_primary_monitor (shell);
background = g_object_ref_sink(PHOSH_BACKGROUND (phosh_background_new (
phosh_wayland_get_zwlr_layer_shell_v1(wl),
monitor->wl_output,
monitor->width,
monitor->height,
monitor == primary_monitor)));
g_hash_table_insert (self->backgrounds,
g_object_ref (monitor),
background);
gtk_widget_show (GTK_WIDGET (background));
return background;
}
static void
create_all_backgrounds (PhoshBackgroundManager *self)
{
PhoshShell *shell = phosh_shell_get_default ();
PhoshMonitorManager *monitor_manager = phosh_shell_get_monitor_manager (shell);
g_hash_table_remove_all (self->backgrounds);
for (int i = 0; i < phosh_monitor_manager_get_num_monitors (monitor_manager); i++) {
PhoshMonitor *monitor = phosh_monitor_manager_get_monitor (monitor_manager, i);
create_background_for_monitor (self, monitor);
}
}
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,
PhoshMonitor *monitor)
{
create_background_for_monitor (self, monitor);
g_signal_handlers_disconnect_by_func (monitor, on_monitor_configured, self);
}
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);
g_signal_connect_object (monitor, "configured",
G_CALLBACK (on_monitor_configured),
self,
G_CONNECT_SWAPPED);
}
static void
on_primary_monitor_changed (PhoshBackgroundManager *self,
GParamSpec *pspec,
PhoshShell *shell)
{
g_return_if_fail (PHOSH_IS_BACKGROUND_MANAGER (self));
g_return_if_fail (PHOSH_IS_SHELL (shell));
create_all_backgrounds (self);
}
static void
phosh_background_manager_dispose (GObject *object)
{
PhoshBackgroundManager *self = PHOSH_BACKGROUND_MANAGER (object);
g_hash_table_destroy (self->backgrounds);
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);
create_all_backgrounds (self);
}
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);
}
/*
* Copyright (C) 2019 Purism SPC
*
* SPDX-License-Identifier: GPL-3.0+
*/
#pragma once
#include <gtk/gtk.h>
#define PHOSH_TYPE_BACKGROUND_MANAGER (phosh_background_manager_get_type())
G_DECLARE_FINAL_TYPE (PhoshBackgroundManager,
phosh_background_manager,
PHOSH,
BACKGROUND_MANAGER,
GObject)
PhoshBackgroundManager *phosh_background_manager_new (void);
......@@ -22,6 +22,15 @@
#include <math.h>
#include <string.h>
enum {
PROP_0,
PROP_PRIMARY,
PROP_LAST_PROP
};
static GParamSpec *props[PROP_LAST_PROP];
enum {
BACKGROUND_LOADED,
N_SIGNALS
......@@ -35,12 +44,51 @@ struct _PhoshBackground
gchar *uri;
GDesktopBackgroundStyle style;
gboolean primary;
GdkPixbuf *pixbuf;
GSettings *settings;
};
G_DEFINE_TYPE (PhoshBackground, phosh_background, PHOSH_TYPE_LAYER_SURFACE)
G_DEFINE_TYPE (PhoshBackground, phosh_background, PHOSH_TYPE_LAYER_SURFACE);
static void
phosh_background_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
PhoshBackground *self = PHOSH_BACKGROUND (object);
switch (property_id) {
case PROP_PRIMARY:
phosh_background_set_primary (self, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
phosh_background_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
PhoshBackground *self = PHOSH_BACKGROUND (object);
switch (property_id) {
case PROP_PRIMARY:
g_value_set_boolean (value, self->primary);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static GdkPixbuf *
......@@ -172,7 +220,11 @@ load_background (PhoshBackground *self)
if (!image)
image = gdk_pixbuf_new_from_xpm_data (xpm_data);
phosh_shell_get_usable_area (phosh_shell_get_default (), NULL, NULL, &width, &height);
if (self->primary)
phosh_shell_get_usable_area (phosh_shell_get_default (), NULL, NULL, &width, &height);
else
g_object_get (self, "width", &width, "height", &height, NULL);
self->pixbuf = image_background (image, width, height, self->style);
/* force background redraw */
......@@ -186,12 +238,14 @@ background_draw_cb (PhoshBackground *self,
cairo_t *cr,
gpointer data)
{
gint x, y;
gint x = 0, y = 0;
g_return_val_if_fail (PHOSH_IS_BACKGROUND (self), TRUE);
g_return_val_if_fail (GDK_IS_PIXBUF (self->pixbuf), TRUE);
phosh_shell_get_usable_area (phosh_shell_get_default (), &x, &y, NULL, NULL);
if (self->primary)
phosh_shell_get_usable_area (phosh_shell_get_default (), &x, &y, NULL, NULL);
gdk_cairo_set_source_pixbuf (cr, self->pixbuf, x, y);
cairo_paint (cr);
return TRUE;
......@@ -285,6 +339,26 @@ phosh_background_class_init (PhoshBackgroundClass *klass)
object_class->constructed = phosh_background_constructed;
object_class->finalize = phosh_background_finalize;
object_class->set_property = phosh_background_set_property;
object_class->get_property = phosh_background_get_property;
/**
* PhoshBackground:primary:
*
* Whether this is the background for the primary monitor.
*/
props[PROP_PRIMARY] =
g_param_spec_boolean ("primary",
"Primary",
"Primary monitor",
FALSE,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS |
G_PARAM_EXPLICIT_NOTIFY |
G_PARAM_CONSTRUCT);
g_object_class_install_properties (object_class, PROP_LAST_PROP, props);
}
......@@ -298,7 +372,8 @@ GtkWidget *
phosh_background_new (gpointer layer_shell,
gpointer wl_output,
guint width,
guint height)
guint height,
gboolean primary)
{
return g_object_new (PHOSH_TYPE_BACKGROUND,
"layer-shell", layer_shell,
......@@ -313,5 +388,21 @@ phosh_background_new (gpointer layer_shell,
"kbd-interactivity", FALSE,
"exclusive-zone", -1,
"namespace", "phosh background",
"primary", primary,
NULL);
}
void
phosh_background_set_primary (PhoshBackground *self, gboolean primary)
{
if (self->primary == primary)
return;
self->primary = primary;
if (self->uri)
load_background (self);
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PRIMARY]);
}
......@@ -6,11 +6,19 @@
#pragma once
#include <gtk/gtk.h>
#include "layersurface.h"
#include "monitor/monitor.h"
#include <gtk/gtk.h>
#define PHOSH_TYPE_BACKGROUND (phosh_background_get_type())
G_DECLARE_FINAL_TYPE (PhoshBackground, phosh_background, PHOSH, BACKGROUND, PhoshLayerSurface)
GtkWidget *phosh_background_new (gpointer layer_shell, gpointer wl_output, guint width, guint height);
GtkWidget *phosh_background_new (gpointer layer_shell,
gpointer wl_output,
guint width,
guint height,
gboolean primary);
void phosh_background_set_primary (PhoshBackground *self, gboolean primary);
......@@ -27,6 +27,8 @@ phosh_sources = [
'polkit-auth-prompt.h',
'background.c',
'background.h',
'background-manager.c',
'background-manager.h',
'batteryinfo.c',
'batteryinfo.h',
'favorites.c',
......
......@@ -23,7 +23,7 @@
#include "shell.h"
#include "batteryinfo.h"
#include "background.h"
#include "background-manager.h"
#include "favorites.h"
#include "home.h"
#include "idle-manager.h"
......@@ -62,10 +62,10 @@ typedef struct
{
PhoshLayerSurface *panel;
PhoshLayerSurface *home;
PhoshLayerSurface *background;
struct popup *favorites;
struct popup *settings;
PhoshBackgroundManager *background_manager;
PhoshMonitor *primary_monitor;
PhoshMonitorManager *monitor_manager;
PhoshLockscreenManager *lockscreen_manager;
......@@ -376,24 +376,6 @@ panels_dispose (PhoshShell *self)
}
static void
background_create (PhoshShell *self)
{
PhoshWayland *wl = phosh_wayland_get_default();
PhoshShellPrivate *priv = phosh_shell_get_instance_private (self);
PhoshMonitor *monitor;
monitor = phosh_shell_get_primary_monitor (self);
g_return_if_fail (monitor);
/* background spans the whole monitor */
priv->background = PHOSH_LAYER_SURFACE (phosh_background_new (
phosh_wayland_get_zwlr_layer_shell_v1(wl),
monitor->wl_output, monitor->width, monitor->height));
gtk_widget_show (GTK_WIDGET (priv->background));
}
static void
css_setup (PhoshShell *self)
{
......@@ -482,12 +464,12 @@ phosh_shell_dispose (GObject *object)
PhoshShellPrivate *priv = phosh_shell_get_instance_private(self);
panels_dispose (self);
g_clear_pointer (&priv->background, phosh_cp_widget_destroy);
g_clear_object (&priv->lockscreen_manager);
g_clear_object (&priv->monitor_manager);
g_clear_object (&priv->wifi_manager);
g_clear_object (&priv->osk_manager);
g_clear_object (&priv->polkit_auth_agent);
g_clear_object (&priv->background_manager);
phosh_system_prompter_unregister ();
phosh_session_unregister ();
......@@ -498,9 +480,11 @@ phosh_shell_dispose (GObject *object)
static gboolean
setup_idle_cb (PhoshShell *self)
{
PhoshShellPrivate *priv = phosh_shell_get_instance_private (self);
panels_create (self);
/* Create background after panel since it needs the panel's size */
background_create (self);
priv->background_manager = phosh_background_manager_new ();
return FALSE;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment