Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 37 additions & 23 deletions src/DBus.vala
Original file line number Diff line number Diff line change
@@ -1,70 +1,84 @@
/*
* SPDX-License-Identifier: GPL-3.0-or-later
* SPDX-FileCopyrightText: 2024 elementary, Inc. (https://elementary.io)
* SPDX-FileCopyrightText: 2024-2025 elementary, Inc. (https://elementary.io)
* 2012-2014 Tom Beckmann
* 2012-2014 Jacob Parker
*/

[DBus (name="org.pantheon.gala")]
public class Gala.DBus {
private static DBus? instance;
private static WindowManagerGala wm;
private WindowManagerGala wm;

[DBus (visible = false)]
public static void init (WindowManagerGala _wm) {
public DBus (WindowManagerGala _wm) {
wm = _wm;
}

public void perform_action (ActionType type) throws DBusError, IOError {
wm.perform_action (type);
}
}


public class Gala.DBusManager : GLib.Object {
public DBusManager (WindowManagerGala wm, DBusAccelerator dbus_accelerator, ScreenshotManager screenshot_manager) {
Bus.own_name (BusType.SESSION, "org.pantheon.gala", BusNameOwnerFlags.NONE,
(connection) => {
if (instance == null)
instance = new DBus ();

try {
connection.register_object ("/org/pantheon/gala", instance);
} catch (Error e) { warning (e.message); }
connection.register_object ("/org/pantheon/gala", new DBus (wm));
} catch (Error e) {
warning (e.message);
}

try {
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")
);

Bus.own_name (BusType.SESSION, "org.gnome.Shell", BusNameOwnerFlags.NONE,
(connection) => {
try {
connection.register_object ("/org/gnome/Shell", DBusAccelerator.init (wm.get_display ()));
connection.register_object ("/org/gnome/Shell/Screenshot", ScreenshotManager.init (wm));
connection.register_object ("/org/gnome/Shell", dbus_accelerator);
connection.register_object ("/org/gnome/Shell/Screenshot", screenshot_manager);
} 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,
() => {},
() => {},
() => critical ("Could not acquire name") );
() => critical ("Could not acquire name")
);

Bus.own_name (BusType.SESSION, "org.gnome.SessionManager.EndSessionDialog", BusNameOwnerFlags.NONE,
(connection) => {
try {
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,
(connection) => {
try {
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") );
}

public void perform_action (ActionType type) throws DBusError, IOError {
wm.perform_action (type);
() => critical ("Could not acquire ScreenSaver bus")
);
}
}
30 changes: 18 additions & 12 deletions src/DBusAccelerator.vala
Original file line number Diff line number Diff line change
Expand Up @@ -72,24 +72,18 @@ namespace Gala {

[DBus (name="org.gnome.Shell")]
public class DBusAccelerator {
private static DBusAccelerator? instance;

[DBus (visible = false)]
public static unowned DBusAccelerator init (Meta.Display display) {
if (instance == null) {
instance = new DBusAccelerator (display);
}

return instance;
}
private const string NOTIFICATION_COMPONENT_NAME = "DBusAccelerator";

public signal void accelerator_activated (uint action, GLib.HashTable<string, Variant> parameters);

private Meta.Display display;
private NotificationsManager notifications_manager;
private GLib.HashTable<unowned string, GrabbedAccelerator> grabbed_accelerators;

private DBusAccelerator (Meta.Display _display) {
public DBusAccelerator (Meta.Display _display, NotificationsManager _notifications_manager) {
display = _display;
notifications_manager = _notifications_manager;

grabbed_accelerators = new HashTable<unowned string, GrabbedAccelerator> (str_hash, str_equal);
display.accelerator_activated.connect (on_accelerator_activated);
}
Expand Down Expand Up @@ -176,7 +170,19 @@ namespace Gala {
level = (int)(double_level * 100);
}

MediaFeedback.send (icon, level);
var hints = new GLib.HashTable<string, Variant> (null, null);
hints.set ("x-canonical-private-synchronous", new Variant.string ("gala-feedback"));
hints.set ("value", new Variant.int32 (level));

notifications_manager.send (
new NotificationsManager.NotificationData (
NOTIFICATION_COMPONENT_NAME,
label,
"",
icon,
hints
)
);
}
}
}
107 changes: 0 additions & 107 deletions src/MediaFeedback.vala

This file was deleted.

121 changes: 121 additions & 0 deletions src/NotificationsManager.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* SPDX-License-Identifier: GPL-3.0-or-later
* SPDX-FileCopyrightText: 2016 Rico Tzschichholz
* 2025 elementary, Inc. (https://elementary.io)
*/

/**
* Gala.NotificationsManager can be used to send notifications to org.freedesktop.Notifications
*/
public class Gala.NotificationsManager : GLib.Object {
[DBus (name = "org.freedesktop.Notifications")]
private interface DBusNotifications : GLib.Object {
public abstract uint32 notify (string app_name, uint32 replaces_id, string app_icon, string summary,
string body, string[] actions, HashTable<string, Variant> hints, int32 expire_timeout) throws DBusError, IOError;
}

private const int EXPIRE_TIMEOUT = 2000;

/**
* Data structure to hold notification data. Component name is used to correctly replace notifications.
*/
[Compact]
public class NotificationData {
public string component_name;
public string summary;
public string body;
public string icon;
public GLib.HashTable<string, Variant> hints;

public NotificationData (
string _component_name,
string _summary,
string _body,
string _icon,
GLib.HashTable<string, Variant> _hints
) {
component_name = _component_name;
summary = _summary;
body = _body;
icon = _icon;
hints = _hints;
}
}

private ThreadPool<NotificationData>? pool = null;
private DBusNotifications? notifications = null;
private GLib.HashTable<string, uint32> replaces_id_table = new GLib.HashTable<string, uint32> (str_hash, str_equal);

construct {
try {
pool = new ThreadPool<NotificationData>.with_owned_data (send_feedback, 1, false);
} catch (ThreadError e) {
warning (e.message);
pool = null;
}

try {
Bus.watch_name (BusType.SESSION, "org.freedesktop.Notifications", BusNameWatcherFlags.NONE, on_watch, on_unwatch);
} catch (IOError e) {
warning (e.message);
}
}

private void on_watch (DBusConnection conn) {
conn.get_proxy.begin<DBusNotifications> (
"org.freedesktop.Notifications", "/org/freedesktop/Notifications", DBusProxyFlags.NONE, null,
(obj, res) => {
try {
notifications = ((DBusConnection) obj).get_proxy.end<DBusNotifications> (res);
} catch (Error e) {
warning (e.message);
notifications = null;
}
}
);
}

private void on_unwatch (DBusConnection conn) {
notifications = null;
}

public void send (owned NotificationData notification_data) {
if (pool == null) {
return;
}

try {
pool.add ((owned) notification_data);
} catch (ThreadError e) {
warning ("NotificationsManager: could't add notificationData: %s", e.message);
}
}

private void send_feedback (owned NotificationData notification_data) {
if (notifications == null) {
return;
}

uint32? replaces_id = replaces_id_table.get (notification_data.component_name);
if (replaces_id == null) {
replaces_id = 0;
}

try {
var notification_id = notifications.notify (
"gala-feedback",
replaces_id,
notification_data.icon,
notification_data.summary,
notification_data.body,
{},
notification_data.hints,
EXPIRE_TIMEOUT
);

replaces_id_table.insert (notification_data.component_name, notification_id);
} catch (Error e) {
critical (e.message);
}
}
}
Loading
Loading