[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;
}
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);
}

View file

@ -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;

View file

@ -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

View file

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

View file

@ -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;

View file

@ -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])

View file

@ -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;
}
}

View file

@ -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;