mirror of
https://github.com/elementary/gala.git
synced 2024-11-27 07:38:47 +03:00
try to find the window a notification belongs to and focus it when the notification is clicked
This commit is contained in:
parent
bd13e5d929
commit
f3fa2b79fc
@ -31,7 +31,7 @@ namespace Gala.Plugins.Notify
|
||||
{
|
||||
this.wm = wm;
|
||||
|
||||
stack = new NotificationStack ();
|
||||
stack = new NotificationStack (wm.get_screen ());
|
||||
wm.ui_group.add_child (stack);
|
||||
track_actor (stack);
|
||||
|
||||
|
@ -29,13 +29,14 @@ namespace Gala.Plugins.Notify
|
||||
const int SPACING = 6;
|
||||
const int PADDING = 4;
|
||||
|
||||
public Screen screen { get; construct; }
|
||||
public uint32 id { get; construct; }
|
||||
public string summary { get; construct set; }
|
||||
public string body { get; construct set; }
|
||||
public Gdk.Pixbuf? icon { get; construct set; }
|
||||
public NotificationUrgency urgency { get; construct; }
|
||||
public int32 expire_timeout { get; construct set; }
|
||||
public Window? window { get; construct; }
|
||||
public uint32 sender_pid { get; construct; }
|
||||
public string[] notification_actions { get; construct set; }
|
||||
|
||||
public uint64 relevancy_time { get; private set; }
|
||||
@ -48,17 +49,18 @@ namespace Gala.Plugins.Notify
|
||||
|
||||
uint remove_timeout = 0;
|
||||
|
||||
public Notification (uint32 id, string summary, string body, Gdk.Pixbuf? icon,
|
||||
NotificationUrgency urgency, int32 expire_timeout, Window? window, string[] actions)
|
||||
public Notification (Screen screen, uint32 id, string summary, string body, Gdk.Pixbuf? icon,
|
||||
NotificationUrgency urgency, int32 expire_timeout, uint32 pid, string[] actions)
|
||||
{
|
||||
Object (
|
||||
screen: screen,
|
||||
id: id,
|
||||
summary: summary,
|
||||
body: body,
|
||||
icon: icon,
|
||||
urgency: urgency,
|
||||
expire_timeout: expire_timeout,
|
||||
window: window,
|
||||
sender_pid: pid,
|
||||
notification_actions: actions
|
||||
);
|
||||
|
||||
@ -81,16 +83,7 @@ namespace Gala.Plugins.Notify
|
||||
|
||||
icon_texture = new GtkClutter.Texture ();
|
||||
|
||||
// TODO replace with the real close button once multitaskingview is merged
|
||||
// close_button = Utils.create_close_button ();
|
||||
close_button = new GtkClutter.Texture ();
|
||||
try {
|
||||
close_button.set_from_pixbuf (Granite.Widgets.Utils.get_close_pixbuf ());
|
||||
} catch (Error e) {
|
||||
close_button.background_color = { 180, 0, 0, 255 };
|
||||
}
|
||||
close_button.width = 28;
|
||||
close_button.height = 28;
|
||||
close_button = Utils.create_close_button ();
|
||||
close_button.opacity = 0;
|
||||
close_button.reactive = true;
|
||||
close_button.set_easing_duration (300);
|
||||
@ -124,6 +117,21 @@ namespace Gala.Plugins.Notify
|
||||
transition.add_transition (slide_transition);
|
||||
|
||||
add_transition ("entry", transition);
|
||||
|
||||
var click = new ClickAction ();
|
||||
click.clicked.connect (() => {
|
||||
var window = get_window ();
|
||||
if (window != null) {
|
||||
var workspace = window.get_workspace ();
|
||||
var time = screen.get_display ().get_current_time ();
|
||||
|
||||
if (workspace != screen.get_active_workspace ())
|
||||
workspace.activate_with_focus (window, time);
|
||||
else
|
||||
window.activate (time);
|
||||
}
|
||||
});
|
||||
add_action (click);
|
||||
}
|
||||
|
||||
public void close ()
|
||||
@ -134,6 +142,24 @@ namespace Gala.Plugins.Notify
|
||||
get_transition ("opacity").completed.connect (() => destroy ());
|
||||
}
|
||||
|
||||
Window? get_window ()
|
||||
{
|
||||
if (sender_pid == 0)
|
||||
return null;
|
||||
|
||||
foreach (var actor in Compositor.get_window_actors (screen)) {
|
||||
var window = actor.get_meta_window ();
|
||||
|
||||
// the windows are sorted by stacking order when returned
|
||||
// from meta_get_window_actors, so we can just pick the first
|
||||
// one we find and have a pretty good match
|
||||
if (window.get_pid () == sender_pid)
|
||||
return window;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void update (string summary, string body, Gdk.Pixbuf? icon, int32 expire_timeout,
|
||||
string[] actions)
|
||||
{
|
||||
|
@ -24,15 +24,19 @@ namespace Gala.Plugins.Notify
|
||||
{
|
||||
public signal void animations_changed (bool running);
|
||||
|
||||
public Screen screen { get; construct; }
|
||||
|
||||
int animation_counter = 0;
|
||||
|
||||
public NotificationStack ()
|
||||
public NotificationStack (Screen screen)
|
||||
{
|
||||
Object (screen: screen);
|
||||
|
||||
width = Notification.WIDTH + 2 * Notification.MARGIN;
|
||||
}
|
||||
|
||||
public void show_notification (uint32 id, string summary, string body, Gdk.Pixbuf? icon,
|
||||
NotificationUrgency urgency, int32 expire_timeout, Window? window, string[] actions)
|
||||
NotificationUrgency urgency, int32 expire_timeout, uint32 sender_pid, string[] actions)
|
||||
{
|
||||
if (animation_counter == 0)
|
||||
animations_changed (true);
|
||||
@ -56,8 +60,8 @@ namespace Gala.Plugins.Notify
|
||||
}
|
||||
}
|
||||
|
||||
var notification = new Notification (id, summary, body, icon, urgency,
|
||||
expire_timeout, window, actions);
|
||||
var notification = new Notification (screen, id, summary, body, icon,
|
||||
urgency, expire_timeout, sender_pid, actions);
|
||||
|
||||
add_child (notification);
|
||||
|
||||
|
@ -28,7 +28,14 @@ namespace Gala.Plugins.Notify
|
||||
CRITICAL = 2
|
||||
}
|
||||
|
||||
[DBus (name="org.freedesktop.Notifications")]
|
||||
[DBus (name = "org.freedesktop.DBus")]
|
||||
private interface DBus : Object
|
||||
{
|
||||
[DBus (name = "GetConnectionUnixProcessID")]
|
||||
public abstract uint32 get_connection_unix_process_id (string name) throws Error;
|
||||
}
|
||||
|
||||
[DBus (name = "org.freedesktop.Notifications")]
|
||||
public class NotifyServer : Object
|
||||
{
|
||||
const int DEFAULT_TMEOUT = 3000;
|
||||
@ -36,15 +43,23 @@ namespace Gala.Plugins.Notify
|
||||
|
||||
[DBus (visible = false)]
|
||||
public signal void show_notification (uint32 id, string summary, string body, Gdk.Pixbuf? icon,
|
||||
NotificationUrgency urgency, int32 expire_timeout, Window? window, string[] actions);
|
||||
NotificationUrgency urgency, int32 expire_timeout, uint32 sender_pid, string[] actions);
|
||||
|
||||
[DBus (visible = false)]
|
||||
public signal void notification_closed (uint32 id);
|
||||
|
||||
uint32 id_counter = 0;
|
||||
|
||||
DBus? bus_proxy = null;
|
||||
|
||||
public NotifyServer ()
|
||||
{
|
||||
try {
|
||||
bus_proxy = Bus.get_proxy_sync (BusType.SESSION, "org.freedesktop.DBus", "/");
|
||||
} catch (Error e) {
|
||||
warning (e.message);
|
||||
bus_proxy = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void close_notification (uint32 id)
|
||||
@ -67,25 +82,24 @@ namespace Gala.Plugins.Notify
|
||||
}
|
||||
|
||||
public new uint32 notify (string app_name, uint32 replaces_id, string app_icon, string summary,
|
||||
string body, string[] actions, HashTable<string, Variant> hints, int32 expire_timeout, BusName name)
|
||||
string body, string[] actions, HashTable<string, Variant> hints, int32 expire_timeout, BusName sender)
|
||||
{
|
||||
var id = replaces_id != 0 ? replaces_id : ++id_counter;
|
||||
var pixbuf = get_pixbuf (hints, app_name, app_icon);
|
||||
var window = get_window ();
|
||||
var timeout = expire_timeout == uint32.MAX ? DEFAULT_TMEOUT : expire_timeout;
|
||||
var urgency = hints.contains ("urgency") ?
|
||||
(NotificationUrgency) hints.lookup ("urgency").get_byte () : NotificationUrgency.NORMAL;
|
||||
|
||||
show_notification (id, summary, body, pixbuf, urgency, timeout, window, actions);
|
||||
uint32 pid = 0;
|
||||
try {
|
||||
pid = bus_proxy.get_connection_unix_process_id (sender);
|
||||
} catch (Error e) { warning (e.message); }
|
||||
|
||||
show_notification (id, summary, body, pixbuf, urgency, timeout, pid, actions);
|
||||
|
||||
return id_counter;
|
||||
}
|
||||
|
||||
Window? get_window ()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Gdk.Pixbuf? get_pixbuf (HashTable<string, Variant> hints, string app, string icon)
|
||||
{
|
||||
// decide on the icon, order:
|
||||
|
Loading…
Reference in New Issue
Block a user