[gnome-flashback] desktop: add light or dark css class based on average color



commit b73b78b510a582907243c0042e1081bdde540f13
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Tue Nov 26 20:04:57 2019 +0200

    desktop: add light or dark css class based on average color

 gnome-flashback/libcommon/gf-background-utils.c |   6 ++
 gnome-flashback/libcommon/gf-background-utils.h |  26 ++---
 gnome-flashback/libdesktop/gf-background.c      |  12 +--
 gnome-flashback/libdesktop/gf-background.h      |   4 +-
 gnome-flashback/libdesktop/gf-desktop-window.c  | 137 ++++++++++++++++--------
 5 files changed, 120 insertions(+), 65 deletions(-)
---
diff --git a/gnome-flashback/libcommon/gf-background-utils.c b/gnome-flashback/libcommon/gf-background-utils.c
index f45bbfb..8a3a6ed 100644
--- a/gnome-flashback/libcommon/gf-background-utils.c
+++ b/gnome-flashback/libcommon/gf-background-utils.c
@@ -507,3 +507,9 @@ gf_background_surface_set_as_root (GdkDisplay      *display,
 
   gdk_x11_display_ungrab (display);
 }
+
+GdkRGBA *
+gf_background_surface_get_average_color (cairo_surface_t *surface)
+{
+  return cairo_surface_get_user_data (surface, &average_color_key);
+}
diff --git a/gnome-flashback/libcommon/gf-background-utils.h b/gnome-flashback/libcommon/gf-background-utils.h
index a2c100e..229c5a6 100644
--- a/gnome-flashback/libcommon/gf-background-utils.h
+++ b/gnome-flashback/libcommon/gf-background-utils.h
@@ -22,18 +22,20 @@
 
 G_BEGIN_DECLS
 
-cairo_surface_t *gf_background_surface_create        (GdkDisplay      *display,
-                                                      GnomeBG         *bg,
-                                                      GdkWindow       *window,
-                                                      int              width,
-                                                      int              height);
-
-cairo_surface_t *gf_background_surface_get_from_root (GdkDisplay      *display,
-                                                      int              width,
-                                                      int              height);
-
-void             gf_background_surface_set_as_root   (GdkDisplay      *display,
-                                                      cairo_surface_t *surface);
+cairo_surface_t *gf_background_surface_create            (GdkDisplay      *display,
+                                                          GnomeBG         *bg,
+                                                          GdkWindow       *window,
+                                                          int              width,
+                                                          int              height);
+
+cairo_surface_t *gf_background_surface_get_from_root     (GdkDisplay      *display,
+                                                          int              width,
+                                                          int              height);
+
+void             gf_background_surface_set_as_root       (GdkDisplay      *display,
+                                                          cairo_surface_t *surface);
+
+GdkRGBA         *gf_background_surface_get_average_color (cairo_surface_t *surface);
 
 G_END_DECLS
 
diff --git a/gnome-flashback/libdesktop/gf-background.c b/gnome-flashback/libdesktop/gf-background.c
index 869fbd2..0beacdf 100644
--- a/gnome-flashback/libdesktop/gf-background.c
+++ b/gnome-flashback/libdesktop/gf-background.c
@@ -446,14 +446,8 @@ gf_background_new (GtkWidget *window)
                        NULL);
 }
 
-gboolean
-gf_background_is_dark (GfBackground *self)
+GdkRGBA *
+gf_background_get_average_color (GfBackground *self)
 {
-  int width;
-  int height;
-
-  width = gf_desktop_window_get_width (GF_DESKTOP_WINDOW (self->window));
-  height = gf_desktop_window_get_height (GF_DESKTOP_WINDOW (self->window));
-
-  return gnome_bg_is_dark (self->bg, width, height);
+  return gf_background_surface_get_average_color (self->surface);
 }
