Disabling mouse tracking when X11 focus leaves wine?

Open forum for end-user questions about Wine. Before asking questions, check out the Wiki as a first step.
Forum Rules
Locked
laut
Newbie
Newbie
Posts: 2
Joined: Tue Sep 02, 2008 6:58 am

Disabling mouse tracking when X11 focus leaves wine?

Post by laut »

Hello all,

I was very pleased to find that Age of Empires II works so well in wine.

Now, one hobby of mine is to create custom AI scripts for the game (see www.aiscripters.com for examples), and let different scripts (mine and other people's) play against each other, mostly unattended.

The problem is, that the running AoEII game still tracks the position of the mouse
pointer whenever I move the mouse (and focus) away from the wine window.
The game view then scrolls to show just one black corner of the map
which is not very informative or entertaining.

Therefore, in this use case, I'd prefer to let the pointer position to be reported
to the game "as a constant" (preferably the center of the wine window)
while the focus is away from the game.

Can this be done without tweaking wine source code, for example
with some X window manager (btw. I use fvwm) mechanism,
or by some already existing wine configuration means?

Or, if tweaking of wine code is needed... I'm no X11 guru but
started to educate myself by compiling both wine 1.0 and 1.1.3...
but noticed that there's quite a lot of stuff to delve in there ...

So I'd be grateful if anyone knowledgeable could evaluate this whole idea
and maybe jump-start me a bit by pointing me to the right source files?

Or, in your opinion, does such functionality belong elsewhere -- like in the
window manager -- rather than in wine?

Or, could my configuration be somehow erratic and this out-of-focus
"mouse tracking" doesn't happen anywhere else?

--laut
vitamin
Moderator
Moderator
Posts: 6605
Joined: Sat Feb 23, 2008 2:29 pm

Re: Disabling mouse tracking when X11 focus leaves wine?

Post by vitamin »

laut wrote:The problem is, that the running AoEII game still tracks the position of the mouse
pointer whenever I move the mouse (and focus) away from the wine window.
The game view then scrolls to show just one black corner of the map
which is not very informative or entertaining.

Therefore, in this use case, I'd prefer to let the pointer position to be reported
to the game "as a constant" (preferably the center of the wine window)
while the focus is away from the game.

Can this be done without tweaking wine source code,
No, you have to modify Wine code for this.
felix
Level 2
Level 2
Posts: 45
Joined: Thu Feb 28, 2008 10:04 am

Disabling mouse tracking when X11 focus leaves wine?

Post by felix »

On Tue, Sep 02, 2008 at 08:30:17AM -0500, vitamin wrote:
laut wrote:
Therefore, in this use case, I'd prefer to let the pointer position to be reported
to the game "as a constant" (preferably the center of the wine window)
while the focus is away from the game.

Can this be done without tweaking wine source code,
No, you have to modify Wine code for this.
Does that also remain true if you Alt+Tab focus away from the wine
window? or does it continue to get mouse movement updates once focus is
gone?

--
Darragh

"Nothing is foolproof to a sufficiently talented fool."
vitamin
Moderator
Moderator
Posts: 6605
Joined: Sat Feb 23, 2008 2:29 pm

Re: Disabling mouse tracking when X11 focus leaves wine?

Post by vitamin »

felix wrote: Does that also remain true if you Alt+Tab focus away from the wine
window? or does it continue to get mouse movement updates once focus is
gone?
Wine does not send any updates because it does not receive any. But program can always request current cursor position. And Wine will report it, clamped to the Wine window coordinates.

Also don't forget that if you running virtual desktop programs might not ever loose focus. This is a bug and a feature.
laut
Newbie
Newbie
Posts: 2
Joined: Tue Sep 02, 2008 6:58 am

Post by laut »

I am not 100% happy with the following quick-and-dirty snippet,
but it seems to work well-enough for my limited goal of
running Age Of Empires II in the computer-vs-computer mode.

Some Windows games assume full-screen operation, and query
mouse position continuously, even when Wine has no focus or
when cursor is outside Wine window. When these programs are
non-focused, it may be useful to report mouse as being in a
constant position, especially when running in a virtual
desktop window.

Consider the following cases:
1. Wine has input focus and X11 cursor is within Wine
2. Wine has focus but cursor is outside Wine
3. no focus and cursor is outside Wine
4. no focus but cursor is inside Wine

The following snippet handles cases 1 and 4 as before.
When the pointer resides outside Wine, the environment
variable WINE_FAKED_POINTER will be used to decide
if a constant position will be reported:

1: Report where the mouse really is, relative to the Wine window.
This is the original (and default) functionality.
2: Report mouse as being in the middle of the wine window.
3: Report mouse as being in an "initial" position.

example:
export WINE_FAKED_POINTER=3
wine age2_x1.exe

The logic for returning the fake position report does not check for
input focus. When using FocusFollowMouse or SloppyFocus
this should be enough.

Or maybe someone who uses click-to-focus feels an urge to continue
working on this...

Anyway, recommendations on cleaner ways to
interact with Wine innards will be appreciated. :)

