mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-14 21:17:54 +00:00
[host] use a global hook to obtain cursor move pos
This commit is contained in:
parent
5518ccb795
commit
1ef61f6cd3
7 changed files with 124 additions and 80 deletions
|
@ -539,8 +539,6 @@ unsigned int Capture::DXGI::Capture()
|
||||||
cursor.w = shapeInfo.Width;
|
cursor.w = shapeInfo.Width;
|
||||||
cursor.h = shapeInfo.Height;
|
cursor.h = shapeInfo.Height;
|
||||||
cursor.pitch = shapeInfo.Pitch;
|
cursor.pitch = shapeInfo.Pitch;
|
||||||
m_hotSpot.x = shapeInfo.HotSpot.x;
|
|
||||||
m_hotSpot.y = shapeInfo.HotSpot.y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we have a mouse update
|
// if we have a mouse update
|
||||||
|
@ -556,24 +554,6 @@ unsigned int Capture::DXGI::Capture()
|
||||||
cursor.y = m_lastCursorY = frameInfo.PointerPosition.Position.y;
|
cursor.y = m_lastCursorY = frameInfo.PointerPosition.Position.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// always report the mouse position to prevent the guest losing sync (ie: dragging windows)
|
|
||||||
POINT curPos;
|
|
||||||
if (GetCursorPos(&curPos))
|
|
||||||
{
|
|
||||||
curPos.x -= m_hotSpot.x;
|
|
||||||
curPos.y -= m_hotSpot.y;
|
|
||||||
|
|
||||||
if (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 (m_lastMouseVis != frameInfo.PointerPosition.Visible)
|
if (m_lastMouseVis != frameInfo.PointerPosition.Visible)
|
||||||
m_lastMouseVis = frameInfo.PointerPosition.Visible;
|
m_lastMouseVis = frameInfo.PointerPosition.Visible;
|
||||||
|
|
|
@ -102,6 +102,5 @@ namespace Capture
|
||||||
|
|
||||||
int m_lastCursorX, m_lastCursorY;
|
int m_lastCursorX, m_lastCursorY;
|
||||||
BOOL m_lastMouseVis;
|
BOOL m_lastMouseVis;
|
||||||
POINT m_hotSpot;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
|
@ -41,6 +41,7 @@ NvFBC::NvFBC() :
|
||||||
m_optNoCrop(false),
|
m_optNoCrop(false),
|
||||||
m_optNoWait(false),
|
m_optNoWait(false),
|
||||||
m_initialized(false),
|
m_initialized(false),
|
||||||
|
m_first(true),
|
||||||
m_hDLL(NULL),
|
m_hDLL(NULL),
|
||||||
m_nvFBC(NULL)
|
m_nvFBC(NULL)
|
||||||
{
|
{
|
||||||
|
@ -60,6 +61,7 @@ bool NvFBC::Initialize(CaptureOptions * options)
|
||||||
if (m_initialized)
|
if (m_initialized)
|
||||||
DeInitialize();
|
DeInitialize();
|
||||||
|
|
||||||
|
m_first = true;
|
||||||
m_options = options;
|
m_options = options;
|
||||||
m_optNoCrop = false;
|
m_optNoCrop = false;
|
||||||
|
|
||||||
|
@ -345,7 +347,11 @@ unsigned int Capture::NvFBC::Capture()
|
||||||
return GRAB_STATUS_REINIT;
|
return GRAB_STATUS_REINIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GRAB_STATUS_OK | GRAB_STATUS_FRAME;
|
// turn off the cursor on the first frame as NvFBC is drawing it
|
||||||
|
if (m_first)
|
||||||
|
return GRAB_STATUS_OK | GRAB_STATUS_FRAME | GRAB_STATUS_CURSOR;
|
||||||
|
else
|
||||||
|
return GRAB_STATUS_OK | GRAB_STATUS_FRAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Capture::NvFBC::GetCursor(CursorInfo & cursor)
|
bool Capture::NvFBC::GetCursor(CursorInfo & cursor)
|
||||||
|
@ -353,6 +359,13 @@ bool Capture::NvFBC::GetCursor(CursorInfo & cursor)
|
||||||
cursor.hasShape = false;
|
cursor.hasShape = false;
|
||||||
cursor.hasPos = false;
|
cursor.hasPos = false;
|
||||||
cursor.visible = false;
|
cursor.visible = false;
|
||||||
|
|
||||||
|
if (m_first)
|
||||||
|
{
|
||||||
|
m_first = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,7 @@ namespace Capture
|
||||||
bool m_optNoWait;
|
bool m_optNoWait;
|
||||||
|
|
||||||
bool m_initialized;
|
bool m_initialized;
|
||||||
|
bool m_first;
|
||||||
HMODULE m_hDLL;
|
HMODULE m_hDLL;
|
||||||
|
|
||||||
NvFBC_CreateFunctionExType m_fnCreateEx;
|
NvFBC_CreateFunctionExType m_fnCreateEx;
|
||||||
|
|
|
@ -27,8 +27,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include "CaptureFactory.h"
|
#include "CaptureFactory.h"
|
||||||
|
|
||||||
Service * Service::m_instance = NULL;
|
|
||||||
|
|
||||||
Service::Service() :
|
Service::Service() :
|
||||||
m_initialized(false),
|
m_initialized(false),
|
||||||
m_memory(NULL),
|
m_memory(NULL),
|
||||||
|
@ -41,10 +39,39 @@ Service::Service() :
|
||||||
{
|
{
|
||||||
m_consoleSessionID = WTSGetActiveConsoleSessionId();
|
m_consoleSessionID = WTSGetActiveConsoleSessionId();
|
||||||
m_ivshmem = IVSHMEM::Get();
|
m_ivshmem = IVSHMEM::Get();
|
||||||
|
|
||||||
|
if (!m_ivshmem->Initialize())
|
||||||
|
throw "IVSHMEM failed to initalize";
|
||||||
|
|
||||||
|
if (m_ivshmem->GetSize() < sizeof(KVMFRHeader))
|
||||||
|
throw "Shared memory is not large enough for the KVMFRHeader";
|
||||||
|
|
||||||
|
m_memory = static_cast<uint8_t*>(m_ivshmem->GetMemory());
|
||||||
|
if (!m_memory)
|
||||||
|
throw "Failed to get IVSHMEM memory";
|
||||||
|
|
||||||
|
if (!InitPointers())
|
||||||
|
throw "Failed to initialize the shared memory pointers";
|
||||||
}
|
}
|
||||||
|
|
||||||
Service::~Service()
|
Service::~Service()
|
||||||
{
|
{
|
||||||
|
DeInitialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT Service::LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
if (nCode == HC_ACTION && wParam == WM_MOUSEMOVE)
|
||||||
|
{
|
||||||
|
MSLLHOOKSTRUCT *msg = (MSLLHOOKSTRUCT *)lParam;
|
||||||
|
volatile KVMFRCursor * cursor = &(m_shmHeader->cursor);
|
||||||
|
volatile char * flags = (volatile char *)&(cursor->flags);
|
||||||
|
|
||||||
|
cursor->x = msg->pt.x;
|
||||||
|
cursor->y = msg->pt.y;
|
||||||
|
INTERLOCKED_OR8(flags, KVMFR_CURSOR_FLAG_POS);
|
||||||
|
}
|
||||||
|
return CallNextHookEx(m_mouseHook, nCode, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Service::Initialize(ICapture * captureDevice)
|
bool Service::Initialize(ICapture * captureDevice)
|
||||||
|
@ -52,35 +79,8 @@ bool Service::Initialize(ICapture * captureDevice)
|
||||||
if (m_initialized)
|
if (m_initialized)
|
||||||
DeInitialize();
|
DeInitialize();
|
||||||
|
|
||||||
m_tryTarget = 0;
|
m_tryTarget = 0;
|
||||||
m_capture = captureDevice;
|
m_capture = captureDevice;
|
||||||
if (!m_ivshmem->Initialize())
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("IVSHMEM failed to initalize");
|
|
||||||
DeInitialize();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_ivshmem->GetSize() < sizeof(KVMFRHeader))
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("Shared memory is not large enough for the KVMFRHeader");
|
|
||||||
DeInitialize();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_memory = static_cast<uint8_t*>(m_ivshmem->GetMemory());
|
|
||||||
if (!m_memory)
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("Failed to get IVSHMEM memory");
|
|
||||||
DeInitialize();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!InitPointers())
|
|
||||||
{
|
|
||||||
DeInitialize();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_capture->GetMaxFrameSize() > m_frameSize)
|
if (m_capture->GetMaxFrameSize() > m_frameSize)
|
||||||
{
|
{
|
||||||
|
@ -90,7 +90,7 @@ bool Service::Initialize(ICapture * captureDevice)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the cursor thread
|
// Create the cursor thread
|
||||||
m_cursorThread = CreateThread(NULL, 0, _CursorThread, this, 0, NULL);
|
m_cursorThread = CreateThread(NULL, 0, _CursorThread, NULL, 0, NULL);
|
||||||
m_cursorEvent = CreateEvent (NULL, FALSE, FALSE, L"CursorEvent");
|
m_cursorEvent = CreateEvent (NULL, FALSE, FALSE, L"CursorEvent");
|
||||||
InitializeCriticalSection(&m_cursorCS);
|
InitializeCriticalSection(&m_cursorCS);
|
||||||
|
|
||||||
|
@ -340,21 +340,20 @@ DWORD Service::CursorThread()
|
||||||
{
|
{
|
||||||
volatile KVMFRCursor * cursor = &(m_shmHeader->cursor);
|
volatile KVMFRCursor * cursor = &(m_shmHeader->cursor);
|
||||||
// wait until the client is ready
|
// wait until the client is ready
|
||||||
while (cursor->flags != 0)
|
while ((cursor->flags & ~KVMFR_CURSOR_FLAG_POS) != 0)
|
||||||
{
|
{
|
||||||
Sleep(1);
|
Sleep(1);
|
||||||
if (!m_capture)
|
if (!m_capture)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t flags = 0;
|
uint8_t flags = cursor->flags;
|
||||||
|
|
||||||
if (ci.hasPos)
|
if (ci.hasPos)
|
||||||
{
|
{
|
||||||
// tell the client where the cursor is
|
|
||||||
flags |= KVMFR_CURSOR_FLAG_POS;
|
|
||||||
cursor->x = ci.x;
|
cursor->x = ci.x;
|
||||||
cursor->y = ci.y;
|
cursor->y = ci.y;
|
||||||
|
flags |= KVMFR_CURSOR_FLAG_POS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ci.hasShape)
|
if (ci.hasShape)
|
||||||
|
|
|
@ -25,6 +25,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
#include "IVSHMEM.h"
|
#include "IVSHMEM.h"
|
||||||
#include "ICapture.h"
|
#include "ICapture.h"
|
||||||
|
#include "common/debug.h"
|
||||||
|
|
||||||
#define MAX_FRAMES 2
|
#define MAX_FRAMES 2
|
||||||
|
|
||||||
|
@ -38,11 +39,26 @@ enum ProcessStatus
|
||||||
class Service
|
class Service
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static Service * Get()
|
static Service & Instance()
|
||||||
{
|
{
|
||||||
if (!m_instance)
|
static Service service;
|
||||||
m_instance = new Service();
|
return service;
|
||||||
return m_instance;
|
}
|
||||||
|
|
||||||
|
static void InstallHook()
|
||||||
|
{
|
||||||
|
if (Instance().m_mouseHook)
|
||||||
|
RemoveHook();
|
||||||
|
Instance().m_mouseHook = SetWindowsHookEx(WH_MOUSE_LL, _LowLevelMouseProc, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RemoveHook()
|
||||||
|
{
|
||||||
|
if (Instance().m_mouseHook)
|
||||||
|
{
|
||||||
|
UnhookWindowsHookEx(Instance().m_mouseHook);
|
||||||
|
Instance().m_mouseHook = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Initialize(ICapture * captureDevice);
|
bool Initialize(ICapture * captureDevice);
|
||||||
|
@ -52,13 +68,16 @@ public:
|
||||||
private:
|
private:
|
||||||
bool InitPointers();
|
bool InitPointers();
|
||||||
|
|
||||||
static Service * m_instance;
|
|
||||||
int m_tryTarget;
|
int m_tryTarget;
|
||||||
int m_lastTryCount;
|
int m_lastTryCount;
|
||||||
|
|
||||||
Service();
|
Service();
|
||||||
~Service();
|
~Service();
|
||||||
|
|
||||||
|
HHOOK m_mouseHook;
|
||||||
|
LRESULT LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam);
|
||||||
|
static LRESULT WINAPI _LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) { return Service::Instance().LowLevelMouseProc(nCode, wParam, lParam); }
|
||||||
|
|
||||||
bool ReInit(volatile char * flags);
|
bool ReInit(volatile char * flags);
|
||||||
|
|
||||||
bool m_initialized;
|
bool m_initialized;
|
||||||
|
@ -77,7 +96,7 @@ private:
|
||||||
uint64_t m_dataOffset[MAX_FRAMES];
|
uint64_t m_dataOffset[MAX_FRAMES];
|
||||||
int m_frameIndex;
|
int m_frameIndex;
|
||||||
|
|
||||||
static DWORD WINAPI _CursorThread(LPVOID lpParameter) { return ((Service *)lpParameter)->CursorThread(); }
|
static DWORD WINAPI _CursorThread(LPVOID lpParameter) { return Service::Instance().CursorThread(); }
|
||||||
DWORD CursorThread();
|
DWORD CursorThread();
|
||||||
|
|
||||||
HANDLE m_cursorThread;
|
HANDLE m_cursorThread;
|
||||||
|
|
|
@ -34,11 +34,13 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
int parseArgs(struct StartupArgs & args);
|
int parseArgs(struct StartupArgs & args);
|
||||||
int run(struct StartupArgs & args);
|
static DWORD WINAPI CaptureThread(LPVOID lpParameter);
|
||||||
|
int run();
|
||||||
|
|
||||||
void doHelp();
|
void doHelp();
|
||||||
void doLicense();
|
void doLicense();
|
||||||
|
|
||||||
|
bool running = true;
|
||||||
bool consoleActive = false;
|
bool consoleActive = false;
|
||||||
void setupConsole();
|
void setupConsole();
|
||||||
|
|
||||||
|
@ -50,6 +52,7 @@ struct StartupArgs
|
||||||
const char * captureDevice;
|
const char * captureDevice;
|
||||||
CaptureOptions captureOptions;
|
CaptureOptions captureOptions;
|
||||||
};
|
};
|
||||||
|
struct StartupArgs args;
|
||||||
|
|
||||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdParam, int iCmdShow)
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdParam, int iCmdShow)
|
||||||
{
|
{
|
||||||
|
@ -57,21 +60,41 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdParam
|
||||||
TraceUtil::Initialize();
|
TraceUtil::Initialize();
|
||||||
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
|
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
|
||||||
|
|
||||||
struct StartupArgs args;
|
|
||||||
args.foreground = false;
|
args.foreground = false;
|
||||||
args.captureDevice = NULL;
|
args.captureDevice = NULL;
|
||||||
|
|
||||||
int ret = parseArgs(args);
|
int ret = parseArgs(args);
|
||||||
if (ret == 0)
|
if (ret != 0)
|
||||||
|
fprintf(stderr, "Failed to parse command line arguments\n");
|
||||||
|
else
|
||||||
{
|
{
|
||||||
ret = run(args);
|
if (args.foreground)
|
||||||
if (ret != 0)
|
setupConsole();
|
||||||
|
|
||||||
|
Service::InstallHook();
|
||||||
|
HANDLE captureThread = CreateThread(NULL, 0, CaptureThread, NULL, 0, NULL);
|
||||||
|
while (running)
|
||||||
{
|
{
|
||||||
if (!args.foreground)
|
MSG msg;
|
||||||
|
BOOL bRet = GetMessage(&msg, NULL, 0, 0);
|
||||||
|
if (bRet == -1 || bRet == 0)
|
||||||
{
|
{
|
||||||
setupConsole();
|
ret = msg.wParam;
|
||||||
fprintf(stderr, "An error occurred, re-run in forground mode (-f) for more information\n");
|
break;
|
||||||
}
|
}
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
Service::RemoveHook();
|
||||||
|
running = false;
|
||||||
|
ret = WaitForSingleObject(captureThread, INFINITE);
|
||||||
|
CloseHandle(captureThread);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
if (!args.foreground)
|
||||||
|
{
|
||||||
|
setupConsole();
|
||||||
|
fprintf(stderr, "An error occurred, re-run in forground mode (-f) for more information\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,11 +108,21 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdParam
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int run(struct StartupArgs & args)
|
static DWORD WINAPI CaptureThread(LPVOID lpParameter)
|
||||||
{
|
{
|
||||||
if (args.foreground)
|
int ret = 0;
|
||||||
setupConsole();
|
while (running)
|
||||||
|
{
|
||||||
|
ret = run();
|
||||||
|
if (ret != 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
running = false;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int run()
|
||||||
|
{
|
||||||
/* increase the system timer resolution */
|
/* increase the system timer resolution */
|
||||||
ULONG currentRes;
|
ULONG currentRes;
|
||||||
NtSetTimerResolution(0, TRUE, ¤tRes);
|
NtSetTimerResolution(0, TRUE, ¤tRes);
|
||||||
|
@ -124,15 +157,15 @@ int run(struct StartupArgs & args)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Service *svc = svc->Get();
|
Service &svc = Service::Instance();
|
||||||
if (!svc->Initialize(captureDevice))
|
if (!svc.Initialize(captureDevice))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
int retry = 0;
|
int retry = 0;
|
||||||
bool running = true;
|
bool running = true;
|
||||||
while (running)
|
while (running)
|
||||||
{
|
{
|
||||||
switch (svc->Process())
|
switch (svc.Process())
|
||||||
{
|
{
|
||||||
case PROCESS_STATUS_OK:
|
case PROCESS_STATUS_OK:
|
||||||
retry = 0;
|
retry = 0;
|
||||||
|
@ -152,7 +185,7 @@ int run(struct StartupArgs & args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
svc->DeInitialize();
|
svc.DeInitialize();
|
||||||
|
|
||||||
if (task)
|
if (task)
|
||||||
AvRevertMmThreadCharacteristics(task);
|
AvRevertMmThreadCharacteristics(task);
|
||||||
|
|
Loading…
Reference in a new issue