Back to index

unity  6.0.0
BGHash.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2011-2012 Canonical Ltd
00003  *
00004  * This program is free software: you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License version 3 as
00006  * published by the Free Software Foundation.
00007  *
00008  * This program is distributed in the hope that it will be useful,
00009  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00010  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011  * GNU General Public License for more details.
00012  *
00013  * You should have received a copy of the GNU General Public License
00014  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00015  *
00016  * Authored by: Gordon Allott <gord.alott@canonical.com>
00017  */
00018 
00019 
00020 #include "BGHash.h"
00021 #include <gdk/gdkx.h>
00022 #include <NuxCore/Logger.h>
00023 #include "unity-shared/UBusMessages.h"
00024 
00025 namespace
00026 {
00027   nux::logging::Logger logger("unity.BGHash");
00028 }
00029 
00030 namespace unity
00031 {
00032 
00033 BGHash::BGHash()
00034   : transition_animator_(500)
00035   , current_color_(unity::colors::Aubergine)
00036   , new_color_(unity::colors::Aubergine)
00037   , old_color_(unity::colors::Aubergine)
00038 {
00039   override_color_.alpha = 0.0f;
00040 
00041   transition_animator_.animation_updated.connect(sigc::mem_fun(this, &BGHash::OnTransitionUpdated));
00042   ubus_manager_.RegisterInterest(UBUS_BACKGROUND_REQUEST_COLOUR_EMIT, [&](GVariant *) { DoUbusColorEmit(); } );
00043 
00044   RefreshColor();
00045 }
00046 
00047 void BGHash::OverrideColor(nux::Color const& color)
00048 {
00049   override_color_ = color;
00050 
00051   if (override_color_.alpha)
00052   {
00053     TransitionToNewColor(override_color_);
00054     return;
00055   }
00056 
00057   RefreshColor();
00058 }
00059 
00060 void BGHash::RefreshColor()
00061 {
00062   Atom         real_type;
00063   gint         result;
00064   gint         real_format;
00065   gulong       items_read;
00066   gulong       items_left;
00067   gchar*       colors;
00068   Atom         representative_colors_atom;
00069   Display*     display;
00070   GdkRGBA      color_gdk;
00071 
00072   representative_colors_atom = gdk_x11_get_xatom_by_name("_GNOME_BACKGROUND_REPRESENTATIVE_COLORS");
00073   display = gdk_x11_display_get_xdisplay(gdk_display_get_default ());
00074 
00075   gdk_error_trap_push();
00076   result = XGetWindowProperty (display,
00077              GDK_ROOT_WINDOW(),
00078              representative_colors_atom,
00079              0L,
00080              G_MAXLONG,
00081              False,
00082              XA_STRING,
00083              &real_type,
00084              &real_format,
00085              &items_read,
00086              &items_left,
00087              (guchar **) &colors);
00088   gdk_flush ();
00089   gdk_error_trap_pop_ignored ();
00090 
00091   if (result == Success && items_read)
00092   {
00093     gdk_rgba_parse(&color_gdk, colors);
00094     nux::Color new_color(color_gdk.red,
00095                          color_gdk.green,
00096                          color_gdk.blue,
00097                          1.0f);
00098     TransitionToNewColor(MatchColor(new_color));
00099     XFree (colors);
00100   }
00101 }
00102 
00103 nux::Color BGHash::InterpolateColor(nux::Color const& colora, nux::Color const& colorb, float value) const
00104 {
00105   // takes two colours, transitions between them, we can do it linearly or whatever
00106   // i don't think it will matter that much
00107   // it doesn't happen too often
00108   return colora + ((colorb - colora) * value);
00109 }
00110 
00111 void BGHash::TransitionToNewColor(nux::color::Color const& new_color)
00112 {
00113   if (new_color == current_color_)
00114     return;
00115 
00116   LOG_DEBUG(logger) << "transitioning from: " << current_color_.red << " to " << new_color.red;
00117 
00118   old_color_ = current_color_;
00119   new_color_ = new_color;
00120 
00121   transition_animator_.Stop();
00122   transition_animator_.Start();
00123 }
00124 
00125 void BGHash::OnTransitionUpdated(double progress)
00126 {
00127   current_color_ = InterpolateColor(old_color_, new_color_, progress);
00128   DoUbusColorEmit();
00129 }
00130 
00131 void BGHash::DoUbusColorEmit()
00132 {
00133   ubus_manager_.SendMessage(UBUS_BACKGROUND_COLOR_CHANGED,
00134                             g_variant_new ("(dddd)",
00135                                            current_color_.red,
00136                                            current_color_.green,
00137                                            current_color_.blue,
00138                                            current_color_.alpha));
00139 }
00140 
00141 nux::Color BGHash::MatchColor(nux::Color const& base_color) const
00142 {
00143   nux::Color colors[12];
00144 
00145   colors[ 0] = nux::Color (0x540e44);
00146   colors[ 1] = nux::Color (0x6e0b2a);
00147   colors[ 2] = nux::Color (0x841617);
00148   colors[ 3] = nux::Color (0x84371b);
00149   colors[ 4] = nux::Color (0x864d20);
00150   colors[ 5] = nux::Color (0x857f31);
00151   colors[ 6] = nux::Color (0x1d6331);
00152   colors[ 7] = nux::Color (0x11582e);
00153   colors[ 8] = nux::Color (0x0e5955);
00154   colors[ 9] = nux::Color (0x192b59);
00155   colors[10] = nux::Color (0x1b134c);
00156   colors[11] = nux::Color (0x2c0d46);
00157 
00158   float closest_diff = 200.0f;
00159   nux::Color chosen_color;
00160   nux::color::HueSaturationValue base_hsv (base_color);
00161 
00162   if (base_hsv.saturation < 0.08)
00163   {
00164     // grayscale image
00165     LOG_DEBUG (logger) << "got a grayscale image";
00166     chosen_color = nux::Color (46 , 52 , 54 );
00167     chosen_color.alpha = 0.72f;
00168   }
00169   else
00170   {
00171     LOG_DEBUG (logger) << "got a colour image";
00172     // full colour image
00173     for (int i = 0; i < 11; i++)
00174     {
00175       nux::color::HueSaturationValue comparison_hsv (colors[i]);
00176       float color_diff = fabs(base_hsv.hue - comparison_hsv.hue);
00177 
00178       if (color_diff < closest_diff)
00179       {
00180         chosen_color = colors[i];
00181         closest_diff = color_diff;
00182       }
00183     }
00184 
00185     nux::color::HueSaturationValue hsv_color (chosen_color);
00186     hsv_color.saturation = std::min(base_hsv.saturation, hsv_color.saturation);
00187     hsv_color.saturation *= (2.0f - hsv_color.saturation);
00188     hsv_color.value = std::min(std::min(base_hsv.value, hsv_color.value), 0.26f);
00189 
00190     chosen_color = nux::Color (nux::color::RedGreenBlue(hsv_color));
00191     chosen_color.alpha = 0.72f;
00192   }
00193 
00194   LOG_DEBUG(logger) << "eventually chose "
00195                     << chosen_color.red << ", "
00196                     << chosen_color.green << ", "
00197                     << chosen_color.blue;
00198   return chosen_color;
00199 }
00200 
00201 nux::Color const& BGHash::CurrentColor() const
00202 {
00203   return current_color_;
00204 }
00205 
00206 }