mirror of
https://github.com/elementary/gala.git
synced 2024-11-30 00:44:06 +03:00
wayland: Launch notifications server as a wayland client (#1882)
This commit is contained in:
parent
4c6f503b31
commit
0e88796b96
@ -34,4 +34,10 @@ namespace Gala {
|
|||||||
// Duration of the nudge animation when trying to switch to at the end of the workspace list
|
// Duration of the nudge animation when trying to switch to at the end of the workspace list
|
||||||
NUDGE = 360,
|
NUDGE = 360,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used as a key for Object.set_data<bool> on Meta.Windows that should be
|
||||||
|
* treated as notifications. Has to be set before the window is mapped.
|
||||||
|
*/
|
||||||
|
public const string NOTIFICATION_DATA_KEY = "elementary-notification";
|
||||||
}
|
}
|
||||||
|
76
src/ShellClients/ManagedClient.vala
Normal file
76
src/ShellClients/ManagedClient.vala
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 elementary, Inc. (https://elementary.io)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* Authored by: Leonhard Kargl <leo.kargl@proton.me>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class that takes care of launching and restarting a subprocess.
|
||||||
|
* On wayland this uses a WaylandClient and emits window_created if a window for the client was created.
|
||||||
|
* On X this just launches a normal subprocess and never emits window_created.
|
||||||
|
*/
|
||||||
|
public class Gala.ManagedClient : Object {
|
||||||
|
public signal void window_created (Meta.Window window);
|
||||||
|
|
||||||
|
public Meta.Display display { get; construct; }
|
||||||
|
public string[] args { get; construct; }
|
||||||
|
|
||||||
|
public Meta.WaylandClient? wayland_client { get; private set; }
|
||||||
|
|
||||||
|
public ManagedClient (Meta.Display display, string[] args) {
|
||||||
|
Object (display: display, args: args);
|
||||||
|
}
|
||||||
|
|
||||||
|
construct {
|
||||||
|
if (Meta.Util.is_wayland_compositor ()) {
|
||||||
|
start_wayland.begin ();
|
||||||
|
|
||||||
|
display.window_created.connect ((window) => {
|
||||||
|
if (wayland_client != null && wayland_client.owns_window (window)) {
|
||||||
|
window_created (window);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
start_x.begin ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void start_wayland () {
|
||||||
|
var subprocess_launcher = new GLib.SubprocessLauncher (STDERR_PIPE | STDOUT_PIPE);
|
||||||
|
try {
|
||||||
|
#if HAS_MUTTER44
|
||||||
|
wayland_client = new Meta.WaylandClient (display.get_context (), subprocess_launcher);
|
||||||
|
#else
|
||||||
|
wayland_client = new Meta.WaylandClient (subprocess_launcher);
|
||||||
|
#endif
|
||||||
|
var subprocess = wayland_client.spawnv (display, args);
|
||||||
|
|
||||||
|
yield subprocess.wait_async ();
|
||||||
|
|
||||||
|
//Restart the daemon if it crashes
|
||||||
|
Timeout.add_seconds (1, () => {
|
||||||
|
start_wayland.begin ();
|
||||||
|
return Source.REMOVE;
|
||||||
|
});
|
||||||
|
} catch (Error e) {
|
||||||
|
warning ("Failed to create dock client: %s", e.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void start_x () {
|
||||||
|
try {
|
||||||
|
var subprocess = new Subprocess.newv (args, NONE);
|
||||||
|
yield subprocess.wait_async ();
|
||||||
|
|
||||||
|
//Restart the daemon if it crashes
|
||||||
|
Timeout.add_seconds (1, () => {
|
||||||
|
start_x.begin ();
|
||||||
|
return Source.REMOVE;
|
||||||
|
});
|
||||||
|
} catch (Error e) {
|
||||||
|
warning ("Failed to create daemon subprocess with x: %s", e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
src/ShellClients/NotificationsClient.vala
Normal file
28
src/ShellClients/NotificationsClient.vala
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 elementary, Inc. (https://elementary.io)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* Authored by: Leonhard Kargl <leo.kargl@proton.me>
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Gala.NotificationsClient : Object {
|
||||||
|
public Meta.Display display { get; construct; }
|
||||||
|
|
||||||
|
private ManagedClient client;
|
||||||
|
|
||||||
|
public NotificationsClient (Meta.Display display) {
|
||||||
|
Object (display: display);
|
||||||
|
}
|
||||||
|
|
||||||
|
construct {
|
||||||
|
client = new ManagedClient (display, { "io.elementary.notifications" });
|
||||||
|
|
||||||
|
client.window_created.connect ((window) => {
|
||||||
|
window.set_data (NOTIFICATION_DATA_KEY, true);
|
||||||
|
window.make_above ();
|
||||||
|
#if HAS_MUTTER_46
|
||||||
|
client.wayland_client.make_dock (window);
|
||||||
|
#endif
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
20
src/ShellClients/ShellClientsManager.vala
Normal file
20
src/ShellClients/ShellClientsManager.vala
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 elementary, Inc. (https://elementary.io)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* Authored by: Leonhard Kargl <leo.kargl@proton.me>
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Gala.ShellClientsManager : Object {
|
||||||
|
public Meta.Display display { get; construct; }
|
||||||
|
|
||||||
|
private NotificationsClient notifications_client;
|
||||||
|
|
||||||
|
public ShellClientsManager (Meta.Display display) {
|
||||||
|
Object (display: display);
|
||||||
|
}
|
||||||
|
|
||||||
|
construct {
|
||||||
|
notifications_client = new NotificationsClient (display);
|
||||||
|
}
|
||||||
|
}
|
@ -83,6 +83,8 @@ namespace Gala {
|
|||||||
|
|
||||||
private DaemonManager daemon_manager;
|
private DaemonManager daemon_manager;
|
||||||
|
|
||||||
|
private ShellClientsManager shell_clients_manager;
|
||||||
|
|
||||||
private WindowGrabTracker window_grab_tracker;
|
private WindowGrabTracker window_grab_tracker;
|
||||||
|
|
||||||
private NotificationStack notification_stack;
|
private NotificationStack notification_stack;
|
||||||
@ -143,6 +145,7 @@ namespace Gala {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override void start () {
|
public override void start () {
|
||||||
|
shell_clients_manager = new ShellClientsManager (get_display ());
|
||||||
daemon_manager = new DaemonManager (get_display ());
|
daemon_manager = new DaemonManager (get_display ());
|
||||||
window_grab_tracker = new WindowGrabTracker (get_display ());
|
window_grab_tracker = new WindowGrabTracker (get_display ());
|
||||||
|
|
||||||
@ -1446,10 +1449,20 @@ namespace Gala {
|
|||||||
move_window_to_next_ws (window);
|
move_window_to_next_ws (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notifications are a special case and have to be always be handled
|
actor.remove_all_transitions ();
|
||||||
// regardless of the animation setting
|
|
||||||
if (!enable_animations && window.window_type != Meta.WindowType.NOTIFICATION) {
|
|
||||||
actor.show ();
|
actor.show ();
|
||||||
|
|
||||||
|
// Notifications are a special case and have to be always be handled
|
||||||
|
// (also regardless of the animation setting)
|
||||||
|
if (window.get_data (NOTIFICATION_DATA_KEY) || window.window_type == NOTIFICATION) {
|
||||||
|
clutter_actor_reparent (actor, notification_group);
|
||||||
|
notification_stack.show_notification (actor, enable_animations);
|
||||||
|
|
||||||
|
map_completed (actor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!enable_animations) {
|
||||||
map_completed (actor);
|
map_completed (actor);
|
||||||
|
|
||||||
if (InternalUtils.get_window_is_normal (window) && window.get_layer () == Meta.StackLayer.BOTTOM) {
|
if (InternalUtils.get_window_is_normal (window) && window.get_layer () == Meta.StackLayer.BOTTOM) {
|
||||||
@ -1459,9 +1472,6 @@ namespace Gala {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
actor.remove_all_transitions ();
|
|
||||||
actor.show ();
|
|
||||||
|
|
||||||
switch (window.window_type) {
|
switch (window.window_type) {
|
||||||
case Meta.WindowType.NORMAL:
|
case Meta.WindowType.NORMAL:
|
||||||
var duration = AnimationDuration.HIDE;
|
var duration = AnimationDuration.HIDE;
|
||||||
@ -1558,12 +1568,6 @@ namespace Gala {
|
|||||||
|
|
||||||
dim_parent_window (window);
|
dim_parent_window (window);
|
||||||
|
|
||||||
break;
|
|
||||||
case Meta.WindowType.NOTIFICATION:
|
|
||||||
clutter_actor_reparent (actor, notification_group);
|
|
||||||
notification_stack.show_notification (actor, enable_animations);
|
|
||||||
map_completed (actor);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
map_completed (actor);
|
map_completed (actor);
|
||||||
@ -1576,7 +1580,30 @@ namespace Gala {
|
|||||||
|
|
||||||
ws_assoc.remove (window);
|
ws_assoc.remove (window);
|
||||||
|
|
||||||
if (!enable_animations && window.window_type != Meta.WindowType.NOTIFICATION) {
|
actor.remove_all_transitions ();
|
||||||
|
|
||||||
|
if (window.get_data (NOTIFICATION_DATA_KEY) || window.window_type == NOTIFICATION) {
|
||||||
|
if (enable_animations) {
|
||||||
|
destroying.add (actor);
|
||||||
|
}
|
||||||
|
|
||||||
|
notification_stack.destroy_notification (actor, enable_animations);
|
||||||
|
|
||||||
|
if (enable_animations) {
|
||||||
|
ulong destroy_handler_id = 0UL;
|
||||||
|
destroy_handler_id = actor.transitions_completed.connect (() => {
|
||||||
|
actor.disconnect (destroy_handler_id);
|
||||||
|
destroying.remove (actor);
|
||||||
|
destroy_completed (actor);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
destroy_completed (actor);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!enable_animations) {
|
||||||
destroy_completed (actor);
|
destroy_completed (actor);
|
||||||
|
|
||||||
if (window.window_type == Meta.WindowType.NORMAL) {
|
if (window.window_type == Meta.WindowType.NORMAL) {
|
||||||
@ -1586,8 +1613,6 @@ namespace Gala {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
actor.remove_all_transitions ();
|
|
||||||
|
|
||||||
switch (window.window_type) {
|
switch (window.window_type) {
|
||||||
case Meta.WindowType.NORMAL:
|
case Meta.WindowType.NORMAL:
|
||||||
var duration = AnimationDuration.CLOSE;
|
var duration = AnimationDuration.CLOSE;
|
||||||
@ -1659,25 +1684,6 @@ namespace Gala {
|
|||||||
destroying.remove (actor);
|
destroying.remove (actor);
|
||||||
destroy_completed (actor);
|
destroy_completed (actor);
|
||||||
});
|
});
|
||||||
break;
|
|
||||||
case Meta.WindowType.NOTIFICATION:
|
|
||||||
if (enable_animations) {
|
|
||||||
destroying.add (actor);
|
|
||||||
}
|
|
||||||
|
|
||||||
notification_stack.destroy_notification (actor, enable_animations);
|
|
||||||
|
|
||||||
if (enable_animations) {
|
|
||||||
ulong destroy_handler_id = 0UL;
|
|
||||||
destroy_handler_id = actor.transitions_completed.connect (() => {
|
|
||||||
actor.disconnect (destroy_handler_id);
|
|
||||||
destroying.remove (actor);
|
|
||||||
destroy_completed (actor);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
destroy_completed (actor);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
destroy_completed (actor);
|
destroy_completed (actor);
|
||||||
|
@ -39,6 +39,9 @@ gala_bin_sources = files(
|
|||||||
'HotCorners/Barrier.vala',
|
'HotCorners/Barrier.vala',
|
||||||
'HotCorners/HotCorner.vala',
|
'HotCorners/HotCorner.vala',
|
||||||
'HotCorners/HotCornerManager.vala',
|
'HotCorners/HotCornerManager.vala',
|
||||||
|
'ShellClients/ManagedClient.vala',
|
||||||
|
'ShellClients/NotificationsClient.vala',
|
||||||
|
'ShellClients/ShellClientsManager.vala',
|
||||||
'Widgets/DwellClickTimer.vala',
|
'Widgets/DwellClickTimer.vala',
|
||||||
'Widgets/IconGroup.vala',
|
'Widgets/IconGroup.vala',
|
||||||
'Widgets/IconGroupContainer.vala',
|
'Widgets/IconGroupContainer.vala',
|
||||||
|
Loading…
Reference in New Issue
Block a user