mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-09 00:31:31 +00:00
[client] input: track pointer confinement state
This commit is contained in:
@@ -196,6 +196,9 @@ static void confinedHandler(void * data,
|
|||||||
atomic_store_explicit(&wlWm.confActive, true, memory_order_release);
|
atomic_store_explicit(&wlWm.confActive, true, memory_order_release);
|
||||||
LG_UNLOCK(wlWm.surfaceLock);
|
LG_UNLOCK(wlWm.surfaceLock);
|
||||||
MTRACE("conf active=1 id=%u valid=%d", proxyId(pointer), valid);
|
MTRACE("conf active=1 id=%u valid=%d", proxyId(pointer), valid);
|
||||||
|
|
||||||
|
if (valid)
|
||||||
|
app_handleGrabEvent(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unconfinedHandler(void * data,
|
static void unconfinedHandler(void * data,
|
||||||
@@ -208,6 +211,9 @@ static void unconfinedHandler(void * data,
|
|||||||
atomic_store_explicit(&wlWm.confActive, false, memory_order_release);
|
atomic_store_explicit(&wlWm.confActive, false, memory_order_release);
|
||||||
LG_UNLOCK(wlWm.surfaceLock);
|
LG_UNLOCK(wlWm.surfaceLock);
|
||||||
MTRACE("conf active=0 id=%u valid=%d", proxyId(pointer), valid);
|
MTRACE("conf active=0 id=%u valid=%d", proxyId(pointer), valid);
|
||||||
|
|
||||||
|
if (valid)
|
||||||
|
app_handleGrabEvent(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct zwp_confined_pointer_v1_listener confinedListener = {
|
static const struct zwp_confined_pointer_v1_listener confinedListener = {
|
||||||
@@ -215,6 +221,65 @@ static const struct zwp_confined_pointer_v1_listener confinedListener = {
|
|||||||
.unconfined = unconfinedHandler,
|
.unconfined = unconfinedHandler,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct zwp_confined_pointer_v1 * createConfine(
|
||||||
|
struct wl_region * region);
|
||||||
|
static bool queueConfSync(void);
|
||||||
|
|
||||||
|
static void confSyncHandler(void * data, struct wl_callback * callback,
|
||||||
|
uint32_t serial)
|
||||||
|
{
|
||||||
|
bool notify = false;
|
||||||
|
bool valid = false;
|
||||||
|
const uint32_t id = proxyId(callback);
|
||||||
|
uint32_t confId = 0;
|
||||||
|
uint64_t confSeq = 0;
|
||||||
|
|
||||||
|
LG_LOCK(wlWm.surfaceLock);
|
||||||
|
if (callback == wlWm.confSync)
|
||||||
|
{
|
||||||
|
valid = true;
|
||||||
|
wl_callback_destroy(callback);
|
||||||
|
wlWm.confSync = NULL;
|
||||||
|
atomic_store_explicit(&wlWm.confActive, false,
|
||||||
|
memory_order_release);
|
||||||
|
notify = wlWm.inputLive;
|
||||||
|
|
||||||
|
if (wlWm.inputLive && wlWm.confReq && wlWm.pointer &&
|
||||||
|
wlWm.pointerConstraints && !wlWm.confinedPointer &&
|
||||||
|
!wlWm.lockedPointer)
|
||||||
|
{
|
||||||
|
wlWm.confinedPointer = createConfine(NULL);
|
||||||
|
confId = proxyId(wlWm.confinedPointer);
|
||||||
|
confSeq = app_mouseSeq();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LG_UNLOCK(wlWm.surfaceLock);
|
||||||
|
|
||||||
|
MTRACE("conf sync id=%u serial=%u valid=%d notify=%d", id, serial,
|
||||||
|
valid, notify);
|
||||||
|
MLOG(confSeq, "conf req id=%u why=sync", confId);
|
||||||
|
|
||||||
|
if (notify)
|
||||||
|
app_handleGrabEvent(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_callback_listener confSyncListener = {
|
||||||
|
.done = confSyncHandler,
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool queueConfSync(void)
|
||||||
|
{
|
||||||
|
if (wlWm.confSync)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
wlWm.confSync = wl_display_sync(wlWm.display);
|
||||||
|
if (!wlWm.confSync)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wl_callback_add_listener(wlWm.confSync, &confSyncListener, NULL);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void lockedHandler(void * data,
|
static void lockedHandler(void * data,
|
||||||
struct zwp_locked_pointer_v1 * pointer)
|
struct zwp_locked_pointer_v1 * pointer)
|
||||||
{
|
{
|
||||||
@@ -437,14 +502,21 @@ static const struct wl_keyboard_listener keyboardListener = {
|
|||||||
.modifiers = keyboardModifiersHandler,
|
.modifiers = keyboardModifiersHandler,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void waylandCleanUpPointer(void)
|
static void waylandCleanUpPointer(bool notify)
|
||||||
{
|
{
|
||||||
|
bool event = false;
|
||||||
uint32_t lockId = 0;
|
uint32_t lockId = 0;
|
||||||
uint32_t confId = 0;
|
uint32_t confId = 0;
|
||||||
uint64_t lockSeq = 0;
|
uint64_t lockSeq = 0;
|
||||||
uint64_t confSeq = 0;
|
uint64_t confSeq = 0;
|
||||||
INTERLOCKED_SECTION(wlWm.surfaceLock,
|
INTERLOCKED_SECTION(wlWm.surfaceLock,
|
||||||
{
|
{
|
||||||
|
if (wlWm.confSync)
|
||||||
|
{
|
||||||
|
wl_callback_destroy(wlWm.confSync);
|
||||||
|
wlWm.confSync = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
atomic_store_explicit(&wlWm.lockActive, false, memory_order_release);
|
atomic_store_explicit(&wlWm.lockActive, false, memory_order_release);
|
||||||
atomic_store_explicit(&wlWm.confActive, false, memory_order_release);
|
atomic_store_explicit(&wlWm.confActive, false, memory_order_release);
|
||||||
|
|
||||||
@@ -463,19 +535,25 @@ static void waylandCleanUpPointer(void)
|
|||||||
wlWm.confinedPointer = NULL;
|
wlWm.confinedPointer = NULL;
|
||||||
confSeq = app_mouseSeq();
|
confSeq = app_mouseSeq();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wlWm.relativePointer)
|
||||||
|
{
|
||||||
|
zwp_relative_pointer_v1_destroy(wlWm.relativePointer);
|
||||||
|
wlWm.relativePointer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_pointer_destroy(wlWm.pointer);
|
||||||
|
wlWm.pointer = NULL;
|
||||||
|
wlWm.pointerInSurface = false;
|
||||||
|
|
||||||
|
event = notify && wlWm.inputLive;
|
||||||
});
|
});
|
||||||
|
|
||||||
MLOG(lockSeq, "lock destroy id=%u why=pointer", lockId);
|
MLOG(lockSeq, "lock destroy id=%u why=pointer", lockId);
|
||||||
MLOG(confSeq, "conf destroy id=%u why=pointer", confId);
|
MLOG(confSeq, "conf destroy id=%u why=pointer", confId);
|
||||||
|
|
||||||
if (wlWm.relativePointer)
|
if (event)
|
||||||
{
|
app_handleGrabEvent(false);
|
||||||
zwp_relative_pointer_v1_destroy(wlWm.relativePointer);
|
|
||||||
wlWm.relativePointer = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_pointer_destroy(wlWm.pointer);
|
|
||||||
wlWm.pointer = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seat-handling listeners.
|
// Seat-handling listeners.
|
||||||
@@ -484,7 +562,7 @@ static void handlePointerCapability(uint32_t capabilities)
|
|||||||
{
|
{
|
||||||
bool hasPointer = capabilities & WL_SEAT_CAPABILITY_POINTER;
|
bool hasPointer = capabilities & WL_SEAT_CAPABILITY_POINTER;
|
||||||
if (!hasPointer && wlWm.pointer)
|
if (!hasPointer && wlWm.pointer)
|
||||||
waylandCleanUpPointer();
|
waylandCleanUpPointer(true);
|
||||||
else if (hasPointer && !wlWm.pointer)
|
else if (hasPointer && !wlWm.pointer)
|
||||||
{
|
{
|
||||||
wlWm.pointer = wl_seat_get_pointer(wlWm.seat);
|
wlWm.pointer = wl_seat_get_pointer(wlWm.seat);
|
||||||
@@ -502,6 +580,16 @@ static void handlePointerCapability(uint32_t capabilities)
|
|||||||
|
|
||||||
if (app_isCaptureMode())
|
if (app_isCaptureMode())
|
||||||
waylandCapturePointer();
|
waylandCapturePointer();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool confReq;
|
||||||
|
INTERLOCKED_SECTION(wlWm.surfaceLock,
|
||||||
|
{
|
||||||
|
confReq = wlWm.confReq;
|
||||||
|
});
|
||||||
|
if (confReq)
|
||||||
|
waylandGrabPointer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -578,6 +666,10 @@ bool waylandInputInit(bool allowNoInput)
|
|||||||
wlWm.warpSupport, !!wlWm.relativePointerManager,
|
wlWm.warpSupport, !!wlWm.relativePointerManager,
|
||||||
!!wlWm.pointerConstraints);
|
!!wlWm.pointerConstraints);
|
||||||
|
|
||||||
|
LG_LOCK(wlWm.surfaceLock);
|
||||||
|
wlWm.inputLive = true;
|
||||||
|
LG_UNLOCK(wlWm.surfaceLock);
|
||||||
|
|
||||||
wlWm.xkb = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
wlWm.xkb = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||||
if (!wlWm.xkb)
|
if (!wlWm.xkb)
|
||||||
DEBUG_WARN("Failed to initialize xkb, keyboard input will not work");
|
DEBUG_WARN("Failed to initialize xkb, keyboard input will not work");
|
||||||
@@ -590,13 +682,15 @@ bool waylandInputInit(bool allowNoInput)
|
|||||||
|
|
||||||
void waylandInputFree(void)
|
void waylandInputFree(void)
|
||||||
{
|
{
|
||||||
|
LG_LOCK(wlWm.surfaceLock);
|
||||||
|
wlWm.inputLive = false;
|
||||||
|
LG_UNLOCK(wlWm.surfaceLock);
|
||||||
|
|
||||||
if (!wlWm.seat)
|
if (!wlWm.seat)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
waylandUngrabPointer();
|
|
||||||
|
|
||||||
if (wlWm.pointer)
|
if (wlWm.pointer)
|
||||||
waylandCleanUpPointer();
|
waylandCleanUpPointer(false);
|
||||||
|
|
||||||
// The only legal way the keyboard can be null is if it never existed.
|
// The only legal way the keyboard can be null is if it never existed.
|
||||||
// When unplugged, the compositor must have an inert object.
|
// When unplugged, the compositor must have an inert object.
|
||||||
@@ -617,59 +711,56 @@ void waylandInputFree(void)
|
|||||||
|
|
||||||
void waylandGrabPointer(void)
|
void waylandGrabPointer(void)
|
||||||
{
|
{
|
||||||
if (!wlWm.pointer ||
|
uint32_t relativeId = 0;
|
||||||
!wlWm.relativePointerManager || !wlWm.pointerConstraints)
|
uint32_t confId = 0;
|
||||||
{
|
uint64_t confSeq = 0;
|
||||||
MTRACE("grab drop pointer=%d relMgr=%d constraints=%d",
|
bool haveConf = false;
|
||||||
!!wlWm.pointer, !!wlWm.relativePointerManager,
|
bool haveLock = false;
|
||||||
!!wlWm.pointerConstraints);
|
bool haveSync = false;
|
||||||
return;
|
bool havePointer = false;
|
||||||
}
|
bool haveConstraints = false;
|
||||||
|
|
||||||
if (!wlWm.warpSupport && !wlWm.relativePointer)
|
|
||||||
{
|
|
||||||
struct zwp_relative_pointer_v1 * relative =
|
|
||||||
zwp_relative_pointer_manager_v1_get_relative_pointer(
|
|
||||||
wlWm.relativePointerManager, wlWm.pointer);
|
|
||||||
zwp_relative_pointer_v1_add_listener(relative,
|
|
||||||
&relativePointerListener, NULL);
|
|
||||||
const uint32_t relativeId = proxyId(relative);
|
|
||||||
wlWm.relativePointer = relative;
|
|
||||||
MTRACE("rel req id=%u why=grab", relativeId);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t confId = 0;
|
|
||||||
uint64_t confSeq = 0;
|
|
||||||
bool haveConf = false;
|
|
||||||
bool haveLock = false;
|
|
||||||
INTERLOCKED_SECTION(wlWm.surfaceLock,
|
INTERLOCKED_SECTION(wlWm.surfaceLock,
|
||||||
{
|
{
|
||||||
if (!wlWm.confinedPointer && !wlWm.lockedPointer)
|
wlWm.confReq = true;
|
||||||
|
|
||||||
|
if (wlWm.pointer && !wlWm.warpSupport && !wlWm.relativePointer &&
|
||||||
|
wlWm.relativePointerManager)
|
||||||
|
{
|
||||||
|
wlWm.relativePointer =
|
||||||
|
zwp_relative_pointer_manager_v1_get_relative_pointer(
|
||||||
|
wlWm.relativePointerManager, wlWm.pointer);
|
||||||
|
zwp_relative_pointer_v1_add_listener(wlWm.relativePointer,
|
||||||
|
&relativePointerListener, NULL);
|
||||||
|
relativeId = proxyId(wlWm.relativePointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wlWm.pointer && wlWm.pointerConstraints &&
|
||||||
|
!wlWm.confinedPointer && !wlWm.lockedPointer && !wlWm.confSync)
|
||||||
{
|
{
|
||||||
atomic_store_explicit(&wlWm.confActive, false,
|
|
||||||
memory_order_release);
|
|
||||||
wlWm.confinedPointer = createConfine(NULL);
|
wlWm.confinedPointer = createConfine(NULL);
|
||||||
confId = proxyId(wlWm.confinedPointer);
|
confId = proxyId(wlWm.confinedPointer);
|
||||||
confSeq = app_mouseSeq();
|
confSeq = app_mouseSeq();
|
||||||
}
|
}
|
||||||
haveConf = !!wlWm.confinedPointer;
|
haveConf = !!wlWm.confinedPointer;
|
||||||
haveLock = !!wlWm.lockedPointer;
|
haveLock = !!wlWm.lockedPointer;
|
||||||
|
haveSync = !!wlWm.confSync;
|
||||||
|
havePointer = !!wlWm.pointer;
|
||||||
|
haveConstraints = !!wlWm.pointerConstraints;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (relativeId)
|
||||||
|
MTRACE("rel req id=%u why=grab", relativeId);
|
||||||
|
|
||||||
if (confId)
|
if (confId)
|
||||||
MLOG(confSeq, "conf req id=%u why=grab", confId);
|
MLOG(confSeq, "conf req id=%u why=grab", confId);
|
||||||
else
|
else
|
||||||
MTRACE("conf skip conf=%d lock=%d", haveConf, haveLock);
|
MTRACE("conf skip pointer=%d constraints=%d conf=%d lock=%d sync=%d",
|
||||||
|
havePointer, haveConstraints, haveConf, haveLock, haveSync);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static uint32_t internalUngrabPointer(bool lock, uint64_t * traceSeq)
|
inline static uint32_t destroyConfine(uint64_t * traceSeq)
|
||||||
{
|
{
|
||||||
*traceSeq = 0;
|
*traceSeq = 0;
|
||||||
if (!wlWm.pointer)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (lock)
|
|
||||||
LG_LOCK(wlWm.surfaceLock);
|
|
||||||
|
|
||||||
uint32_t confId = 0;
|
uint32_t confId = 0;
|
||||||
if (wlWm.confinedPointer)
|
if (wlWm.confinedPointer)
|
||||||
@@ -679,34 +770,57 @@ inline static uint32_t internalUngrabPointer(bool lock, uint64_t * traceSeq)
|
|||||||
wlWm.confinedPointer = NULL;
|
wlWm.confinedPointer = NULL;
|
||||||
atomic_store_explicit(&wlWm.confActive, false, memory_order_release);
|
atomic_store_explicit(&wlWm.confActive, false, memory_order_release);
|
||||||
*traceSeq = app_mouseSeq();
|
*traceSeq = app_mouseSeq();
|
||||||
}
|
|
||||||
|
|
||||||
if (lock)
|
if (!queueConfSync())
|
||||||
LG_UNLOCK(wlWm.surfaceLock);
|
DEBUG_ERROR("Failed to queue pointer release sync");
|
||||||
|
|
||||||
if (!wlWm.warpSupport)
|
|
||||||
{
|
|
||||||
if (!wlWm.relativePointer)
|
|
||||||
{
|
|
||||||
wlWm.relativePointer =
|
|
||||||
zwp_relative_pointer_manager_v1_get_relative_pointer(
|
|
||||||
wlWm.relativePointerManager, wlWm.pointer);
|
|
||||||
zwp_relative_pointer_v1_add_listener(wlWm.relativePointer,
|
|
||||||
&relativePointerListener, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
app_resyncMouseBasic();
|
|
||||||
app_handleMouseBasic();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return confId;
|
return confId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ungrabBasic(void)
|
||||||
|
{
|
||||||
|
if (wlWm.warpSupport)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint32_t relativeId = 0;
|
||||||
|
LG_LOCK(wlWm.surfaceLock);
|
||||||
|
if (wlWm.pointer && !wlWm.relativePointer &&
|
||||||
|
wlWm.relativePointerManager)
|
||||||
|
{
|
||||||
|
wlWm.relativePointer =
|
||||||
|
zwp_relative_pointer_manager_v1_get_relative_pointer(
|
||||||
|
wlWm.relativePointerManager, wlWm.pointer);
|
||||||
|
zwp_relative_pointer_v1_add_listener(wlWm.relativePointer,
|
||||||
|
&relativePointerListener, NULL);
|
||||||
|
relativeId = proxyId(wlWm.relativePointer);
|
||||||
|
}
|
||||||
|
LG_UNLOCK(wlWm.surfaceLock);
|
||||||
|
|
||||||
|
if (relativeId)
|
||||||
|
MTRACE("rel req id=%u why=ungrab", relativeId);
|
||||||
|
|
||||||
|
app_resyncMouseBasic();
|
||||||
|
app_handleMouseBasic();
|
||||||
|
}
|
||||||
|
|
||||||
void waylandUngrabPointer(void)
|
void waylandUngrabPointer(void)
|
||||||
{
|
{
|
||||||
|
bool notify;
|
||||||
uint64_t confSeq;
|
uint64_t confSeq;
|
||||||
const uint32_t confId = internalUngrabPointer(true, &confSeq);
|
uint32_t confId;
|
||||||
|
|
||||||
|
LG_LOCK(wlWm.surfaceLock);
|
||||||
|
wlWm.confReq = false;
|
||||||
|
confId = destroyConfine(&confSeq);
|
||||||
|
notify = !wlWm.confSync && wlWm.inputLive;
|
||||||
|
LG_UNLOCK(wlWm.surfaceLock);
|
||||||
|
|
||||||
MLOG(confSeq, "conf destroy id=%u why=ungrab", confId);
|
MLOG(confSeq, "conf destroy id=%u why=ungrab", confId);
|
||||||
|
ungrabBasic();
|
||||||
|
|
||||||
|
if (notify)
|
||||||
|
app_handleGrabEvent(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void waylandCapturePointer(void)
|
void waylandCapturePointer(void)
|
||||||
@@ -724,20 +838,17 @@ void waylandCapturePointer(void)
|
|||||||
uint64_t lockSeq = 0;
|
uint64_t lockSeq = 0;
|
||||||
INTERLOCKED_SECTION(wlWm.surfaceLock,
|
INTERLOCKED_SECTION(wlWm.surfaceLock,
|
||||||
{
|
{
|
||||||
if (wlWm.confinedPointer)
|
wlWm.confReq = true;
|
||||||
{
|
confId = destroyConfine(&confSeq);
|
||||||
confId = proxyId(wlWm.confinedPointer);
|
|
||||||
zwp_confined_pointer_v1_destroy(wlWm.confinedPointer);
|
|
||||||
wlWm.confinedPointer = NULL;
|
|
||||||
atomic_store_explicit(&wlWm.confActive, false,
|
|
||||||
memory_order_release);
|
|
||||||
confSeq = app_mouseSeq();
|
|
||||||
}
|
|
||||||
|
|
||||||
atomic_store_explicit(&wlWm.lockActive, false, memory_order_release);
|
if (wlWm.pointer && !wlWm.lockedPointer)
|
||||||
wlWm.lockedPointer = createLock();
|
{
|
||||||
lockId = proxyId(wlWm.lockedPointer);
|
atomic_store_explicit(&wlWm.lockActive, false,
|
||||||
lockSeq = app_mouseSeq();
|
memory_order_release);
|
||||||
|
wlWm.lockedPointer = createLock();
|
||||||
|
lockId = proxyId(wlWm.lockedPointer);
|
||||||
|
lockSeq = app_mouseSeq();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
MLOG(confSeq, "conf destroy id=%u why=capture", confId);
|
MLOG(confSeq, "conf destroy id=%u why=capture", confId);
|
||||||
@@ -772,20 +883,31 @@ void waylandUncapturePointer(void)
|
|||||||
* - if the user has opted to use captureInputOnly mode.
|
* - if the user has opted to use captureInputOnly mode.
|
||||||
*/
|
*/
|
||||||
if (!wlWm.warpSupport || !app_isFormatValid() || app_isCaptureOnlyMode())
|
if (!wlWm.warpSupport || !app_isFormatValid() || app_isCaptureOnlyMode())
|
||||||
confDropId = internalUngrabPointer(false, &confDropSeq);
|
|
||||||
else if (wlWm.pointer)
|
|
||||||
{
|
{
|
||||||
atomic_store_explicit(&wlWm.confActive, false,
|
wlWm.confReq = false;
|
||||||
memory_order_release);
|
confDropId = destroyConfine(&confDropSeq);
|
||||||
wlWm.confinedPointer = createConfine(NULL);
|
}
|
||||||
confReqId = proxyId(wlWm.confinedPointer);
|
else
|
||||||
confReqSeq = app_mouseSeq();
|
{
|
||||||
|
wlWm.confReq = true;
|
||||||
|
if (wlWm.pointer && !wlWm.confSync && !wlWm.confinedPointer)
|
||||||
|
{
|
||||||
|
wlWm.confinedPointer = createConfine(NULL);
|
||||||
|
confReqId = proxyId(wlWm.confinedPointer);
|
||||||
|
confReqSeq = app_mouseSeq();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
MLOG(lockSeq, "lock destroy id=%u why=uncapture", lockId);
|
MLOG(lockSeq, "lock destroy id=%u why=uncapture", lockId);
|
||||||
MLOG(confDropSeq, "conf destroy id=%u why=uncapture", confDropId);
|
MLOG(confDropSeq, "conf destroy id=%u why=uncapture", confDropId);
|
||||||
MLOG(confReqSeq, "conf req id=%u why=uncapture", confReqId);
|
MLOG(confReqSeq, "conf req id=%u why=uncapture", confReqId);
|
||||||
|
ungrabBasic();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool waylandIsPointerGrabbed(void)
|
||||||
|
{
|
||||||
|
return atomic_load_explicit(&wlWm.confActive, memory_order_acquire);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool waylandIsPointerCaptured(void)
|
bool waylandIsPointerCaptured(void)
|
||||||
|
|||||||
@@ -321,6 +321,7 @@ struct LG_DisplayServerOps LGDS_Wayland =
|
|||||||
.setPointer = waylandSetPointer,
|
.setPointer = waylandSetPointer,
|
||||||
.grabPointer = waylandGrabPointer,
|
.grabPointer = waylandGrabPointer,
|
||||||
.ungrabPointer = waylandUngrabPointer,
|
.ungrabPointer = waylandUngrabPointer,
|
||||||
|
.isPointerGrabbed = waylandIsPointerGrabbed,
|
||||||
.capturePointer = waylandCapturePointer,
|
.capturePointer = waylandCapturePointer,
|
||||||
.uncapturePointer = waylandUncapturePointer,
|
.uncapturePointer = waylandUncapturePointer,
|
||||||
.isPointerCaptured = waylandIsPointerCaptured,
|
.isPointerCaptured = waylandIsPointerCaptured,
|
||||||
|
|||||||
@@ -195,6 +195,9 @@ struct WaylandDSState
|
|||||||
struct zwp_relative_pointer_v1 * relativePointer;
|
struct zwp_relative_pointer_v1 * relativePointer;
|
||||||
struct zwp_confined_pointer_v1 * confinedPointer;
|
struct zwp_confined_pointer_v1 * confinedPointer;
|
||||||
struct zwp_locked_pointer_v1 * lockedPointer;
|
struct zwp_locked_pointer_v1 * lockedPointer;
|
||||||
|
struct wl_callback * confSync;
|
||||||
|
bool confReq;
|
||||||
|
bool inputLive;
|
||||||
bool showPointer;
|
bool showPointer;
|
||||||
uint32_t pointerEnterSerial;
|
uint32_t pointerEnterSerial;
|
||||||
|
|
||||||
@@ -379,6 +382,7 @@ void waylandUngrabKeyboard(void);
|
|||||||
void waylandUngrabPointer(void);
|
void waylandUngrabPointer(void);
|
||||||
void waylandCapturePointer(void);
|
void waylandCapturePointer(void);
|
||||||
void waylandUncapturePointer(void);
|
void waylandUncapturePointer(void);
|
||||||
|
bool waylandIsPointerGrabbed(void);
|
||||||
bool waylandIsPointerCaptured(void);
|
bool waylandIsPointerCaptured(void);
|
||||||
void waylandRealignPointer(void);
|
void waylandRealignPointer(void);
|
||||||
void waylandWarpPointer(int x, int y, bool exiting);
|
void waylandWarpPointer(int x, int y, bool exiting);
|
||||||
|
|||||||
@@ -341,6 +341,8 @@ static bool x11Init(const LG_DSInitParams params)
|
|||||||
XSetIOErrorHandler(x11IOErrorHandler);
|
XSetIOErrorHandler(x11IOErrorHandler);
|
||||||
|
|
||||||
memset(&x11, 0, sizeof(x11));
|
memset(&x11, 0, sizeof(x11));
|
||||||
|
atomic_init(&x11.captureActive, false);
|
||||||
|
atomic_init(&x11.pointerGrabbed, false);
|
||||||
x11.xValuator = -1;
|
x11.xValuator = -1;
|
||||||
x11.yValuator = -1;
|
x11.yValuator = -1;
|
||||||
x11.display = XOpenDisplay(NULL);
|
x11.display = XOpenDisplay(NULL);
|
||||||
@@ -1508,7 +1510,7 @@ static void x11XInputEvent(XGenericEventCookie *cookie)
|
|||||||
XIDeviceEvent *device = cookie->data;
|
XIDeviceEvent *device = cookie->data;
|
||||||
app_updateCursorPos(device->event_x, device->event_y);
|
app_updateCursorPos(device->event_x, device->event_y);
|
||||||
|
|
||||||
if (!x11.pointerGrabbed)
|
if (!atomic_load_explicit(&x11.pointerGrabbed, memory_order_acquire))
|
||||||
app_handleMouseRelative(0.0, 0.0, 0.0, 0.0);
|
app_handleMouseRelative(0.0, 0.0, 0.0, 0.0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1886,7 +1888,7 @@ static void x11PrintGrabError(const char * type, int dev, Status ret)
|
|||||||
|
|
||||||
static void x11GrabPointer(void)
|
static void x11GrabPointer(void)
|
||||||
{
|
{
|
||||||
if (x11.pointerGrabbed)
|
if (atomic_load_explicit(&x11.pointerGrabbed, memory_order_acquire))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unsigned char mask_bits[XIMaskLen(XI_LASTEVENT)] = { 0 };
|
unsigned char mask_bits[XIMaskLen(XI_LASTEVENT)] = { 0 };
|
||||||
@@ -1935,26 +1937,36 @@ static void x11GrabPointer(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
x11.pointerGrabbed = true;
|
atomic_store_explicit(&x11.pointerGrabbed, true, memory_order_release);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void x11UngrabPointer(void)
|
static void x11UngrabPointer(void)
|
||||||
{
|
{
|
||||||
atomic_store_explicit(&x11.captureActive, false, memory_order_release);
|
atomic_store_explicit(&x11.captureActive, false, memory_order_release);
|
||||||
|
|
||||||
if (!x11.pointerGrabbed)
|
if (!atomic_load_explicit(&x11.pointerGrabbed, memory_order_acquire))
|
||||||
|
{
|
||||||
|
app_handleGrabEvent(false);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
XIUngrabDevice(x11.display, x11.pointerDev, CurrentTime);
|
XIUngrabDevice(x11.display, x11.pointerDev, CurrentTime);
|
||||||
XSync(x11.display, False);
|
XSync(x11.display, False);
|
||||||
|
|
||||||
x11.pointerGrabbed = false;
|
atomic_store_explicit(&x11.pointerGrabbed, false, memory_order_release);
|
||||||
|
app_handleGrabEvent(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool x11IsPointerGrabbed(void)
|
||||||
|
{
|
||||||
|
return atomic_load_explicit(&x11.pointerGrabbed, memory_order_acquire);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void x11CapturePointer(void)
|
static void x11CapturePointer(void)
|
||||||
{
|
{
|
||||||
x11GrabPointer();
|
x11GrabPointer();
|
||||||
atomic_store_explicit(&x11.captureActive, x11.pointerGrabbed,
|
atomic_store_explicit(&x11.captureActive,
|
||||||
|
atomic_load_explicit(&x11.pointerGrabbed, memory_order_acquire),
|
||||||
memory_order_release);
|
memory_order_release);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2152,6 +2164,7 @@ struct LG_DisplayServerOps LGDS_X11 =
|
|||||||
.setPointer = x11SetPointer,
|
.setPointer = x11SetPointer,
|
||||||
.grabPointer = x11GrabPointer,
|
.grabPointer = x11GrabPointer,
|
||||||
.ungrabPointer = x11UngrabPointer,
|
.ungrabPointer = x11UngrabPointer,
|
||||||
|
.isPointerGrabbed = x11IsPointerGrabbed,
|
||||||
.capturePointer = x11CapturePointer,
|
.capturePointer = x11CapturePointer,
|
||||||
.uncapturePointer = x11UncapturePointer,
|
.uncapturePointer = x11UncapturePointer,
|
||||||
.isPointerCaptured = x11IsPointerCaptured,
|
.isPointerCaptured = x11IsPointerCaptured,
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ struct X11DSState
|
|||||||
int yValuator;
|
int yValuator;
|
||||||
|
|
||||||
_Atomic(bool) captureActive;
|
_Atomic(bool) captureActive;
|
||||||
bool pointerGrabbed;
|
_Atomic(bool) pointerGrabbed;
|
||||||
bool keyboardGrabbed;
|
bool keyboardGrabbed;
|
||||||
bool entered;
|
bool entered;
|
||||||
bool focused;
|
bool focused;
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ void app_handleKeyRelease(int scancode);
|
|||||||
void app_handleKeyboardModifiers(bool ctrl, bool shift, bool alt, bool super);
|
void app_handleKeyboardModifiers(bool ctrl, bool shift, bool alt, bool super);
|
||||||
void app_handleKeyboardLEDs(bool numLock, bool capsLock, bool scrollLock);
|
void app_handleKeyboardLEDs(bool numLock, bool capsLock, bool scrollLock);
|
||||||
void app_handleEnterEvent(bool entered);
|
void app_handleEnterEvent(bool entered);
|
||||||
|
void app_handleGrabEvent(bool active);
|
||||||
void app_handleFocusEvent(bool focused);
|
void app_handleFocusEvent(bool focused);
|
||||||
void app_handleCloseEvent(void);
|
void app_handleCloseEvent(void);
|
||||||
void app_handleRenderEvent(const uint64_t timeUs);
|
void app_handleRenderEvent(const uint64_t timeUs);
|
||||||
|
|||||||
@@ -207,6 +207,7 @@ struct LG_DisplayServerOps
|
|||||||
/* (un)grabPointer is used to toggle cursor tracking/confine in normal mode */
|
/* (un)grabPointer is used to toggle cursor tracking/confine in normal mode */
|
||||||
void (*grabPointer)(void);
|
void (*grabPointer)(void);
|
||||||
void (*ungrabPointer)(void);
|
void (*ungrabPointer)(void);
|
||||||
|
bool (*isPointerGrabbed)(void);
|
||||||
/* (un)capturePointer is used do toggle special cursor tracking in capture mode */
|
/* (un)capturePointer is used do toggle special cursor tracking in capture mode */
|
||||||
void (*capturePointer)(void);
|
void (*capturePointer)(void);
|
||||||
void (*uncapturePointer)(void);
|
void (*uncapturePointer)(void);
|
||||||
@@ -290,6 +291,7 @@ struct LG_DisplayServerOps
|
|||||||
DEBUG_ASSERT((x)->setPointer ); \
|
DEBUG_ASSERT((x)->setPointer ); \
|
||||||
DEBUG_ASSERT((x)->grabPointer ); \
|
DEBUG_ASSERT((x)->grabPointer ); \
|
||||||
DEBUG_ASSERT((x)->ungrabPointer ); \
|
DEBUG_ASSERT((x)->ungrabPointer ); \
|
||||||
|
DEBUG_ASSERT((x)->isPointerGrabbed ); \
|
||||||
DEBUG_ASSERT((x)->capturePointer ); \
|
DEBUG_ASSERT((x)->capturePointer ); \
|
||||||
DEBUG_ASSERT((x)->uncapturePointer ); \
|
DEBUG_ASSERT((x)->uncapturePointer ); \
|
||||||
DEBUG_ASSERT((x)->isPointerCaptured ); \
|
DEBUG_ASSERT((x)->isPointerCaptured ); \
|
||||||
|
|||||||
@@ -469,7 +469,7 @@ void app_handleButtonPress(int button)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!core_inputEnabled() || !g_cursor.inView)
|
if (!core_inputEnabled() || !g_cursor.inView || !g_cursor.viewReq)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!purespice_mousePress(button))
|
if (!purespice_mousePress(button))
|
||||||
@@ -674,6 +674,11 @@ void app_handleMouseRelative(double normx, double normy,
|
|||||||
core_handleMouseNormal(normx, normy);
|
core_handleMouseNormal(normx, normy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void app_handleGrabEvent(bool active)
|
||||||
|
{
|
||||||
|
core_handleGrabEvent(active);
|
||||||
|
}
|
||||||
|
|
||||||
// On some display servers normal cursor logic does not work due to the lack of
|
// On some display servers normal cursor logic does not work due to the lack of
|
||||||
// cursor warp support. Instead, we attempt a best-effort emulation which works
|
// cursor warp support. Instead, we attempt a best-effort emulation which works
|
||||||
// with a 1:1 mouse movement patch applied in the guest. For anything fancy, use
|
// with a 1:1 mouse movement patch applied in the guest. For anything fancy, use
|
||||||
|
|||||||
@@ -66,28 +66,21 @@ bool core_inputEnabled(void)
|
|||||||
((g_cursor.grab && g_params.captureInputOnly) || !g_params.captureInputOnly);
|
((g_cursor.grab && g_params.captureInputOnly) || !g_params.captureInputOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
void core_invalidatePointer(bool detectInView)
|
static void applyView(bool active, bool force)
|
||||||
{
|
{
|
||||||
/* if the display server does not support warp, then we can not operate in
|
if (active && !g_cursor.viewReq)
|
||||||
* always relative mode and we should not grab the pointer */
|
|
||||||
enum LG_DSWarpSupport warpSupport = LG_DS_WARP_NONE;
|
|
||||||
app_getProp(LG_DS_WARP_SUPPORT, &warpSupport);
|
|
||||||
|
|
||||||
MTRACE("invalidate detect=%d inWin=%d inView=%d grab=%d warp=%d "
|
|
||||||
"support=%d", detectInView, g_cursor.inWindow, g_cursor.inView,
|
|
||||||
g_cursor.grab, g_cursor.warpState, warpSupport);
|
|
||||||
|
|
||||||
if (detectInView)
|
|
||||||
{
|
{
|
||||||
bool inView = isInView();
|
MTRACE("view active skip=req");
|
||||||
// do not allow the view to become active if any mouse buttons are being held,
|
return;
|
||||||
// this fixes issues with meta window resizing.
|
|
||||||
if (inView && g_cursor.buttons)
|
|
||||||
return;
|
|
||||||
|
|
||||||
g_cursor.inView = inView;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!force && g_cursor.inView == active)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MTRACE("view active=%d old=%d req=%d force=%d", active,
|
||||||
|
g_cursor.inView, g_cursor.viewReq, force);
|
||||||
|
|
||||||
|
g_cursor.inView = active;
|
||||||
g_cursor.draw = (g_params.alwaysShowCursor || g_params.captureInputOnly)
|
g_cursor.draw = (g_params.alwaysShowCursor || g_params.captureInputOnly)
|
||||||
? true : g_cursor.inView;
|
? true : g_cursor.inView;
|
||||||
g_cursor.redraw = true;
|
g_cursor.redraw = true;
|
||||||
@@ -98,9 +91,6 @@ void core_invalidatePointer(bool detectInView)
|
|||||||
if (g_params.hideMouse)
|
if (g_params.hideMouse)
|
||||||
g_state.ds->setPointer(LG_POINTER_NONE);
|
g_state.ds->setPointer(LG_POINTER_NONE);
|
||||||
|
|
||||||
if (warpSupport != LG_DS_WARP_NONE && !g_params.captureInputOnly)
|
|
||||||
g_state.ds->grabPointer();
|
|
||||||
|
|
||||||
if (g_params.grabKeyboardOnFocus)
|
if (g_params.grabKeyboardOnFocus)
|
||||||
g_state.ds->grabKeyboard();
|
g_state.ds->grabKeyboard();
|
||||||
}
|
}
|
||||||
@@ -109,36 +99,96 @@ void core_invalidatePointer(bool detectInView)
|
|||||||
if (g_params.hideMouse)
|
if (g_params.hideMouse)
|
||||||
g_state.ds->setPointer(LG_POINTER_SQUARE);
|
g_state.ds->setPointer(LG_POINTER_SQUARE);
|
||||||
|
|
||||||
if (warpSupport != LG_DS_WARP_NONE)
|
|
||||||
g_state.ds->ungrabPointer();
|
|
||||||
|
|
||||||
g_state.ds->ungrabKeyboard();
|
g_state.ds->ungrabKeyboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
g_cursor.warpState = WARP_STATE_ON;
|
g_cursor.warpState = WARP_STATE_ON;
|
||||||
}
|
}
|
||||||
|
|
||||||
void core_setCursorInView(bool enable)
|
void core_invalidatePointer(bool detectInView)
|
||||||
{
|
{
|
||||||
MTRACE("view req=%d old=%d focus=%d inWin=%d grab=%d",
|
MTRACE("invalidate detect=%d inWin=%d req=%d active=%d grab=%d "
|
||||||
enable, g_cursor.inView, g_state.focused, g_cursor.inWindow,
|
"warp=%d", detectInView, g_cursor.inWindow, g_cursor.viewReq,
|
||||||
g_cursor.grab);
|
g_cursor.inView, g_cursor.grab, g_cursor.warpState);
|
||||||
|
|
||||||
// if the state has not changed, don't do anything else
|
if (!detectInView)
|
||||||
if (g_cursor.inView == enable)
|
|
||||||
{
|
{
|
||||||
MTRACE("view skip=same value=%d", enable);
|
applyView(g_cursor.inView, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool inView = isInView();
|
||||||
|
|
||||||
|
/* do not allow the view to become active if any mouse buttons are being
|
||||||
|
* held, this fixes issues with meta window resizing. */
|
||||||
|
if (inView && g_cursor.buttons)
|
||||||
|
return;
|
||||||
|
|
||||||
|
core_setCursorInView(inView);
|
||||||
|
}
|
||||||
|
|
||||||
|
void core_setCursorInView(bool enable)
|
||||||
|
{
|
||||||
|
MTRACE("view req=%d oldReq=%d active=%d focus=%d inWin=%d grab=%d",
|
||||||
|
enable, g_cursor.viewReq, g_cursor.inView, g_state.focused,
|
||||||
|
g_cursor.inWindow, g_cursor.grab);
|
||||||
|
|
||||||
if (enable && !g_state.focused)
|
if (enable && !g_state.focused)
|
||||||
{
|
{
|
||||||
MTRACE("view skip=focus");
|
MTRACE("view skip=focus");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_cursor.inView = enable;
|
enum LG_DSWarpSupport warpSupport = LG_DS_WARP_NONE;
|
||||||
core_invalidatePointer(false);
|
app_getProp(LG_DS_WARP_SUPPORT, &warpSupport);
|
||||||
|
|
||||||
|
const bool immediate = g_cursor.grab || g_params.captureInputOnly ||
|
||||||
|
warpSupport == LG_DS_WARP_NONE;
|
||||||
|
|
||||||
|
if (g_cursor.viewReq == enable)
|
||||||
|
{
|
||||||
|
if (immediate)
|
||||||
|
applyView(enable, false);
|
||||||
|
else if (enable && !g_cursor.inView)
|
||||||
|
{
|
||||||
|
g_state.ds->grabPointer();
|
||||||
|
applyView(g_state.ds->isPointerGrabbed(), false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
MTRACE("view skip=same value=%d", enable);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_cursor.viewReq = enable;
|
||||||
|
|
||||||
|
if (immediate)
|
||||||
|
{
|
||||||
|
applyView(enable, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enable)
|
||||||
|
{
|
||||||
|
g_state.ds->grabPointer();
|
||||||
|
applyView(g_state.ds->isPointerGrabbed(), false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
g_state.ds->ungrabPointer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void core_handleGrabEvent(bool active)
|
||||||
|
{
|
||||||
|
MTRACE("conf active=%d req=%d old=%d grab=%d", active,
|
||||||
|
g_cursor.viewReq, g_cursor.inView, g_cursor.grab);
|
||||||
|
|
||||||
|
enum LG_DSWarpSupport warpSupport = LG_DS_WARP_NONE;
|
||||||
|
app_getProp(LG_DS_WARP_SUPPORT, &warpSupport);
|
||||||
|
|
||||||
|
if (g_cursor.grab || g_params.captureInputOnly ||
|
||||||
|
warpSupport == LG_DS_WARP_NONE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
applyView(active, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void core_setGrab(bool enable)
|
void core_setGrab(bool enable)
|
||||||
@@ -202,6 +252,9 @@ void core_setGrabQuiet(bool enable)
|
|||||||
|
|
||||||
g_state.ds->uncapturePointer();
|
g_state.ds->uncapturePointer();
|
||||||
|
|
||||||
|
if (!g_params.captureInputOnly && warpSupport != LG_DS_WARP_NONE)
|
||||||
|
applyView(g_state.ds->isPointerGrabbed(), false);
|
||||||
|
|
||||||
/* if exiting capture when input on capture only we need to align the local
|
/* if exiting capture when input on capture only we need to align the local
|
||||||
* cursor to the guest's location before it is shown. */
|
* cursor to the guest's location before it is shown. */
|
||||||
if (g_params.captureInputOnly || !g_params.hideMouse)
|
if (g_params.captureInputOnly || !g_params.hideMouse)
|
||||||
@@ -507,12 +560,13 @@ void core_handleGuestMouseUpdate(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const bool overlay = app_isOverlayMode();
|
const bool overlay = app_isOverlayMode();
|
||||||
if (overlay || !g_cursor.inView)
|
if (overlay || !g_cursor.inView || !g_cursor.viewReq)
|
||||||
{
|
{
|
||||||
MTRACE("guest drop=%s guest=%d,%d local=%.3f,%.3f inWin=%d "
|
MTRACE("guest drop=%s guest=%d,%d local=%.3f,%.3f inWin=%d "
|
||||||
"inView=%d", overlay ? "overlay" : "view", g_cursor.guest.x,
|
"inView=%d req=%d", overlay ? "overlay" : "view",
|
||||||
|
g_cursor.guest.x,
|
||||||
g_cursor.guest.y, localPos.x, localPos.y, g_cursor.inWindow,
|
g_cursor.guest.y, localPos.x, localPos.y, g_cursor.inWindow,
|
||||||
g_cursor.inView);
|
g_cursor.inView, g_cursor.viewReq);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -588,6 +642,13 @@ void core_handleMouseNormal(double ex, double ey)
|
|||||||
if (!core_inputEnabled())
|
if (!core_inputEnabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (g_cursor.viewReq != g_cursor.inView)
|
||||||
|
{
|
||||||
|
if (g_cursor.viewReq)
|
||||||
|
core_setCursorInView(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* scale the movement to the guest */
|
/* scale the movement to the guest */
|
||||||
if (g_cursor.useScale && g_params.scaleMouseInput)
|
if (g_cursor.useScale && g_params.scaleMouseInput)
|
||||||
{
|
{
|
||||||
@@ -600,7 +661,9 @@ void core_handleMouseNormal(double ex, double ey)
|
|||||||
const bool inView = isInView();
|
const bool inView = isInView();
|
||||||
if (!g_cursor.inView)
|
if (!g_cursor.inView)
|
||||||
{
|
{
|
||||||
if (inView)
|
if (g_cursor.viewReq)
|
||||||
|
return;
|
||||||
|
else if (inView)
|
||||||
g_cursor.realign = true;
|
g_cursor.realign = true;
|
||||||
else /* nothing to do if we are outside the viewport */
|
else /* nothing to do if we are outside the viewport */
|
||||||
return;
|
return;
|
||||||
@@ -691,6 +754,9 @@ fallback:
|
|||||||
ex += guest.x - (g_cursor.guest.x + g_cursor.guest.hx);
|
ex += guest.x - (g_cursor.guest.x + g_cursor.guest.hx);
|
||||||
ey += guest.y - (g_cursor.guest.y + g_cursor.guest.hy);
|
ey += guest.y - (g_cursor.guest.y + g_cursor.guest.hy);
|
||||||
core_setCursorInView(true);
|
core_setCursorInView(true);
|
||||||
|
|
||||||
|
if (!g_cursor.inView)
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_cursor.realign = false;
|
g_cursor.realign = false;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
bool core_inputEnabled(void);
|
bool core_inputEnabled(void);
|
||||||
void core_invalidatePointer(bool detectInView);
|
void core_invalidatePointer(bool detectInView);
|
||||||
void core_setCursorInView(bool enable);
|
void core_setCursorInView(bool enable);
|
||||||
|
void core_handleGrabEvent(bool active);
|
||||||
void core_setGrab(bool enable);
|
void core_setGrab(bool enable);
|
||||||
void core_setGrabQuiet(bool enable);
|
void core_setGrabQuiet(bool enable);
|
||||||
bool core_warpPointer(int x, int y, bool exiting);
|
bool core_warpPointer(int x, int y, bool exiting);
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ static void lgInit(void)
|
|||||||
g_cursor.scale.y = 1.0;
|
g_cursor.scale.y = 1.0;
|
||||||
g_cursor.draw = false;
|
g_cursor.draw = false;
|
||||||
g_cursor.inView = false;
|
g_cursor.inView = false;
|
||||||
|
g_cursor.viewReq = false;
|
||||||
g_cursor.guest.valid = false;
|
g_cursor.guest.valid = false;
|
||||||
|
|
||||||
// if spice is not in use, hide the local cursor
|
// if spice is not in use, hide the local cursor
|
||||||
|
|||||||
@@ -295,6 +295,9 @@ struct CursorState
|
|||||||
/* true if the cursor is currently in the guest view area */
|
/* true if the cursor is currently in the guest view area */
|
||||||
bool inView;
|
bool inView;
|
||||||
|
|
||||||
|
/* true if the cursor should be confined to the guest view area */
|
||||||
|
bool viewReq;
|
||||||
|
|
||||||
/* true if the guest should be realigned to the host when next drawn */
|
/* true if the guest should be realigned to the host when next drawn */
|
||||||
bool realign;
|
bool realign;
|
||||||
|
|
||||||
|
|||||||
@@ -130,7 +130,15 @@ static void ungrab(void)
|
|||||||
push(EV_UNGRAB, 0, 0, false);
|
push(EV_UNGRAB, 0, 0, false);
|
||||||
m.conf.req = false;
|
m.conf.req = false;
|
||||||
if (!m.conf.hold)
|
if (!m.conf.hold)
|
||||||
|
{
|
||||||
m.conf.on = false;
|
m.conf.on = false;
|
||||||
|
core_handleGrabEvent(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool grabbed(void)
|
||||||
|
{
|
||||||
|
return m.conf.on;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void capture(void)
|
static void capture(void)
|
||||||
@@ -186,6 +194,7 @@ static struct LG_DisplayServerOps ds = {
|
|||||||
.ungrabKeyboard = keyNoop,
|
.ungrabKeyboard = keyNoop,
|
||||||
.grabPointer = grab,
|
.grabPointer = grab,
|
||||||
.ungrabPointer = ungrab,
|
.ungrabPointer = ungrab,
|
||||||
|
.isPointerGrabbed = grabbed,
|
||||||
.capturePointer = capture,
|
.capturePointer = capture,
|
||||||
.uncapturePointer = uncapture,
|
.uncapturePointer = uncapture,
|
||||||
.isPointerCaptured = captured,
|
.isPointerCaptured = captured,
|
||||||
@@ -245,8 +254,10 @@ static void reset(void)
|
|||||||
memset(&g_cursor, 0, sizeof(g_cursor));
|
memset(&g_cursor, 0, sizeof(g_cursor));
|
||||||
memset(&g_params, 0, sizeof(g_params));
|
memset(&g_params, 0, sizeof(g_params));
|
||||||
|
|
||||||
m.support = LG_DS_WARP_SURFACE;
|
m.support = LG_DS_WARP_SURFACE;
|
||||||
m.valid = true;
|
m.valid = true;
|
||||||
|
m.conf.req = true;
|
||||||
|
m.conf.on = true;
|
||||||
|
|
||||||
g_state.ds = &ds;
|
g_state.ds = &ds;
|
||||||
g_state.focused = true;
|
g_state.focused = true;
|
||||||
@@ -269,6 +280,7 @@ static void reset(void)
|
|||||||
|
|
||||||
g_cursor.inWindow = true;
|
g_cursor.inWindow = true;
|
||||||
g_cursor.inView = true;
|
g_cursor.inView = true;
|
||||||
|
g_cursor.viewReq = true;
|
||||||
g_cursor.warpState = WARP_STATE_ON;
|
g_cursor.warpState = WARP_STATE_ON;
|
||||||
g_cursor.guest.valid = true;
|
g_cursor.guest.valid = true;
|
||||||
g_cursor.scale = (struct DoublePoint) { 1.0, 1.0 };
|
g_cursor.scale = (struct DoublePoint) { 1.0, 1.0 };
|
||||||
@@ -315,8 +327,6 @@ static void startExit(void)
|
|||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
setLocal(109, 50);
|
setLocal(109, 50);
|
||||||
m.conf.req = true;
|
|
||||||
m.conf.on = true;
|
|
||||||
m.conf.hold = true;
|
m.conf.hold = true;
|
||||||
|
|
||||||
core_handleMouseNormal(2, 0);
|
core_handleMouseNormal(2, 0);
|
||||||
@@ -343,17 +353,29 @@ static void startConf(void)
|
|||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
setLocal(50, 50);
|
setLocal(50, 50);
|
||||||
g_cursor.inView = false;
|
m.conf.req = false;
|
||||||
|
m.conf.on = false;
|
||||||
|
g_cursor.inView = false;
|
||||||
|
g_cursor.viewReq = false;
|
||||||
|
|
||||||
core_handleMouseNormal(0, 0);
|
core_handleMouseNormal(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setConf(bool active)
|
||||||
|
{
|
||||||
|
m.conf.on = active;
|
||||||
|
core_handleGrabEvent(active);
|
||||||
|
}
|
||||||
|
|
||||||
static void testConfWait(void)
|
static void testConfWait(void)
|
||||||
{
|
{
|
||||||
startConf();
|
startConf();
|
||||||
CHECK(m.conf.req);
|
CHECK(m.conf.req);
|
||||||
CHECK(!m.conf.on);
|
CHECK(!m.conf.on);
|
||||||
CHECK(!g_cursor.inView);
|
CHECK(!g_cursor.inView);
|
||||||
|
|
||||||
|
setConf(true);
|
||||||
|
CHECK(g_cursor.inView);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void testConfGuest(void)
|
static void testConfGuest(void)
|
||||||
@@ -362,6 +384,10 @@ static void testConfGuest(void)
|
|||||||
core_handleGuestMouseUpdate();
|
core_handleGuestMouseUpdate();
|
||||||
CHECK(m.conf.req);
|
CHECK(m.conf.req);
|
||||||
CHECK(count(EV_GUEST) == 0);
|
CHECK(count(EV_GUEST) == 0);
|
||||||
|
|
||||||
|
setConf(true);
|
||||||
|
core_handleGuestMouseUpdate();
|
||||||
|
CHECK(count(EV_GUEST) == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void testCapWait(void)
|
static void testCapWait(void)
|
||||||
|
|||||||
Reference in New Issue
Block a user