mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-25 06:47:19 +00:00
[client] ds: refactor app and cursor state into app.c and core.c
This commit is contained in:
parent
33fed48277
commit
4e1c0cc0d0
@ -297,10 +297,8 @@ static int sdlEventFilter(void * userdata, SDL_Event * event)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
app_updateCursorPos(event->motion.x, event->motion.y);
|
app_updateCursorPos(event->motion.x, event->motion.y);
|
||||||
if (app_cursorIsGrabbed())
|
app_handleMouseRelitive(event->motion.xrel, event->motion.yrel,
|
||||||
app_handleMouseGrabbed(event->motion.xrel, event->motion.yrel);
|
event->motion.xrel, event->motion.yrel);
|
||||||
else
|
|
||||||
app_handleMouseNormal(event->motion.xrel, event->motion.yrel);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_MOUSEBUTTONDOWN:
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
@ -457,8 +455,7 @@ static void sdlWarpPointer(int x, int y, bool exiting)
|
|||||||
|
|
||||||
static void sdlRealignPointer(void)
|
static void sdlRealignPointer(void)
|
||||||
{
|
{
|
||||||
// no need to care about grab, realign only happens in normal mode
|
app_handleMouseRelitive(0.0, 0.0, 0.0, 0.0);
|
||||||
app_handleMouseNormal(0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool sdlIsValidPointerPos(int x, int y)
|
static bool sdlIsValidPointerPos(int x, int y)
|
||||||
|
@ -808,7 +808,7 @@ static void x11GenericEvent(XGenericEventCookie *cookie)
|
|||||||
app_updateCursorPos(device->event_x, device->event_y);
|
app_updateCursorPos(device->event_x, device->event_y);
|
||||||
|
|
||||||
if (!x11.pointerGrabbed)
|
if (!x11.pointerGrabbed)
|
||||||
app_handleMouseNormal(0.0, 0.0);
|
app_handleMouseRelitive(0.0, 0.0, 0.0, 0.0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -857,17 +857,7 @@ static void x11GenericEvent(XGenericEventCookie *cookie)
|
|||||||
prev_axis[0] = axis[0];
|
prev_axis[0] = axis[0];
|
||||||
prev_axis[1] = axis[1];
|
prev_axis[1] = axis[1];
|
||||||
|
|
||||||
if (app_cursorIsGrabbed())
|
app_handleMouseRelitive(axis[0], axis[1], raw_axis[0], raw_axis[1]);
|
||||||
{
|
|
||||||
if (app_cursorWantsRaw())
|
|
||||||
app_handleMouseGrabbed(raw_axis[0], raw_axis[1]);
|
|
||||||
else
|
|
||||||
app_handleMouseGrabbed(axis[0], axis[1]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (app_cursorInWindow())
|
|
||||||
app_handleMouseNormal(axis[0], axis[1]);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1077,7 +1067,7 @@ static void x11WarpPointer(int x, int y, bool exiting)
|
|||||||
|
|
||||||
static void x11RealignPointer(void)
|
static void x11RealignPointer(void)
|
||||||
{
|
{
|
||||||
app_handleMouseNormal(0, 0);
|
app_handleMouseRelitive(0.0, 0.0, 0.0, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool x11IsValidPointerPos(int x, int y)
|
static bool x11IsValidPointerPos(int x, int y)
|
||||||
|
@ -37,16 +37,16 @@ LG_MsgAlert;
|
|||||||
|
|
||||||
bool app_isRunning(void);
|
bool app_isRunning(void);
|
||||||
bool app_inputEnabled(void);
|
bool app_inputEnabled(void);
|
||||||
bool app_cursorIsGrabbed(void);
|
|
||||||
bool app_cursorWantsRaw(void);
|
|
||||||
bool app_cursorInWindow(void);
|
|
||||||
void app_updateCursorPos(double x, double y);
|
void app_updateCursorPos(double x, double y);
|
||||||
void app_updateWindowPos(int x, int y);
|
void app_updateWindowPos(int x, int y);
|
||||||
void app_handleResizeEvent(int w, int h, const struct Border border);
|
void app_handleResizeEvent(int w, int h, const struct Border border);
|
||||||
void app_handleMouseGrabbed(double ex, double ey);
|
|
||||||
void app_handleMouseNormal(double ex, double ey);
|
void app_handleMouseRelitive(double normx, double normy,
|
||||||
|
double rawx, double rawy);
|
||||||
|
|
||||||
void app_handleMouseBasic(void);
|
void app_handleMouseBasic(void);
|
||||||
void app_resyncMouseBasic(void);
|
void app_resyncMouseBasic(void);
|
||||||
|
|
||||||
void app_handleButtonPress(int button);
|
void app_handleButtonPress(int button);
|
||||||
void app_handleButtonRelease(int button);
|
void app_handleButtonRelease(int button);
|
||||||
void app_handleKeyPress(int scancode);
|
void app_handleKeyPress(int scancode);
|
||||||
|
211
client/src/app.c
211
client/src/app.c
@ -40,27 +40,6 @@ bool app_isRunning(void)
|
|||||||
g_state.state == APP_STATE_RESTART;
|
g_state.state == APP_STATE_RESTART;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool app_inputEnabled(void)
|
|
||||||
{
|
|
||||||
return g_params.useSpiceInput && !g_state.ignoreInput &&
|
|
||||||
((g_cursor.grab && g_params.captureInputOnly) || !g_params.captureInputOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool app_cursorInWindow(void)
|
|
||||||
{
|
|
||||||
return g_cursor.inWindow;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool app_cursorIsGrabbed(void)
|
|
||||||
{
|
|
||||||
return g_cursor.grab;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool app_cursorWantsRaw(void)
|
|
||||||
{
|
|
||||||
return g_params.rawMouse;
|
|
||||||
}
|
|
||||||
|
|
||||||
void app_updateCursorPos(double x, double y)
|
void app_updateCursorPos(double x, double y)
|
||||||
{
|
{
|
||||||
g_cursor.pos.x = x;
|
g_cursor.pos.x = x;
|
||||||
@ -71,7 +50,7 @@ void app_updateCursorPos(double x, double y)
|
|||||||
void app_handleFocusEvent(bool focused)
|
void app_handleFocusEvent(bool focused)
|
||||||
{
|
{
|
||||||
g_state.focused = focused;
|
g_state.focused = focused;
|
||||||
if (!app_inputEnabled())
|
if (!core_inputEnabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!focused)
|
if (!focused)
|
||||||
@ -89,7 +68,7 @@ void app_handleEnterEvent(bool entered)
|
|||||||
if (entered)
|
if (entered)
|
||||||
{
|
{
|
||||||
g_cursor.inWindow = true;
|
g_cursor.inWindow = true;
|
||||||
if (!app_inputEnabled())
|
if (!core_inputEnabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
g_cursor.realign = true;
|
g_cursor.realign = true;
|
||||||
@ -99,7 +78,7 @@ void app_handleEnterEvent(bool entered)
|
|||||||
g_cursor.inWindow = false;
|
g_cursor.inWindow = false;
|
||||||
core_setCursorInView(false);
|
core_setCursorInView(false);
|
||||||
|
|
||||||
if (!app_inputEnabled())
|
if (!core_inputEnabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!g_params.alwaysShowCursor)
|
if (!g_params.alwaysShowCursor)
|
||||||
@ -182,36 +161,9 @@ void spiceClipboardNotice(const SpiceDataType type)
|
|||||||
g_state.ds->cbNotice(cb_spiceTypeToLGType(type));
|
g_state.ds->cbNotice(cb_spiceTypeToLGType(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_handleMouseGrabbed(double ex, double ey)
|
|
||||||
{
|
|
||||||
if (!app_inputEnabled())
|
|
||||||
return;
|
|
||||||
|
|
||||||
int x, y;
|
|
||||||
if (g_params.rawMouse && !g_cursor.sens)
|
|
||||||
{
|
|
||||||
/* raw unscaled input are always round numbers */
|
|
||||||
x = floor(ex);
|
|
||||||
y = floor(ey);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* apply sensitivity */
|
|
||||||
ex = (ex / 10.0) * (g_cursor.sens + 10);
|
|
||||||
ey = (ey / 10.0) * (g_cursor.sens + 10);
|
|
||||||
util_cursorToInt(ex, ey, &x, &y);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x == 0 && y == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!spice_mouse_motion(x, y))
|
|
||||||
DEBUG_ERROR("failed to send mouse motion message");
|
|
||||||
}
|
|
||||||
|
|
||||||
void app_handleButtonPress(int button)
|
void app_handleButtonPress(int button)
|
||||||
{
|
{
|
||||||
if (!app_inputEnabled() || !g_cursor.inView)
|
if (!core_inputEnabled() || !g_cursor.inView)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
g_cursor.buttons |= (1U << button);
|
g_cursor.buttons |= (1U << button);
|
||||||
@ -222,7 +174,7 @@ void app_handleButtonPress(int button)
|
|||||||
|
|
||||||
void app_handleButtonRelease(int button)
|
void app_handleButtonRelease(int button)
|
||||||
{
|
{
|
||||||
if (!app_inputEnabled())
|
if (!core_inputEnabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
g_cursor.buttons &= ~(1U << button);
|
g_cursor.buttons &= ~(1U << button);
|
||||||
@ -246,7 +198,7 @@ void app_handleKeyPress(int sc)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!app_inputEnabled())
|
if (!core_inputEnabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (g_params.ignoreWindowsKeys && (sc == KEY_LEFTMETA || sc == KEY_RIGHTMETA))
|
if (g_params.ignoreWindowsKeys && (sc == KEY_LEFTMETA || sc == KEY_RIGHTMETA))
|
||||||
@ -291,7 +243,7 @@ void app_handleKeyRelease(int sc)
|
|||||||
g_state.escapeActive = false;
|
g_state.escapeActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!app_inputEnabled())
|
if (!core_inputEnabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// avoid sending key up events when we didn't send a down
|
// avoid sending key up events when we didn't send a down
|
||||||
@ -314,146 +266,19 @@ void app_handleKeyRelease(int sc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_handleMouseNormal(double ex, double ey)
|
void app_handleMouseRelitive(double normx, double normy,
|
||||||
|
double rawx, double rawy)
|
||||||
{
|
{
|
||||||
// prevent cursor handling outside of capture if the position is not known
|
if (g_cursor.grab)
|
||||||
if (!g_cursor.guest.valid)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!app_inputEnabled())
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* scale the movement to the guest */
|
|
||||||
if (g_cursor.useScale && g_params.scaleMouseInput)
|
|
||||||
{
|
{
|
||||||
ex *= g_cursor.scale.x / g_cursor.dpiScale;
|
if (g_params.rawMouse)
|
||||||
ey *= g_cursor.scale.y / g_cursor.dpiScale;
|
core_handleMouseGrabbed(rawx, rawy);
|
||||||
}
|
else
|
||||||
|
core_handleMouseGrabbed(normx, normy);
|
||||||
bool testExit = true;
|
|
||||||
if (!g_cursor.inView)
|
|
||||||
{
|
|
||||||
const bool inView =
|
|
||||||
g_cursor.pos.x >= g_state.dstRect.x &&
|
|
||||||
g_cursor.pos.x < g_state.dstRect.x + g_state.dstRect.w &&
|
|
||||||
g_cursor.pos.y >= g_state.dstRect.y &&
|
|
||||||
g_cursor.pos.y < g_state.dstRect.y + g_state.dstRect.h;
|
|
||||||
|
|
||||||
core_setCursorInView(inView);
|
|
||||||
if (inView)
|
|
||||||
g_cursor.realign = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* nothing to do if we are outside the viewport */
|
|
||||||
if (!g_cursor.inView)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* do not pass mouse events to the guest if we do not have focus, this must be
|
|
||||||
* done after the inView test has been performed so that when focus is gained
|
|
||||||
* we know if we should be drawing the cursor.
|
|
||||||
*/
|
|
||||||
if (!g_state.focused)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* if we have been instructed to realign */
|
|
||||||
if (g_cursor.realign)
|
|
||||||
{
|
|
||||||
g_cursor.realign = false;
|
|
||||||
|
|
||||||
struct DoublePoint guest;
|
|
||||||
util_localCurToGuest(&guest);
|
|
||||||
|
|
||||||
/* add the difference to the offset */
|
|
||||||
ex += guest.x - (g_cursor.guest.x + g_cursor.guest.hx);
|
|
||||||
ey += guest.y - (g_cursor.guest.y + g_cursor.guest.hy);
|
|
||||||
|
|
||||||
/* don't test for an exit as we just entered, we can get into a enter/exit
|
|
||||||
* loop otherwise */
|
|
||||||
testExit = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if we are in "autoCapture" and the delta was large don't test for exit */
|
|
||||||
if (g_params.autoCapture &&
|
|
||||||
(fabs(ex) > 100.0 / g_cursor.scale.x || fabs(ey) > 100.0 / g_cursor.scale.y))
|
|
||||||
testExit = false;
|
|
||||||
|
|
||||||
/* if any buttons are held we should not allow exit to happen */
|
|
||||||
if (g_cursor.buttons)
|
|
||||||
testExit = false;
|
|
||||||
|
|
||||||
if (testExit)
|
|
||||||
{
|
|
||||||
/* translate the move to the guests orientation */
|
|
||||||
struct DoublePoint move = {.x = ex, .y = ey};
|
|
||||||
util_rotatePoint(&move);
|
|
||||||
|
|
||||||
/* translate the guests position to our coordinate space */
|
|
||||||
struct DoublePoint local;
|
|
||||||
util_guestCurToLocal(&local);
|
|
||||||
|
|
||||||
/* check if the move would push the cursor outside the guest's viewport */
|
|
||||||
if (
|
|
||||||
local.x + move.x < g_state.dstRect.x ||
|
|
||||||
local.y + move.y < g_state.dstRect.y ||
|
|
||||||
local.x + move.x >= g_state.dstRect.x + g_state.dstRect.w ||
|
|
||||||
local.y + move.y >= g_state.dstRect.y + g_state.dstRect.h)
|
|
||||||
{
|
|
||||||
local.x += move.x;
|
|
||||||
local.y += move.y;
|
|
||||||
const int tx = (local.x <= 0.0) ? floor(local.x) : ceil(local.x);
|
|
||||||
const int ty = (local.y <= 0.0) ? floor(local.y) : ceil(local.y);
|
|
||||||
|
|
||||||
if (core_isValidPointerPos(
|
|
||||||
g_state.windowPos.x + g_state.border.left + tx,
|
|
||||||
g_state.windowPos.y + g_state.border.top + ty))
|
|
||||||
{
|
|
||||||
core_setCursorInView(false);
|
|
||||||
|
|
||||||
/* preempt the window leave flag if the warp will leave our window */
|
|
||||||
if (tx < 0 || ty < 0 || tx > g_state.windowW || ty > g_state.windowH)
|
|
||||||
g_cursor.inWindow = false;
|
|
||||||
|
|
||||||
/* ungrab the pointer and move the local cursor to the exit point */
|
|
||||||
g_state.ds->ungrabPointer();
|
|
||||||
core_warpPointer(tx, ty, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int x, y;
|
|
||||||
util_cursorToInt(ex, ey, &x, &y);
|
|
||||||
|
|
||||||
if (x == 0 && y == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (g_params.autoCapture)
|
|
||||||
{
|
|
||||||
g_cursor.delta.x += x;
|
|
||||||
g_cursor.delta.y += y;
|
|
||||||
|
|
||||||
if (fabs(g_cursor.delta.x) > 50.0 || fabs(g_cursor.delta.y) > 50.0)
|
|
||||||
{
|
|
||||||
g_cursor.delta.x = 0;
|
|
||||||
g_cursor.delta.y = 0;
|
|
||||||
core_warpPointer(g_state.windowCX, g_state.windowCY, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_cursor.guest.x = g_state.srcSize.x / 2;
|
|
||||||
g_cursor.guest.y = g_state.srcSize.y / 2;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
if (g_cursor.inWindow)
|
||||||
/* assume the mouse will move to the location we attempt to move it to so we
|
core_handleMouseNormal(normx, normy);
|
||||||
* avoid warp out of window issues. The cursorThread will correct this if
|
|
||||||
* wrong after the movement has ocurred on the guest */
|
|
||||||
g_cursor.guest.x += x;
|
|
||||||
g_cursor.guest.y += y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!spice_mouse_motion(x, y))
|
|
||||||
DEBUG_ERROR("failed to send mouse motion message");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline double clamp(double x, double min, double max)
|
static inline double clamp(double x, double min, double max)
|
||||||
@ -473,7 +298,7 @@ void app_handleMouseBasic()
|
|||||||
if (!g_cursor.guest.valid || !g_state.haveSrcSize || !g_state.focused)
|
if (!g_cursor.guest.valid || !g_state.haveSrcSize || !g_state.focused)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!app_inputEnabled())
|
if (!core_inputEnabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const bool inView =
|
const bool inView =
|
||||||
@ -529,7 +354,7 @@ void app_handleResizeEvent(int w, int h, const struct Border border)
|
|||||||
g_state.windowCY = h / 2;
|
g_state.windowCY = h / 2;
|
||||||
core_updatePositionInfo();
|
core_updatePositionInfo();
|
||||||
|
|
||||||
if (app_inputEnabled())
|
if (core_inputEnabled())
|
||||||
{
|
{
|
||||||
/* if the window is moved/resized causing a loss of focus while grabbed, it
|
/* if the window is moved/resized causing a loss of focus while grabbed, it
|
||||||
* makes it impossible to re-focus the window, so we quietly re-enter
|
* makes it impossible to re-focus the window, so we quietly re-enter
|
||||||
|
@ -30,6 +30,12 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
|
|
||||||
#define RESIZE_TIMEOUT (10 * 1000) // 10ms
|
#define RESIZE_TIMEOUT (10 * 1000) // 10ms
|
||||||
|
|
||||||
|
bool core_inputEnabled(void)
|
||||||
|
{
|
||||||
|
return g_params.useSpiceInput && !g_state.ignoreInput &&
|
||||||
|
((g_cursor.grab && g_params.captureInputOnly) || !g_params.captureInputOnly);
|
||||||
|
}
|
||||||
|
|
||||||
void core_setCursorInView(bool enable)
|
void core_setCursorInView(bool enable)
|
||||||
{
|
{
|
||||||
// if the state has not changed, don't do anything else
|
// if the state has not changed, don't do anything else
|
||||||
@ -291,3 +297,172 @@ void core_stopFrameThread(void)
|
|||||||
|
|
||||||
g_state.frameThread = NULL;
|
g_state.frameThread = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void core_handleMouseGrabbed(double ex, double ey)
|
||||||
|
{
|
||||||
|
if (!core_inputEnabled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
int x, y;
|
||||||
|
if (g_params.rawMouse && !g_cursor.sens)
|
||||||
|
{
|
||||||
|
/* raw unscaled input are always round numbers */
|
||||||
|
x = floor(ex);
|
||||||
|
y = floor(ey);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* apply sensitivity */
|
||||||
|
ex = (ex / 10.0) * (g_cursor.sens + 10);
|
||||||
|
ey = (ey / 10.0) * (g_cursor.sens + 10);
|
||||||
|
util_cursorToInt(ex, ey, &x, &y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x == 0 && y == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!spice_mouse_motion(x, y))
|
||||||
|
DEBUG_ERROR("failed to send mouse motion message");
|
||||||
|
}
|
||||||
|
|
||||||
|
void core_handleMouseNormal(double ex, double ey)
|
||||||
|
{
|
||||||
|
// prevent cursor handling outside of capture if the position is not known
|
||||||
|
if (!g_cursor.guest.valid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!core_inputEnabled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* scale the movement to the guest */
|
||||||
|
if (g_cursor.useScale && g_params.scaleMouseInput)
|
||||||
|
{
|
||||||
|
ex *= g_cursor.scale.x / g_cursor.dpiScale;
|
||||||
|
ey *= g_cursor.scale.y / g_cursor.dpiScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool testExit = true;
|
||||||
|
if (!g_cursor.inView)
|
||||||
|
{
|
||||||
|
const bool inView =
|
||||||
|
g_cursor.pos.x >= g_state.dstRect.x &&
|
||||||
|
g_cursor.pos.x < g_state.dstRect.x + g_state.dstRect.w &&
|
||||||
|
g_cursor.pos.y >= g_state.dstRect.y &&
|
||||||
|
g_cursor.pos.y < g_state.dstRect.y + g_state.dstRect.h;
|
||||||
|
|
||||||
|
core_setCursorInView(inView);
|
||||||
|
if (inView)
|
||||||
|
g_cursor.realign = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* nothing to do if we are outside the viewport */
|
||||||
|
if (!g_cursor.inView)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do not pass mouse events to the guest if we do not have focus, this must be
|
||||||
|
* done after the inView test has been performed so that when focus is gained
|
||||||
|
* we know if we should be drawing the cursor.
|
||||||
|
*/
|
||||||
|
if (!g_state.focused)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* if we have been instructed to realign */
|
||||||
|
if (g_cursor.realign)
|
||||||
|
{
|
||||||
|
g_cursor.realign = false;
|
||||||
|
|
||||||
|
struct DoublePoint guest;
|
||||||
|
util_localCurToGuest(&guest);
|
||||||
|
|
||||||
|
/* add the difference to the offset */
|
||||||
|
ex += guest.x - (g_cursor.guest.x + g_cursor.guest.hx);
|
||||||
|
ey += guest.y - (g_cursor.guest.y + g_cursor.guest.hy);
|
||||||
|
|
||||||
|
/* don't test for an exit as we just entered, we can get into a enter/exit
|
||||||
|
* loop otherwise */
|
||||||
|
testExit = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if we are in "autoCapture" and the delta was large don't test for exit */
|
||||||
|
if (g_params.autoCapture &&
|
||||||
|
(fabs(ex) > 100.0 / g_cursor.scale.x || fabs(ey) > 100.0 / g_cursor.scale.y))
|
||||||
|
testExit = false;
|
||||||
|
|
||||||
|
/* if any buttons are held we should not allow exit to happen */
|
||||||
|
if (g_cursor.buttons)
|
||||||
|
testExit = false;
|
||||||
|
|
||||||
|
if (testExit)
|
||||||
|
{
|
||||||
|
/* translate the move to the guests orientation */
|
||||||
|
struct DoublePoint move = {.x = ex, .y = ey};
|
||||||
|
util_rotatePoint(&move);
|
||||||
|
|
||||||
|
/* translate the guests position to our coordinate space */
|
||||||
|
struct DoublePoint local;
|
||||||
|
util_guestCurToLocal(&local);
|
||||||
|
|
||||||
|
/* check if the move would push the cursor outside the guest's viewport */
|
||||||
|
if (
|
||||||
|
local.x + move.x < g_state.dstRect.x ||
|
||||||
|
local.y + move.y < g_state.dstRect.y ||
|
||||||
|
local.x + move.x >= g_state.dstRect.x + g_state.dstRect.w ||
|
||||||
|
local.y + move.y >= g_state.dstRect.y + g_state.dstRect.h)
|
||||||
|
{
|
||||||
|
local.x += move.x;
|
||||||
|
local.y += move.y;
|
||||||
|
const int tx = (local.x <= 0.0) ? floor(local.x) : ceil(local.x);
|
||||||
|
const int ty = (local.y <= 0.0) ? floor(local.y) : ceil(local.y);
|
||||||
|
|
||||||
|
if (core_isValidPointerPos(
|
||||||
|
g_state.windowPos.x + g_state.border.left + tx,
|
||||||
|
g_state.windowPos.y + g_state.border.top + ty))
|
||||||
|
{
|
||||||
|
core_setCursorInView(false);
|
||||||
|
|
||||||
|
/* preempt the window leave flag if the warp will leave our window */
|
||||||
|
if (tx < 0 || ty < 0 || tx > g_state.windowW || ty > g_state.windowH)
|
||||||
|
g_cursor.inWindow = false;
|
||||||
|
|
||||||
|
/* ungrab the pointer and move the local cursor to the exit point */
|
||||||
|
g_state.ds->ungrabPointer();
|
||||||
|
core_warpPointer(tx, ty, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int x, y;
|
||||||
|
util_cursorToInt(ex, ey, &x, &y);
|
||||||
|
|
||||||
|
if (x == 0 && y == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (g_params.autoCapture)
|
||||||
|
{
|
||||||
|
g_cursor.delta.x += x;
|
||||||
|
g_cursor.delta.y += y;
|
||||||
|
|
||||||
|
if (fabs(g_cursor.delta.x) > 50.0 || fabs(g_cursor.delta.y) > 50.0)
|
||||||
|
{
|
||||||
|
g_cursor.delta.x = 0;
|
||||||
|
g_cursor.delta.y = 0;
|
||||||
|
core_warpPointer(g_state.windowCX, g_state.windowCY, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_cursor.guest.x = g_state.srcSize.x / 2;
|
||||||
|
g_cursor.guest.y = g_state.srcSize.y / 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* assume the mouse will move to the location we attempt to move it to so we
|
||||||
|
* avoid warp out of window issues. The cursorThread will correct this if
|
||||||
|
* wrong after the movement has ocurred on the guest */
|
||||||
|
g_cursor.guest.x += x;
|
||||||
|
g_cursor.guest.y += y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!spice_mouse_motion(x, y))
|
||||||
|
DEBUG_ERROR("failed to send mouse motion message");
|
||||||
|
}
|
||||||
|
@ -22,6 +22,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
bool core_inputEnabled(void);
|
||||||
void core_setCursorInView(bool enable);
|
void core_setCursorInView(bool enable);
|
||||||
void core_setGrab(bool enable);
|
void core_setGrab(bool enable);
|
||||||
void core_setGrabQuiet(bool enable);
|
void core_setGrabQuiet(bool enable);
|
||||||
@ -31,5 +32,8 @@ void core_alignToGuest(void);
|
|||||||
bool core_isValidPointerPos(int x, int y);
|
bool core_isValidPointerPos(int x, int y);
|
||||||
bool core_startFrameThread(void);
|
bool core_startFrameThread(void);
|
||||||
void core_stopFrameThread(void);
|
void core_stopFrameThread(void);
|
||||||
|
void core_handleMouseGrabbed(double ex, double ey);
|
||||||
|
void core_handleMouseNormal(double ex, double ey);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -87,7 +87,7 @@ static void lgInit(void)
|
|||||||
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
|
||||||
if (!app_inputEnabled() && g_params.hideMouse)
|
if (!core_inputEnabled() && g_params.hideMouse)
|
||||||
g_state.ds->showPointer(false);
|
g_state.ds->showPointer(false);
|
||||||
else
|
else
|
||||||
g_state.ds->showPointer(true);
|
g_state.ds->showPointer(true);
|
||||||
@ -296,7 +296,7 @@ static int cursorThread(void * unused)
|
|||||||
g_cursor.guest.valid = true;
|
g_cursor.guest.valid = true;
|
||||||
|
|
||||||
// if the state just became valid
|
// if the state just became valid
|
||||||
if (valid != true && app_inputEnabled())
|
if (valid != true && core_inputEnabled())
|
||||||
{
|
{
|
||||||
core_alignToGuest();
|
core_alignToGuest();
|
||||||
app_resyncMouseBasic();
|
app_resyncMouseBasic();
|
||||||
|
Loading…
Reference in New Issue
Block a user