[c-host] dxgi: use low level mouse input by default

This is known to prevent cursor updates on the secure desktop
(UAC) but DXGI DD does not provide us with the real mouse
coordinates when applications have 'captured' the cursor.
This commit is contained in:
Geoffrey McRae 2020-01-29 21:58:39 +11:00
parent e30b54ddb2
commit dc4d820666

View File

@ -25,6 +25,8 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include "common/locking.h" #include "common/locking.h"
#include "common/event.h" #include "common/event.h"
#include "windows/mousehook.h"
#include <assert.h> #include <assert.h>
#include <dxgi.h> #include <dxgi.h>
#include <d3d11.h> #include <d3d11.h>
@ -82,6 +84,9 @@ struct iface
unsigned int stride; unsigned int stride;
CaptureFormat format; CaptureFormat format;
LG_Lock pointerLock;
bool decouplePointer;
int hotspotX , hotspotY;
int lastPointerX, lastPointerY; int lastPointerX, lastPointerY;
bool lastPointerVisible; bool lastPointerVisible;
}; };
@ -96,6 +101,28 @@ static CaptureResult dxgi_releaseFrame();
// implementation // implementation
static void on_mouseMove(int x, int y)
{
LG_LOCK(this->pointerLock);
x -= this->hotspotX;
y -= this->hotspotY;
this->lastPointerX = x;
this->lastPointerY = y;
CapturePointer pointer =
{
.positionUpdate = true,
.visible = this->lastPointerVisible,
.x = x,
.y = y
};
this->postPointerBufferFn(pointer);
LG_UNLOCK(this->pointerLock);
}
static const char * dxgi_getName() static const char * dxgi_getName()
{ {
return "DXGI"; return "DXGI";
@ -133,6 +160,14 @@ static void dxgi_initOptions()
.type = OPTION_TYPE_BOOL, .type = OPTION_TYPE_BOOL,
.value.x_bool = false .value.x_bool = false
}, },
{
.module = "dxgi",
.name = "decouplePointer",
.description = "Use a low level hook to obtain cursor position information",
.type = OPTION_TYPE_BOOL,
.value.x_bool = true
},
{0} {0}
}; };
@ -161,10 +196,18 @@ static bool dxgi_create(CaptureGetPointerBuffer getPointerBufferFn, CapturePostP
if (this->maxTextures <= 0) if (this->maxTextures <= 0)
this->maxTextures = 1; this->maxTextures = 1;
this->useAcquireLock = option_get_bool("dxgi", "useAcquireLock"); this->useAcquireLock = option_get_bool("dxgi", "useAcquireLock" );
this->decouplePointer = option_get_bool("dxgi", "decouplePointer");
this->texture = calloc(sizeof(struct Texture), this->maxTextures); this->texture = calloc(sizeof(struct Texture), this->maxTextures);
this->getPointerBufferFn = getPointerBufferFn; this->getPointerBufferFn = getPointerBufferFn;
this->postPointerBufferFn = postPointerBufferFn; this->postPointerBufferFn = postPointerBufferFn;
LG_LOCK_INIT(this->pointerLock);
if (this->decouplePointer)
mouseHook_install(on_mouseMove);
return true; return true;
} }
@ -529,6 +572,8 @@ static bool dxgi_deinit()
{ {
assert(this); assert(this);
mouseHook_remove();
for(int i = 0; i < this->maxTextures; ++i) for(int i = 0; i < this->maxTextures; ++i)
{ {
this->texture[i].state = TEXTURE_STATE_UNUSED; this->texture[i].state = TEXTURE_STATE_UNUSED;
@ -712,22 +757,20 @@ static CaptureResult dxgi_capture()
frameInfo.PointerPosition.Visible != this->lastPointerVisible frameInfo.PointerPosition.Visible != this->lastPointerVisible
) )
{ {
LG_LOCK(this->pointerLock);
/* the pointer position is invalid if the pointer is not visible */ /* the pointer position is invalid if the pointer is not visible */
if (frameInfo.PointerPosition.Visible) if (!this->decouplePointer && frameInfo.PointerPosition.Visible)
{ {
pointer.positionUpdate = true; pointer.positionUpdate = true;
pointer.x = this->lastPointerX = frameInfo.PointerPosition.Position.x;
this->lastPointerX = this->lastPointerY = frameInfo.PointerPosition.Position.y;
frameInfo.PointerPosition.Position.x;
pointer.y =
this->lastPointerY =
frameInfo.PointerPosition.Position.y;
} }
pointer.visible = this->lastPointerVisible = frameInfo.PointerPosition.Visible;
this->lastPointerVisible =
frameInfo.PointerPosition.Visible;
postPointer = true; postPointer = true;
LG_UNLOCK(this->pointerLock);
} }
} }
@ -758,6 +801,12 @@ static CaptureResult dxgi_capture()
return CAPTURE_RESULT_ERROR; return CAPTURE_RESULT_ERROR;
} }
// needed in decouple mode
LG_LOCK(this->pointerLock);
this->hotspotX = shapeInfo.HotSpot.x;
this->hotspotY = shapeInfo.HotSpot.y;
LG_UNLOCK(this->pointerLock);
pointer.shapeUpdate = true; pointer.shapeUpdate = true;
pointer.width = shapeInfo.Width; pointer.width = shapeInfo.Width;
pointer.height = shapeInfo.Height; pointer.height = shapeInfo.Height;
@ -768,7 +817,12 @@ static CaptureResult dxgi_capture()
// post back the pointer information // post back the pointer information
if (postPointer) if (postPointer)
{
LG_LOCK(this->pointerLock);
pointer.visible = this->lastPointerVisible;
this->postPointerBufferFn(pointer); this->postPointerBufferFn(pointer);
LG_UNLOCK(this->pointerLock);
}
return CAPTURE_RESULT_OK; return CAPTURE_RESULT_OK;
} }