47
if (plugin.background_group != null)
48
(plugin.background_group as BackgroundManager).changed.connect (() => background_changed ());
50
assert_not_reached ();
48
54
public void perform_action (ActionType type)
50
56
plugin.perform_action (type);
60
const double SATURATION_WEIGHT = 1.5;
61
const double WEIGHT_THRESHOLD = 1.0;
63
class DummyOffscreenEffect : Clutter.OffscreenEffect {
64
public signal void done_painting ();
65
public override void post_paint ()
72
public struct ColorInformation
82
* Emitted when the background change occured and the transition ended.
83
* You can safely call get_optimal_panel_alpha then. It is not guaranteed
84
* that this signal will be emitted only once per group of changes as often
85
* done by GUIs. The change may not be visible to the user.
87
public signal void background_changed ();
90
* Attaches a dummy offscreen effect to the background at monitor to get its
91
* isolated color data. Then calculate the red, green and blue components of
92
* the average color in that area and the mean color value and variance. All
93
* variables are returned as a tuple in that order.
95
* @param monitor The monitor where the panel will be placed
96
* @param reference_x X coordinate of the rectangle used to gather color data
97
* relative to the monitor you picked. Values will be clamped
99
* @param reference_y Y coordinate
100
* @param refenrece_width Width of the rectangle
101
* @param reference_height Height of the rectangle
103
public async ColorInformation get_background_color_information (int monitor,
104
int reference_x, int reference_y, int reference_width, int reference_height)
107
var background = plugin.background_group.get_child_at_index (monitor);
108
if (background == null)
109
throw new DBusError.INVALID_ARGS ("Invalid monitor requested");
111
var effect = new DummyOffscreenEffect ();
112
background.add_effect (effect);
114
var tex_width = (int)background.width;
115
var tex_height = (int)background.height;
117
int x_start = reference_x;
118
int y_start = reference_y;
119
int width = int.min (tex_width - reference_x, reference_width);
120
int height = int.min (tex_height - reference_y, reference_height);
122
if (x_start > tex_width || x_start > tex_height || width <= 0 || height <= 0)
123
throw new DBusError.INVALID_ARGS ("Invalid rectangle specified");
125
double variance = 0, mean = 0,
126
rTotal = 0, gTotal = 0, bTotal = 0;
128
ulong paint_signal_handler = 0;
129
paint_signal_handler = effect.done_painting.connect (() => {
130
SignalHandler.disconnect (effect, paint_signal_handler);
131
background.remove_effect (effect);
133
var pixels = new uint8[tex_width * tex_height * 4];
134
CoglFixes.texture_get_data ((Cogl.Texture)effect.get_texture (),
135
Cogl.PixelFormat.BGRA_8888_PRE, 0, pixels);
137
int size = width * height;
139
double mean_squares = 0;
142
double max, min, score, delta, scoreTotal = 0,
143
rTotal2 = 0, gTotal2 = 0, bTotal2 = 0;
145
// code to calculate weighted average color is copied from
146
// plank's lib/Drawing/DrawingService.vala average_color()
147
// http://bazaar.launchpad.net/~docky-core/plank/trunk/view/head:/lib/Drawing/DrawingService.vala
148
for (int y = y_start; y < height; y++) {
149
for (int x = x_start; x < width; x++) {
150
int i = y * width * 4 + x * 4;
153
uint8 g = pixels[i + 1];
154
uint8 b = pixels[i + 2];
156
pixel = (0.3 * r + 0.6 * g + 0.11 * b) - 128f;
158
min = uint8.min (r, uint8.min (g, b));
159
max = uint8.max (r, uint8.max (g, b));
162
// prefer colored pixels over shades of grey
163
score = SATURATION_WEIGHT * (delta == 0 ? 0.0 : delta / max);
175
mean_squares += pixel * pixel;
184
if (scoreTotal > 0.0) {
185
bTotal /= scoreTotal;
186
gTotal /= scoreTotal;
187
rTotal /= scoreTotal;
190
bTotal2 /= size * uint8.MAX;
191
gTotal2 /= size * uint8.MAX;
192
rTotal2 /= size * uint8.MAX;
194
// combine weighted and not weighted sum depending on the average "saturation"
195
// if saturation isn't reasonable enough
196
// s = 0.0 -> f = 0.0 ; s = WEIGHT_THRESHOLD -> f = 1.0
197
if (scoreTotal <= WEIGHT_THRESHOLD) {
198
var f = 1.0 / WEIGHT_THRESHOLD * scoreTotal;
200
bTotal = bTotal * f + bTotal2 * rf;
201
gTotal = gTotal * f + gTotal2 * rf;
202
rTotal = rTotal * f + rTotal2 * rf;
205
// there shouldn't be values larger then 1.0
206
var max_val = double.max (rTotal, double.max (gTotal, bTotal));
214
mean_squares *= mean_squares / size;
216
variance = Math.sqrt (mean_squares - mean * mean) / (double) size;
218
get_background_color_information.callback ();
221
background.queue_redraw ();
225
return { rTotal, gTotal, bTotal, mean, variance };