[all] update KVMFR to provide cursor hotspot information

This commit bumps the KVMFR protocol version as it adds additional
hotspot x & y fields to the KVMFRCursor struct. This corrects the issue
of invalid alignment of the local mouse when the shape has an offset
such as the 'I' beam.
This commit is contained in:
Geoffrey McRae 2020-08-20 13:46:18 +10:00
parent 10fbdeb294
commit 7e362050f7
9 changed files with 45 additions and 13 deletions

View file

@ -1 +1 @@
B2-rc4-0-g969effedde+1 B2-rc4-3-gc66a339bbc+1

View file

@ -328,6 +328,9 @@ static int cursorThread(void * unused)
continue; continue;
} }
state.cursor.hx = cursor->hx;
state.cursor.hy = cursor->hy;
const uint8_t * data = (const uint8_t *)(cursor + 1); const uint8_t * data = (const uint8_t *)(cursor + 1);
if (!state.lgr->on_mouse_shape( if (!state.lgr->on_mouse_shape(
state.lgrData, state.lgrData,
@ -760,8 +763,8 @@ static void alignMouseWithGuest()
if (state.ignoreInput || !params.useSpiceInput) if (state.ignoreInput || !params.useSpiceInput)
return; return;
state.curLastX = (int)round((float)state.cursor.x / state.scaleX) + state.dstRect.x; state.curLastX = (int)round((float)(state.cursor.x + state.cursor.hx) / state.scaleX) + state.dstRect.x;
state.curLastY = (int)round((float)state.cursor.y / state.scaleY) + state.dstRect.y; state.curLastY = (int)round((float)(state.cursor.y + state.cursor.hy) / state.scaleY) + state.dstRect.y;
SDL_WarpMouseInWindow(state.window, state.curLastX, state.curLastY); SDL_WarpMouseInWindow(state.window, state.curLastX, state.curLastY);
} }
@ -773,8 +776,8 @@ static void alignMouseWithHost()
if (!state.haveCursorPos || state.serverMode) if (!state.haveCursorPos || state.serverMode)
return; return;
state.curLastX = (int)round((float)state.cursor.x / state.scaleX) + state.dstRect.x; state.curLastX = (int)round((float)(state.cursor.x + state.cursor.hx) / state.scaleX) + state.dstRect.x;
state.curLastY = (int)round((float)state.cursor.y / state.scaleY) + state.dstRect.y; state.curLastY = (int)round((float)(state.cursor.y + state.cursor.hy) / state.scaleY) + state.dstRect.y;
handleMouseMoveEvent(state.curLocalX, state.curLocalY); handleMouseMoveEvent(state.curLocalX, state.curLocalY);
} }

View file

