[gnome-flashback] desktop: use representative color for rubberband



commit 8ad1554fd6a4b3efc44109a7b8b6475564290e19
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Tue Nov 12 20:44:28 2019 +0200

    desktop: use representative color for rubberband

 configure.ac                                   |  1 +
 gnome-flashback/libdesktop/gf-desktop-window.c | 74 ++++++++++++++++++++++++++
 gnome-flashback/libdesktop/gf-icon-view.c      | 55 +++++++++++++++++++
 gnome-flashback/libdesktop/gf-icon-view.h      |  5 +-
 4 files changed, 134 insertions(+), 1 deletion(-)
---
diff --git a/configure.ac b/configure.ac
index bc27f10..ab71c41 100644
--- a/configure.ac
+++ b/configure.ac
@@ -158,6 +158,7 @@ PKG_CHECK_MODULES([DESKTOP], [
   gnome-desktop-3.0 >= $LIBGNOME_DESKTOP_REQUIRED
   gtk+-3.0 >= $GTK_REQUIRED
   libsystemd
+  x11
 ])
 
 PKG_CHECK_MODULES([END_SESSION_DIALOG], [
diff --git a/gnome-flashback/libdesktop/gf-desktop-window.c b/gnome-flashback/libdesktop/gf-desktop-window.c
index b71a665..25cbdd3 100644
--- a/gnome-flashback/libdesktop/gf-desktop-window.c
+++ b/gnome-flashback/libdesktop/gf-desktop-window.c
@@ -20,6 +20,7 @@
 
 #include <gdk/gdkx.h>
 #include <libgnome-desktop/gnome-bg.h>
+#include <X11/Xatom.h>
 
 #include "gf-background.h"
 #include "gf-icon-view.h"
@@ -68,6 +69,76 @@ static guint window_signals[LAST_SIGNAL] = { 0 };
 
 G_DEFINE_TYPE (GfDesktopWindow, gf_desktop_window, GTK_TYPE_WINDOW)
 
+static gboolean
+get_representative_color (GfDesktopWindow *self,
+                          GdkRGBA         *color)
+{
+  GdkDisplay *display;
+  Display *xdisplay;
+  Atom atom;
+  int status;
+  Atom actual_type;
+  int actual_format;
+  unsigned long n_items;
+  unsigned long bytes_after;
+  unsigned char *prop;
+
+  display = gtk_widget_get_display (GTK_WIDGET (self));
+  xdisplay = gdk_x11_display_get_xdisplay (display);
+
+  atom = XInternAtom (xdisplay, "_GNOME_BACKGROUND_REPRESENTATIVE_COLORS", True);
+  if (atom == None)
+    return FALSE;
+
+  gdk_x11_display_error_trap_push (display);
+
+  status = XGetWindowProperty (xdisplay,
+                               XDefaultRootWindow (xdisplay),
+                               atom,
+                               0,
+                               G_MAXLONG,
+                               False,
+                               XA_STRING,
+                               &actual_type,
+                               &actual_format,
+                               &n_items,
+                               &bytes_after,
+                               &prop);
+
+  gdk_x11_display_error_trap_pop_ignored (display);
+
+  if (status != Success)
+    return FALSE;
+
+  if (n_items == 0)
+    {
+      XFree (prop);
+      return FALSE;
+    }
+
+  gdk_rgba_parse (color, (const char *) prop);
+  XFree (prop);
+
+  return TRUE;
+}
+
+static void
+update_representative_color (GfDesktopWindow *self)
+{
+  GdkRGBA color;
+  GfIconView *icon_view;
+
+  icon_view = GF_ICON_VIEW (self->icon_view);
+
+  if (icon_view == NULL)
+    return;
+
+  if (get_representative_color (self, &color))
+    gf_icon_view_set_representative_color (icon_view, &color);
+  else
+    gf_icon_view_set_representative_color (icon_view, NULL);
+}
+
 static void
 update_css_class (GfDesktopWindow *self)
 {
@@ -202,6 +273,7 @@ changed_cb (GfBackground    *background,
             GfDesktopWindow *self)
 {
   update_css_class (self);
+  update_representative_color (self);
 }
 
 static void
@@ -247,6 +319,8 @@ show_icons_changed (GfDesktopWindow *self)
       g_assert (self->icon_view == NULL);
       self->icon_view = gf_icon_view_new ();
 
+      update_representative_color (self);
+
       gtk_container_add (GTK_CONTAINER (self), self->icon_view);
       gtk_widget_show (self->icon_view);
     }
diff --git a/gnome-flashback/libdesktop/gf-icon-view.c b/gnome-flashback/libdesktop/gf-icon-view.c
index 9abc9b3..79ab699 100644
--- a/gnome-flashback/libdesktop/gf-icon-view.c
+++ b/gnome-flashback/libdesktop/gf-icon-view.c
@@ -55,6 +55,7 @@ struct _GfIconView
 
   GList           *selected_icons;
 
+  GtkCssProvider  *rubberband_css;
   GtkStyleContext *rubberband_style;
   GdkRectangle     rubberband_rect;
   GList           *rubberband_icons;
@@ -970,6 +971,7 @@ gf_icon_view_dispose (GObject *object)
 
   g_clear_pointer (&self->selected_icons, g_list_free);
 
+  g_clear_object (&self->rubberband_css);
   g_clear_object (&self->rubberband_style);
   g_clear_pointer (&self->rubberband_icons, g_list_free);
 
@@ -998,10 +1000,14 @@ static void
 ensure_rubberband_style (GfIconView *self)
 {
   GtkWidgetPath *path;
+  GdkScreen *screen;
+  GtkStyleProvider *provider;
+  guint priority;
 
   if (self->rubberband_style != NULL)
     return;
 
+  self->rubberband_css = gtk_css_provider_new ();
   self->rubberband_style = gtk_style_context_new ();
 
   path = gtk_widget_path_new ();
@@ -1012,6 +1018,12 @@ ensure_rubberband_style (GfIconView *self)
 
   gtk_style_context_set_path (self->rubberband_style, path);
   gtk_widget_path_unref (path);
+
+  screen = gtk_widget_get_screen (GTK_WIDGET (self));
+  provider = GTK_STYLE_PROVIDER (self->rubberband_css);
+  priority = GTK_STYLE_PROVIDER_PRIORITY_APPLICATION;
+
+  gtk_style_context_add_provider_for_screen (screen, provider, priority);
 }
 
 static gboolean
@@ -1148,3 +1160,46 @@ gf_icon_view_new (void)
 {
   return g_object_new (GF_TYPE_ICON_VIEW, NULL);
 }
+
+void
+gf_icon_view_set_representative_color (GfIconView *self,
+                                       GdkRGBA    *color)
+{
+  ensure_rubberband_style (self);
+
+  if (color != NULL)
+    {
+      double shade;
+      GdkRGBA background;
+      GdkRGBA border;
+      char *background_css;
+      char *border_css;
+      char *css;
+
+      shade = color->green < 0.5 ? 1.1 : 0.9;
+
+      background = *color;
+      background.alpha = 0.6;
+
+      border.red = color->red * shade;
+      border.green = color->green * shade;
+      border.blue = color->green * shade;
+      border.alpha = 1.0;
+
+      background_css = gdk_rgba_to_string (&background);
+      border_css = gdk_rgba_to_string (&border);
+
+      css = g_strdup_printf (".rubberband { background-color: %s; border: 1px solid %s; }",
+                             background_css, border_css);
+
+      g_free (background_css);
+      g_free (border_css);
+
+      gtk_css_provider_load_from_data (self->rubberband_css, css, -1, NULL);
+      g_free (css);
+    }
+  else
+    {
+      gtk_css_provider_load_from_data (self->rubberband_css, "", -1, NULL);
+    }
+}
diff --git a/gnome-flashback/libdesktop/gf-icon-view.h b/gnome-flashback/libdesktop/gf-icon-view.h
index 2d365e5..d9fc068 100644
--- a/gnome-flashback/libdesktop/gf-icon-view.h
+++ b/gnome-flashback/libdesktop/gf-icon-view.h
@@ -25,7 +25,10 @@ G_BEGIN_DECLS
 #define GF_TYPE_ICON_VIEW (gf_icon_view_get_type ())
 G_DECLARE_FINAL_TYPE (GfIconView, gf_icon_view, GF, ICON_VIEW, GtkEventBox)
 
-GtkWidget *gf_icon_view_new (void);
+GtkWidget *gf_icon_view_new                      (void);
+
+void       gf_icon_view_set_representative_color (GfIconView *self,
+                                                  GdkRGBA    *color);
 
 G_END_DECLS
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]