Hide cursor while warping on Wayland

Based on https://gitlab.freedesktop.org/xorg/xserver/-/issues/734 we
hide the window cursor prior to warping, which allows XWayland to
reposition the cursor.  This is only performed when Wayland is detected;
all other configurations call the standard warp routine

Fixes https://gitlab.com/kicad/code/kicad/issues/9785
This commit is contained in:
Seth Hillbrand 2022-06-24 09:54:28 -07:00
parent 35375a98c6
commit a118f20464
5 changed files with 53 additions and 9 deletions

View File

@ -248,7 +248,7 @@ void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent )
{ {
if( !justWarped ) if( !justWarped )
{ {
m_parentPanel->WarpPointer( x + warpX, y + warpY ); KIPLATFORM::UI::WarpPointer( m_parentPanel, x + warpX, y + warpY );
m_dragStartPoint += VECTOR2D( warpX, warpY ); m_dragStartPoint += VECTOR2D( warpX, warpY );
justWarped = true; justWarped = true;
} }
@ -290,7 +290,7 @@ void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent )
{ {
if( !justWarped ) if( !justWarped )
{ {
m_parentPanel->WarpPointer( x, y + warpY ); KIPLATFORM::UI::WarpPointer( m_parentPanel, x, y + warpY );
m_dragStartPoint += VECTOR2D( 0, warpY ); m_dragStartPoint += VECTOR2D( 0, warpY );
justWarped = true; justWarped = true;
} }
@ -741,17 +741,17 @@ void WX_VIEW_CONTROLS::WarpMouseCursor( const VECTOR2D& aPosition, bool aWorldCo
if( aWarpView ) if( aWarpView )
{ {
m_view->SetCenter( clampedPosition ); m_view->SetCenter( clampedPosition );
m_parentPanel->WarpPointer( screenSize.x / 2, screenSize.y / 2 ); KIPLATFORM::UI::WarpPointer( m_parentPanel, screenSize.x / 2, screenSize.y / 2 );
} }
} }
else else
{ {
m_parentPanel->WarpPointer( screenPos.x, screenPos.y ); KIPLATFORM::UI::WarpPointer( m_parentPanel, screenPos.x, screenPos.y );
} }
} }
else else
{ {
m_parentPanel->WarpPointer( aPosition.x, aPosition.y ); KIPLATFORM::UI::WarpPointer( m_parentPanel, aPosition.x, aPosition.y );
} }
refreshMouse(); refreshMouse();
@ -766,7 +766,7 @@ void WX_VIEW_CONTROLS::CenterOnCursor() const
if( GetMousePosition( false ) != screenCenter ) if( GetMousePosition( false ) != screenCenter )
{ {
m_view->SetCenter( GetCursorPosition() ); m_view->SetCenter( GetCursorPosition() );
m_parentPanel->WarpPointer( KiROUND( screenSize.x / 2 ), KiROUND( screenSize.y / 2 ) ); KIPLATFORM::UI::WarpPointer( m_parentPanel, KiROUND( screenSize.x / 2 ), KiROUND( screenSize.y / 2 ) );
} }
} }
@ -909,7 +909,7 @@ void WX_VIEW_CONTROLS::handleCursorCapture( int x, int y )
} }
if( warp ) if( warp )
m_parentPanel->WarpPointer( x, y ); KIPLATFORM::UI::WarpPointer( m_parentPanel, x, y );
} }
} }

View File

@ -26,7 +26,7 @@
#include <wx/window.h> #include <wx/window.h>
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include <gdk/gdk.h>
bool KIPLATFORM::UI::IsDarkTheme() bool KIPLATFORM::UI::IsDarkTheme()
{ {
@ -81,6 +81,7 @@ bool KIPLATFORM::UI::IsStockCursorOk( wxStockCursor aCursor )
case wxCURSOR_BULLSEYE: case wxCURSOR_BULLSEYE:
case wxCURSOR_HAND: case wxCURSOR_HAND:
case wxCURSOR_ARROW: case wxCURSOR_ARROW:
case wxCURSOR_BLANK:
return true; return true;
default: default:
return false; return false;
@ -144,3 +145,26 @@ bool KIPLATFORM::UI::AllowIconsInMenus()
return !!allowed; return !!allowed;
} }
void KIPLATFORM::UI::WarpPointer( wxWindow* aWindow, int aX, int aY )
{
if( !wxGetEnv( wxT( "WAYLAND_DISPLAY" ), nullptr ) )
{
aWindow->WarpPointer( aX, aY );
}
else
{
GdkDisplay* disp = gtk_widget_get_display( static_cast<GtkWidget*>( aWindow->GetHandle() ) );
GdkWindow* win = gdk_display_get_window_at_pointer( disp, nullptr, nullptr );
GdkCursor* blank_cursor = gdk_cursor_new_for_display( disp, GDK_BLANK_CURSOR );
GdkCursor* cur_cursor = gdk_window_get_cursor( win );
if( cur_cursor )
g_object_ref( cur_cursor );
gdk_window_set_cursor( win, blank_cursor );
aWindow->WarpPointer( aX, aY );
gdk_window_set_cursor( win, cur_cursor );
}
}

View File

@ -120,6 +120,14 @@ namespace KIPLATFORM
* If the user has disabled icons system-wide, we check that here * If the user has disabled icons system-wide, we check that here
*/ */
bool AllowIconsInMenus(); bool AllowIconsInMenus();
/**
* Move the mouse cursor to a specific position relative to the window
* @param aWindow Window in which to position to mouse cursor
* @param aX destination x position
* @param aY destination y position
*/
void WarpPointer( wxWindow* aWindow, int aX, int aY );
} }
} }

View File

@ -138,3 +138,9 @@ bool KIPLATFORM::UI::AllowIconsInMenus()
{ {
return true; return true;
} }
void KIPLATFORM::UI::WarpPointer( wxWindow* aWindow, int aX, int aY )
{
aWindow->WarpPointer( aX, aY );
}

View File

@ -137,4 +137,10 @@ void KIPLATFORM::UI::SetOverlayScrolling( const wxWindow* aWindow, bool overlay
bool KIPLATFORM::UI::AllowIconsInMenus() bool KIPLATFORM::UI::AllowIconsInMenus()
{ {
return true; return true;
} }
void KIPLATFORM::UI::WarpPointer( wxWindow* aWindow, int aX, int aY )
{
aWindow->WarpPointer( aX, aY );
}