mirror of
https://github.com/elementary/gala.git
synced 2024-11-27 15:45:31 +03:00
ShellClients: Add Panels API
This commit is contained in:
parent
e4933a652f
commit
7ac65758ed
@ -439,4 +439,12 @@
|
||||
<description></description>
|
||||
</key>
|
||||
</schema>
|
||||
|
||||
<schema path="/io/elementary/desktop/wm/shell/" id="io.elementary.desktop.wm.shell">
|
||||
<key type="aas" name="trusted-clients">
|
||||
<default>[['io.elementary.dock'], ["io.elementary.wingpanel"]]</default>
|
||||
<summary>Clients to be launched by gala as trusted for interacting with the shell wl protcol.</summary>
|
||||
<description>An array of arrays of arguments to be used to launch the client.</description>
|
||||
</key>
|
||||
</schema>
|
||||
</schemalist>
|
||||
|
191
src/ShellClients/HideTracker.vala
Normal file
191
src/ShellClients/HideTracker.vala
Normal file
@ -0,0 +1,191 @@
|
||||
/*
|
||||
* 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.HideTracker : Object {
|
||||
private const uint UPDATE_TIMEOUT = 200;
|
||||
|
||||
public signal void hide ();
|
||||
public signal void show ();
|
||||
|
||||
public Meta.Display display { get; construct; }
|
||||
public PanelWindow panel { get; construct; }
|
||||
public PanelWindow.HideMode hide_mode { get; set; default = NEVER; }
|
||||
|
||||
private bool hovered = false;
|
||||
|
||||
private bool overlap = false;
|
||||
private bool focus_overlap = false;
|
||||
private bool focus_maximized_overlap = false;
|
||||
|
||||
private uint update_timeout_id = 0;
|
||||
|
||||
public HideTracker (Meta.Display display, PanelWindow panel) {
|
||||
Object (display: display, panel: panel);
|
||||
}
|
||||
|
||||
construct {
|
||||
var current_focus_window = display.focus_window;
|
||||
track_focus_window (current_focus_window);
|
||||
display.notify["focus-window"].connect (() => {
|
||||
untrack_focus_window (current_focus_window);
|
||||
current_focus_window = display.focus_window;
|
||||
track_focus_window (current_focus_window);
|
||||
});
|
||||
|
||||
display.window_created.connect ((window) => {
|
||||
schedule_update ();
|
||||
window.unmanaged.connect (schedule_update);
|
||||
});
|
||||
|
||||
var cursor_tracker = display.get_cursor_tracker ();
|
||||
cursor_tracker.position_invalidated.connect (() => {
|
||||
#if HAS_MUTTER45
|
||||
var has_pointer = panel.window.has_pointer ();
|
||||
#else
|
||||
var has_pointer = window_has_pointer ();
|
||||
#endif
|
||||
|
||||
if (hovered != has_pointer) {
|
||||
hovered = has_pointer;
|
||||
schedule_update ();
|
||||
}
|
||||
});
|
||||
|
||||
display.get_workspace_manager ().active_workspace_changed.connect (schedule_update);
|
||||
}
|
||||
|
||||
//Can be removed with mutter > 45
|
||||
private bool window_has_pointer () {
|
||||
var cursor_tracker = display.get_cursor_tracker ();
|
||||
Graphene.Point pointer_pos;
|
||||
cursor_tracker.get_pointer (out pointer_pos, null);
|
||||
|
||||
var window_rect = panel.get_custom_window_rect ();
|
||||
Graphene.Rect graphene_window_rect = {
|
||||
{
|
||||
window_rect.x,
|
||||
window_rect.y
|
||||
},
|
||||
{
|
||||
window_rect.width,
|
||||
window_rect.height
|
||||
}
|
||||
};
|
||||
return graphene_window_rect.contains_point (pointer_pos);
|
||||
}
|
||||
|
||||
private void track_focus_window (Meta.Window? window) {
|
||||
if (window == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.position_changed.connect (schedule_update);
|
||||
window.size_changed.connect (schedule_update);
|
||||
schedule_update ();
|
||||
}
|
||||
|
||||
private void untrack_focus_window (Meta.Window? window) {
|
||||
if (window == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.position_changed.disconnect (schedule_update);
|
||||
window.size_changed.disconnect (schedule_update);
|
||||
schedule_update ();
|
||||
}
|
||||
|
||||
public void schedule_update () {
|
||||
if (update_timeout_id != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
update_timeout_id = Timeout.add (UPDATE_TIMEOUT, () => {
|
||||
update_overlap ();
|
||||
update_timeout_id = 0;
|
||||
return Source.REMOVE;
|
||||
});
|
||||
}
|
||||
|
||||
private void update_overlap () {
|
||||
overlap = false;
|
||||
focus_overlap = false;
|
||||
focus_maximized_overlap = false;
|
||||
|
||||
foreach (var window in display.get_workspace_manager ().get_active_workspace ().list_windows ()) {
|
||||
if (window == panel.window) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (window.minimized) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var type = window.get_window_type ();
|
||||
if (type == DESKTOP || type == DOCK || type == MENU || type == SPLASHSCREEN) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!panel.get_custom_window_rect ().overlap (window.get_frame_rect ())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
overlap = true;
|
||||
|
||||
if (window != display.focus_window) {
|
||||
continue;
|
||||
}
|
||||
|
||||
focus_overlap = true;
|
||||
focus_maximized_overlap = window.get_maximized () == BOTH;
|
||||
}
|
||||
|
||||
update_hidden ();
|
||||
}
|
||||
|
||||
private void update_hidden () {
|
||||
switch (hide_mode) {
|
||||
case NEVER:
|
||||
toggle_display (false);
|
||||
break;
|
||||
|
||||
case MAXIMIZED_FOCUS_WINDOW:
|
||||
toggle_display (focus_maximized_overlap);
|
||||
break;
|
||||
|
||||
case OVERLAPPING_FOCUS_WINDOW:
|
||||
toggle_display (focus_overlap);
|
||||
break;
|
||||
|
||||
case OVERLAPPING_WINDOW:
|
||||
toggle_display (overlap);
|
||||
break;
|
||||
|
||||
case ALWAYS:
|
||||
toggle_display (true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void toggle_display (bool should_hide) {
|
||||
if (should_hide) {
|
||||
// Don't hide if we have transients, e.g. an open popover, dialog, etc.
|
||||
var has_transients = false;
|
||||
panel.window.foreach_transient (() => {
|
||||
has_transients = true;
|
||||
return false;
|
||||
});
|
||||
|
||||
if (hovered || has_transients) {
|
||||
return;
|
||||
}
|
||||
|
||||
hide ();
|
||||
} else {
|
||||
show ();
|
||||
}
|
||||
}
|
||||
}
|
132
src/ShellClients/PanelClone.vala
Normal file
132
src/ShellClients/PanelClone.vala
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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.PanelClone : Object {
|
||||
private const int ANIMATION_DURATION = 250;
|
||||
|
||||
public WindowManager wm { get; construct; }
|
||||
public PanelWindow panel { get; construct; }
|
||||
|
||||
public PanelWindow.HideMode hide_mode {
|
||||
get {
|
||||
return hide_tracker.hide_mode;
|
||||
}
|
||||
set {
|
||||
hide_tracker.hide_mode = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool panel_hidden { get; private set; default = false; }
|
||||
|
||||
private SafeWindowClone clone;
|
||||
private Meta.WindowActor actor;
|
||||
private HideTracker hide_tracker;
|
||||
|
||||
public PanelClone (WindowManager wm, PanelWindow panel) {
|
||||
Object (wm: wm, panel: panel);
|
||||
}
|
||||
|
||||
construct {
|
||||
clone = new SafeWindowClone (panel.window, true) {
|
||||
visible = false
|
||||
};
|
||||
wm.ui_group.add_child (clone);
|
||||
|
||||
actor = (Meta.WindowActor) panel.window.get_compositor_private ();
|
||||
// WindowActor position and Window position aren't necessarily the same.
|
||||
// The clone needs the actor position
|
||||
actor.notify["x"].connect (update_clone_position);
|
||||
actor.notify["y"].connect (update_clone_position);
|
||||
// Actor visibility might be changed by something else e.g. workspace switch
|
||||
// but we want to keep it in sync with us
|
||||
actor.notify["visible"].connect (update_visible);
|
||||
|
||||
notify["panel-hidden"].connect (() => {
|
||||
update_visible ();
|
||||
// When hidden changes schedule an update to make sure it's actually
|
||||
// correct since things might have changed during the animation
|
||||
hide_tracker.schedule_update ();
|
||||
});
|
||||
|
||||
hide_tracker = new HideTracker (wm.get_display (), panel);
|
||||
hide_tracker.hide.connect (hide);
|
||||
hide_tracker.show.connect (show);
|
||||
|
||||
update_visible ();
|
||||
update_clone_position ();
|
||||
}
|
||||
|
||||
private void update_visible () {
|
||||
actor.visible = !panel_hidden;
|
||||
}
|
||||
|
||||
private void update_clone_position () {
|
||||
clone.set_position (calculate_clone_x (panel_hidden), calculate_clone_y (panel_hidden));
|
||||
}
|
||||
|
||||
private float calculate_clone_x (bool hidden) {
|
||||
switch (panel.anchor) {
|
||||
case TOP:
|
||||
case BOTTOM:
|
||||
return actor.x;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private float calculate_clone_y (bool hidden) {
|
||||
switch (panel.anchor) {
|
||||
case TOP:
|
||||
return hidden ? actor.y - actor.height : actor.y;
|
||||
case BOTTOM:
|
||||
return hidden ? actor.y + actor.height : actor.y;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void hide () {
|
||||
if (panel_hidden) {
|
||||
return;
|
||||
}
|
||||
|
||||
panel_hidden = true;
|
||||
|
||||
if (panel.anchor != TOP && panel.anchor != BOTTOM) {
|
||||
warning ("Animated hide not supported for side yet.");
|
||||
return;
|
||||
}
|
||||
|
||||
clone.visible = true;
|
||||
|
||||
clone.save_easing_state ();
|
||||
clone.set_easing_mode (Clutter.AnimationMode.EASE_OUT_QUAD);
|
||||
clone.set_easing_duration (wm.enable_animations && !wm.workspace_view.is_opened () ? ANIMATION_DURATION : 0);
|
||||
clone.y = calculate_clone_y (true);
|
||||
clone.restore_easing_state ();
|
||||
}
|
||||
|
||||
public void show () {
|
||||
if (!panel_hidden) {
|
||||
return;
|
||||
}
|
||||
|
||||
var animation_duration = wm.enable_animations && !wm.workspace_view.is_opened () ? ANIMATION_DURATION : 0;
|
||||
|
||||
clone.save_easing_state ();
|
||||
clone.set_easing_mode (Clutter.AnimationMode.EASE_OUT_QUAD);
|
||||
clone.set_easing_duration (animation_duration);
|
||||
clone.y = calculate_clone_y (false);
|
||||
clone.restore_easing_state ();
|
||||
|
||||
Timeout.add (animation_duration, () => {
|
||||
clone.visible = false;
|
||||
panel_hidden = false;
|
||||
return Source.REMOVE;
|
||||
});
|
||||
}
|
||||
}
|
258
src/ShellClients/PanelWindow.vala
Normal file
258
src/ShellClients/PanelWindow.vala
Normal file
@ -0,0 +1,258 @@
|
||||
/*
|
||||
* 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.PanelWindow : Object {
|
||||
public enum HideMode {
|
||||
NEVER,
|
||||
MAXIMIZED_FOCUS_WINDOW,
|
||||
OVERLAPPING_FOCUS_WINDOW,
|
||||
OVERLAPPING_WINDOW,
|
||||
ALWAYS
|
||||
}
|
||||
|
||||
private const int BARRIER_OFFSET = 50; // Allow hot corner trigger
|
||||
|
||||
private static HashTable<Meta.Window, Meta.Strut?> window_struts = new HashTable<Meta.Window, Meta.Strut?> (null, null);
|
||||
|
||||
public WindowManager wm { get; construct; }
|
||||
public Meta.Window window { get; construct; }
|
||||
|
||||
public bool hidden { get; private set; default = false; }
|
||||
|
||||
public Meta.Side anchor;
|
||||
|
||||
private Barrier? barrier;
|
||||
|
||||
private PanelClone clone;
|
||||
|
||||
private int width = -1;
|
||||
private int height = -1;
|
||||
|
||||
public PanelWindow (WindowManager wm, Meta.Window window, Meta.Side anchor) {
|
||||
Object (wm: wm, window: window);
|
||||
|
||||
// Meta.Side seems to be currently not supported as GLib.Object property ...?
|
||||
// At least it always crashed for me with some paramspec, g_type_fundamental backtrace
|
||||
this.anchor = anchor;
|
||||
}
|
||||
|
||||
construct {
|
||||
window.size_changed.connect (position_window);
|
||||
|
||||
window.unmanaged.connect (() => {
|
||||
destroy_barrier ();
|
||||
|
||||
if (window_struts.remove (window)) {
|
||||
update_struts ();
|
||||
}
|
||||
});
|
||||
|
||||
window.stick ();
|
||||
|
||||
clone = new PanelClone (wm, this);
|
||||
}
|
||||
|
||||
#if HAS_MUTTER46
|
||||
public Mtk.Rectangle get_custom_window_rect () {
|
||||
#else
|
||||
public Meta.Rectangle get_custom_window_rect () {
|
||||
#endif
|
||||
var window_rect = window.get_frame_rect ();
|
||||
|
||||
if (width > 0) {
|
||||
window_rect.width = width;
|
||||
}
|
||||
|
||||
if (height > 0) {
|
||||
window_rect.height = height;
|
||||
}
|
||||
|
||||
return window_rect;
|
||||
}
|
||||
|
||||
public void set_size (int width, int height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
position_window ();
|
||||
set_hide_mode (clone.hide_mode); // Resetup barriers etc.
|
||||
}
|
||||
|
||||
public void update_anchor (Meta.Side anchor) {
|
||||
this.anchor = anchor;
|
||||
|
||||
position_window ();
|
||||
set_hide_mode (clone.hide_mode); // Resetup barriers etc.
|
||||
}
|
||||
|
||||
private void position_window () {
|
||||
var display = wm.get_display ();
|
||||
var monitor_geom = display.get_monitor_geometry (display.get_primary_monitor ());
|
||||
var window_rect = get_custom_window_rect ();
|
||||
|
||||
switch (anchor) {
|
||||
case TOP:
|
||||
position_window_top (monitor_geom, window_rect);
|
||||
break;
|
||||
|
||||
case BOTTOM:
|
||||
position_window_bottom (monitor_geom, window_rect);
|
||||
break;
|
||||
|
||||
default:
|
||||
warning ("Side not supported yet");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if HAS_MUTTER45
|
||||
private void position_window_top (Mtk.Rectangle monitor_geom, Mtk.Rectangle window_rect) {
|
||||
#else
|
||||
private void position_window_top (Meta.Rectangle monitor_geom, Meta.Rectangle window_rect) {
|
||||
#endif
|
||||
var x = monitor_geom.x + (monitor_geom.width - window_rect.width) / 2;
|
||||
|
||||
move_window_idle (x, monitor_geom.y);
|
||||
}
|
||||
|
||||
#if HAS_MUTTER45
|
||||
private void position_window_bottom (Mtk.Rectangle monitor_geom, Mtk.Rectangle window_rect) {
|
||||
#else
|
||||
private void position_window_bottom (Meta.Rectangle monitor_geom, Meta.Rectangle window_rect) {
|
||||
#endif
|
||||
var x = monitor_geom.x + (monitor_geom.width - window_rect.width) / 2;
|
||||
var y = monitor_geom.y + monitor_geom.height - window_rect.height;
|
||||
|
||||
move_window_idle (x, y);
|
||||
}
|
||||
|
||||
private void move_window_idle (int x, int y) {
|
||||
Idle.add (() => {
|
||||
window.move_frame (false, x, y);
|
||||
return Source.REMOVE;
|
||||
});
|
||||
}
|
||||
|
||||
public void set_hide_mode (HideMode hide_mode) {
|
||||
clone.hide_mode = hide_mode;
|
||||
|
||||
destroy_barrier ();
|
||||
|
||||
if (hide_mode != NEVER) {
|
||||
unmake_exclusive ();
|
||||
setup_barrier ();
|
||||
} else {
|
||||
make_exclusive ();
|
||||
}
|
||||
}
|
||||
|
||||
private void make_exclusive () {
|
||||
window.size_changed.connect (update_strut);
|
||||
update_strut ();
|
||||
}
|
||||
|
||||
private void update_strut () {
|
||||
var rect = get_custom_window_rect ();
|
||||
|
||||
Meta.Strut strut = {
|
||||
rect,
|
||||
anchor
|
||||
};
|
||||
|
||||
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 wm.get_display ().get_workspace_manager ().get_workspaces ()) {
|
||||
workspace.set_builtin_struts (list);
|
||||
}
|
||||
}
|
||||
|
||||
private void unmake_exclusive () {
|
||||
if (window in window_struts) {
|
||||
window.size_changed.disconnect (update_strut);
|
||||
window_struts.remove (window);
|
||||
update_struts ();
|
||||
}
|
||||
}
|
||||
|
||||
private void destroy_barrier () {
|
||||
if (barrier != null) {
|
||||
barrier.destroy ();
|
||||
barrier = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void setup_barrier () {
|
||||
var display = wm.get_display ();
|
||||
var monitor_geom = display.get_monitor_geometry (display.get_primary_monitor ());
|
||||
var scale = display.get_monitor_scale (display.get_primary_monitor ());
|
||||
var offset = InternalUtils.scale_to_int (BARRIER_OFFSET, scale);
|
||||
|
||||
switch (anchor) {
|
||||
case TOP:
|
||||
setup_barrier_top (monitor_geom, offset);
|
||||
break;
|
||||
|
||||
case BOTTOM:
|
||||
setup_barrier_bottom (monitor_geom, offset);
|
||||
break;
|
||||
|
||||
default:
|
||||
warning ("Barrier side not supported yet");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if HAS_MUTTER45
|
||||
private void setup_barrier_top (Mtk.Rectangle monitor_geom, int offset) {
|
||||
#else
|
||||
private void setup_barrier_top (Meta.Rectangle monitor_geom, int offset) {
|
||||
#endif
|
||||
barrier = new Barrier (
|
||||
monitor_geom.x + offset,
|
||||
monitor_geom.y,
|
||||
monitor_geom.x + monitor_geom.width - offset,
|
||||
monitor_geom.y,
|
||||
POSITIVE_Y,
|
||||
0,
|
||||
0,
|
||||
int.MAX,
|
||||
int.MAX
|
||||
);
|
||||
|
||||
barrier.trigger.connect (clone.show);
|
||||
}
|
||||
|
||||
#if HAS_MUTTER45
|
||||
private void setup_barrier_bottom (Mtk.Rectangle monitor_geom, int offset) {
|
||||
#else
|
||||
private void setup_barrier_bottom (Meta.Rectangle monitor_geom, int offset) {
|
||||
#endif
|
||||
barrier = new Barrier (
|
||||
monitor_geom.x + offset,
|
||||
monitor_geom.y + monitor_geom.height,
|
||||
monitor_geom.x + monitor_geom.width - offset,
|
||||
monitor_geom.y + monitor_geom.height,
|
||||
NEGATIVE_Y,
|
||||
0,
|
||||
0,
|
||||
int.MAX,
|
||||
int.MAX
|
||||
);
|
||||
|
||||
barrier.trigger.connect (clone.show);
|
||||
}
|
||||
}
|
@ -6,15 +6,85 @@
|
||||
*/
|
||||
|
||||
public class Gala.ShellClientsManager : Object {
|
||||
public Meta.Display display { get; construct; }
|
||||
private static ShellClientsManager instance;
|
||||
|
||||
public static void init (WindowManager wm) {
|
||||
if (instance != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
instance = new ShellClientsManager (wm);
|
||||
}
|
||||
|
||||
public static ShellClientsManager? get_instance () {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public WindowManager wm { get; construct; }
|
||||
|
||||
private NotificationsClient notifications_client;
|
||||
private ManagedClient[] protocol_clients = {};
|
||||
|
||||
public ShellClientsManager (Meta.Display display) {
|
||||
Object (display: display);
|
||||
private GLib.HashTable<Meta.Window, PanelWindow> windows = new GLib.HashTable<Meta.Window, PanelWindow> (null, null);
|
||||
|
||||
private ShellClientsManager (WindowManager wm) {
|
||||
Object (wm: wm);
|
||||
}
|
||||
|
||||
construct {
|
||||
notifications_client = new NotificationsClient (display);
|
||||
notifications_client = new NotificationsClient (wm.get_display ());
|
||||
|
||||
var shell_settings = new Settings ("io.elementary.desktop.wm.shell");
|
||||
var clients = shell_settings.get_value ("trusted-clients");
|
||||
foreach (var client in clients) {
|
||||
protocol_clients += new ManagedClient (wm.get_display (), client.get_strv ());
|
||||
}
|
||||
}
|
||||
|
||||
public void set_anchor (Meta.Window window, Meta.Side side) {
|
||||
if (window in windows) {
|
||||
windows[window].update_anchor (side);
|
||||
return;
|
||||
}
|
||||
|
||||
#if HAS_MUTTER46
|
||||
foreach (var client in protocol_clients) {
|
||||
if (client.wayland_client.owns_window (window)) {
|
||||
client.wayland_client.make_dock (window);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// TODO: Return if requested by window that's not a trusted client?
|
||||
|
||||
windows[window] = new PanelWindow (wm, window, side);
|
||||
|
||||
// connect_after so we make sure the PanelWindow can destroy its barriers and struts
|
||||
window.unmanaged.connect_after (() => windows.remove (window));
|
||||
}
|
||||
|
||||
/**
|
||||
* The size given here is only used for the hide mode. I.e. struts
|
||||
* and collision detection with other windows use this size. By default
|
||||
* or if set to -1 the size of the window is used.
|
||||
*
|
||||
* TODO: Maybe use for strut only?
|
||||
*/
|
||||
public void set_size (Meta.Window window, int width, int height) {
|
||||
if (!(window in windows)) {
|
||||
warning ("Set anchor for window before size.");
|
||||
return;
|
||||
}
|
||||
|
||||
windows[window].set_size (width, height);
|
||||
}
|
||||
|
||||
public void set_hide_mode (Meta.Window window, PanelWindow.HideMode hide_mode) {
|
||||
if (!(window in windows)) {
|
||||
warning ("Set anchor for window before hide mode.");
|
||||
return;
|
||||
}
|
||||
|
||||
windows[window].set_hide_mode (hide_mode);
|
||||
}
|
||||
}
|
||||
|
@ -83,8 +83,6 @@ namespace Gala {
|
||||
|
||||
private DaemonManager daemon_manager;
|
||||
|
||||
private ShellClientsManager shell_clients_manager;
|
||||
|
||||
private WindowGrabTracker window_grab_tracker;
|
||||
|
||||
private NotificationStack notification_stack;
|
||||
@ -145,7 +143,7 @@ namespace Gala {
|
||||
}
|
||||
|
||||
public override void start () {
|
||||
shell_clients_manager = new ShellClientsManager (get_display ());
|
||||
ShellClientsManager.init (this);
|
||||
daemon_manager = new DaemonManager (get_display ());
|
||||
window_grab_tracker = new WindowGrabTracker (get_display ());
|
||||
|
||||
|
@ -39,8 +39,11 @@ gala_bin_sources = files(
|
||||
'HotCorners/Barrier.vala',
|
||||
'HotCorners/HotCorner.vala',
|
||||
'HotCorners/HotCornerManager.vala',
|
||||
'ShellClients/HideTracker.vala',
|
||||
'ShellClients/ManagedClient.vala',
|
||||
'ShellClients/NotificationsClient.vala',
|
||||
'ShellClients/PanelClone.vala',
|
||||
'ShellClients/PanelWindow.vala',
|
||||
'ShellClients/ShellClientsManager.vala',
|
||||
'Widgets/DwellClickTimer.vala',
|
||||
'Widgets/IconGroup.vala',
|
||||
|
Loading…
Reference in New Issue
Block a user