Skip to content

Commit

Permalink
Background: minor changes
Browse files Browse the repository at this point in the history
* move dbus interfaces out of the classes bodies, use constants for path and
  name.

* use enumeration values where applicable and skip the namespace when possible.

* simplify the response callback in the notify_background().

* make the notification_closed() callback return ALLOW_ONCE in more types of
  reasons.

* remove temporary variables where applicable.

Signed-off-by: Gustavo Marques <[email protected]>
  • Loading branch information
Marukesu committed Jun 7, 2023
1 parent 99914e2 commit bf258a7
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 88 deletions.
92 changes: 51 additions & 41 deletions src/Background/NotificationRequest.vala
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,44 @@
* SPDX-License-Identifier: LGPL-2.1-or-later
*/

[DBus (name = "org.freedesktop.Notifications")]
private interface Fdo.Notifications : Object {
public signal void action_invoked (uint32 id, string action_key);
public signal void notification_closed (uint32 id, CloseReason reason);

public const string NAME = "org.freedesktop.Notifications";
public const string PATH = "/org/freedesktop/Notifications";

[DBus (signature = "u")]
public enum CloseReason {
EXPIRED = 1,
DIMISSED,
CANCELLED
}

public abstract void close_notification (uint32 id) throws DBusError, IOError;
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;
}

