~ricotz/gala/session-dialog-text

« back to all changes in this revision

Viewing changes to src/DBus.vala

  • Committer: RabbitBot
  • Author(s): Tom Beckmann, Victor Martinez
  • Date: 2014-03-18 04:30:24 UTC
  • mfrom: (369.1.4 gala-panel-opacity)
  • Revision ID: rabbitbot-20140318043024-1xdv1axew14ik7ju
adds a get_optimal_panel_alpha() method and a background_changed() signal to gala's dbus interface for use by wingpanel

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
//  
2
 
//  Copyright (C) 2012 Tom Beckmann
 
2
//  Copyright (C) 2012 - 2014 Tom Beckmann, Jacob Parker
3
3
// 
4
4
//  This program is free software: you can redistribute it and/or modify
5
5
//  it under the terms of the GNU General Public License as published by
43
43
                
44
44
                private DBus ()
45
45
                {
 
46
#if HAS_MUTTER38
 
47
                        if (plugin.background_group != null)
 
48
                                (plugin.background_group as BackgroundManager).changed.connect (() => background_changed ());
 
49
                        else
 
50
                                assert_not_reached ();
 
51
#endif
46
52
                }
47
53
                
48
54
                public void perform_action (ActionType type)
49
55
                {
50
56
                        plugin.perform_action (type);
51
57
                }
 
58
 
 
59
#if HAS_MUTTER38
 
60
                const double SATURATION_WEIGHT = 1.5;
 
61
                const double WEIGHT_THRESHOLD = 1.0;
 
62
 
 
63
                class DummyOffscreenEffect : Clutter.OffscreenEffect {
 
64
                        public signal void done_painting ();
 
65
                        public override void post_paint ()
 
66
                        {
 
67
                                base.post_paint ();
 
68
                                done_painting ();
 
69
                        }
 
70
                }
 
71
 
 
72
                public struct ColorInformation
 
73
                {
 
74
                        double average_red;
 
75
                        double average_green;
 
76
                        double average_blue;
 
77
                        double mean;
 
78
                        double variance;
 
79
                }
 
80
 
 
81
                /**
 
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.
 
86
                 */
 
87
                public signal void background_changed ();
 
88
 
 
89
                /**
 
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.
 
94
                 *
 
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
 
98
                 *                         to its dimensions
 
99
                 * @param reference_y      Y coordinate
 
100
                 * @param refenrece_width  Width of the rectangle
 
101
                 * @param reference_height Height of the rectangle
 
102
                 */
 
103
                public async ColorInformation get_background_color_information (int monitor,
 
104
                        int reference_x, int reference_y, int reference_width, int reference_height)
 
105
                        throws DBusError
 
106
                {
 
107
                        var background = plugin.background_group.get_child_at_index (monitor);
 
108
                        if (background == null)
 
109
                                throw new DBusError.INVALID_ARGS ("Invalid monitor requested");
 
110
 
 
111
                        var effect = new DummyOffscreenEffect ();
 
112
                        background.add_effect (effect);
 
113
 
 
114
                        var tex_width = (int)background.width;
 
115
                        var tex_height = (int)background.height;
 
116
 
 
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);
 
121
 
 
122
                        if (x_start > tex_width || x_start > tex_height || width <= 0 || height <= 0)
 
123
                                throw new DBusError.INVALID_ARGS ("Invalid rectangle specified");
 
124
 
 
125
                        double variance = 0, mean = 0,
 
126
                               rTotal = 0, gTotal = 0, bTotal = 0;
 
127
 
 
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);
 
132
 
 
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);
 
136
 
 
137
                                int size = width * height;
 
138
 
 
139
                                double mean_squares = 0;
 
140
                                double pixel = 0;
 
141
 
 
142
                                double max, min, score, delta, scoreTotal = 0,
 
143
                                       rTotal2 = 0, gTotal2 = 0, bTotal2 = 0;
 
144
 
 
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;
 
151
 
 
152
                                                uint8 r = pixels[i];
 
153
                                                uint8 g = pixels[i + 1];
 
154
                                                uint8 b = pixels[i + 2];
 
155
 
 
156
                                                pixel = (0.3 * r + 0.6 * g + 0.11 * b) - 128f;
 
157
 
 
158
                                                min = uint8.min (r, uint8.min (g, b));
 
159
                                                max = uint8.max (r, uint8.max (g, b));
 
160
                                                delta = max - min;
 
161
 
 
162
                                                // prefer colored pixels over shades of grey
 
163
                                                score = SATURATION_WEIGHT * (delta == 0 ? 0.0 : delta / max);
 
164
 
 
165
                                                rTotal += score * r;
 
166
                                                gTotal += score * g;
 
167
                                                bTotal += score * b;
 
168
                                                scoreTotal += score;
 
169
 
 
170
                                                rTotal += r;
 
171
                                                gTotal += g;
 
172
                                                bTotal += b;
 
173
 
 
174
                                                mean += pixel;
 
175
                                                mean_squares += pixel * pixel;
 
176
                                        }
 
177
                                }
 
178
 
 
179
                                scoreTotal /= size;
 
180
                                bTotal /= size;
 
181
                                gTotal /= size;
 
182
                                rTotal /= size;
 
183
 
 
184
                                if (scoreTotal > 0.0) {
 
185
                                        bTotal /= scoreTotal;
 
186
                                        gTotal /= scoreTotal;
 
187
                                        rTotal /= scoreTotal;
 
188
                                }
 
189
 
 
190
                                bTotal2 /= size * uint8.MAX;
 
191
                                gTotal2 /= size * uint8.MAX;
 
192
                                rTotal2 /= size * uint8.MAX;
 
193
 
 
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;
 
199
                                        var rf = 1.0 - f;
 
200
                                        bTotal = bTotal * f + bTotal2 * rf;
 
201
                                        gTotal = gTotal * f + gTotal2 * rf;
 
202
                                        rTotal = rTotal * f + rTotal2 * rf;
 
203
                                }
 
204
 
 
205
                                // there shouldn't be values larger then 1.0
 
206
                                var max_val = double.max (rTotal, double.max (gTotal, bTotal));
 
207
                                if (max_val > 1.0) {
 
208
                                        bTotal /= max_val;
 
209
                                        gTotal /= max_val;
 
210
                                        rTotal /= max_val;
 
211
                                }
 
212
 
 
213
                                mean /= size;
 
214
                                mean_squares *= mean_squares / size;
 
215
 
 
216
                                variance = Math.sqrt (mean_squares - mean * mean) / (double) size;
 
217
 
 
218
                                get_background_color_information.callback ();
 
219
                        });
 
220
 
 
221
                        background.queue_redraw ();
 
222
 
 
223
                        yield;
 
224
 
 
225
                        return { rTotal, gTotal, bTotal, mean, variance };
 
226
                }
 
227
#endif
52
228
        }
53
229
}