mirror of
https://github.com/elementary/gala.git
synced 2024-12-26 02:33:27 +03:00
DBus: cleanup (#2001)
This commit is contained in:
parent
66679ca796
commit
c84a10d0f9
301
src/DBus.vala
301
src/DBus.vala
@ -1,255 +1,70 @@
|
|||||||
//
|
/*
|
||||||
// Copyright (C) 2012 - 2014 Tom Beckmann, Jacob Parker
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
//
|
* SPDX-FileCopyrightText: 2024 elementary, Inc. (https://elementary.io)
|
||||||
// This program is free software: you can redistribute it and/or modify
|
* 2012-2014 Tom Beckmann
|
||||||
// it under the terms of the GNU General Public License as published by
|
* 2012-2014 Jacob Parker
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
*/
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace Gala {
|
[DBus (name="org.pantheon.gala")]
|
||||||
[DBus (name="org.pantheon.gala")]
|
public class Gala.DBus {
|
||||||
public class DBus {
|
private static DBus? instance;
|
||||||
private static DBus? instance;
|
private static WindowManagerGala wm;
|
||||||
private static WindowManagerGala wm;
|
|
||||||
|
|
||||||
[DBus (visible = false)]
|
[DBus (visible = false)]
|
||||||
public static void init (WindowManagerGala _wm) {
|
public static void init (WindowManagerGala _wm) {
|
||||||
wm = _wm;
|
wm = _wm;
|
||||||
|
|
||||||
Bus.own_name (BusType.SESSION, "org.pantheon.gala", BusNameOwnerFlags.NONE,
|
Bus.own_name (BusType.SESSION, "org.pantheon.gala", BusNameOwnerFlags.NONE,
|
||||||
(connection) => {
|
(connection) => {
|
||||||
if (instance == null)
|
if (instance == null)
|
||||||
instance = new DBus ();
|
instance = new DBus ();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
connection.register_object ("/org/pantheon/gala", instance);
|
connection.register_object ("/org/pantheon/gala", instance);
|
||||||
} catch (Error e) { warning (e.message); }
|
} catch (Error e) { warning (e.message); }
|
||||||
|
|
||||||
try {
|
try {
|
||||||
connection.register_object ("/org/pantheon/gala/DesktopInterface", new DesktopIntegration (wm));
|
connection.register_object ("/org/pantheon/gala/DesktopInterface", new DesktopIntegration (wm));
|
||||||
} catch (Error e) { warning (e.message); }
|
} catch (Error e) { warning (e.message); }
|
||||||
},
|
},
|
||||||
() => {},
|
() => {},
|
||||||
() => warning ("Could not acquire name\n") );
|
() => warning ("Could not acquire name\n") );
|
||||||
|
|
||||||
Bus.own_name (BusType.SESSION, "org.gnome.Shell", BusNameOwnerFlags.NONE,
|
Bus.own_name (BusType.SESSION, "org.gnome.Shell", BusNameOwnerFlags.NONE,
|
||||||
(connection) => {
|
(connection) => {
|
||||||
try {
|
try {
|
||||||
connection.register_object ("/org/gnome/Shell", DBusAccelerator.init (wm));
|
connection.register_object ("/org/gnome/Shell", DBusAccelerator.init (wm));
|
||||||
connection.register_object ("/org/gnome/Shell/Screenshot", ScreenshotManager.init (wm));
|
connection.register_object ("/org/gnome/Shell/Screenshot", ScreenshotManager.init (wm));
|
||||||
} catch (Error e) { warning (e.message); }
|
} catch (Error e) { warning (e.message); }
|
||||||
},
|
},
|
||||||
() => {},
|
() => {},
|
||||||
() => critical ("Could not acquire name") );
|
() => critical ("Could not acquire name") );
|
||||||
|
|
||||||
Bus.own_name (BusType.SESSION, "org.gnome.Shell.Screenshot", BusNameOwnerFlags.REPLACE,
|
Bus.own_name (BusType.SESSION, "org.gnome.Shell.Screenshot", BusNameOwnerFlags.REPLACE,
|
||||||
() => {},
|
() => {},
|
||||||
() => {},
|
() => {},
|
||||||
() => critical ("Could not acquire name") );
|
() => critical ("Could not acquire name") );
|
||||||
|
|
||||||
Bus.own_name (BusType.SESSION, "org.gnome.SessionManager.EndSessionDialog", BusNameOwnerFlags.NONE,
|
Bus.own_name (BusType.SESSION, "org.gnome.SessionManager.EndSessionDialog", BusNameOwnerFlags.NONE,
|
||||||
(connection) => {
|
(connection) => {
|
||||||
try {
|
try {
|
||||||
connection.register_object ("/org/gnome/SessionManager/EndSessionDialog", SessionManager.init ());
|
connection.register_object ("/org/gnome/SessionManager/EndSessionDialog", SessionManager.init ());
|
||||||
} catch (Error e) { warning (e.message); }
|
} catch (Error e) { warning (e.message); }
|
||||||
},
|
},
|
||||||
() => {},
|
() => {},
|
||||||
() => critical ("Could not acquire name") );
|
() => critical ("Could not acquire name") );
|
||||||
|
|
||||||
Bus.own_name (BusType.SESSION, "org.gnome.ScreenSaver", BusNameOwnerFlags.REPLACE,
|
Bus.own_name (BusType.SESSION, "org.gnome.ScreenSaver", BusNameOwnerFlags.REPLACE,
|
||||||
(connection) => {
|
(connection) => {
|
||||||
try {
|
try {
|
||||||
connection.register_object ("/org/gnome/ScreenSaver", wm.screensaver);
|
connection.register_object ("/org/gnome/ScreenSaver", wm.screensaver);
|
||||||
} catch (Error e) { warning (e.message); }
|
} catch (Error e) { warning (e.message); }
|
||||||
},
|
},
|
||||||
() => {},
|
() => {},
|
||||||
() => critical ("Could not acquire ScreenSaver bus") );
|
() => critical ("Could not acquire ScreenSaver bus") );
|
||||||
}
|
}
|
||||||
|
|
||||||
private DBus () {
|
public void perform_action (ActionType type) throws DBusError, IOError {
|
||||||
if (wm.background_group != null)
|
wm.perform_action (type);
|
||||||
((BackgroundContainer) wm.background_group).changed.connect (() => background_changed ());
|
|
||||||
else
|
|
||||||
assert_not_reached ();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void perform_action (ActionType type) throws DBusError, IOError {
|
|
||||||
wm.perform_action (type);
|
|
||||||
}
|
|
||||||
|
|
||||||
private const double SATURATION_WEIGHT = 1.5;
|
|
||||||
private const double WEIGHT_THRESHOLD = 1.0;
|
|
||||||
|
|
||||||
private class DummyOffscreenEffect : Clutter.OffscreenEffect {
|
|
||||||
public signal void done_painting ();
|
|
||||||
|
|
||||||
public override void post_paint (Clutter.PaintNode node, Clutter.PaintContext context) {
|
|
||||||
base.post_paint (node, context);
|
|
||||||
done_painting ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct ColorInformation {
|
|
||||||
double average_red;
|
|
||||||
double average_green;
|
|
||||||
double average_blue;
|
|
||||||
double mean;
|
|
||||||
double variance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emitted when the background change occurred 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 reference_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, IOError {
|
|
||||||
var background = wm.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,
|
|
||||||
r_total = 0, g_total = 0, b_total = 0;
|
|
||||||
|
|
||||||
ulong paint_signal_handler = 0;
|
|
||||||
paint_signal_handler = effect.done_painting.connect (() => {
|
|
||||||
SignalHandler.disconnect (effect, paint_signal_handler);
|
|
||||||
background.remove_effect (effect);
|
|
||||||
|
|
||||||
var texture = (Cogl.Texture)effect.get_texture ();
|
|
||||||
var pixels = new uint8[texture.get_width () * texture.get_height () * 4];
|
|
||||||
texture.get_data (Cogl.PixelFormat.BGRA_8888_PRE, 0, pixels);
|
|
||||||
|
|
||||||
int size = width * height;
|
|
||||||
|
|
||||||
double mean_squares = 0;
|
|
||||||
double pixel = 0;
|
|
||||||
|
|
||||||
double max, min, score, delta, score_total = 0,
|
|
||||||
r_total2 = 0, g_total2 = 0, b_total2 = 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);
|
|
||||||
|
|
||||||
r_total += score * r;
|
|
||||||
g_total += score * g;
|
|
||||||
b_total += score * b;
|
|
||||||
score_total += score;
|
|
||||||
|
|
||||||
r_total += r;
|
|
||||||
g_total += g;
|
|
||||||
b_total += b;
|
|
||||||
|
|
||||||
mean += pixel;
|
|
||||||
mean_squares += pixel * pixel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
score_total /= size;
|
|
||||||
b_total /= size;
|
|
||||||
g_total /= size;
|
|
||||||
r_total /= size;
|
|
||||||
|
|
||||||
if (score_total > 0.0) {
|
|
||||||
b_total /= score_total;
|
|
||||||
g_total /= score_total;
|
|
||||||
r_total /= score_total;
|
|
||||||
}
|
|
||||||
|
|
||||||
b_total2 /= size * uint8.MAX;
|
|
||||||
g_total2 /= size * uint8.MAX;
|
|
||||||
r_total2 /= 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 (score_total <= WEIGHT_THRESHOLD) {
|
|
||||||
var f = 1.0 / WEIGHT_THRESHOLD * score_total;
|
|
||||||
var rf = 1.0 - f;
|
|
||||||
b_total = b_total * f + b_total2 * rf;
|
|
||||||
g_total = g_total * f + g_total2 * rf;
|
|
||||||
r_total = r_total * f + r_total2 * rf;
|
|
||||||
}
|
|
||||||
|
|
||||||
// there shouldn't be values larger then 1.0
|
|
||||||
var max_val = double.max (r_total, double.max (g_total, b_total));
|
|
||||||
if (max_val > 1.0) {
|
|
||||||
b_total /= max_val;
|
|
||||||
g_total /= max_val;
|
|
||||||
r_total /= 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 { r_total, g_total, b_total, mean, variance };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user