sdlwindow: Forward cursor in absolute mode to host compositor

This commit is contained in:
Joshua Ashton 2023-01-12 01:29:25 +00:00
parent 86ff9cfc58
commit 2d7ec208c4
4 changed files with 75 additions and 7 deletions

View file

@ -34,6 +34,7 @@ enum UserEvents
USER_EVENT_TITLE,
USER_EVENT_VISIBLE,
USER_EVENT_GRAB,
USER_EVENT_CURSOR,
USER_EVENT_COUNT
};
@ -44,6 +45,15 @@ static std::mutex g_SDLWindowTitleLock;
static std::string g_SDLWindowTitle;
static bool g_bUpdateSDLWindowTitle = false;
struct SDLPendingCursor
{
uint32_t width, height, xhot, yhot;
std::vector<uint32_t> data;
};
static std::mutex g_SDLCursorLock;
static SDLPendingCursor g_SDLPendingCursorData;
static bool g_bUpdateSDLCursor = false;
//-----------------------------------------------------------------------------
// Purpose: Convert from the remote scancode to a Linux event keycode
//-----------------------------------------------------------------------------
@ -316,6 +326,24 @@ void inputSDLThreadRun( void )
bRelativeMouse = grab;
}
}
if ( event.type == g_unSDLUserEventID + USER_EVENT_CURSOR )
{
std::unique_lock lock(g_SDLCursorLock);
if ( g_bUpdateSDLCursor )
{
SDL_Surface *surface = SDL_CreateRGBSurfaceFrom(
g_SDLPendingCursorData.data.data(),
g_SDLPendingCursorData.width,
g_SDLPendingCursorData.height,
32,
g_SDLPendingCursorData.width * sizeof(uint32_t),
0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
SDL_Cursor *cursor = SDL_CreateColorCursor( surface, g_SDLPendingCursorData.xhot, g_SDLPendingCursorData.yhot );
SDL_SetCursor( cursor );
g_bUpdateSDLCursor = false;
}
}
break;
}
}
@ -372,8 +400,39 @@ void sdlwindow_grab( bool bGrab )
if ( g_bForceRelativeMouse )
return;
static bool s_bWasGrabbed = false;
if ( s_bWasGrabbed == bGrab )
return;
s_bWasGrabbed = bGrab;
SDL_Event event;
event.type = g_unSDLUserEventID + USER_EVENT_GRAB;
event.user.code = bGrab ? 1 : 0;
SDL_PushEvent( &event );
}
void sdlwindow_cursor(void* pixels, uint32_t width, uint32_t height, uint32_t xhot, uint32_t yhot)
{
if ( !BIsNested() )
return;
if ( g_bForceRelativeMouse )
return;
{
std::unique_lock lock( g_SDLCursorLock );
g_SDLPendingCursorData.width = width;
g_SDLPendingCursorData.height = height;
g_SDLPendingCursorData.xhot = xhot;
g_SDLPendingCursorData.yhot = yhot;
g_SDLPendingCursorData.data.resize( width * height );
memcpy(g_SDLPendingCursorData.data.data(), pixels, width * height * sizeof(uint32_t));
g_bUpdateSDLCursor = true;
}
SDL_Event event;
event.type = g_unSDLUserEventID + USER_EVENT_CURSOR;
SDL_PushEvent( &event );
}

View file

@ -13,5 +13,6 @@ void sdlwindow_title( const char* title );
// called from other threads with interesting things have happened with clients that might warrant updating the nested window
void sdlwindow_visible( bool bVisible );
void sdlwindow_grab( bool bGrab );
void sdlwindow_cursor(void* pixels, uint32_t width, uint32_t height, uint32_t xhot, uint32_t yhot);
extern SDL_Window *g_SDLWindow;

View file

@ -1364,14 +1364,12 @@ bool MouseCursor::getTexture()
}
}
if (bNoCursor != m_imageEmpty) {
m_imageEmpty = bNoCursor;
m_imageEmpty = bNoCursor;
if ( !g_bForceRelativeMouse )
{
sdlwindow_grab( m_imageEmpty );
bSteamCompMgrGrab = BIsNested() && m_imageEmpty;
}
if ( !g_bForceRelativeMouse )
{
sdlwindow_grab( m_imageEmpty );
bSteamCompMgrGrab = BIsNested() && m_imageEmpty;
}
m_dirty = false;
@ -1391,6 +1389,7 @@ bool MouseCursor::getTexture()
}
m_texture = vulkan_create_texture_from_bits(surfaceWidth, surfaceHeight, image->width, image->height, DRM_FORMAT_ARGB8888, texCreateFlags, cursorBuffer.data());
sdlwindow_cursor(cursorBuffer.data(), image->width, image->height, image->xhot, image->yhot);
assert(m_texture);
XFree(image);
@ -1910,6 +1909,13 @@ paint_all(bool async)
}
}
if (input)
{
// Make sure to un-dirty the texture before we do any painting logic.
// We determine whether we are grabbed etc this way.
global_focus.cursor->undirty();
}
bool bForceHideCursor = BIsNested() && !bSteamCompMgrGrab;
bool bDrewCursor = false;

View file

@ -71,6 +71,8 @@ public:
m_y = y;
}
void undirty() { getTexture(); }
private:
void warp(int x, int y);
void checkSuspension();