mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-14 21:17:54 +00:00
[client] ds: detect when the cursor exits into an overlapping window
This adds a new method to the display server interface to allow the application to notify the ds when there is a guest cursor position update along with the translated local guest cursor position. This makes it possible for the display server to keep the local cursor position in sync with the guest cursor so that window leave events can be detected when the cursor would move into an overlapping window. Wayland currently just has a stub for this, and the X11 implementation still needs some minor tweaking.
This commit is contained in:
parent
cd56321e65
commit
d0a12f6097
11 changed files with 122 additions and 54 deletions
|
@ -106,3 +106,7 @@ void waylandShowPointer(bool show)
|
|||
wlWm.showPointer = show;
|
||||
wl_pointer_set_cursor(wlWm.pointer, wlWm.pointerEnterSerial, show ? wlWm.cursor : NULL, 0, 0);
|
||||
}
|
||||
|
||||
void waylandGuestPointerUpdated(double x, double y, int localX, int localY)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -138,43 +138,43 @@ static bool waylandGetProp(LG_DSProperty prop, void * ret)
|
|||
|
||||
struct LG_DisplayServerOps LGDS_Wayland =
|
||||
{
|
||||
.setup = waylandSetup,
|
||||
.probe = waylandProbe,
|
||||
.earlyInit = waylandEarlyInit,
|
||||
.init = waylandInit,
|
||||
.startup = waylandStartup,
|
||||
.shutdown = waylandShutdown,
|
||||
.free = waylandFree,
|
||||
.getProp = waylandGetProp,
|
||||
.setup = waylandSetup,
|
||||
.probe = waylandProbe,
|
||||
.earlyInit = waylandEarlyInit,
|
||||
.init = waylandInit,
|
||||
.startup = waylandStartup,
|
||||
.shutdown = waylandShutdown,
|
||||
.free = waylandFree,
|
||||
.getProp = waylandGetProp,
|
||||
|
||||
#ifdef ENABLE_EGL
|
||||
.getEGLDisplay = waylandGetEGLDisplay,
|
||||
.getEGLNativeWindow = waylandGetEGLNativeWindow,
|
||||
.eglSwapBuffers = waylandEGLSwapBuffers,
|
||||
.getEGLDisplay = waylandGetEGLDisplay,
|
||||
.getEGLNativeWindow = waylandGetEGLNativeWindow,
|
||||
.eglSwapBuffers = waylandEGLSwapBuffers,
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_OPENGL
|
||||
.glCreateContext = waylandGLCreateContext,
|
||||
.glDeleteContext = waylandGLDeleteContext,
|
||||
.glMakeCurrent = waylandGLMakeCurrent,
|
||||
.glSetSwapInterval = waylandGLSetSwapInterval,
|
||||
.glSwapBuffers = waylandGLSwapBuffers,
|
||||
.glCreateContext = waylandGLCreateContext,
|
||||
.glDeleteContext = waylandGLDeleteContext,
|
||||
.glMakeCurrent = waylandGLMakeCurrent,
|
||||
.glSetSwapInterval = waylandGLSetSwapInterval,
|
||||
.glSwapBuffers = waylandGLSwapBuffers,
|
||||
#endif
|
||||
|
||||
.showPointer = waylandShowPointer,
|
||||
.grabPointer = waylandGrabPointer,
|
||||
.ungrabPointer = waylandUngrabPointer,
|
||||
.grabKeyboard = waylandGrabKeyboard,
|
||||
.ungrabKeyboard = waylandUngrabKeyboard,
|
||||
.warpPointer = waylandWarpPointer,
|
||||
.realignPointer = waylandRealignPointer,
|
||||
.isValidPointerPos = waylandIsValidPointerPos,
|
||||
.inhibitIdle = waylandInhibitIdle,
|
||||
.uninhibitIdle = waylandUninhibitIdle,
|
||||
.wait = waylandWait,
|
||||
.setWindowSize = waylandSetWindowSize,
|
||||
.setFullscreen = waylandSetFullscreen,
|
||||
.getFullscreen = waylandGetFullscreen,
|
||||
.guestPointerUpdated = waylandGuestPointerUpdated,
|
||||
.showPointer = waylandShowPointer,
|
||||
.grabPointer = waylandGrabPointer,
|
||||
.ungrabPointer = waylandUngrabPointer,
|
||||
.grabKeyboard = waylandGrabKeyboard,
|
||||
.ungrabKeyboard = waylandUngrabKeyboard,
|
||||
.warpPointer = waylandWarpPointer,
|
||||
.realignPointer = waylandRealignPointer,
|
||||
.isValidPointerPos = waylandIsValidPointerPos,
|
||||
.inhibitIdle = waylandInhibitIdle,
|
||||
.uninhibitIdle = waylandUninhibitIdle,
|
||||
.wait = waylandWait,
|
||||
.setWindowSize = waylandSetWindowSize,
|
||||
.setFullscreen = waylandSetFullscreen,
|
||||
.getFullscreen = waylandGetFullscreen,
|
||||
|
||||
.cbInit = waylandCBInit,
|
||||
.cbNotice = waylandCBNotice,
|
||||
|
|
|
@ -190,6 +190,7 @@ void waylandCBRelease(void);
|
|||
// cursor module
|
||||
bool waylandCursorInit(void);
|
||||
void waylandCursorFree(void);
|
||||
void waylandGuestPointerUpdated(double x, double y, int localX, int localY);
|
||||
void waylandShowPointer(bool show);
|
||||
|
||||
// gl module
|
||||
|
|
|
@ -41,6 +41,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
|
||||
#include "app.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/time.h"
|
||||
|
||||
#define _NET_WM_STATE_REMOVE 0
|
||||
#define _NET_WM_STATE_ADD 1
|
||||
|
@ -105,7 +106,8 @@ static bool x11Init(const LG_DSInitParams params)
|
|||
.event_mask =
|
||||
StructureNotifyMask |
|
||||
PropertyChangeMask |
|
||||
ExposureMask
|
||||
ExposureMask |
|
||||
PointerMotionMask
|
||||
};
|
||||
unsigned long swaMask = CWEventMask;
|
||||
|
||||
|
@ -677,6 +679,8 @@ static int x11EventThread(void * unused)
|
|||
|
||||
static void x11GenericEvent(XGenericEventCookie *cookie)
|
||||
{
|
||||
static int button_state = 0;
|
||||
|
||||
if (cookie->extension != x11.xinputOp)
|
||||
return;
|
||||
|
||||
|
@ -718,10 +722,10 @@ static void x11GenericEvent(XGenericEventCookie *cookie)
|
|||
|
||||
case XI_Enter:
|
||||
{
|
||||
if (x11.entered)
|
||||
XIEnterEvent *xie = cookie->data;
|
||||
if (x11.entered || xie->event != x11.window)
|
||||
return;
|
||||
|
||||
XIEnterEvent *xie = cookie->data;
|
||||
app_updateCursorPos(xie->event_x, xie->event_y);
|
||||
app_handleEnterEvent(true);
|
||||
x11.entered = true;
|
||||
|
@ -730,10 +734,11 @@ static void x11GenericEvent(XGenericEventCookie *cookie)
|
|||
|
||||
case XI_Leave:
|
||||
{
|
||||
if (!x11.entered)
|
||||
XILeaveEvent *xie = cookie->data;
|
||||
if (!x11.entered || xie->event != x11.window ||
|
||||
button_state != 0 || app_isCaptureMode())
|
||||
return;
|
||||
|
||||
XILeaveEvent *xie = cookie->data;
|
||||
app_updateCursorPos(xie->event_x, xie->event_y);
|
||||
app_handleEnterEvent(false);
|
||||
x11.entered = false;
|
||||
|
@ -793,8 +798,9 @@ static void x11GenericEvent(XGenericEventCookie *cookie)
|
|||
if (raw->time == prev_time && raw->detail == prev_detail)
|
||||
return;
|
||||
|
||||
prev_time = raw->time;
|
||||
prev_detail = raw->detail;
|
||||
prev_time = raw->time;
|
||||
prev_detail = raw->detail;
|
||||
button_state |= (1 << raw->detail);
|
||||
|
||||
app_handleButtonPress(
|
||||
raw->detail > 5 ? raw->detail - 2 : raw->detail);
|
||||
|
@ -814,8 +820,9 @@ static void x11GenericEvent(XGenericEventCookie *cookie)
|
|||
if (raw->time == prev_time && raw->detail == prev_detail)
|
||||
return;
|
||||
|
||||
prev_time = raw->time;
|
||||
prev_detail = raw->detail;
|
||||
prev_time = raw->time;
|
||||
prev_detail = raw->detail;
|
||||
button_state &= ~(1 << raw->detail);
|
||||
|
||||
app_handleButtonRelease(
|
||||
raw->detail > 5 ? raw->detail - 2 : raw->detail);
|
||||
|
@ -957,6 +964,29 @@ static void x11GLSwapBuffers(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void x11GuestPointerUpdated(double x, double y, int localX, int localY)
|
||||
{
|
||||
if (app_isCaptureMode() || !x11.entered)
|
||||
return;
|
||||
|
||||
// avoid running too often
|
||||
static uint64_t last_warp = 0;
|
||||
uint64_t now = microtime();
|
||||
if (now - last_warp < 10000)
|
||||
return;
|
||||
last_warp = now;
|
||||
|
||||
XIWarpPointer(
|
||||
x11.display,
|
||||
x11.pointerDev,
|
||||
None,
|
||||
x11.window,
|
||||
0, 0, 0, 0,
|
||||
localX, localY);
|
||||
|
||||
XSync(x11.display, False);
|
||||
}
|
||||
|
||||
static void x11ShowPointer(bool show)
|
||||
{
|
||||
if (show)
|
||||
|
@ -1000,6 +1030,8 @@ static void x11GrabPointer(void)
|
|||
XISetMask(mask.mask, XI_RawButtonRelease);
|
||||
XISetMask(mask.mask, XI_RawMotion );
|
||||
XISetMask(mask.mask, XI_Motion );
|
||||
XISetMask(mask.mask, XI_Enter );
|
||||
XISetMask(mask.mask, XI_Leave );
|
||||
|
||||
Status ret = XIGrabDevice(
|
||||
x11.display,
|
||||
|
@ -1189,20 +1221,21 @@ struct LG_DisplayServerOps LGDS_X11 =
|
|||
.glSetSwapInterval = x11GLSetSwapInterval,
|
||||
.glSwapBuffers = x11GLSwapBuffers,
|
||||
#endif
|
||||
.showPointer = x11ShowPointer,
|
||||
.grabPointer = x11GrabPointer,
|
||||
.ungrabPointer = x11UngrabPointer,
|
||||
.grabKeyboard = x11GrabKeyboard,
|
||||
.ungrabKeyboard = x11UngrabKeyboard,
|
||||
.warpPointer = x11WarpPointer,
|
||||
.realignPointer = x11RealignPointer,
|
||||
.isValidPointerPos = x11IsValidPointerPos,
|
||||
.inhibitIdle = x11InhibitIdle,
|
||||
.uninhibitIdle = x11UninhibitIdle,
|
||||
.wait = x11Wait,
|
||||
.setWindowSize = x11SetWindowSize,
|
||||
.setFullscreen = x11SetFullscreen,
|
||||
.getFullscreen = x11GetFullscreen,
|
||||
.guestPointerUpdated = x11GuestPointerUpdated,
|
||||
.showPointer = x11ShowPointer,
|
||||
.grabPointer = x11GrabPointer,
|
||||
.ungrabPointer = x11UngrabPointer,
|
||||
.grabKeyboard = x11GrabKeyboard,
|
||||
.ungrabKeyboard = x11UngrabKeyboard,
|
||||
.warpPointer = x11WarpPointer,
|
||||
.realignPointer = x11RealignPointer,
|
||||
.isValidPointerPos = x11IsValidPointerPos,
|
||||
.inhibitIdle = x11InhibitIdle,
|
||||
.uninhibitIdle = x11UninhibitIdle,
|
||||
.wait = x11Wait,
|
||||
.setWindowSize = x11SetWindowSize,
|
||||
.setFullscreen = x11SetFullscreen,
|
||||
.getFullscreen = x11GetFullscreen,
|
||||
|
||||
.cbInit = x11CBInit,
|
||||
.cbNotice = x11CBNotice,
|
||||
|
|
|
@ -37,6 +37,7 @@ LG_MsgAlert;
|
|||
|
||||
bool app_isRunning(void);
|
||||
bool app_inputEnabled(void);
|
||||
bool app_isCaptureMode(void);
|
||||
void app_updateCursorPos(double x, double y);
|
||||
void app_updateWindowPos(int x, int y);
|
||||
void app_handleResizeEvent(int w, int h, double scale, const struct Border border);
|
||||
|
|
|
@ -129,6 +129,7 @@ struct LG_DisplayServerOps
|
|||
#endif
|
||||
|
||||
/* dm specific cursor implementations */
|
||||
void (*guestPointerUpdated)(double x, double y, int localX, int localY);
|
||||
void (*showPointer)(bool show);
|
||||
void (*grabPointer)();
|
||||
void (*ungrabPointer)();
|
||||
|
@ -194,6 +195,7 @@ struct LG_DisplayServerOps
|
|||
ASSERT_OPENGL_FN((x)->glMakeCurrent ); \
|
||||
ASSERT_OPENGL_FN((x)->glSetSwapInterval); \
|
||||
ASSERT_OPENGL_FN((x)->glSwapBuffers ); \
|
||||
assert((x)->guestPointerUpdated); \
|
||||
assert((x)->showPointer ); \
|
||||
assert((x)->grabPointer ); \
|
||||
assert((x)->ungrabPointer ); \
|
||||
|
|
|
@ -33,4 +33,11 @@ bool util_guestCurToLocal(struct DoublePoint *local);
|
|||
void util_localCurToGuest(struct DoublePoint *guest);
|
||||
void util_rotatePoint(struct DoublePoint *point);
|
||||
|
||||
static inline double util_clamp(double x, double min, double max)
|
||||
{
|
||||
if (x < min) return min;
|
||||
if (x > max) return max;
|
||||
return x;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -41,6 +41,11 @@ bool app_isRunning(void)
|
|||
g_state.state == APP_STATE_RESTART;
|
||||
}
|
||||
|
||||
bool app_isCaptureMode(void)
|
||||
{
|
||||
return g_cursor.grab;
|
||||
}
|
||||
|
||||
void app_updateCursorPos(double x, double y)
|
||||
{
|
||||
g_cursor.pos.x = x;
|
||||
|
|
|
@ -326,6 +326,17 @@ void core_stopFrameThread(void)
|
|||
g_state.frameThread = NULL;
|
||||
}
|
||||
|
||||
void core_handleGuestMouseUpdate(void)
|
||||
{
|
||||
int x, y;
|
||||
struct DoublePoint localPos;
|
||||
util_guestCurToLocal(&localPos);
|
||||
localPos.x = util_clamp(localPos.x, 0.0, g_state.dstRect.w);
|
||||
localPos.y = util_clamp(localPos.y, 0.0, g_state.dstRect.h);
|
||||
util_cursorToInt(localPos.x, localPos.y, &x, &y);
|
||||
g_state.ds->guestPointerUpdated(g_cursor.guest.x, g_cursor.guest.y, x, y);
|
||||
}
|
||||
|
||||
void core_handleMouseGrabbed(double ex, double ey)
|
||||
{
|
||||
if (!core_inputEnabled())
|
||||
|
|
|
@ -32,6 +32,7 @@ void core_alignToGuest(void);
|
|||
bool core_isValidPointerPos(int x, int y);
|
||||
bool core_startFrameThread(void);
|
||||
void core_stopFrameThread(void);
|
||||
void core_handleGuestMouseUpdate(void);
|
||||
void core_handleMouseGrabbed(double ex, double ey);
|
||||
void core_handleMouseNormal(double ex, double ey);
|
||||
|
||||
|
|
|
@ -306,6 +306,9 @@ static int cursorThread(void * unused)
|
|||
core_alignToGuest();
|
||||
app_resyncMouseBasic();
|
||||
}
|
||||
|
||||
// tell the DS there was an update
|
||||
core_handleGuestMouseUpdate();
|
||||
}
|
||||
|
||||
lgmpClientMessageDone(queue);
|
||||
|
|
Loading…
Reference in a new issue