mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-12-23 14:03:40 +00:00
[host] improve mouse sync with the client
This commit is contained in:
parent
d8b4d0c1ce
commit
db907b1b67
@ -350,20 +350,20 @@ size_t DXGI::GetMaxFrameSize()
|
|||||||
return (m_width * m_height * 4);
|
return (m_width * m_height * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
GrabStatus Capture::DXGI::Capture()
|
unsigned int Capture::DXGI::Capture()
|
||||||
{
|
{
|
||||||
if (!m_initialized)
|
if (!m_initialized)
|
||||||
return GRAB_STATUS_ERROR;
|
return GRAB_STATUS_ERROR;
|
||||||
|
|
||||||
CursorInfo cursor = { 0 };
|
CursorInfo cursor = { 0 };
|
||||||
bool cursorUpdated = false;
|
|
||||||
DXGI_OUTDUPL_FRAME_INFO frameInfo;
|
DXGI_OUTDUPL_FRAME_INFO frameInfo;
|
||||||
IDXGIResourcePtr res;
|
IDXGIResourcePtr res;
|
||||||
|
unsigned int ret;
|
||||||
|
|
||||||
HRESULT status;
|
HRESULT status;
|
||||||
for (int retryCount = 0; retryCount < 2; ++retryCount)
|
for (int retryCount = 0; retryCount < 2; ++retryCount)
|
||||||
{
|
{
|
||||||
GrabStatus ret = ReleaseFrame();
|
ret = ReleaseFrame();
|
||||||
if (ret != GRAB_STATUS_OK)
|
if (ret != GRAB_STATUS_OK)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -396,7 +396,7 @@ GrabStatus Capture::DXGI::Capture()
|
|||||||
m_lastCursorX != frameInfo.PointerPosition.Position.x ||
|
m_lastCursorX != frameInfo.PointerPosition.Position.x ||
|
||||||
m_lastCursorY != frameInfo.PointerPosition.Position.y
|
m_lastCursorY != frameInfo.PointerPosition.Position.y
|
||||||
) {
|
) {
|
||||||
cursorUpdated = true;
|
ret |= GRAB_STATUS_CURSOR;
|
||||||
cursor.hasPos = true;
|
cursor.hasPos = true;
|
||||||
cursor.x = m_lastCursorX = frameInfo.PointerPosition.Position.x;
|
cursor.x = m_lastCursorX = frameInfo.PointerPosition.Position.x;
|
||||||
cursor.y = m_lastCursorY = frameInfo.PointerPosition.Position.y;
|
cursor.y = m_lastCursorY = frameInfo.PointerPosition.Position.y;
|
||||||
@ -404,12 +404,24 @@ GrabStatus Capture::DXGI::Capture()
|
|||||||
|
|
||||||
if (m_lastMouseVis != frameInfo.PointerPosition.Visible)
|
if (m_lastMouseVis != frameInfo.PointerPosition.Visible)
|
||||||
{
|
{
|
||||||
cursorUpdated = true;
|
ret |= GRAB_STATUS_CURSOR;
|
||||||
m_lastMouseVis = frameInfo.PointerPosition.Visible;
|
m_lastMouseVis = frameInfo.PointerPosition.Visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor.visible = m_lastMouseVis == TRUE;
|
cursor.visible = m_lastMouseVis == TRUE;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// always report the mouse position to prevent the guest losing sync (ie: dragging windows)
|
||||||
|
POINT curPos;
|
||||||
|
if (GetCursorPos(&curPos) && (curPos.x != m_lastCursorX || curPos.y != m_lastCursorY))
|
||||||
|
{
|
||||||
|
ret |= GRAB_STATUS_CURSOR;
|
||||||
|
cursor.hasPos = true;
|
||||||
|
cursor.x = m_lastCursorX = curPos.x;
|
||||||
|
cursor.y = m_lastCursorY = curPos.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if the pointer shape has changed
|
// if the pointer shape has changed
|
||||||
if (frameInfo.PointerShapeBufferSize > 0)
|
if (frameInfo.PointerShapeBufferSize > 0)
|
||||||
@ -442,7 +454,7 @@ GrabStatus Capture::DXGI::Capture()
|
|||||||
|
|
||||||
buf->pointerSize = 0;
|
buf->pointerSize = 0;
|
||||||
cursor.shape = buf;
|
cursor.shape = buf;
|
||||||
cursorUpdated = true;
|
ret |= GRAB_STATUS_CURSOR;
|
||||||
|
|
||||||
DXGI_OUTDUPL_POINTER_SHAPE_INFO shapeInfo;
|
DXGI_OUTDUPL_POINTER_SHAPE_INFO shapeInfo;
|
||||||
status = m_dup->GetFramePointerShape(buf->bufferSize, buf->buffer, &buf->pointerSize, &shapeInfo);
|
status = m_dup->GetFramePointerShape(buf->bufferSize, buf->buffer, &buf->pointerSize, &shapeInfo);
|
||||||
@ -467,7 +479,7 @@ GrabStatus Capture::DXGI::Capture()
|
|||||||
cursor.pitch = shapeInfo.Pitch;
|
cursor.pitch = shapeInfo.Pitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cursorUpdated)
|
if (ret & GRAB_STATUS_CURSOR)
|
||||||
{
|
{
|
||||||
// push the cursor update into the queue
|
// push the cursor update into the queue
|
||||||
EnterCriticalSection(&m_cursorCS);
|
EnterCriticalSection(&m_cursorCS);
|
||||||
@ -479,20 +491,23 @@ GrabStatus Capture::DXGI::Capture()
|
|||||||
if (frameInfo.LastPresentTime.QuadPart == 0)
|
if (frameInfo.LastPresentTime.QuadPart == 0)
|
||||||
{
|
{
|
||||||
// if there is nothing to update, just start again
|
// if there is nothing to update, just start again
|
||||||
if (!cursorUpdated)
|
if (!ret)
|
||||||
{
|
{
|
||||||
--retryCount;
|
--retryCount;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = NULL;
|
res = NULL;
|
||||||
return GRAB_STATUS_CURSOR;
|
ret |= GRAB_STATUS_OK;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// success, break out of the retry loop
|
// success, break out of the retry loop
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret |= GRAB_STATUS_FRAME;
|
||||||
|
|
||||||
// ensure we have a frame
|
// ensure we have a frame
|
||||||
if (!m_releaseFrame)
|
if (!m_releaseFrame)
|
||||||
{
|
{
|
||||||
@ -508,7 +523,8 @@ GrabStatus Capture::DXGI::Capture()
|
|||||||
return GRAB_STATUS_ERROR;
|
return GRAB_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GRAB_STATUS_OK;
|
ret |= GRAB_STATUS_OK;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
GrabStatus Capture::DXGI::ReleaseFrame()
|
GrabStatus Capture::DXGI::ReleaseFrame()
|
||||||
|
@ -58,7 +58,7 @@ namespace Capture
|
|||||||
|
|
||||||
enum FrameType GetFrameType();
|
enum FrameType GetFrameType();
|
||||||
size_t GetMaxFrameSize();
|
size_t GetMaxFrameSize();
|
||||||
GrabStatus Capture();
|
unsigned int Capture();
|
||||||
GrabStatus GetFrame (struct FrameInfo & frame );
|
GrabStatus GetFrame (struct FrameInfo & frame );
|
||||||
bool GetCursor(CursorInfo & cursor);
|
bool GetCursor(CursorInfo & cursor);
|
||||||
void FreeCursor(CursorInfo & cursor);
|
void FreeCursor(CursorInfo & cursor);
|
||||||
|
@ -54,11 +54,12 @@ struct FrameInfo
|
|||||||
|
|
||||||
enum GrabStatus
|
enum GrabStatus
|
||||||
{
|
{
|
||||||
GRAB_STATUS_OK,
|
GRAB_STATUS_OK = 1,
|
||||||
GRAB_STATUS_TIMEOUT,
|
GRAB_STATUS_TIMEOUT = 2,
|
||||||
GRAB_STATUS_REINIT,
|
GRAB_STATUS_REINIT = 4,
|
||||||
GRAB_STATUS_CURSOR,
|
GRAB_STATUS_CURSOR = 8,
|
||||||
GRAB_STATUS_ERROR
|
GRAB_STATUS_FRAME = 16,
|
||||||
|
GRAB_STATUS_ERROR = 32
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<const char *> CaptureOptions;
|
typedef std::vector<const char *> CaptureOptions;
|
||||||
@ -74,7 +75,7 @@ public:
|
|||||||
virtual bool ReInitialize() = 0;
|
virtual bool ReInitialize() = 0;
|
||||||
virtual enum FrameType GetFrameType() = 0;
|
virtual enum FrameType GetFrameType() = 0;
|
||||||
virtual size_t GetMaxFrameSize() = 0;
|
virtual size_t GetMaxFrameSize() = 0;
|
||||||
virtual enum GrabStatus Capture() = 0;
|
virtual unsigned int Capture() = 0;
|
||||||
virtual enum GrabStatus GetFrame(struct FrameInfo & frame) = 0;
|
virtual enum GrabStatus GetFrame(struct FrameInfo & frame) = 0;
|
||||||
virtual bool GetCursor(CursorInfo & cursor) = 0;
|
virtual bool GetCursor(CursorInfo & cursor) = 0;
|
||||||
virtual void FreeCursor(CursorInfo & cursor) = 0;
|
virtual void FreeCursor(CursorInfo & cursor) = 0;
|
||||||
|
133
host/Service.cpp
133
host/Service.cpp
@ -193,87 +193,88 @@ bool Service::Process()
|
|||||||
INTERLOCKED_AND8(flags, ~(KVMFR_HEADER_FLAG_RESTART));
|
INTERLOCKED_AND8(flags, ~(KVMFR_HEADER_FLAG_RESTART));
|
||||||
}
|
}
|
||||||
|
|
||||||
GrabStatus result;
|
unsigned int status;
|
||||||
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
bool cursorOnly = false;
|
|
||||||
bool repeat = false;
|
bool repeat = false;
|
||||||
|
|
||||||
for(int i = 0; i < 2; ++i)
|
for(int i = 0; i < 2; ++i)
|
||||||
{
|
{
|
||||||
// capture a frame of data
|
status = m_capture->Capture();
|
||||||
switch (m_capture->Capture())
|
if (status & GRAB_STATUS_OK)
|
||||||
{
|
{
|
||||||
case GRAB_STATUS_OK:
|
ok = true;
|
||||||
ok = true;
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case GRAB_STATUS_TIMEOUT:
|
|
||||||
if (m_haveFrame)
|
|
||||||
{
|
|
||||||
ok = true;
|
|
||||||
repeat = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// capture timeouts are not errors
|
|
||||||
--i;
|
|
||||||
continue;
|
|
||||||
|
|
||||||
case GRAB_STATUS_CURSOR:
|
|
||||||
ok = true;
|
|
||||||
cursorOnly = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GRAB_STATUS_ERROR:
|
|
||||||
DEBUG_ERROR("Capture failed");
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case GRAB_STATUS_REINIT:
|
|
||||||
DEBUG_INFO("ReInitialize Requested");
|
|
||||||
|
|
||||||
INTERLOCKED_OR8(flags, KVMFR_HEADER_FLAG_PAUSED);
|
|
||||||
if(WTSGetActiveConsoleSessionId() != m_consoleSessionID)
|
|
||||||
{
|
|
||||||
DEBUG_INFO("User switch detected, waiting to regain control");
|
|
||||||
while (WTSGetActiveConsoleSessionId() != m_consoleSessionID)
|
|
||||||
Sleep(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!m_capture->CanInitialize())
|
|
||||||
Sleep(100);
|
|
||||||
|
|
||||||
if (!m_capture->ReInitialize())
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("ReInitialize Failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_capture->GetMaxFrameSize() > m_frameSize)
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("Maximum frame size of %zd bytes excceds maximum space available", m_capture->GetMaxFrameSize());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
INTERLOCKED_AND8(flags, ~KVMFR_HEADER_FLAG_PAUSED);
|
|
||||||
|
|
||||||
// re-init request should not count towards a failure to capture
|
|
||||||
--i;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ok)
|
if (status & GRAB_STATUS_TIMEOUT)
|
||||||
break;
|
{
|
||||||
|
if (m_haveFrame)
|
||||||
|
{
|
||||||
|
ok = true;
|
||||||
|
repeat = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// timeouts should not count towards a failure to capture
|
||||||
|
--i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status & GRAB_STATUS_ERROR)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Capture failed, retrying");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status & GRAB_STATUS_REINIT)
|
||||||
|
{
|
||||||
|
DEBUG_INFO("ReInitialize Requested");
|
||||||
|
|
||||||
|
INTERLOCKED_OR8(flags, KVMFR_HEADER_FLAG_PAUSED);
|
||||||
|
if (WTSGetActiveConsoleSessionId() != m_consoleSessionID)
|
||||||
|
{
|
||||||
|
DEBUG_INFO("User switch detected, waiting to regain control");
|
||||||
|
while (WTSGetActiveConsoleSessionId() != m_consoleSessionID)
|
||||||
|
Sleep(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!m_capture->CanInitialize())
|
||||||
|
Sleep(100);
|
||||||
|
|
||||||
|
if (!m_capture->ReInitialize())
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("ReInitialize Failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_capture->GetMaxFrameSize() > m_frameSize)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Maximum frame size of %zd bytes excceds maximum space available", m_capture->GetMaxFrameSize());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
INTERLOCKED_AND8(flags, ~KVMFR_HEADER_FLAG_PAUSED);
|
||||||
|
|
||||||
|
// re-init request should not count towards a failure to capture
|
||||||
|
--i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_ERROR("Capture interface returned an unexpected result");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!ok)
|
if (!ok)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Capture retry count exceeded");
|
DEBUG_ERROR("Capture retry count exceeded");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetEvent(m_cursorEvent);
|
if (status & GRAB_STATUS_CURSOR)
|
||||||
|
SetEvent(m_cursorEvent);
|
||||||
|
|
||||||
if (!cursorOnly)
|
if (status & GRAB_STATUS_FRAME)
|
||||||
{
|
{
|
||||||
volatile KVMFRFrame * fi = &(m_shmHeader->frame);
|
volatile KVMFRFrame * fi = &(m_shmHeader->frame);
|
||||||
|
|
||||||
@ -284,7 +285,7 @@ bool Service::Process()
|
|||||||
frame.buffer = m_frame[m_frameIndex];
|
frame.buffer = m_frame[m_frameIndex];
|
||||||
frame.bufferSize = m_frameSize;
|
frame.bufferSize = m_frameSize;
|
||||||
|
|
||||||
result = m_capture->GetFrame(frame);
|
GrabStatus result = m_capture->GetFrame(frame);
|
||||||
if (result != GRAB_STATUS_OK)
|
if (result != GRAB_STATUS_OK)
|
||||||
{
|
{
|
||||||
DEBUG_INFO("GetFrame failed");
|
DEBUG_INFO("GetFrame failed");
|
||||||
|
Loading…
Reference in New Issue
Block a user