From 463b609993229b53ce83a3d37892149979679bb3 Mon Sep 17 00:00:00 2001 From: Alex Shvartzkop Date: Tue, 12 Mar 2024 10:31:23 +0300 Subject: [PATCH] Disable infinite panning when using XWayland. Cursor warping doesn't work properly in this scenario. https://gitlab.com/kicad/code/kicad/-/issues/14109 --- common/view/wx_view_controls.cpp | 8 ++-- include/view/wx_view_controls.h | 3 ++ libs/kiplatform/gtk/ui.cpp | 63 ++++++++++++++----------- libs/kiplatform/include/kiplatform/ui.h | 3 +- libs/kiplatform/msw/ui.cpp | 4 +- libs/kiplatform/osx/ui.mm | 4 +- 6 files changed, 49 insertions(+), 36 deletions(-) diff --git a/common/view/wx_view_controls.cpp b/common/view/wx_view_controls.cpp index 8126ce86e1..13443eaab0 100644 --- a/common/view/wx_view_controls.cpp +++ b/common/view/wx_view_controls.cpp @@ -81,7 +81,8 @@ WX_VIEW_CONTROLS::WX_VIEW_CONTROLS( VIEW* aView, EDA_DRAW_PANEL_GAL* aParentPane m_lastTimestamp( 0 ), #endif m_cursorPos( 0, 0 ), - m_updateCursor( true ) + m_updateCursor( true ), + m_infinitePanWorks( false ) { LoadSettings(); @@ -276,7 +277,8 @@ void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent ) { if( !justWarped ) { - if( KIPLATFORM::UI::WarpPointer( m_parentPanel, x + warpX, y + warpY ) ) + if( m_infinitePanWorks + && KIPLATFORM::UI::WarpPointer( m_parentPanel, x + warpX, y + warpY ) ) { m_dragStartPoint += VECTOR2D( warpX, warpY ); justWarped = true; @@ -452,7 +454,7 @@ void WX_VIEW_CONTROLS::onButton( wxMouseEvent& aEvent ) { m_dragStartPoint = VECTOR2D( aEvent.GetX(), aEvent.GetY() ); setState( DRAG_PANNING ); - KIPLATFORM::UI::InfiniteDragPrepareWindow( m_parentPanel ); + m_infinitePanWorks = KIPLATFORM::UI::InfiniteDragPrepareWindow( m_parentPanel ); #if defined USE_MOUSE_CAPTURE if( !m_parentPanel->HasCapture() ) diff --git a/include/view/wx_view_controls.h b/include/view/wx_view_controls.h index 1a7980bcd0..25c91d7729 100644 --- a/include/view/wx_view_controls.h +++ b/include/view/wx_view_controls.h @@ -200,6 +200,9 @@ private: ///< Flag deciding whether the cursor position should be calculated using the mouse position. bool m_updateCursor; + ///< Flag to indicate if infinite panning works on this platform. + bool m_infinitePanWorks; + ///< A #ZOOM_CONTROLLER that determines zoom steps. This is platform-specific. std::unique_ptr m_zoomController; }; diff --git a/libs/kiplatform/gtk/ui.cpp b/libs/kiplatform/gtk/ui.cpp index 67d16ebfd9..469168811b 100644 --- a/libs/kiplatform/gtk/ui.cpp +++ b/libs/kiplatform/gtk/ui.cpp @@ -513,48 +513,54 @@ static bool wayland_warp_pointer( GtkWidget* aWidget, GdkDisplay* aDisplay, GdkW } -void KIPLATFORM::UI::InfiniteDragPrepareWindow( wxWindow* aWindow ) +bool KIPLATFORM::UI::InfiniteDragPrepareWindow( wxWindow* aWindow ) { wxLogTrace( traceWayland, wxS( "InfiniteDragPrepareWindow" ) ); - if( s_wl_confined_pointer != NULL ) - { - KIPLATFORM::UI::InfiniteDragReleaseWindow(); - } - GtkWidget* widget = static_cast( aWindow->GetHandle() ); GdkDisplay* disp = gtk_widget_get_display( widget ); - if( !GDK_IS_WAYLAND_DISPLAY( disp ) ) + if( GDK_IS_WAYLAND_DISPLAY( disp ) ) { - return; - } + if( s_wl_confined_pointer != NULL ) + { + KIPLATFORM::UI::InfiniteDragReleaseWindow(); + } - GdkSeat* seat = gdk_display_get_default_seat( disp ); - GdkDevice* ptrdev = gdk_seat_get_pointer( seat ); - GdkWindow* win = aWindow->GTKGetDrawingWindow(); + GdkSeat* seat = gdk_display_get_default_seat( disp ); + GdkDevice* ptrdev = gdk_seat_get_pointer( seat ); + GdkWindow* win = aWindow->GTKGetDrawingWindow(); - wl_display* wldisp = gdk_wayland_display_get_wl_display( disp ); - wl_surface* wlsurf = gdk_wayland_window_get_wl_surface( win ); - wl_pointer* wlptr = gdk_wayland_device_get_wl_pointer( ptrdev ); + wl_display* wldisp = gdk_wayland_display_get_wl_display( disp ); + wl_surface* wlsurf = gdk_wayland_window_get_wl_surface( win ); + wl_pointer* wlptr = gdk_wayland_device_get_wl_pointer( ptrdev ); - initialize_wayland( wldisp ); + initialize_wayland( wldisp ); - gint x, y, width, height; - gdk_window_get_geometry( gdk_window_get_toplevel( win ), &x, &y, &width, &height ); + gint x, y, width, height; + gdk_window_get_geometry( gdk_window_get_toplevel( win ), &x, &y, &width, &height ); - wxLogTrace( traceWayland, wxS( "Confine region: %d %d %d %d" ), x, y, width, height ); + wxLogTrace( traceWayland, wxS( "Confine region: %d %d %d %d" ), x, y, width, height ); - s_wl_confinement_region = wl_compositor_create_region( s_wl_compositor ); - wl_region_add( s_wl_confinement_region, x, y, width, height ); + s_wl_confinement_region = wl_compositor_create_region( s_wl_compositor ); + wl_region_add( s_wl_confinement_region, x, y, width, height ); - s_wl_confined_pointer = zwp_pointer_constraints_v1_confine_pointer( - s_wl_pointer_constraints, wlsurf, wlptr, s_wl_confinement_region, - ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT ); + s_wl_confined_pointer = zwp_pointer_constraints_v1_confine_pointer( + s_wl_pointer_constraints, wlsurf, wlptr, s_wl_confinement_region, + ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT ); - zwp_confined_pointer_v1_add_listener(s_wl_confined_pointer, &confined_pointer_listener, NULL); + zwp_confined_pointer_v1_add_listener( s_wl_confined_pointer, &confined_pointer_listener, + NULL ); - wl_display_roundtrip( wldisp ); + wl_display_roundtrip( wldisp ); + } + else if( wxGetEnv( wxT( "WAYLAND_DISPLAY" ), nullptr ) ) + { + // Not working under XWayland + return false; + } + + return true; }; @@ -579,9 +585,10 @@ void KIPLATFORM::UI::InfiniteDragReleaseWindow() #else // No Wayland support -void KIPLATFORM::UI::InfiniteDragPrepareWindow( wxWindow* aWindow ) +bool KIPLATFORM::UI::InfiniteDragPrepareWindow( wxWindow* aWindow ) { - // Not needed on X11 + // Not working under XWayland + return !wxGetEnv( wxT( "WAYLAND_DISPLAY" ), nullptr ); }; diff --git a/libs/kiplatform/include/kiplatform/ui.h b/libs/kiplatform/include/kiplatform/ui.h index 482fa0a08e..9126c6ab91 100644 --- a/libs/kiplatform/include/kiplatform/ui.h +++ b/libs/kiplatform/include/kiplatform/ui.h @@ -164,8 +164,9 @@ namespace KIPLATFORM * Required to make the infinite mouse-drag work with fast movement. * See https://gitlab.com/kicad/code/kicad/-/issues/7207#note_1562089503 * @param aWindow Window in which to position to mouse cursor + * @return true if infinite panning is supported */ - void InfiniteDragPrepareWindow( wxWindow* aWindow ); + bool InfiniteDragPrepareWindow( wxWindow* aWindow ); /** * On Wayland, allows the cursor to freely move again after a drag (see `InfiniteDragPrepareWindow`). diff --git a/libs/kiplatform/msw/ui.cpp b/libs/kiplatform/msw/ui.cpp index de556e16d6..5b2cced663 100644 --- a/libs/kiplatform/msw/ui.cpp +++ b/libs/kiplatform/msw/ui.cpp @@ -184,9 +184,9 @@ void KIPLATFORM::UI::ImmControl( wxWindow* aWindow, bool aEnable ) } -void KIPLATFORM::UI::InfiniteDragPrepareWindow( wxWindow* aWindow ) +bool KIPLATFORM::UI::InfiniteDragPrepareWindow( wxWindow* aWindow ) { - // Not needed on this platform + return true; } diff --git a/libs/kiplatform/osx/ui.mm b/libs/kiplatform/osx/ui.mm index c7047f51ba..1aeb8360ef 100644 --- a/libs/kiplatform/osx/ui.mm +++ b/libs/kiplatform/osx/ui.mm @@ -184,9 +184,9 @@ void KIPLATFORM::UI::ImmControl( wxWindow* aWindow, bool aEnable ) } -void KIPLATFORM::UI::InfiniteDragPrepareWindow( wxWindow* aWindow ) +bool KIPLATFORM::UI::InfiniteDragPrepareWindow( wxWindow* aWindow ) { - // Not needed on this platform + return true; }