Skip to content

Commit

Permalink
steamcompmgr: Warp cursor off of Steam when cursor is hidden
Browse files Browse the repository at this point in the history
Stops misleading hover events from happening while also not intefering with touch.
  • Loading branch information
Joshua-Ashton committed Jan 19, 2022
1 parent 51b8a2c commit 603310e
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 1 deletion.
67 changes: 66 additions & 1 deletion src/steamcompmgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,13 @@ get_window_last_done_commit( win *w, std::shared_ptr<commit_t> &commit )
commit = w->commit_queue[ lastCommit ];
}

// For Steam, etc.
static bool
window_wants_no_focus_when_mouse_hidden( win *w )
{
return w && w->appID == 769;
}

/**
* Constructor for a cursor. It is hidden in the beginning (normally until moved by user).
*/
Expand All @@ -752,6 +759,8 @@ MouseCursor::MouseCursor(xwayland_ctx_t *ctx)
, m_hideForMovement(true)
, m_ctx(ctx)
{
m_lastX = g_nNestedWidth / 2;
m_lastY = g_nNestedHeight / 2;
}

void MouseCursor::queryPositions(int &rootX, int &rootY, int &winX, int &winY)
Expand Down Expand Up @@ -784,9 +793,19 @@ void MouseCursor::checkSuspension()
unsigned int buttonMask;
queryButtonMask(buttonMask);

bool bWasHidden = m_hideForMovement;

if (buttonMask & ( Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )) {
m_hideForMovement = false;
m_lastMovedTime = get_time_in_milliseconds();

// Move the cursor back to where we left it if the window didn't want us to give
// it hover/focus where we left it and we moved it before.
win *window = m_ctx->focus.inputFocusWindow;
if (window_wants_no_focus_when_mouse_hidden(window) && bWasHidden)
{
XWarpPointer(m_ctx->dpy, None, x11_win(m_ctx->focus.inputFocusWindow), 0, 0, 0, 0, m_lastX, m_lastY);
}
}

const bool suspended = get_time_in_milliseconds() - m_lastMovedTime > cursorHideTime;
Expand All @@ -798,6 +817,15 @@ void MouseCursor::checkSuspension()
// Rearm warp count
if (window) {
window->mouseMoved = 0;

// Move the cursor to the bottom right corner, just off screen if we can
// if the window (ie. Steam) doesn't want hover/focus events.
if ( window_wants_no_focus_when_mouse_hidden(window) )
{
m_lastX = m_x;
m_lastY = m_y;
XWarpPointer(m_ctx->dpy, None, x11_win(m_ctx->focus.inputFocusWindow), 0, 0, 0, 0, window->a.width, window->a.height);
}
}

// We're hiding the cursor, force redraw if we were showing it
Expand Down Expand Up @@ -931,7 +959,15 @@ void MouseCursor::constrainPosition()

if (rootX - window->a.x >= window->a.width || rootY - window->a.y >= window->a.height ||
rootX - window->a.x < 0 || rootY - window->a.y < 0 ) {
warp(window->a.width / 2, window->a.height / 2);
// If this is Steam and doesn't want focus and we got OOB,
// then put is in the bottom right.
if ( window_wants_no_focus_when_mouse_hidden( window ) && m_hideForMovement )
warp(window->a.width, window->a.height);
else
warp(window->a.width / 2, window->a.height / 2);

m_lastX = window->a.width / 2;
m_lastY = window->a.height / 2;
}
}

Expand Down Expand Up @@ -964,6 +1000,12 @@ void MouseCursor::move(int x, int y)
return;

m_lastMovedTime = get_time_in_milliseconds();
// Move the cursor back to centre if the window didn't want us to give
// it hover/focus where we left it.
if ( m_hideForMovement && window_wants_no_focus_when_mouse_hidden(window) )
{
XWarpPointer(m_ctx->dpy, None, x11_win(m_ctx->focus.inputFocusWindow), 0, 0, 0, 0, m_lastX, m_lastY);
}
m_hideForMovement = false;
}

Expand Down Expand Up @@ -2048,6 +2090,9 @@ determine_and_apply_focus(xwayland_ctx_t *ctx, std::vector<win*>& vecGlobalPossi

Window keyboardFocusWindow = keyboardFocusWin ? keyboardFocusWin->id : None;

bool bResetToCorner = false;
bool bResetToCenter = false;

if ( ctx->focus.inputFocusWindow != inputFocus ||
ctx->focus.inputFocusMode != inputFocus->inputFocusMode ||
ctx->currentKeyboardFocusWindow != keyboardFocusWindow )
Expand All @@ -2060,6 +2105,16 @@ determine_and_apply_focus(xwayland_ctx_t *ctx, std::vector<win*>& vecGlobalPossi
if ( !ctx->focus.overrideWindow || ctx->focus.overrideWindow != keyboardFocusWin )
XSetInputFocus(ctx->dpy, keyboardFocusWin->id, RevertToNone, CurrentTime);

// If the window doesn't want focus when hidden, move it away
// as we are going to hide it straight after.
// otherwise, if we switch from wanting it to not
// (steam -> game)
// put us back in the centre of the screen.
if (window_wants_no_focus_when_mouse_hidden(inputFocus))
bResetToCorner = true;
else if ( window_wants_no_focus_when_mouse_hidden(inputFocus) != window_wants_no_focus_when_mouse_hidden(ctx->focus.inputFocusWindow) )
bResetToCenter = true;

ctx->focus.inputFocusWindow = inputFocus;
ctx->focus.inputFocusMode = inputFocus->inputFocusMode;
ctx->currentKeyboardFocusWindow = keyboardFocusWin->id;
Expand Down Expand Up @@ -2097,6 +2152,16 @@ determine_and_apply_focus(xwayland_ctx_t *ctx, std::vector<win*>& vecGlobalPossi
XResizeWindow(ctx->dpy, ctx->focus.focusWindow->id, ctx->focus.focusWindow->requestedWidth, ctx->focus.focusWindow->requestedHeight);
}

if ( inputFocus )
{
// Cannot simply XWarpPointer here as we immediately go on to
// do wlserver_mousefocus and need to update m_x and m_y of the cursor.
if ( bResetToCorner )
ctx->cursor->forcePosition(inputFocus->a.width, inputFocus->a.height);
else if ( bResetToCenter )
ctx->cursor->forcePosition(inputFocus->a.width / 2, inputFocus->a.height / 2);
}

Window root_return = None, parent_return = None;
Window *children = NULL;
unsigned int nchildren = 0;
Expand Down
12 changes: 12 additions & 0 deletions src/steamcompmgr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ class MouseCursor

void hide() { m_lastMovedTime = 0; checkSuspension(); }

bool isHidden() { return m_hideForMovement; }

void forcePosition(int x, int y)
{
warp(x, y);
m_x = x;
m_y = y;
}

private:
void warp(int x, int y);
void checkSuspension();
Expand All @@ -75,6 +84,9 @@ class MouseCursor
PointerBarrier m_scaledFocusBarriers[4] = { None };

xwayland_ctx_t *m_ctx;

int m_lastX = 0;
int m_lastY = 0;
};

extern std::vector< wlr_surface * > wayland_surfaces_deleted;
Expand Down

0 comments on commit 603310e

Please sign in to comment.