Commit 19bafdf2 authored by Guido Gunther's avatar Guido Gunther

PhoshBackground: Implement zoom style

Listen for picture-option and handle scaled (as already implemented)
and zoom. If the style is unknown default to zoom like gnome-shell.

Code taken from GnomeBG.
Signed-off-by: Guido Gunther's avatarGuido Günther <guido.gunther@puri.sm>
parent 6db7529e
......@@ -3,6 +3,11 @@
*
* SPDX-License-Identifier: GPL-3+
* Author: Guido Günther <agx@sigxcpu.org>
*
* Derived in parts from GnomeBG which is
*
* Copyright (C) 2000 Eazel, Inc.
* Copyright (C) 2007-2008 Red Hat, Inc.
*/
#define G_LOG_DOMAIN "phosh-background"
......@@ -11,6 +16,9 @@
#include "shell.h"
#include "panel.h"
#define GNOME_DESKTOP_USE_UNSTABLE_API
#include <libgnome-desktop/gnome-bg.h>
#include <math.h>
#include <string.h>
......@@ -24,6 +32,9 @@ struct _PhoshBackground
{
PhoshLayerSurface parent;
gchar *uri;
GDesktopBackgroundStyle style;
GdkPixbuf *pixbuf;
GSettings *settings;
};
......@@ -33,13 +44,49 @@ G_DEFINE_TYPE (PhoshBackground, phosh_background, PHOSH_TYPE_LAYER_SURFACE)
static GdkPixbuf *
image_background (GdkPixbuf *image, guint width, guint height)
pb_scale_to_min (GdkPixbuf *src, int min_width, int min_height)
{
double factor;
int src_width, src_height;
int new_width, new_height;
GdkPixbuf *dest;
src_width = gdk_pixbuf_get_width (src);
src_height = gdk_pixbuf_get_height (src);
factor = MAX (min_width / (double) src_width, min_height / (double) src_height);
new_width = floor (src_width * factor + 0.5);
new_height = floor (src_height * factor + 0.5);
dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
gdk_pixbuf_get_has_alpha (src),
8, min_width, min_height);
if (!dest)
return NULL;
/* crop the result */
gdk_pixbuf_scale (src, dest,
0, 0,
min_width, min_height,
(new_width - min_width) / -2,
(new_height - min_height) / -2,
factor,
factor,
GDK_INTERP_BILINEAR);
return dest;
}
static GdkPixbuf *
pb_scale_to_fit (GdkPixbuf *src, int width, int height)
{
gint orig_width, orig_height;
gint final_width, final_height;
gint off_x, off_y;
gdouble ratio_horiz, ratio_vert, ratio;
GdkPixbuf *bg, *scaled_bg;
g_autoptr(GdkPixbuf) bg = NULL;
GdkPixbuf *scaled_bg;
const gchar *xpm_data[] = {"1 1 1 1", "_ c WebGrey", "_"};
bg = gdk_pixbuf_new_from_xpm_data (xpm_data);
......@@ -47,21 +94,19 @@ image_background (GdkPixbuf *image, guint width, guint height)
width,
height,
GDK_INTERP_BILINEAR);
g_object_unref (bg);
/* FIXME: use libgnome-desktop's background handling instead */
orig_width = gdk_pixbuf_get_width (image);
orig_height = gdk_pixbuf_get_height (image);
orig_width = gdk_pixbuf_get_width (src);
orig_height = gdk_pixbuf_get_height (src);
ratio_horiz = (double) width / orig_width;
ratio_vert = (double) height / orig_height;
ratio = ratio_horiz > ratio_vert ? ratio_vert : ratio_horiz;
final_width = ceil (ratio * orig_width);
final_height = ceil (ratio * orig_height);
off_x = (width - final_width) / 2;
off_y = (height - final_height) / 2;
gdk_pixbuf_composite (image,
gdk_pixbuf_composite (src,
scaled_bg,
off_x, off_y, /* dest x,y */
final_width,
......@@ -74,26 +119,47 @@ image_background (GdkPixbuf *image, guint width, guint height)
return scaled_bg;
}
static GdkPixbuf *
image_background (GdkPixbuf *image, guint width, guint height, GDesktopBackgroundStyle style)
{
GdkPixbuf *scaled_bg;
switch (style) {
case G_DESKTOP_BACKGROUND_STYLE_SCALED:
scaled_bg = pb_scale_to_fit (image, width, height);
break;
case G_DESKTOP_BACKGROUND_STYLE_NONE:
case G_DESKTOP_BACKGROUND_STYLE_WALLPAPER:
case G_DESKTOP_BACKGROUND_STYLE_CENTERED:
case G_DESKTOP_BACKGROUND_STYLE_STRETCHED:
case G_DESKTOP_BACKGROUND_STYLE_SPANNED:
g_warning ("Unimplemented style %d, using zoom", style);
/* fallthrough */
case G_DESKTOP_BACKGROUND_STYLE_ZOOM:
default:
scaled_bg = pb_scale_to_min (image, width, height);
break;
}
return scaled_bg;
}
static void
load_background (PhoshBackground *self,
const char* uri)
load_background (PhoshBackground *self)
{
g_autoptr(GdkPixbuf) image = NULL;
const gchar *xpm_data[] = {"1 1 1 1", "_ c WebGrey", "_"};
GError *err = NULL;
gint width, height;
if (self->pixbuf) {
g_object_unref (self->pixbuf);
self->pixbuf = NULL;
}
g_clear_object (&self->pixbuf);
/* FIXME: support GnomeDesktop.BGSlideShow as well */
if (!g_str_has_prefix(uri, "file:///")) {
g_warning ("Only file URIs supported for backgrounds not %s", uri);
if (!g_str_has_prefix(self->uri, "file:///")) {
g_warning ("Only file URIs supported for backgrounds not %s", self->uri);
} else {
image = gdk_pixbuf_new_from_file (&uri[strlen("file://")], &err);
image = gdk_pixbuf_new_from_file (&self->uri[strlen("file://")], &err);
if (!image) {
const char *reason = err ? err->message : "unknown error";
g_warning ("Failed to load background: %s", reason);
......@@ -107,7 +173,7 @@ load_background (PhoshBackground *self,
image = gdk_pixbuf_new_from_xpm_data (xpm_data);
phosh_shell_get_usable_area (phosh_shell_get_default (), NULL, NULL, &width, &height);
self->pixbuf = image_background (image, width, height);
self->pixbuf = image_background (image, width, height, self->style);
/* force background redraw */
gtk_widget_queue_draw (GTK_WIDGET (self));
......@@ -120,11 +186,12 @@ background_draw_cb (PhoshBackground *self,
cairo_t *cr,
gpointer data)
{
gint x, y, width, height;
gint x, y;
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, &width, &height);
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;
......@@ -132,19 +199,18 @@ background_draw_cb (PhoshBackground *self,
static void
background_setting_changed_cb (PhoshBackground *self,
on_background_setting_changed (PhoshBackground *self,
const gchar *key,
GSettings *settings)
{
g_autofree gchar *uri = g_settings_get_string (settings, key);
g_return_if_fail (PHOSH_IS_BACKGROUND (self));
g_return_if_fail (G_IS_SETTINGS (settings));
if (!uri)
return;
g_free (self->uri);
self->uri = g_settings_get_string (settings, "picture-uri");
self->style = g_settings_get_enum (settings, "picture-options");
load_background (self, uri);
load_background (self);
}
......@@ -156,7 +222,7 @@ rotation_notify_cb (PhoshBackground *self,
g_return_if_fail (PHOSH_IS_BACKGROUND (self));
g_return_if_fail (PHOSH_IS_SHELL (shell));
background_setting_changed_cb (self, "picture-uri", self->settings);
on_background_setting_changed (self, NULL, self->settings);
}
......@@ -166,7 +232,7 @@ on_phosh_background_configured (PhoshLayerSurface *surface)
PhoshBackground *self = PHOSH_BACKGROUND (surface);
/* Load background initially */
background_setting_changed_cb (self, "picture-uri", self->settings);
on_background_setting_changed (self, NULL, self->settings);
}
......@@ -181,7 +247,9 @@ phosh_background_constructed (GObject *object)
self->settings = g_settings_new ("org.gnome.desktop.background");
g_signal_connect_swapped (self->settings, "changed::picture-uri",
G_CALLBACK (background_setting_changed_cb), self);
G_CALLBACK (on_background_setting_changed), self);
g_signal_connect_swapped (self->settings, "changed::picture-options",
G_CALLBACK (on_background_setting_changed), self);
g_signal_connect_swapped (phosh_shell_get_default (),
"notify::rotation",
......@@ -199,6 +267,7 @@ phosh_background_finalize (GObject *object)
PhoshBackground *self = PHOSH_BACKGROUND (object);
g_object_unref (self->pixbuf);
g_clear_pointer (&self->uri, g_free);
g_clear_object (&self->settings);
parent_class->finalize (object);
......
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