From a7b59c0dd01637e99ac918c713170b2c630bf41d Mon Sep 17 00:00:00 2001 From: Matheus Castello Date: Thu, 22 Apr 2021 23:22:34 -0300 Subject: [PATCH] fix(GTK): pointer events in wrong locations using Wayland For GTK applications using Wayland the title bar is rendered by the window itself and not by the composer. And it seems to me that GTK counts the title bar as part of the window and uses it to trigger the window events, leading to erroneous considerations about the size and location of pointers in the area where it is used to draw the components. The fix adds a GtkEventBox in the window, instead of use the window events we will be based on the events of the GtkEventBox which we can assure that the GTK will take into account the title bar. Related-to: #5706 Signed-off-by: Matheus Castello --- .../GtkCoreWindowExtension.cs | 30 +++++++++++-------- src/Uno.UI.Runtime.Skia.Gtk/GtkHost.cs | 12 +++++--- .../UI/Xaml/Controls/TextBoxViewExtension.cs | 3 +- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/Uno.UI.Runtime.Skia.Gtk/GtkCoreWindowExtension.cs b/src/Uno.UI.Runtime.Skia.Gtk/GtkCoreWindowExtension.cs index a23d2a32b401..cc2496ed5190 100644 --- a/src/Uno.UI.Runtime.Skia.Gtk/GtkCoreWindowExtension.cs +++ b/src/Uno.UI.Runtime.Skia.Gtk/GtkCoreWindowExtension.cs @@ -49,19 +49,23 @@ public void SetPointerCapture() public GtkCoreWindowExtension(object owner) { _owner = (CoreWindow)owner; - _ownerEvents = (ICoreWindowEvents)owner; - - GtkHost.Window.AddEvents((int)RequestedEvents); - - GtkHost.Window.EnterNotifyEvent += OnWindowEnterEvent; - GtkHost.Window.LeaveNotifyEvent += OnWindowLeaveEvent; - GtkHost.Window.ButtonPressEvent += OnWindowButtonPressEvent; - GtkHost.Window.ButtonReleaseEvent += OnWindowButtonReleaseEvent; - GtkHost.Window.MotionNotifyEvent += OnWindowMotionEvent; - GtkHost.Window.ScrollEvent += OnWindowScrollEvent; - GtkHost.Window.TouchEvent += OnWindowTouchEvent; - GtkHost.Window.ProximityInEvent += OnWindowProximityInEvent; - GtkHost.Window.ProximityOutEvent += OnWindowProximityOutEvent; + _ownerEvents = (ICoreWindowEvents)owner; + + // even though we are not going to use events directly in the window here maintain the masks + GtkHost.Window.AddEvents((int)RequestedEvents); + // add masks for the GtkEventBox + GtkHost.EventBox.AddEvents((int)RequestedEvents); + + // Use GtkEventBox to fix Wayland titlebar events + GtkHost.EventBox.EnterNotifyEvent += OnWindowEnterEvent; + GtkHost.EventBox.LeaveNotifyEvent += OnWindowLeaveEvent; + GtkHost.EventBox.ButtonPressEvent += OnWindowButtonPressEvent; + GtkHost.EventBox.ButtonReleaseEvent += OnWindowButtonReleaseEvent; + GtkHost.EventBox.MotionNotifyEvent += OnWindowMotionEvent; + GtkHost.EventBox.ScrollEvent += OnWindowScrollEvent; + GtkHost.EventBox.TouchEvent += OnWindowTouchEvent; + GtkHost.EventBox.ProximityInEvent += OnWindowProximityInEvent; + GtkHost.EventBox.ProximityOutEvent += OnWindowProximityOutEvent; InitializeKeyboard(); } diff --git a/src/Uno.UI.Runtime.Skia.Gtk/GtkHost.cs b/src/Uno.UI.Runtime.Skia.Gtk/GtkHost.cs index 5049ac957c9a..6dea88dce5ab 100644 --- a/src/Uno.UI.Runtime.Skia.Gtk/GtkHost.cs +++ b/src/Uno.UI.Runtime.Skia.Gtk/GtkHost.cs @@ -26,11 +26,13 @@ public class GtkHost : ISkiaHost private readonly string[] _args; private readonly Func _appBuilder; private static Gtk.Window _window; + private static Gtk.EventBox _eventBox; private UnoDrawingArea _area; private Fixed _fix; private GtkDisplayInformationExtension _displayInformationExtension; public static Gtk.Window Window => _window; + public static Gtk.EventBox EventBox => _eventBox; public GtkHost(Func appBuilder, string[] args) { @@ -108,13 +110,15 @@ void Dispatch(System.Action d) WUX.Window.Current.OnNativeSizeChanged(new Windows.Foundation.Size(e.Allocation.Width, e.Allocation.Height)); }; - var overlay = new Overlay(); - - _area = new UnoDrawingArea(); + var overlay = new Overlay(); + + _eventBox = new EventBox(); + _area = new UnoDrawingArea(); _fix = new Fixed(); overlay.Add(_area); overlay.AddOverlay(_fix); - _window.Add(overlay); + _eventBox.Add(overlay); + _window.Add(_eventBox); /* avoids double invokes at window level */ _area.AddEvents((int)GtkCoreWindowExtension.RequestedEvents); diff --git a/src/Uno.UI.Runtime.Skia.Gtk/UI/Xaml/Controls/TextBoxViewExtension.cs b/src/Uno.UI.Runtime.Skia.Gtk/UI/Xaml/Controls/TextBoxViewExtension.cs index 152b2f748b68..536c3307419e 100644 --- a/src/Uno.UI.Runtime.Skia.Gtk/UI/Xaml/Controls/TextBoxViewExtension.cs +++ b/src/Uno.UI.Runtime.Skia.Gtk/UI/Xaml/Controls/TextBoxViewExtension.cs @@ -36,7 +36,8 @@ public TextBoxViewExtension(TextBoxView owner, GtkWindow window) private Fixed GetWindowTextInputLayer() { - var overlay = (Overlay)_window.Child; + // now we have the GtkEventBox + var overlay = (Overlay)((EventBox) _window.Child).Child; return overlay.Children.OfType().First(); }