mirror of
https://github.com/elementary/gala.git
synced 2024-12-25 02:02:11 +03:00
adds a get_optimal_panel_alpha() method and a background_changed() signal to gala's dbus interface for use by wingpanel
This commit is contained in:
commit
aa7bd8b540
@ -71,7 +71,7 @@ link_directories(${DEPS_LIBRARY_DIRS})
|
||||
|
||||
find_package(Vala REQUIRED)
|
||||
include(ValaVersion)
|
||||
ensure_vala_version("0.16.1" MINIMUM)
|
||||
ensure_vala_version("0.22.0" MINIMUM)
|
||||
|
||||
include(ValaPrecompile)
|
||||
vala_precompile(VALA_C
|
||||
@ -106,6 +106,7 @@ PACKAGES
|
||||
gdesktopenums-3.0
|
||||
gnome-desktop-3.0
|
||||
xfixes-4.0
|
||||
cogl-fixes
|
||||
OPTIONS
|
||||
-g
|
||||
--vapidir=${CMAKE_CURRENT_SOURCE_DIR}/vapi/
|
||||
|
@ -27,6 +27,8 @@ namespace Gala
|
||||
{
|
||||
const uint ANIMATION_TRANSITION_DURATION = 1500;
|
||||
|
||||
public signal void changed ();
|
||||
|
||||
public Meta.Screen screen { get; construct; }
|
||||
public int monitor { get; construct; }
|
||||
public Settings settings { get; construct; }
|
||||
@ -107,6 +109,8 @@ namespace Gala
|
||||
if (all || key_changed == "picture-opacity") {
|
||||
if (image != null)
|
||||
image.opacity = (uint8)(settings.get_int ("picture-opacity") / 100.0 * 255);
|
||||
|
||||
changed ();
|
||||
}
|
||||
|
||||
// update pattern
|
||||
@ -118,6 +122,8 @@ namespace Gala
|
||||
var secondary_color = Clutter.Color.from_string (settings.get_string ("secondary-color"));
|
||||
var shading_type = shading_string_to_enum (settings.get_string ("color-shading-type"));
|
||||
pattern.content = cache.load_pattern (monitor, primary_color, secondary_color, shading_type);
|
||||
|
||||
changed ();
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,6 +138,8 @@ namespace Gala
|
||||
image.animate (Clutter.AnimationMode.EASE_OUT_QUAD, ANIMATION_TRANSITION_DURATION,
|
||||
opacity: 0).completed.connect (() => {
|
||||
image.destroy ();
|
||||
|
||||
changed ();
|
||||
});
|
||||
return;
|
||||
}
|
||||
@ -146,6 +154,8 @@ namespace Gala
|
||||
if (image != null)
|
||||
image.destroy ();
|
||||
image = new_image;
|
||||
|
||||
changed ();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@ namespace Gala
|
||||
public class BackgroundManager : Meta.BackgroundGroup
|
||||
{
|
||||
public Meta.Screen screen { get; construct; }
|
||||
public signal void changed ();
|
||||
|
||||
public BackgroundManager (Meta.Screen screen)
|
||||
{
|
||||
@ -41,6 +42,10 @@ namespace Gala
|
||||
|
||||
void update ()
|
||||
{
|
||||
var reference_child = get_child_at_index (0);
|
||||
if (reference_child != null)
|
||||
(reference_child as Background).changed.disconnect (background_changed);
|
||||
|
||||
remove_all_children ();
|
||||
|
||||
var settings = BackgroundSettings.get_default ().schema;
|
||||
@ -53,8 +58,16 @@ namespace Gala
|
||||
background.set_size (geom.width, geom.height);
|
||||
|
||||
add_child (background);
|
||||
|
||||
if (i == 0)
|
||||
background.changed.connect (background_changed);
|
||||
}
|
||||
}
|
||||
|
||||
void background_changed ()
|
||||
{
|
||||
changed ();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
178
src/DBus.vala
178
src/DBus.vala
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (C) 2012 Tom Beckmann
|
||||
// Copyright (C) 2012 - 2014 Tom Beckmann, Jacob Parker
|
||||
//
|
||||
// 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
|
||||
@ -43,11 +43,187 @@ namespace Gala
|
||||
|
||||
private DBus ()
|
||||
{
|
||||
#if HAS_MUTTER38
|
||||
if (plugin.background_group != null)
|
||||
(plugin.background_group as BackgroundManager).changed.connect (() => background_changed ());
|
||||
else
|
||||
assert_not_reached ();
|
||||
#endif
|
||||
}
|
||||
|
||||
public void perform_action (ActionType type)
|
||||
{
|
||||
plugin.perform_action (type);
|
||||
}
|
||||
|
||||
#if HAS_MUTTER38
|
||||
const double SATURATION_WEIGHT = 1.5;
|
||||
const double WEIGHT_THRESHOLD = 1.0;
|
||||
|
||||
class DummyOffscreenEffect : Clutter.OffscreenEffect {
|
||||
public signal void done_painting ();
|
||||
public override void post_paint ()
|
||||
{
|
||||
base.post_paint ();
|
||||
done_painting ();
|
||||
}
|
||||
}
|
||||
|
||||
public struct ColorInformation
|
||||
{
|
||||
double average_red;
|
||||
double average_green;
|
||||
double average_blue;
|
||||
double mean;
|
||||
double variance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Emitted when the background change occured and the transition ended.
|
||||
* You can safely call get_optimal_panel_alpha then. It is not guaranteed
|
||||
* that this signal will be emitted only once per group of changes as often
|
||||
* done by GUIs. The change may not be visible to the user.
|
||||
*/
|
||||
public signal void background_changed ();
|
||||
|
||||
/**
|
||||
* Attaches a dummy offscreen effect to the background at monitor to get its
|
||||
* isolated color data. Then calculate the red, green and blue components of
|
||||
* the average color in that area and the mean color value and variance. All
|
||||
* variables are returned as a tuple in that order.
|
||||
*
|
||||
* @param monitor The monitor where the panel will be placed
|
||||
* @param reference_x X coordinate of the rectangle used to gather color data
|
||||
* relative to the monitor you picked. Values will be clamped
|
||||
* to its dimensions
|
||||
* @param reference_y Y coordinate
|
||||
* @param refenrece_width Width of the rectangle
|
||||
* @param reference_height Height of the rectangle
|
||||
*/
|
||||
public async ColorInformation get_background_color_information (int monitor,
|
||||
int reference_x, int reference_y, int reference_width, int reference_height)
|
||||
throws DBusError
|
||||
{
|
||||
var background = plugin.background_group.get_child_at_index (monitor);
|
||||
if (background == null)
|
||||
throw new DBusError.INVALID_ARGS ("Invalid monitor requested");
|
||||
|
||||
var effect = new DummyOffscreenEffect ();
|
||||
background.add_effect (effect);
|
||||
|
||||
var tex_width = (int)background.width;
|
||||
var tex_height = (int)background.height;
|
||||
|
||||
int x_start = reference_x;
|
||||
int y_start = reference_y;
|
||||
int width = int.min (tex_width - reference_x, reference_width);
|
||||
int height = int.min (tex_height - reference_y, reference_height);
|
||||
|
||||
if (x_start > tex_width || x_start > tex_height || width <= 0 || height <= 0)
|
||||
throw new DBusError.INVALID_ARGS ("Invalid rectangle specified");
|
||||
|
||||
double variance = 0, mean = 0,
|
||||
rTotal = 0, gTotal = 0, bTotal = 0;
|
||||
|
||||
ulong paint_signal_handler = 0;
|
||||
paint_signal_handler = effect.done_painting.connect (() => {
|
||||
SignalHandler.disconnect (effect, paint_signal_handler);
|
||||
background.remove_effect (effect);
|
||||
|
||||
var pixels = new uint8[tex_width * tex_height * 4];
|
||||
CoglFixes.texture_get_data ((Cogl.Texture)effect.get_texture (),
|
||||
Cogl.PixelFormat.BGRA_8888_PRE, 0, pixels);
|
||||
|
||||
int size = width * height;
|
||||
|
||||
double mean_squares = 0;
|
||||
double pixel = 0;
|
||||
|
||||
double max, min, score, delta, scoreTotal = 0,
|
||||
rTotal2 = 0, gTotal2 = 0, bTotal2 = 0;
|
||||
|
||||
// code to calculate weighted average color is copied from
|
||||
// plank's lib/Drawing/DrawingService.vala average_color()
|
||||
// http://bazaar.launchpad.net/~docky-core/plank/trunk/view/head:/lib/Drawing/DrawingService.vala
|
||||
for (int y = y_start; y < height; y++) {
|
||||
for (int x = x_start; x < width; x++) {
|
||||
int i = y * width * 4 + x * 4;
|
||||
|
||||
uint8 r = pixels[i];
|
||||
uint8 g = pixels[i + 1];
|
||||
uint8 b = pixels[i + 2];
|
||||
|
||||
pixel = (0.3 * r + 0.6 * g + 0.11 * b) - 128f;
|
||||
|
||||
min = uint8.min (r, uint8.min (g, b));
|
||||
max = uint8.max (r, uint8.max (g, b));
|
||||
delta = max - min;
|
||||
|
||||
// prefer colored pixels over shades of grey
|
||||
score = SATURATION_WEIGHT * (delta == 0 ? 0.0 : delta / max);
|
||||
|
||||
rTotal += score * r;
|
||||
gTotal += score * g;
|
||||
bTotal += score * b;
|
||||
scoreTotal += score;
|
||||
|
||||
rTotal += r;
|
||||
gTotal += g;
|
||||
bTotal += b;
|
||||
|
||||
mean += pixel;
|
||||
mean_squares += pixel * pixel;
|
||||
}
|
||||
}
|
||||
|
||||
scoreTotal /= size;
|
||||
bTotal /= size;
|
||||
gTotal /= size;
|
||||
rTotal /= size;
|
||||
|
||||
if (scoreTotal > 0.0) {
|
||||
bTotal /= scoreTotal;
|
||||
gTotal /= scoreTotal;
|
||||
rTotal /= scoreTotal;
|
||||
}
|
||||
|
||||
bTotal2 /= size * uint8.MAX;
|
||||
gTotal2 /= size * uint8.MAX;
|
||||
rTotal2 /= size * uint8.MAX;
|
||||
|
||||
// combine weighted and not weighted sum depending on the average "saturation"
|
||||
// if saturation isn't reasonable enough
|
||||
// s = 0.0 -> f = 0.0 ; s = WEIGHT_THRESHOLD -> f = 1.0
|
||||
if (scoreTotal <= WEIGHT_THRESHOLD) {
|
||||
var f = 1.0 / WEIGHT_THRESHOLD * scoreTotal;
|
||||
var rf = 1.0 - f;
|
||||
bTotal = bTotal * f + bTotal2 * rf;
|
||||
gTotal = gTotal * f + gTotal2 * rf;
|
||||
rTotal = rTotal * f + rTotal2 * rf;
|
||||
}
|
||||
|
||||
// there shouldn't be values larger then 1.0
|
||||
var max_val = double.max (rTotal, double.max (gTotal, bTotal));
|
||||
if (max_val > 1.0) {
|
||||
bTotal /= max_val;
|
||||
gTotal /= max_val;
|
||||
rTotal /= max_val;
|
||||
}
|
||||
|
||||
mean /= size;
|
||||
mean_squares *= mean_squares / size;
|
||||
|
||||
variance = Math.sqrt (mean_squares - mean * mean) / (double) size;
|
||||
|
||||
get_background_color_information.callback ();
|
||||
});
|
||||
|
||||
background.queue_redraw ();
|
||||
|
||||
yield;
|
||||
|
||||
return { rTotal, gTotal, bTotal, mean, variance };
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
7
vapi/cogl-fixes.vapi
Normal file
7
vapi/cogl-fixes.vapi
Normal file
@ -0,0 +1,7 @@
|
||||
namespace CoglFixes
|
||||
{
|
||||
[CCode (cname = "cogl_texture_get_data")]
|
||||
public static extern int texture_get_data (Cogl.Texture texture, Cogl.PixelFormat format, uint rowstride, [CCode (array_length = false)] uint8[] pixels);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user