diff --git a/panels/background/background.gresource.xml b/panels/background/background.gresource.xml index 7fa4dbac6..c715aad9a 100644 --- a/panels/background/background.gresource.xml +++ b/panels/background/background.gresource.xml @@ -3,5 +3,7 @@ cc-background-chooser.ui cc-background-panel.ui + cc-background-preview.ui + preview.css diff --git a/panels/background/cc-background-panel.c b/panels/background/cc-background-panel.c index c00e69c25..c4d32a1ec 100644 --- a/panels/background/cc-background-panel.c +++ b/panels/background/cc-background-panel.c @@ -31,6 +31,7 @@ #include "cc-background-chooser.h" #include "cc-background-item.h" +#include "cc-background-preview.h" #include "cc-background-resources.h" #include "cc-background-xml.h" @@ -61,10 +62,8 @@ struct _CcBackgroundPanel GCancellable *copy_cancellable; GtkWidget *bottom_hbox; - GtkWidget *desktop_drawing_area; - GtkWidget *desktop_slide_image; - GtkWidget *lock_drawing_area; - GtkWidget *lock_slide_image; + CcBackgroundPreview *desktop_preview; + CcBackgroundPreview *lock_screen_preview; GtkWidget *spinner; GtkWidget *chooser; @@ -72,41 +71,6 @@ struct _CcBackgroundPanel CC_PANEL_REGISTER (CcBackgroundPanel, cc_background_panel) -static GdkPixbuf* -get_or_create_cached_pixbuf (CcBackgroundPanel *panel, - GtkWidget *widget, - CcBackgroundItem *background) -{ - const gint preview_width = 309; - const gint preview_height = 168; - gint scale_factor; - GdkPixbuf *pixbuf; - - scale_factor = gtk_widget_get_scale_factor (widget); - pixbuf = cc_background_item_get_frame_thumbnail (background, - panel->thumb_factory, - preview_width, - preview_height, - scale_factor, - -2, TRUE); - - return pixbuf; -} - -static void -update_display_preview (CcBackgroundPanel *panel, - GtkWidget *widget, - cairo_t *cr, - CcBackgroundItem *background) -{ - g_autoptr(GdkPixbuf) pixbuf = NULL; - - pixbuf = get_or_create_cached_pixbuf (panel, widget, background); - - gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0); - cairo_paint (cr); -} - static CcBackgroundItem * get_current_background (CcBackgroundPanel *panel, GSettings *settings) @@ -122,7 +86,6 @@ update_preview (CcBackgroundPanel *panel, GSettings *settings, CcBackgroundItem *item) { - gboolean changes_with_time; CcBackgroundItem *current_background; current_background = get_current_background (panel, settings); @@ -138,23 +101,10 @@ update_preview (CcBackgroundPanel *panel, cc_background_item_load (current_background, NULL); } - changes_with_time = FALSE; - - if (current_background) - { - changes_with_time = cc_background_item_changes_with_time (current_background); - } - if (settings == panel->settings) - { - gtk_widget_set_visible (panel->desktop_slide_image, changes_with_time); - gtk_widget_queue_draw (panel->desktop_drawing_area); - } + cc_background_preview_set_item (panel->desktop_preview, current_background); else - { - gtk_widget_set_visible (panel->lock_slide_image, changes_with_time); - gtk_widget_queue_draw (panel->lock_drawing_area); - } + cc_background_preview_set_item (panel->lock_screen_preview, current_background); } static gchar * @@ -439,24 +389,6 @@ on_chooser_background_chosen_cb (CcBackgroundChooser *chooser, set_background (self, self->lock_settings, item); } -static gboolean -on_preview_draw_cb (GtkWidget *widget, - cairo_t *cr, - CcBackgroundPanel *panel) -{ - update_display_preview (panel, widget, cr, panel->current_background); - return TRUE; -} - -static gboolean -on_lock_preview_draw_cb (GtkWidget *widget, - cairo_t *cr, - CcBackgroundPanel *panel) -{ - update_display_preview (panel, widget, cr, panel->current_lock_background); - return TRUE; -} - static const char * cc_background_panel_get_help_uri (CcPanel *panel) { @@ -500,6 +432,7 @@ cc_background_panel_class_init (CcBackgroundPanelClass *klass) GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); g_type_ensure (CC_TYPE_BACKGROUND_CHOOSER); + g_type_ensure (CC_TYPE_BACKGROUND_PREVIEW); panel_class->get_help_uri = cc_background_panel_get_help_uri; @@ -509,14 +442,10 @@ cc_background_panel_class_init (CcBackgroundPanelClass *klass) gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/background/cc-background-panel.ui"); gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, bottom_hbox); - gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, desktop_drawing_area); - gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, desktop_slide_image); - gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, lock_drawing_area); - gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, lock_slide_image); + gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, desktop_preview); + gtk_widget_class_bind_template_child (widget_class, CcBackgroundPanel, lock_screen_preview); gtk_widget_class_bind_template_callback (widget_class, on_chooser_background_chosen_cb); - gtk_widget_class_bind_template_callback (widget_class, on_lock_preview_draw_cb); - gtk_widget_class_bind_template_callback (widget_class, on_preview_draw_cb); } static void diff --git a/panels/background/cc-background-panel.ui b/panels/background/cc-background-panel.ui index 11a4fc925..d3c2aa884 100644 --- a/panels/background/cc-background-panel.ui +++ b/panels/background/cc-background-panel.ui @@ -25,13 +25,10 @@ center vertical - - 310 - 170 + True False center - @@ -39,37 +36,6 @@ True False 12 - - - True - False - center - 12 - 2 - - - True - False - slideshow-symbolic - - - - - True - False - - - - - - - False - 0 - Changes throughout the day - - - - @@ -82,51 +48,11 @@ start center - - 310 - 170 + True False + True center - - - - - - True - False - 12 - - - True - False - center - 12 - 2 - - - True - False - slideshow-symbolic - - - - - True - False - - - - - - - False - 0 - Changes throughout the day - - - - diff --git a/panels/background/cc-background-preview.c b/panels/background/cc-background-preview.c new file mode 100644 index 000000000..f2f986676 --- /dev/null +++ b/panels/background/cc-background-preview.c @@ -0,0 +1,322 @@ +/* cc-background-preview.c + * + * Copyright 2019 Georges Basile Stavracas Neto + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include "cc-background-preview.h" + +struct _CcBackgroundPreview +{ + GtkBox parent; + + GtkLabel *desktop_clock_label; + GtkWidget *drawing_area; + GtkLabel *lock_screen_label; + GtkStack *stack; + + GnomeDesktopThumbnailFactory *thumbnail_factory; + + CcBackgroundItem *item; + GSettings *desktop_settings; + + guint lock_screen_time_timeout_id; + gboolean is_lock_screen; + GDateTime *previous_time; + gboolean is_24h_format; +}; + +G_DEFINE_TYPE (CcBackgroundPreview, cc_background_preview, GTK_TYPE_BOX) + +enum +{ + PROP_0, + PROP_IS_LOCK_SCREEN, + PROP_ITEM, + N_PROPS +}; + +static GParamSpec *properties [N_PROPS]; + +/* Auxiliary methods */ + +static void +update_lock_screen_label (CcBackgroundPreview *self, + gboolean force) +{ + g_autoptr(GDateTime) now = NULL; + g_autofree gchar *label = NULL; + + now = g_date_time_new_now_local (); + + /* Don't update the label if the hour:minute pair did not change */ + if (!force && self->previous_time && + g_date_time_get_hour (now) == g_date_time_get_hour (self->previous_time) && + g_date_time_get_minute (now) == g_date_time_get_minute (self->previous_time)) + { + return; + } + + if (self->is_24h_format) + label = g_date_time_format (now, "%R"); + else + label = g_date_time_format (now, "%I:%M %p"); + + gtk_label_set_label (self->lock_screen_label, label); + gtk_label_set_label (self->desktop_clock_label, label); + + g_clear_pointer (&self->previous_time, g_date_time_unref); + self->previous_time = g_steal_pointer (&now); +} + +static void +update_clock_format (CcBackgroundPreview *self) +{ + g_autofree gchar *clock_format = NULL; + gboolean is_24h_format; + + clock_format = g_settings_get_string (self->desktop_settings, "clock-format"); + is_24h_format = g_strcmp0 (clock_format, "24h") == 0; + + if (is_24h_format != self->is_24h_format) + { + self->is_24h_format = is_24h_format; + update_lock_screen_label (self, TRUE); + } +} + +static void +load_custom_css (CcBackgroundPreview *self) +{ + g_autoptr(GtkCssProvider) provider = NULL; + + /* use custom CSS */ + provider = gtk_css_provider_new (); + gtk_css_provider_load_from_resource (provider, "/org/gnome/control-center/background/preview.css"); + gtk_style_context_add_provider_for_screen (gdk_screen_get_default (), + GTK_STYLE_PROVIDER (provider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + +} + +static gboolean +update_clock_cb (gpointer data) +{ + CcBackgroundPreview *self = data; + + update_lock_screen_label (self, FALSE); + + return G_SOURCE_CONTINUE; +} + +static void +start_monitor_time (CcBackgroundPreview *self) +{ + if (self->lock_screen_time_timeout_id > 0) + return; + + self->lock_screen_time_timeout_id = g_timeout_add_seconds (1, + update_clock_cb, + self); +} + +static void +stop_monitor_time (CcBackgroundPreview *self) +{ + if (self->lock_screen_time_timeout_id > 0) + { + g_source_remove (self->lock_screen_time_timeout_id); + self->lock_screen_time_timeout_id = 0; + } +} + + +/* Callbacks */ + +static gboolean +on_preview_draw_cb (GtkWidget *widget, + cairo_t *cr, + CcBackgroundPreview *self) +{ + g_autoptr(GdkPixbuf) pixbuf = NULL; + GtkAllocation allocation; + gint scale_factor; + + if (!self->item) + return FALSE; + + scale_factor = gtk_widget_get_scale_factor (widget); + gtk_widget_get_allocation (widget, &allocation); + pixbuf = cc_background_item_get_frame_thumbnail (self->item, + self->thumbnail_factory, + allocation.width, + allocation.height, + scale_factor, + 0, + TRUE); + + + gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0); + cairo_paint (cr); + + return TRUE; +} + +/* GObject overrides */ + +static void +cc_background_preview_finalize (GObject *object) +{ + CcBackgroundPreview *self = (CcBackgroundPreview *)object; + + g_clear_object (&self->desktop_settings); + g_clear_object (&self->item); + g_clear_object (&self->thumbnail_factory); + + g_clear_pointer (&self->previous_time, g_date_time_unref); + + stop_monitor_time (self); + + G_OBJECT_CLASS (cc_background_preview_parent_class)->finalize (object); +} + +static void +cc_background_preview_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + CcBackgroundPreview *self = CC_BACKGROUND_PREVIEW (object); + + switch (prop_id) + { + case PROP_IS_LOCK_SCREEN: + g_value_set_boolean (value, self->is_lock_screen); + break; + + case PROP_ITEM: + g_value_set_object (value, self->item); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +cc_background_preview_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + CcBackgroundPreview *self = CC_BACKGROUND_PREVIEW (object); + + switch (prop_id) + { + case PROP_IS_LOCK_SCREEN: + self->is_lock_screen = g_value_get_boolean (value); + gtk_stack_set_visible_child_name (self->stack, + self->is_lock_screen ? "lock" : "desktop"); + if (self->is_lock_screen) + start_monitor_time (self); + else + stop_monitor_time (self); + break; + + case PROP_ITEM: + cc_background_preview_set_item (self, g_value_get_object (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +cc_background_preview_class_init (CcBackgroundPreviewClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + object_class->finalize = cc_background_preview_finalize; + object_class->get_property = cc_background_preview_get_property; + object_class->set_property = cc_background_preview_set_property; + + properties[PROP_IS_LOCK_SCREEN] = g_param_spec_boolean ("is-lock-screen", + "Lock screen", + "Whether the preview is of the lock screen", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + properties[PROP_ITEM] = g_param_spec_object ("item", + "Item", + "Background item", + CC_TYPE_BACKGROUND_ITEM, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, N_PROPS, properties); + + gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/background/cc-background-preview.ui"); + + gtk_widget_class_bind_template_child (widget_class, CcBackgroundPreview, desktop_clock_label); + gtk_widget_class_bind_template_child (widget_class, CcBackgroundPreview, drawing_area); + gtk_widget_class_bind_template_child (widget_class, CcBackgroundPreview, lock_screen_label); + gtk_widget_class_bind_template_child (widget_class, CcBackgroundPreview, stack); + + gtk_widget_class_bind_template_callback (widget_class, on_preview_draw_cb); +} + +static void +cc_background_preview_init (CcBackgroundPreview *self) +{ + gtk_widget_init_template (GTK_WIDGET (self)); + + self->thumbnail_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE); + self->desktop_settings = g_settings_new ("org.gnome.desktop.interface"); + + g_signal_connect_object (self->desktop_settings, + "changed::clock-format", + G_CALLBACK (update_clock_format), + self, + G_CONNECT_SWAPPED); + + update_clock_format (self); + load_custom_css (self); +} + +CcBackgroundItem* +cc_background_preview_get_item (CcBackgroundPreview *self) +{ + g_return_val_if_fail (CC_IS_BACKGROUND_PREVIEW (self), NULL); + + return self->item; +} + +void +cc_background_preview_set_item (CcBackgroundPreview *self, + CcBackgroundItem *item) +{ + g_return_if_fail (CC_IS_BACKGROUND_PREVIEW (self)); + g_return_if_fail (CC_IS_BACKGROUND_ITEM (item)); + + if (!g_set_object (&self->item, item)) + return; + + gtk_widget_queue_draw (self->drawing_area); + + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ITEM]); +} diff --git a/panels/background/cc-background-preview.h b/panels/background/cc-background-preview.h new file mode 100644 index 000000000..e8e20d49d --- /dev/null +++ b/panels/background/cc-background-preview.h @@ -0,0 +1,36 @@ +/* cc-background-preview.h + * + * Copyright 2019 Georges Basile Stavracas Neto + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#pragma once + +#include + +#include "cc-background-item.h" + +G_BEGIN_DECLS + +#define CC_TYPE_BACKGROUND_PREVIEW (cc_background_preview_get_type()) +G_DECLARE_FINAL_TYPE (CcBackgroundPreview, cc_background_preview, CC, BACKGROUND_PREVIEW, GtkBox) + +CcBackgroundItem* cc_background_preview_get_item (CcBackgroundPreview *self); +void cc_background_preview_set_item (CcBackgroundPreview *self, + CcBackgroundItem *item); + +G_END_DECLS diff --git a/panels/background/cc-background-preview.ui b/panels/background/cc-background-preview.ui new file mode 100644 index 000000000..c20b2c3e4 --- /dev/null +++ b/panels/background/cc-background-preview.ui @@ -0,0 +1,141 @@ + + + + + diff --git a/panels/background/meson.build b/panels/background/meson.build index 2585808eb..7482431f3 100644 --- a/panels/background/meson.build +++ b/panels/background/meson.build @@ -62,6 +62,8 @@ common_sources += gnome.mkenums( resource_data = files( 'cc-background-chooser.ui', 'cc-background-panel.ui', + 'cc-background-preview.ui', + 'preview.css', ) common_sources += gnome.compile_resources( @@ -81,6 +83,7 @@ sources = common_sources + files( 'cc-background-grilo-miner.c', 'cc-background-item.c', 'cc-background-panel.c', + 'cc-background-preview.c', 'cc-background-xml.c', ) diff --git a/panels/background/preview.css b/panels/background/preview.css new file mode 100644 index 000000000..f4966eb24 --- /dev/null +++ b/panels/background/preview.css @@ -0,0 +1,27 @@ +frame.desktop-preview { + min-height: 10px; + padding: 0 4px; + background-color: black; +} + +frame.desktop-preview image { + color: white; +} + +frame.desktop-preview label { + color: white; + font-weight: bold; + font-size: 6px; +} + +frame.lock-screen-preview { + border: solid rgba(0, 0, 0, 0.33); + border-width: 10px 0 0 0; +} + +frame.lock-screen-preview label { + color: white; + font-weight: bold; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); + font-size: 1.2em; +}