--laut

Code: Select all

/* This function resides in dlls/winex11.drv/mouse.c */

/********************************************************************
 *		GetCursorPos (X11DRV.@)
 */
BOOL X11DRV_GetCursorPos(LPPOINT pos)
{
    Display *display = thread_display();
    Window root, child;
    int rootX, rootY, winX, winY;
    unsigned int xstate;

    wine_tsx11_lock();
    if ((GetTickCount() - last_time_modified > 100) &&
        XQueryPointer( display, root_window, &root, &child,
                       &rootX, &rootY, &winX, &winY, &xstate ))
    {
        int have_pointer = child != 0;

        static int fake_pointer_mode = -1;
        static int original_x = 0;
        static int original_y = 0;
         
        /* FIXME: thread-safety ? Or is wine_tsx11_lock() enough? */
        if (fake_pointer_mode < 1) {
            char* opt = getenv("WINE_FAKED_POINTER");
            fake_pointer_mode =
                (opt && *opt >= '1' && *opt <= '9')
                ? *opt - '0'
                : 1;
                /* Save initial position to be used in mode 3 */
            if (have_pointer) {
                original_x = winX;
                original_y = winY;
            } else {
                original_x = (virtual_screen_rect.right - virtual_screen_rect.left) / 2;
                original_y = (virtual_screen_rect.bottom - virtual_screen_rect.top) / 2;
            }
            WINE_DPRINTF("%s: mode=%d, x=%d, y=%d\n",
                         __FUNCTION__, fake_pointer_mode,
                         original_x, original_y);
        }
        
        /* Pointer within Wine window: report truthfully */
        if (have_pointer || fake_pointer_mode==1) {
            update_button_state( xstate );
            winX += virtual_screen_rect.left;
            winY += virtual_screen_rect.top;
            TRACE("pointer at (%d,%d)\n", winX, winY );
            cursor_pos.x = winX;
            cursor_pos.y = winY;
        } else {
         
            switch (fake_pointer_mode) {
            case 2:
                winX = (virtual_screen_rect.right - virtual_screen_rect.left) / 2;
                winY = (virtual_screen_rect.bottom - virtual_screen_rect.top) / 2;
                break;
            case 3:
                winX = original_x; winY = original_y;
                break;
            case 1:
            default:
                /* like before, report mouse in its correct position */
                winX = winX; winY = winY;
                break;
            }
            
            /* For the moment, we do not update button state here. */
            cursor_pos.x = winX;
            cursor_pos.y = winY;
            cursor_pos.x += virtual_screen_rect.left;
            cursor_pos.y += virtual_screen_rect.top;
        }
    }
    *pos = cursor_pos;
    wine_tsx11_unlock();
    return TRUE;
}
Locked