mirror of
https://github.com/elementary/gala.git
synced 2024-12-18 23:02:14 +03:00
X11: Use window shape to fix input for invisible windows (#2142)
This commit is contained in:
parent
f21d780fe8
commit
4850f1b0f6
@ -400,5 +400,50 @@ namespace Gala {
|
|||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static HashTable<Meta.Window, X.XserverRegion?> regions = new HashTable<Meta.Window, X.XserverRegion?> (null, null);
|
||||||
|
|
||||||
|
public static void x11_set_window_pass_through (Meta.Window window) {
|
||||||
|
unowned var x11_display = window.display.get_x11_display ();
|
||||||
|
|
||||||
|
#if HAS_MUTTER46
|
||||||
|
var x_window = x11_display.lookup_xwindow (window);
|
||||||
|
#else
|
||||||
|
var x_window = window.get_xwindow ();
|
||||||
|
#endif
|
||||||
|
unowned var xdisplay = x11_display.get_xdisplay ();
|
||||||
|
|
||||||
|
regions[window] = X.Fixes.create_region_from_window (xdisplay, x_window, 0);
|
||||||
|
|
||||||
|
X.Xrectangle rect = {};
|
||||||
|
|
||||||
|
var region = X.Fixes.create_region (xdisplay, {rect});
|
||||||
|
|
||||||
|
X.Fixes.set_window_shape_region (xdisplay, x_window, 2, 0, 0, region);
|
||||||
|
|
||||||
|
X.Fixes.destroy_region (xdisplay, region);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void x11_unset_window_pass_through (Meta.Window window) {
|
||||||
|
unowned var x11_display = window.display.get_x11_display ();
|
||||||
|
|
||||||
|
#if HAS_MUTTER46
|
||||||
|
var x_window = x11_display.lookup_xwindow (window);
|
||||||
|
#else
|
||||||
|
var x_window = window.get_xwindow ();
|
||||||
|
#endif
|
||||||
|
unowned var xdisplay = x11_display.get_xdisplay ();
|
||||||
|
|
||||||
|
var region = regions[window];
|
||||||
|
|
||||||
|
if (region == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
X.Fixes.set_window_shape_region (xdisplay, x_window, 2, 0, 0, region);
|
||||||
|
|
||||||
|
regions.remove (window);
|
||||||
|
X.Fixes.destroy_region (xdisplay, region);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
* SPDX-FileCopyrightText: 2024 elementary, Inc. (https://elementary.io)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This class is used to workaround https://github.com/elementary/gala/issues/2101 */
|
|
||||||
public class Gala.DelegateActor : GLib.Object {
|
|
||||||
public const int OUT_OF_BOUNDS = 1000000;
|
|
||||||
|
|
||||||
public Meta.WindowActor actor { get; construct; }
|
|
||||||
|
|
||||||
/* Current window actor position or position before the window was moved out of bounds */
|
|
||||||
public float x { get; private set; default = 0.0f; }
|
|
||||||
public float y { get; private set; default = 0.0f; }
|
|
||||||
|
|
||||||
/* Current window position or position before it was moved out of bounds */
|
|
||||||
public int actual_x { get; private set; default = 0; }
|
|
||||||
public int actual_y { get; private set; default = 0; }
|
|
||||||
|
|
||||||
public DelegateActor (Meta.WindowActor actor) {
|
|
||||||
Object (actor: actor);
|
|
||||||
}
|
|
||||||
|
|
||||||
construct {
|
|
||||||
actor.meta_window.position_changed.connect ((_window) => {
|
|
||||||
var rect = _window.get_frame_rect ();
|
|
||||||
|
|
||||||
if (rect.x != OUT_OF_BOUNDS) {
|
|
||||||
actual_x = rect.x;
|
|
||||||
Idle.add_once (() => {
|
|
||||||
x = actor.x;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (rect.y != OUT_OF_BOUNDS) {
|
|
||||||
actual_y = rect.y;
|
|
||||||
Idle.add_once (() => {
|
|
||||||
y = actor.y;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -48,8 +48,8 @@ public class Gala.PanelClone : Object {
|
|||||||
actor = (Meta.WindowActor) panel.window.get_compositor_private ();
|
actor = (Meta.WindowActor) panel.window.get_compositor_private ();
|
||||||
// WindowActor position and Window position aren't necessarily the same.
|
// WindowActor position and Window position aren't necessarily the same.
|
||||||
// The clone needs the actor position
|
// The clone needs the actor position
|
||||||
panel.delegate_actor.notify["x"].connect (update_clone_position);
|
actor.notify["x"].connect (update_clone_position);
|
||||||
panel.delegate_actor.notify["y"].connect (update_clone_position);
|
actor.notify["y"].connect (update_clone_position);
|
||||||
// Actor visibility might be changed by something else e.g. workspace switch
|
// Actor visibility might be changed by something else e.g. workspace switch
|
||||||
// but we want to keep it in sync with us
|
// but we want to keep it in sync with us
|
||||||
actor.notify["visible"].connect (update_visible);
|
actor.notify["visible"].connect (update_visible);
|
||||||
@ -97,7 +97,7 @@ public class Gala.PanelClone : Object {
|
|||||||
switch (panel.anchor) {
|
switch (panel.anchor) {
|
||||||
case TOP:
|
case TOP:
|
||||||
case BOTTOM:
|
case BOTTOM:
|
||||||
return panel.delegate_actor.x;
|
return actor.x;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -106,9 +106,9 @@ public class Gala.PanelClone : Object {
|
|||||||
private float calculate_clone_y (bool hidden) {
|
private float calculate_clone_y (bool hidden) {
|
||||||
switch (panel.anchor) {
|
switch (panel.anchor) {
|
||||||
case TOP:
|
case TOP:
|
||||||
return hidden ? panel.delegate_actor.y - actor.height : panel.delegate_actor.y;
|
return hidden ? actor.y - actor.height : actor.y;
|
||||||
case BOTTOM:
|
case BOTTOM:
|
||||||
return hidden ? panel.delegate_actor.y + actor.height : panel.delegate_actor.y;
|
return hidden ? actor.y + actor.height : actor.y;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -128,7 +128,7 @@ public class Gala.PanelClone : Object {
|
|||||||
panel_hidden = true;
|
panel_hidden = true;
|
||||||
|
|
||||||
if (!Meta.Util.is_wayland_compositor ()) {
|
if (!Meta.Util.is_wayland_compositor ()) {
|
||||||
panel.window.move_frame (false, DelegateActor.OUT_OF_BOUNDS, DelegateActor.OUT_OF_BOUNDS);
|
Utils.x11_set_window_pass_through (panel.window);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (panel.anchor != TOP && panel.anchor != BOTTOM) {
|
if (panel.anchor != TOP && panel.anchor != BOTTOM) {
|
||||||
@ -151,7 +151,7 @@ public class Gala.PanelClone : Object {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!Meta.Util.is_wayland_compositor ()) {
|
if (!Meta.Util.is_wayland_compositor ()) {
|
||||||
panel.window.move_frame (false, panel.delegate_actor.actual_x, panel.delegate_actor.actual_y);
|
Utils.x11_unset_window_pass_through (panel.window);
|
||||||
}
|
}
|
||||||
|
|
||||||
clone.save_easing_state ();
|
clone.save_easing_state ();
|
||||||
|
@ -15,7 +15,6 @@ public class Gala.PanelWindow : Object {
|
|||||||
|
|
||||||
public Meta.Side anchor;
|
public Meta.Side anchor;
|
||||||
|
|
||||||
public DelegateActor delegate_actor;
|
|
||||||
private PanelClone clone;
|
private PanelClone clone;
|
||||||
|
|
||||||
private uint idle_move_id = 0;
|
private uint idle_move_id = 0;
|
||||||
@ -46,7 +45,6 @@ public class Gala.PanelWindow : Object {
|
|||||||
|
|
||||||
window.stick ();
|
window.stick ();
|
||||||
|
|
||||||
delegate_actor = new DelegateActor ((Meta.WindowActor) window.get_compositor_private ());
|
|
||||||
clone = new PanelClone (wm, this);
|
clone = new PanelClone (wm, this);
|
||||||
|
|
||||||
var monitor_manager = wm.get_display ().get_context ().get_backend ().get_monitor_manager ();
|
var monitor_manager = wm.get_display ().get_context ().get_backend ().get_monitor_manager ();
|
||||||
@ -64,8 +62,6 @@ public class Gala.PanelWindow : Object {
|
|||||||
public Meta.Rectangle get_custom_window_rect () {
|
public Meta.Rectangle get_custom_window_rect () {
|
||||||
#endif
|
#endif
|
||||||
var window_rect = window.get_frame_rect ();
|
var window_rect = window.get_frame_rect ();
|
||||||
window_rect.x = delegate_actor.actual_x;
|
|
||||||
window_rect.y = delegate_actor.actual_y;
|
|
||||||
|
|
||||||
if (width > 0) {
|
if (width > 0) {
|
||||||
window_rect.width = width;
|
window_rect.width = width;
|
||||||
|
@ -41,7 +41,6 @@ gala_bin_sources = files(
|
|||||||
'HotCorners/Barrier.vala',
|
'HotCorners/Barrier.vala',
|
||||||
'HotCorners/HotCorner.vala',
|
'HotCorners/HotCorner.vala',
|
||||||
'HotCorners/HotCornerManager.vala',
|
'HotCorners/HotCornerManager.vala',
|
||||||
'ShellClients/DelegateActor.vala',
|
|
||||||
'ShellClients/HideTracker.vala',
|
'ShellClients/HideTracker.vala',
|
||||||
'ShellClients/ManagedClient.vala',
|
'ShellClients/ManagedClient.vala',
|
||||||
'ShellClients/NotificationsClient.vala',
|
'ShellClients/NotificationsClient.vala',
|
||||||
|
@ -6,8 +6,12 @@ namespace X {
|
|||||||
namespace Fixes {
|
namespace Fixes {
|
||||||
[CCode (cheader_filename = "X11/extensions/Xfixes.h", cname = "XFixesCreateRegion")]
|
[CCode (cheader_filename = "X11/extensions/Xfixes.h", cname = "XFixesCreateRegion")]
|
||||||
public static X.XserverRegion create_region (X.Display display, [CCode (array_length = true)] X.Xrectangle[] rectangles);
|
public static X.XserverRegion create_region (X.Display display, [CCode (array_length = true)] X.Xrectangle[] rectangles);
|
||||||
|
[CCode (cheader_filename = "X11/extensions/Xfixes.h", cname = "XFixesCreateRegionFromWindow")]
|
||||||
|
public static X.XserverRegion create_region_from_window (X.Display display, X.Window window, int shape_kind);
|
||||||
[CCode (cheader_filename = "X11/extensions/Xfixes.h", cname = "XFixesDestroyRegion")]
|
[CCode (cheader_filename = "X11/extensions/Xfixes.h", cname = "XFixesDestroyRegion")]
|
||||||
public static void destroy_region (X.Display display, X.XserverRegion region);
|
public static void destroy_region (X.Display display, X.XserverRegion region);
|
||||||
|
[CCode (cheader_filename = "X11/extensions/Xfixes.h", cname = "XFixesSetWindowShapeRegion")]
|
||||||
|
public static void set_window_shape_region (X.Display display, X.Window win, int shape_kind, int x_off, int y_off, XserverRegion region);
|
||||||
}
|
}
|
||||||
[SimpleType]
|
[SimpleType]
|
||||||
[CCode (cheader_filename = "X11/extensions/Xfixes.h", cname = "XserverRegion", has_type_id = false)]
|
[CCode (cheader_filename = "X11/extensions/Xfixes.h", cname = "XserverRegion", has_type_id = false)]
|
||||||
|
Loading…
Reference in New Issue
Block a user