@ -36,6 +36,12 @@ enum RunState
APP_STATE_SHUTDOWN APP_STATE_SHUTDOWN
}; };
struct CursorInfo
{
int x , y;
int hx, hy;
};
struct AppState struct AppState
{ {
enum RunState state; enum RunState state;
@ -49,7 +55,7 @@ struct AppState
int windowW, windowH; int windowW, windowH;
SDL_Point srcSize; SDL_Point srcSize;
LG_RendererRect dstRect; LG_RendererRect dstRect;
SDL_Point cursor; struct CursorInfo cursor;
bool cursorVisible; bool cursorVisible;
bool serverMode; bool serverMode;

View file

@ -51,7 +51,7 @@ typedef enum CursorType
CursorType; CursorType;
#define KVMFR_MAGIC "KVMFR---" #define KVMFR_MAGIC "KVMFR---"
#define KVMFR_VERSION 2 #define KVMFR_VERSION 3
typedef struct KVMFR typedef struct KVMFR
{ {
@ -65,6 +65,7 @@ typedef struct KVMFRCursor
{ {
int16_t x, y; // cursor x & y position int16_t x, y; // cursor x & y position
CursorType type; // shape buffer data type CursorType type; // shape buffer data type
int8_t hx, hy; // shape hotspot x & y
uint32_t width; // width of the shape uint32_t width; // width of the shape
uint32_t height; // height of the shape uint32_t height; // height of the shape
uint32_t pitch; // row length in bytes of the shape uint32_t pitch; // row length in bytes of the shape

View file

@ -67,6 +67,7 @@ typedef struct CapturePointer
bool shapeUpdate; bool shapeUpdate;
CaptureFormat format; CaptureFormat format;
unsigned int hx, hy;
unsigned int width, height; unsigned int width, height;
unsigned int pitch; unsigned int pitch;
} }

View file

@ -827,7 +827,26 @@ static CaptureResult dxgi_capture()
return CAPTURE_RESULT_ERROR; return CAPTURE_RESULT_ERROR;
} }
CURSORINFO ci = { .cbSize = sizeof(CURSORINFO) };
if (!GetCursorInfo(&ci))
{
DEBUG_ERROR("GetCursorInfo failed");
return CAPTURE_RESULT_ERROR;
}
ICONINFO ii;
if (!GetIconInfo(ci.hCursor, &ii))
{
DEBUG_ERROR("GetIconInfo failed");
return CAPTURE_RESULT_ERROR;
}
DeleteObject(ii.hbmMask);
DeleteObject(ii.hbmColor);
pointer.shapeUpdate = true; pointer.shapeUpdate = true;
pointer.hx = ii.xHotspot;
pointer.hy = ii.yHotspot;
pointer.width = shapeInfo.Width; pointer.width = shapeInfo.Width;
pointer.height = shapeInfo.Height; pointer.height = shapeInfo.Height;
pointer.pitch = shapeInfo.Pitch; pointer.pitch = shapeInfo.Pitch;

View file

@ -352,8 +352,8 @@ static int pointerThread(void * unused)
} }
this->mouseVisible = pointer.visible; this->mouseVisible = pointer.visible;
this->mouseHotX = pointer.x; this->mouseHotX = pointer.hx;
this->mouseHotY = pointer.y; this->mouseHotY = pointer.hy;
} }
if (events[0]) if (events[0])

View file

@ -288,8 +288,8 @@ CaptureResult NvFBCToSysGetCursor(NvFBCHandle handle, CapturePointer * pointer,
return CAPTURE_RESULT_ERROR; return CAPTURE_RESULT_ERROR;
} }
pointer->x = params.dwXHotSpot; pointer->hx = params.dwXHotSpot;
pointer->y = params.dwYHotSpot; pointer->hy = params.dwYHotSpot;
pointer->width = params.dwWidth; pointer->width = params.dwWidth;
pointer->height = params.dwHeight; pointer->height = params.dwHeight;
pointer->pitch = params.dwPitch; pointer->pitch = params.dwPitch;
@ -327,4 +327,4 @@ CaptureResult NvFBCToSysGetCursor(NvFBCHandle handle, CapturePointer * pointer,
memcpy(buffer, params.pBits, params.dwBufferSize); memcpy(buffer, params.pBits, params.dwBufferSize);
return CAPTURE_RESULT_OK; return CAPTURE_RESULT_OK;
} }

View file

@ -336,7 +336,8 @@ static void sendPointer(bool newClient)
if (app.pointerInfo.shapeUpdate) if (app.pointerInfo.shapeUpdate)
{ {
// remember which slot has the latest shape cursor->hx = app.pointerInfo.hx;
cursor->hy = app.pointerInfo.hy;
cursor->width = app.pointerInfo.width; cursor->width = app.pointerInfo.width;
cursor->height = app.pointerInfo.height; cursor->height = app.pointerInfo.height;
cursor->pitch = app.pointerInfo.pitch; cursor->pitch = app.pointerInfo.pitch;
@ -489,6 +490,7 @@ int app_main(int argc, char * argv[])
DEBUG_ERROR("lgmpHostMemAlloc Failed (Pointer): %s", lgmpStatusString(status)); DEBUG_ERROR("lgmpHostMemAlloc Failed (Pointer): %s", lgmpStatusString(status));
goto fail; goto fail;
} }
memset(lgmpHostMemPtr(app.pointerMemory[i]), 0, MAX_POINTER_SIZE);
} }
app.pointerShapeValid = false; app.pointerShapeValid = false;