diff --git a/gnome-flashback/libdesktop/gf-background.h b/gnome-flashback/libdesktop/gf-background.h
index 2aa466f..ba4192d 100644
--- a/gnome-flashback/libdesktop/gf-background.h
+++ b/gnome-flashback/libdesktop/gf-background.h
@@ -25,9 +25,9 @@ G_BEGIN_DECLS
 #define GF_TYPE_BACKGROUND (gf_background_get_type ())
 G_DECLARE_FINAL_TYPE (GfBackground, gf_background, GF, BACKGROUND, GObject)
 
-GfBackground *gf_background_new     (GtkWidget    *window);
+GfBackground *gf_background_new               (GtkWidget    *window);
 
-gboolean      gf_background_is_dark (GfBackground *self);
+GdkRGBA      *gf_background_get_average_color (GfBackground *self);
 
 G_END_DECLS
 
diff --git a/gnome-flashback/libdesktop/gf-desktop-window.c b/gnome-flashback/libdesktop/gf-desktop-window.c
index bbb1b22..55fa234 100644
--- a/gnome-flashback/libdesktop/gf-desktop-window.c
+++ b/gnome-flashback/libdesktop/gf-desktop-window.c
@@ -45,6 +45,8 @@ struct _GfDesktopWindow
   guint            move_resize_id;
 
   gboolean         ready;
+
+  GdkRGBA         *representative_color;
 };
 
 enum
@@ -128,40 +130,73 @@ get_representative_color (GfDesktopWindow *self,
   return TRUE;
 }
 
-static void
-update_representative_color (GfDesktopWindow *self)
+static gboolean
+color_is_dark (GdkRGBA *color)
 {
-  GdkRGBA color;
-  GfIconView *icon_view;
-
-  icon_view = GF_ICON_VIEW (self->icon_view);
+  double relative_luminance;
 
-  if (icon_view == NULL)
-    return;
+  /* CCIR 601 */
+  relative_luminance = 0.299 * color->red +
+                       0.587 * color->green +
+                       0.114 * color->blue;
 
-  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);
+  return relative_luminance < 0.5;
 }
 
 static void
 update_css_class (GfDesktopWindow *self)
 {
-  gboolean dark;
   GtkStyleContext *context;
 
-  dark = FALSE;
+  context = gtk_widget_get_style_context (GTK_WIDGET (self));
 
-  if (self->background != NULL)
-    dark = gf_background_is_dark (self->background);
+  if (self->representative_color != NULL)
+    {
+      if (color_is_dark (self->representative_color))
+        {
+          gtk_style_context_remove_class (context, "light");
+          gtk_style_context_add_class (context, "dark");
+        }
+      else
+        {
+          gtk_style_context_remove_class (context, "dark");
+          gtk_style_context_add_class (context, "light");
+        }
+    }
+  else
+    {
+      gtk_style_context_remove_class (context, "dark");
+      gtk_style_context_remove_class (context, "light");
+    }
+}
 
-  context = gtk_widget_get_style_context (GTK_WIDGET (self));
+static void
+update_representative_color (GfDesktopWindow *self)
+{
+  g_clear_pointer (&self->representative_color, gdk_rgba_free);
+
+  if (self->background != NULL)
+    {
+      GdkRGBA *color;
 
-  if (!dark)
-    gtk_style_context_remove_class (context, "dark");
+      color = gf_background_get_average_color (self->background);
+      self->representative_color = gdk_rgba_copy (color);
+    }
   else
-    gtk_style_context_add_class (context, "dark");
+    {
+      GdkRGBA color;
+
+      if (get_representative_color (self, &color))
+        self->representative_color = gdk_rgba_copy (&color);
+    }
+
+  if (self->icon_view != NULL)
+    {
+      gf_icon_view_set_representative_color (GF_ICON_VIEW (self->icon_view),
+                                             self->representative_color);
+    }
+
+  update_css_class (self);
 }
 
 static void
@@ -179,7 +214,6 @@ ensure_surface (GfDesktopWindow *self)
                                                        self->height);
 
   gtk_widget_queue_draw (widget);