[DBus (name = "org.freedesktop.impl.portal.Request")]
public class NotificationRequest : Object {
public class Background.NotificationRequest : Object {
[DBus (visible = false)]
public signal void response (uint32 result);
public signal void response (NotifyBackgroundResult result);

private const string ACTION_ALLOW_BACKGROUND = "background.allow";
private const string ACTION_FORBID_BACKGROUND = "background.forbid";

private static HashTable<uint32, NotificationRequest> notification_by_id;
private static Notifications notifications;
private static HashTable<uint32, unowned NotificationRequest> requests;
private static Fdo.Notifications notifications;

private uint32 id = 0;

Expand All @@ -24,60 +52,41 @@ public class NotificationRequest : Object {
FAILED
}

[DBus (name = "org.freedesktop.Notifications")]
public interface Notifications : Object {
public signal void action_invoked (uint32 id, string action_key);
public signal void notification_closed (uint32 id, uint32 reason);

public abstract void close_notification (uint32 id) throws DBusError, IOError;
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;
}

[DBus (visible = false)]
public static void init (DBusConnection connection) {
notification_by_id = new HashTable<uint32, NotificationRequest> (null, null);
requests = new HashTable<uint32, unowned NotificationRequest> (null, null);

try {
notifications = connection.get_proxy_sync ("org.freedesktop.Notifications", "/org/freedesktop/Notifications");
notifications.action_invoked.connect (on_action_invoked);
notifications.notification_closed.connect (on_notification_closed);
notifications = connection.get_proxy_sync (Fdo.Notifications.NAME, Fdo.Notifications.PATH);
notifications.action_invoked.connect (action_invoked);
notifications.notification_closed.connect (notification_closed);
} catch {
warning ("Cannot connect to notifications dbus, background portal working with reduced functionality.");
warning ("Cannot connect to notifications dbus, portal working with reduced functionality.");
}
}

private static void on_action_invoked (uint32 id, string action_key) {
var notification = notification_by_id.take (id);
private static void action_invoked (uint32 id, string action_key) {
unowned var notification = requests.take (id);
if (notification == null) {
return;
}

if (action_key == ACTION_ALLOW_BACKGROUND) {
notification.response (NotifyBackgroundResult.ALLOW);
notification.response (ALLOW);
} else {
notification.response (NotifyBackgroundResult.FORBID);
notification.response (FORBID);
}
}

private static void on_notification_closed (uint32 id, uint32 reason) {
var notification = notification_by_id.take (id);
private static void notification_closed (uint32 id, Fdo.Notifications.CloseReason reason) {
unowned var notification = requests.take (id);
if (notification == null) {
return;
}

if (reason == 2) { //Dismissed by user
notification.response (NotifyBackgroundResult.ALLOW_ONCE);
} else if (reason == 3) { //Closed via DBus call
notification.response (NotifyBackgroundResult.CANCELLED);
if (reason == CANCELLED) { // Closed via DBus call
notification.response (CANCELLED);
} else { // Dismissed, Expired, or something internal to the server
notification.response (ALLOW_ONCE);
}
}

Expand All @@ -89,6 +98,7 @@ public class NotificationRequest : Object {
ACTION_FORBID_BACKGROUND,
_("Forbid")
};

var hints = new HashTable<string, Variant> (null, null);
hints["desktop-entry"] = app_id;
hints["urgency"] = (uint8) 1;
Expand All @@ -103,10 +113,10 @@ public class NotificationRequest : Object {
-1
);

notification_by_id.set (id, this);
requests[id] = this;
} catch (Error e) {
warning ("Failed to send notification for app id '%s': %s", app_id, e.message);
response (NotifyBackgroundResult.FAILED);
warning ("Failed to notify background activity from '%s': %s", app_id, e.message);
response (FAILED);
}
}

Expand Down
87 changes: 40 additions & 47 deletions src/Background/Portal.vala
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,41 @@
* SPDX-License-Identifier: LGPL-2.1-or-later
*/

[DBus (name = "org.pantheon.gala.DesktopIntegration")]
private interface Gala.DesktopIntegration : Object {
public signal void running_applications_changed ();

public const string NAME = "org.pantheon.gala";
public const string PATH = "/org/pantheon/gala/DesktopInterface";

public struct RunningApplications {
string app_id;
HashTable<string,Variant> details;
}

public abstract RunningApplications[] get_running_applications () throws DBusError, IOError;
}

[DBus (name = "org.freedesktop.impl.portal.Background")]
public class Background.Portal : Object {
public signal void running_applications_changed ();

private Gala.DesktopIntegration? desktop_integration;
private DBusConnection connection;
private DesktopIntegration desktop_integration;

public Portal (DBusConnection connection) {
this.connection = connection;
NotificationRequest.init (connection);
try {
desktop_integration = connection.get_proxy_sync ("org.pantheon.gala", "/org/pantheon/gala/DesktopInterface");
desktop_integration = connection.get_proxy_sync (Gala.DesktopIntegration.NAME, Gala.DesktopIntegration.PATH);
desktop_integration.running_applications_changed.connect (() => running_applications_changed ());
} catch {
warning ("Cannot connect to compositor, background portal working with reduced functionality.");
}
}

[DBus (name = "org.pantheon.gala.DesktopIntegration")]
public interface DesktopIntegration : Object {
public struct RunningApplications {
string app_id;
HashTable<string,Variant> details;
warning ("Cannot connect to compositor, portal working with reduced functionality.");
}

public signal void running_applications_changed ();
public abstract RunningApplications[] get_running_applications () throws DBusError, IOError;
}

[DBus (signature = "u")]
private enum ApplicationState {
BACKGROUND,
RUNNING,
Expand All @@ -43,18 +49,18 @@ public class Background.Portal : Object {
throw new DBusError.FAILED ("No connection to compositor.");
}

var apps = desktop_integration.get_running_applications ();
var results = new HashTable<string, Variant> (null, null);
foreach (var app in apps) {
debug ("getting application states");

foreach (var app in desktop_integration.get_running_applications ()) {
var app_id = app.app_id;
if (app_id.has_suffix (".desktop")) {
app_id = app_id.slice (0, app_id.last_index_of_char ('.'));
}

var app_state = ApplicationState.RUNNING; //FIXME: Don't hardcode: needs implementation on the gala side

results[app_id] = (uint32) app_state;
debug ("App state of '%s' set to %u (= %s).", app_id, app_state, app_state.to_string ());
results[app_id] = app_state;
}

return results;
Expand All @@ -69,40 +75,32 @@ public class Background.Portal : Object {
) throws DBusError, IOError {
debug ("Notify background for '%s'.", app_id);

uint32 _response = 2;
var _results = new HashTable<string, Variant> (str_hash, str_equal);
uint32 _response = 2;

var notification_request = new NotificationRequest ();

notification_request.response.connect ((result) => {
switch (result) {
case NotificationRequest.NotifyBackgroundResult.CANCELLED:
_response = 1;
break;
case NotificationRequest.NotifyBackgroundResult.FAILED:
break;
default:
_response = 0;
_results["result"] = (uint32) result;
break;
var notification = new NotificationRequest ();
notification.response.connect ((result) => {
if (result == CANCELLED) {
_response = 1;
} else if (result != FAILED) {
_response = 0;
_results["result"] = result;
}

debug ("Response to background activity of '%s': %s.", app_id, result.to_string ());

notify_background.callback ();
});

uint register_id = 0;
try {
register_id = connection.register_object<NotificationRequest> (handle, notification_request);
register_id = connection.register_object<NotificationRequest> (handle, notification);
} catch (Error e) {
warning ("Failed to export request object: %s", e.message);
throw new DBusError.OBJECT_PATH_IN_USE (e.message);
}

debug ("Sending desktop notification for '%s'.", app_id);
notification_request.send_notification (app_id, name);

notification.send_notification (app_id, name);
yield;

connection.unregister_object (register_id);
Expand Down Expand Up @@ -135,11 +133,10 @@ public class Background.Portal : Object {
*/
var app_info = new DesktopAppInfo (_app_id + ".desktop");
if (app_info == null) {
_app_id = string.joinv ("-", commandline).replace ("--", "-");
_app_id = string.joinv ("-", commandline).replace ("--", "-").replace ("--", "-");
}

var path = Path.build_filename (Environment.get_user_config_dir (), "autostart", _app_id + ".desktop");

if (!enable) {
FileUtils.unlink (path);
return false;
Expand All @@ -158,29 +155,25 @@ public class Background.Portal : Object {
key_file.set_string (KeyFileDesktop.GROUP, KeyFileDesktop.KEY_COMMENT, string.joinv (" ", commandline));
}

key_file.set_string (KeyFileDesktop.GROUP, KeyFileDesktop.KEY_EXEC, flatpak_quote_argv (commandline));

if (flags == AutostartFlags.DBUS_ACTIVATABLE) {
key_file.set_boolean (KeyFileDesktop.GROUP, KeyFileDesktop.KEY_DBUS_ACTIVATABLE, true);
}
key_file.set_string (KeyFileDesktop.GROUP, KeyFileDesktop.KEY_EXEC, quote_argv (commandline));
key_file.set_boolean (KeyFileDesktop.GROUP, KeyFileDesktop.KEY_DBUS_ACTIVATABLE, flags == DBUS_ACTIVATABLE);

if (app_id.strip () != "") {
if (app_id != "") {
key_file.set_string (KeyFileDesktop.GROUP, "X-Flatpak", app_id);
}

try {
key_file.save_to_file (path);
} catch (Error e) {
warning ("Failed to write autostart file: %s", e.message);
return false;
throw new DBusError.FAILED (e.message);
}

debug ("Autostart file installed for '%s'.", app_id);

debug ("Autostart file installed at '%s'.", path);
return true;
}

private string flatpak_quote_argv (string[] argv) {
private string quote_argv (string[] argv) {
var builder = new StringBuilder ();

foreach (var arg in argv) {
Expand Down

0 comments on commit bf258a7

Please sign in to comment.