mirror of
https://github.com/elementary/gala.git
synced 2024-11-25 03:06:14 +01:00
Add ShellComponentManager
This commit is contained in:
parent
053ab0ead4
commit
a503516bb0
69
src/ManagedClient.vala
Normal file
69
src/ManagedClient.vala
Normal file
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* 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 shown
|
||||
* On X this just launches a normal subprocess
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -38,6 +38,7 @@ namespace Gala {
|
||||
private static Pantheon.Desktop.WidgetInterface wayland_pantheon_widget_interface;
|
||||
private static Pantheon.Desktop.ExtendedBehaviorInterface wayland_pantheon_extended_behavior_interface;
|
||||
private static Wl.Global shell_global;
|
||||
private static ShellComponentManager component_manager;
|
||||
|
||||
public void init_pantheon_shell (Meta.Context context) {
|
||||
unowned Wl.Display? wl_disp = get_display_from_context (context);
|
||||
@ -72,6 +73,9 @@ namespace Gala {
|
||||
var resource = new Wl.Resource (client, ref Pantheon.Desktop.ShellInterface.iface, (int) version, id);
|
||||
resource.set_implementation (&wayland_pantheon_shell_interface, null, (res) => {});
|
||||
});
|
||||
|
||||
component_manager = new ShellComponentManager ();
|
||||
component_manager.init (context.get_display ());
|
||||
}
|
||||
|
||||
public class PanelSurface : GLib.Object {
|
||||
@ -243,7 +247,7 @@ namespace Gala {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO
|
||||
component_manager.set_anchor (window, TOP);
|
||||
}
|
||||
|
||||
internal static void set_keep_above (Wl.Client client, Wl.Resource resource) {
|
||||
|
110
src/ShellComponentManager.vala
Normal file
110
src/ShellComponentManager.vala
Normal file
@ -0,0 +1,110 @@
|
||||
public class Gala.ShellComponentManager : Object {
|
||||
private GLib.HashTable<Meta.Window, Meta.Side> window_anchors;
|
||||
private GLib.HashTable<Meta.Window, Meta.Strut?> window_struts;
|
||||
private GLib.HashTable<Meta.Window, ManagedClient> window_to_client;
|
||||
private Meta.Display display;
|
||||
private string[] components = {"io.elementary.dock"};
|
||||
private ManagedClient[] clients = {};
|
||||
|
||||
construct {
|
||||
window_anchors = new GLib.HashTable<Meta.Window, Meta.Side> (null, null);
|
||||
window_struts = new GLib.HashTable<Meta.Window, Meta.Strut?> (null, null);
|
||||
window_to_client = new GLib.HashTable<Meta.Window, ManagedClient> (null, null);
|
||||
}
|
||||
|
||||
public void init (Meta.Display display) {
|
||||
this.display = display;
|
||||
|
||||
foreach (var args in components) {
|
||||
var client = new ManagedClient (display, components);
|
||||
client.window_created.connect ((window) => {
|
||||
window_to_client[window] = client;
|
||||
window.unmanaged.connect (() => window_to_client.remove (window));
|
||||
});
|
||||
clients += client;
|
||||
}
|
||||
}
|
||||
|
||||
public void set_anchor (Meta.Window window, Meta.Side side) {
|
||||
#if !HAS_MUTTER46
|
||||
critical ("Mutter 46 required for wayland docks");
|
||||
return;
|
||||
#else
|
||||
var client = window_to_client[window];
|
||||
|
||||
if (client == null) {
|
||||
critical ("Window doesn't belong to a known client, can't set anchor.");
|
||||
return;
|
||||
}
|
||||
|
||||
client.make_dock (window);
|
||||
|
||||
position_window (window, side);
|
||||
|
||||
window_anchors[window] = side;
|
||||
|
||||
window.unmanaged.connect (() => {
|
||||
window_anchors.remove (window);
|
||||
if (window_struts.remove (window)) {
|
||||
update_struts ();
|
||||
}
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
public void make_exclusive (Meta.Window window) {
|
||||
if (!(window in window_anchors)) {
|
||||
warning ("Set an anchor before making a window area exclusive.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (window in window_struts) {
|
||||
warning ("Window is already exclusive.");
|
||||
return;
|
||||
}
|
||||
|
||||
window.size_changed.connect (update_strut);
|
||||
update_strut (window);
|
||||
}
|
||||
|
||||
private void update_strut (Meta.Window window) {
|
||||
var rect = window.get_frame_rect ();
|
||||
|
||||
Meta.Strut strut = {
|
||||
rect,
|
||||
window_anchors[window]
|
||||
};
|
||||
|
||||
window_struts[window] = strut;
|
||||
|
||||
update_struts ();
|
||||
}
|
||||
|
||||
private void update_struts () {
|
||||
var list = new SList<Meta.Strut?> ();
|
||||
|
||||
foreach (var window_strut in window_struts.get_values ()) {
|
||||
list.append (window_strut);
|
||||
}
|
||||
|
||||
foreach (var workspace in display.get_workspace_manager ().get_workspaces ()) {
|
||||
workspace.set_builtin_struts (list);
|
||||
}
|
||||
}
|
||||
|
||||
public void unmake_exclusive (Meta.Window window) {
|
||||
if (window in window_struts) {
|
||||
window.size_changed.disconnect (update_strut);
|
||||
window_struts.remove (window);
|
||||
}
|
||||
}
|
||||
|
||||
private void position_window (Meta.Window window, Meta.Side side) {
|
||||
switch (side) {
|
||||
case TOP:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ gala_bin_sources = files(
|
||||
'InternalUtils.vala',
|
||||
'KeyboardManager.vala',
|
||||
'Main.vala',
|
||||
'ManagedClient.vala',
|
||||
'MediaFeedback.vala',
|
||||
'NotificationStack.vala',
|
||||
'PantheonShell.vala',
|
||||
@ -13,6 +14,7 @@ gala_bin_sources = files(
|
||||
'ScreenSaverManager.vala',
|
||||
'ScreenshotManager.vala',
|
||||
'SessionManager.vala',
|
||||
'ShellComponentManager.vala',
|
||||
'WindowListener.vala',
|
||||
'WindowManager.vala',
|
||||
'WindowStateSaver.vala',
|
||||
|
Loading…
Reference in New Issue
Block a user