-  update_css_class (self);
 }
 
 static GdkFilterReturn
@@ -188,23 +222,43 @@ filter_func (GdkXEvent *xevent,
              gpointer   user_data)
 {
   XEvent *x;
-  GdkAtom atom;
   GfDesktopWindow *self;
+  GdkDisplay *display;
+  Display *xdisplay;
+  Atom pixmap_atom;
+  Atom color_atom;
 
   x = (XEvent *) xevent;
 
   if (x->type != PropertyNotify)
     return GDK_FILTER_CONTINUE;
 
-  atom = gdk_atom_intern_static_string ("_XROOTPMAP_ID");
+  self = GF_DESKTOP_WINDOW (user_data);
 
-  if (x->xproperty.atom != gdk_x11_atom_to_xatom (atom))
-    return GDK_FILTER_CONTINUE;
+  display = gtk_widget_get_display (GTK_WIDGET (self));
+  xdisplay = gdk_x11_display_get_xdisplay (display);
 
-  self = GF_DESKTOP_WINDOW (user_data);
+  pixmap_atom = XInternAtom (xdisplay, "_XROOTPMAP_ID", False);
+  color_atom = XInternAtom (xdisplay,
+                            "_GNOME_BACKGROUND_REPRESENTATIVE_COLORS",
+                            False);
 
-  g_clear_pointer (&self->surface, cairo_surface_destroy);
-  ensure_surface (self);
+  if (x->xproperty.atom == pixmap_atom)
+    {
+      GdkScreen *screen;
+
+      screen = gtk_widget_get_screen (GTK_WIDGET (self));
+
+      if (!gdk_screen_is_composited (screen))
+        {
+          g_clear_pointer (&self->surface, cairo_surface_destroy);
+          ensure_surface (self);
+        }
+    }
+  else if (x->xproperty.atom != color_atom)
+    {
+      update_representative_color (self);
+    }
 
   return GDK_FILTER_CONTINUE;
 }
@@ -249,15 +303,9 @@ composited_changed_cb (GdkScreen       *screen,
     return;
 
   if (gdk_screen_is_composited (screen))
-    {
-      remove_event_filter (self);
-      g_clear_pointer (&self->surface, cairo_surface_destroy);
-    }
+    g_clear_pointer (&self->surface, cairo_surface_destroy);
   else
-    {
-      add_event_filter (self);
-      ensure_surface (self);
-    }
+    ensure_surface (self);
 }
 
 static void
@@ -281,7 +329,6 @@ static void
 changed_cb (GfBackground    *background,
             GfDesktopWindow *self)
 {
-  update_css_class (self);
   update_representative_color (self);
 }
 
@@ -310,11 +357,11 @@ draw_background_changed (GfDesktopWindow *self)
 
       screen = gtk_widget_get_screen (GTK_WIDGET (self));
 
+      add_event_filter (self);
+      update_representative_color (self);
+
       if (!gdk_screen_is_composited (screen))
-        {
-          add_event_filter (self);
-          ensure_surface (self);
-        }
+        ensure_surface (self);
 
       emit_ready (self);
     }
@@ -328,7 +375,11 @@ show_icons_changed (GfDesktopWindow *self)
       g_assert (self->icon_view == NULL);
       self->icon_view = gf_icon_view_new ();
 
-      update_representative_color (self);
+      if (self->representative_color != NULL)
+        {
+          gf_icon_view_set_representative_color (GF_ICON_VIEW (self->icon_view),
+                                                 self->representative_color);
+        }
 
       gtk_container_add (GTK_CONTAINER (self), self->icon_view);
       gtk_widget_show (self->icon_view);
@@ -561,6 +612,8 @@ gf_desktop_window_finalize (GObject *object)
   remove_event_filter (self);
   g_clear_pointer (&self->surface, cairo_surface_destroy);
 
+  g_clear_pointer (&self->representative_color, gdk_rgba_free);
+
   if (self->move_resize_id != 0)
     {
       g_source_remove (self->move_resize_id);


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