From 7e362050f7fde568f2c6347e8c328af3b20dd060 Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Thu, 20 Aug 2020 13:46:18 +1000 Subject: [PATCH] [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. --- VERSION | 2 +- client/src/main.c | 11 +++++++---- client/src/main.h | 8 +++++++- common/include/common/KVMFR.h | 3 ++- host/include/interface/capture.h | 1 + host/platform/Windows/capture/DXGI/src/dxgi.c | 19 +++++++++++++++++++ .../Windows/capture/NVFBC/src/nvfbc.c | 4 ++-- .../Windows/capture/NVFBC/src/wrapper.cpp | 6 +++--- host/src/app.c | 4 +++- 9 files changed, 45 insertions(+), 13 deletions(-) diff --git a/VERSION b/VERSION index 3eb14bfa..926196d5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -B2-rc4-0-g969effedde+1 \ No newline at end of file +B2-rc4-3-gc66a339bbc+1 \ No newline at end of file diff --git a/client/src/main.c b/client/src/main.c index e016aca1..5de27644 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -328,6 +328,9 @@ static int cursorThread(void * unused) continue; } + state.cursor.hx = cursor->hx; + state.cursor.hy = cursor->hy; + const uint8_t * data = (const uint8_t *)(cursor + 1); if (!state.lgr->on_mouse_shape( state.lgrData, @@ -760,8 +763,8 @@ static void alignMouseWithGuest() if (state.ignoreInput || !params.useSpiceInput) return; - state.curLastX = (int)round((float)state.cursor.x / state.scaleX) + state.dstRect.x; - state.curLastY = (int)round((float)state.cursor.y / state.scaleY) + state.dstRect.y; + 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.cursor.hy) / state.scaleY) + state.dstRect.y; SDL_WarpMouseInWindow(state.window, state.curLastX, state.curLastY); } @@ -773,8 +776,8 @@ static void alignMouseWithHost() if (!state.haveCursorPos || state.serverMode) return; - state.curLastX = (int)round((float)state.cursor.x / state.scaleX) + state.dstRect.x; - state.curLastY = (int)round((float)state.cursor.y / state.scaleY) + state.dstRect.y; + 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.cursor.hy) / state.scaleY) + state.dstRect.y; handleMouseMoveEvent(state.curLocalX, state.curLocalY); } diff --git a/client/src/main.h b/client/src/main.h index 7305671f..1ab10677 100644 --- a/client/src/main.h +++ b/client/src/main.h @@ -36,6 +36,12 @@ enum RunState APP_STATE_SHUTDOWN }; +struct CursorInfo +{ + int x , y; + int hx, hy; +}; + struct AppState { enum RunState state; @@ -49,7 +55,7 @@ struct AppState int windowW, windowH; SDL_Point srcSize; LG_RendererRect dstRect; - SDL_Point cursor; + struct CursorInfo cursor; bool cursorVisible; bool serverMode; diff --git a/common/include/common/KVMFR.h b/common/include/common/KVMFR.h index 8557d878..48c10716 100644 --- a/common/include/common/KVMFR.h +++ b/common/include/common/KVMFR.h @@ -51,7 +51,7 @@ typedef enum CursorType CursorType; #define KVMFR_MAGIC "KVMFR---" -#define KVMFR_VERSION 2 +#define KVMFR_VERSION 3 typedef struct KVMFR { @@ -65,6 +65,7 @@ typedef struct KVMFRCursor { int16_t x, y; // cursor x & y position CursorType type; // shape buffer data type + int8_t hx, hy; // shape hotspot x & y uint32_t width; // width of the shape uint32_t height; // height of the shape uint32_t pitch; // row length in bytes of the shape diff --git a/host/include/interface/capture.h b/host/include/interface/capture.h index 783e7305..f72ceb4c 100644 --- a/host/include/interface/capture.h +++ b/host/include/interface/capture.h @@ -67,6 +67,7 @@ typedef struct CapturePointer bool shapeUpdate; CaptureFormat format; + unsigned int hx, hy; unsigned int width, height; unsigned int pitch; } diff --git a/host/platform/Windows/capture/DXGI/src/dxgi.c b/host/platform/Windows/capture/DXGI/src/dxgi.c index 90940bf0..59d0b62e 100644 --- a/host/platform/Windows/capture/DXGI/src/dxgi.c +++ b/host/platform/Windows/capture/DXGI/src/dxgi.c @@ -827,7 +827,26 @@ static CaptureResult dxgi_capture() 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.hx = ii.xHotspot; + pointer.hy = ii.yHotspot; pointer.width = shapeInfo.Width; pointer.height = shapeInfo.Height; pointer.pitch = shapeInfo.Pitch; diff --git a/host/platform/Windows/capture/NVFBC/src/nvfbc.c b/host/platform/Windows/capture/NVFBC/src/nvfbc.c index 886434be..8ccb56a3 100644 --- a/host/platform/Windows/capture/NVFBC/src/nvfbc.c +++ b/host/platform/Windows/capture/NVFBC/src/nvfbc.c @@ -352,8 +352,8 @@ static int pointerThread(void * unused) } this->mouseVisible = pointer.visible; - this->mouseHotX = pointer.x; - this->mouseHotY = pointer.y; + this->mouseHotX = pointer.hx; + this->mouseHotY = pointer.hy; } if (events[0]) diff --git a/host/platform/Windows/capture/NVFBC/src/wrapper.cpp b/host/platform/Windows/capture/NVFBC/src/wrapper.cpp index 044134fe..b011298a 100644 --- a/host/platform/Windows/capture/NVFBC/src/wrapper.cpp +++ b/host/platform/Windows/capture/NVFBC/src/wrapper.cpp @@ -288,8 +288,8 @@ CaptureResult NvFBCToSysGetCursor(NvFBCHandle handle, CapturePointer * pointer, return CAPTURE_RESULT_ERROR; } - pointer->x = params.dwXHotSpot; - pointer->y = params.dwYHotSpot; + pointer->hx = params.dwXHotSpot; + pointer->hy = params.dwYHotSpot; pointer->width = params.dwWidth; pointer->height = params.dwHeight; pointer->pitch = params.dwPitch; @@ -327,4 +327,4 @@ CaptureResult NvFBCToSysGetCursor(NvFBCHandle handle, CapturePointer * pointer, memcpy(buffer, params.pBits, params.dwBufferSize); return CAPTURE_RESULT_OK; -} \ No newline at end of file +} diff --git a/host/src/app.c b/host/src/app.c index a58db794..3e639c54 100644 --- a/host/src/app.c +++ b/host/src/app.c @@ -336,7 +336,8 @@ static void sendPointer(bool newClient) 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->height = app.pointerInfo.height; cursor->pitch = app.pointerInfo.pitch; @@ -489,6 +490,7 @@ int app_main(int argc, char * argv[]) DEBUG_ERROR("lgmpHostMemAlloc Failed (Pointer): %s", lgmpStatusString(status)); goto fail; } + memset(lgmpHostMemPtr(app.pointerMemory[i]), 0, MAX_POINTER_SIZE); } app.pointerShapeValid = false;