Mouse woes and luck of interest

Vitaliy Margolen wine-devel at kievinfo.com
Sun Oct 15 00:27:38 CDT 2006


As you know Wine has number of problems with it's mouse handling. Just
enough to look at the bugzilla to see how many programs affected. After
spending several weeks trying to find and fix this problems I in the
dead-end now.

Most of Wines problems coming from the way Wine receives and handles
it's mouse events. On windows mouse events generated by the mouse driver
itself and the mouse pointer just another "user" of these events. Wine
works backwards - from mouse pointer.

In short we have 3 major problems that needs to be fixed:
1. GetCursorPos() have to return old (cached) cursor position inside
hook handler.
2. Any changes to the cursor position inside hook handler will be lost
after all hooks are handled.
3. Mouse move events generated event when pointer is "stuck" at the edge
of the screen.
4. Hook handler can see mouse events that happen anywhere not just in
application's window(s).

1) used by number of programs to generate relative mouse movements.
Using this might be the only way to fix mouse warping problems in
dinput. There is no other way to know if application itself set new
cursor position.

2) this is more of the consequence of 1). I have a simple test to prove it.

3) most games don't warp mouse pointer themselves because there is no
need for that. We have to do it because of this and next problem.

4) it's a limitation of X that forces us to do mouse warping. That
brings lots of other problems that is pretty hard to deal with.

Does anyone have any additional ideas suggestions and comments for my
patches that I have submitted to fix these problems? Or no one really
cares about having working mouse? It's been broken this way for number
of years now and the only "fix" people attempted to submit was move of
"MOUSE_HACK" from define into registry.

Yet I haven't seen a single person commenting on these patches. And as
usual I have a misunderstanding with Alexandre about this patches. I
can't understand what other testes required to prove that what we have
is not correct then attached test? It's simple and straight forward test
for 1) and 2). I do understand Alexandre's concern that some parts
create a 'race condition' but it is not clear to me how can it happen
nor how else to archive the same results.

x11drv fixes:
[1] http://winehq.org/pipermail/wine-patches/2006-October/031772.html
[2] http://winehq.org/pipermail/wine-patches/2006-October/031773.html
[3] http://winehq.org/pipermail/wine-patches/2006-October/031774.html

x11drv, dinput and wined3d changes
[1] http://winehq.org/pipermail/wine-patches/2006-October/031305.html
[2] http://winehq.org/pipermail/wine-patches/2006-October/031309.html
[3] http://winehq.org/pipermail/wine-patches/2006-October/031306.html
[4] http://winehq.org/pipermail/wine-patches/2006-October/031307.html
[5] http://winehq.org/pipermail/wine-patches/2006-October/031308.html


Vitaliy Margolen.
-------------- next part --------------
#include <windows.h>
#include <stdio.h>

static POINT last_hook_pos;

LRESULT CALLBACK hook_proc( int code, WPARAM wparam, LPARAM lparam )
{
    MSLLHOOKSTRUCT *hook = (MSLLHOOKSTRUCT *)lparam;
    POINT pt;

    if (code == HC_ACTION)
    {
        GetCursorPos(&pt);
        if (pt.x != last_hook_pos.x || pt.y != last_hook_pos.y)
            fprintf(stderr, "(%ld %ld) != (%ld %ld)\n", pt.x, pt.y, last_hook_pos.x, last_hook_pos.y);
        last_hook_pos = hook->pt;

        SetCursorPos(pt.x+10, pt.y+10);
    }
    return CallNextHookEx( 0, code, wparam, lparam );
}

static DWORD wnd_proc(void)
{
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) 
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    POINT pt;

    switch (message) 
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        return;
    case WM_MOUSEMOVE:
        GetCursorPos(&pt);
        if (pt.x != last_hook_pos.x || pt.y != last_hook_pos.y)
            fprintf(stderr, "MSG: (%ld %ld) != (%ld %ld)\n", pt.x, pt.y, last_hook_pos.x, last_hook_pos.y);

        break;
    }
    return DefWindowProc(hWnd, message, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                     LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wcex;
    HWND hwnd;
    HHOOK hook;

    memset(&wcex, 0, sizeof(wcex));
    wcex.cbSize         = sizeof(WNDCLASSEX);
    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = (WNDPROC)WndProc;
    wcex.hInstance      = hInstance;
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.lpszClassName  = "MainWindow";
    RegisterClassEx(&wcex);

    hwnd = CreateWindow("MainWindow", "Title", WS_OVERLAPPEDWINDOW,
                        10, 10, 200, 200, NULL, NULL, NULL, NULL);
    ShowWindow(hwnd, SW_SHOW);

    GetCursorPos(&last_hook_pos);
    hook = SetWindowsHookExA(WH_MOUSE_LL, hook_proc, hInstance, 0);

    wnd_proc();
    UnhookWindowsHookEx(hook);

    DestroyWindow(hwnd);
    return 0;
}


More information about the wine-devel mailing list