http://bugs.winehq.org/show_bug.cgi?id=6971
--- Comment #297 from Forest Hale lordhavoc@ghdigital.com 2009-12-09 12:09:07 --- (In reply to comment #296)
(In reply to comment #295)
A basic list of possible approaches: XInput2 - not relevant yet.
To whom? Ubuntu's pulled Xorg 7.5 for Lucid, Fedora 12 shipped with Xorg 7.5. Gentoo has it available, to the best of my limited knowledge. Debian only has it in experimental, but it's pretty danged close to hitting unstable from what I've seen.
This assumes that everyone runs the very latest and chooses their distribution based on how recently the latest release occurred (switching distribution according to the whims of release cycles), an inappropriate assumption in my view.
DGA Mouse - warp pointer to emulate real mouse movement.
If _I_ was writing the patch, I'd do the XInput 2 version, because it's the least work in Wine and also cleans up the somewhat messy DInput exclusive-mode handling, and then see if I could implement a DGA fallback usefully under the resulting structure. If neither of those was available, I'd suggest Wine just refuse to provide whatever mode the application is asking for.
To require XInput2 is unreasonable for the above reason, but to implement support for it before implementing fallbacks is perfectly reasonable.
Hidden Mouse - hide real mouse pointer, capture mouse movement and display a fake mouse pointer using additional drawing commands before glXSwapBuffers each frame (this is okay because cooperative mouse is chiefly used by games which continuously refresh the window).
This one sounds like a DInput/WineD3D-specific hack, which relies on certain features ("capture mouse movement" for example), the lack of which prompted us to focus on XInput2 in the first place. The key for spotting a hack is the parenthetical qualification which addresses the chief use only.
It is extremely common for any game to use DirectInput, and it is always in cooperative mode unless the game is fullscreen.
This affects nearly all games that have a mouse-controlled view turning behavior.
What games use co-operative mouse, anyway? I thought co-operative mouse would generally be used by non-game things that want to read the mouse while something else is nominally in charge (VoIP software, things like that program with the cat chasing your mouse cursor around the screen)
I do not know of very many applications that use DirectInput, but I know of many games, I do not need to list the many affected games as they should all be linked to this bug already.
Here is the usage pattern in question: 1. Open a window. 2. Attach D3D context. 3. Activate DI cooperative mode. 4. Each frame, poll DI events and utilize either the current mouse position (for a mouse-driven user interface such as in RTS and RPG games, as well as in menus of all games) or the delta (to look around) - wine is not notified of which information is desired. 5. The mouse pointer is hidden or shown according to the whims of the game, Wine does not reliably know which behavior the game is using at any given moment, and both pieces of data (position and delta) must be valid at all times.
When operating with plain X11 input, the only data that can be obtained is the current mouse position, and measuring deltas from this causes border problems.
When I do ports of games to Linux, I have to replace the DI cooperative mode mechanism used in the game with two different modes of operation in X11 - show mouse pointer and behave normally like an application, or hide pointer and warp it back to center frequently frame to get deltas (or use DGA to get the deltas directly without acceleration).
The problem I mentioned is that Wine may have to show the mouse pointer and report deltas at the same time on plain X11 (no DGA, no XInput2), and to this end it might have to draw a mouse pointer before the glXSwapBuffers occurs (in both D3D and GL cases), however this does not help regular applications.
With DGA the mouse movement can be reliably faked based on the deltas.
I do not know if XInput2 will live up to the promises and solve this bug, I certainly hope so and I fully support the idea of implementing an XInput2 solution first - but I still see a need to solve this bug with DGA and plain X11 as well, for users who do not have XInput2 yet.
Note for implementors of delta reading on plain X11: Each time a mouse move is parsed, it produces a delta from the previous position, however if the mouse position is getting dangerously near the borders (typically whenever it's out of the middle area of the window) a warp is needed to re-center it, this warp produces a move as well and must be ignored - to do this, XSendEvent is used to produce a fake mouse move event in the X11 stream, which updates the "last known" position variables but does not produce a delta (by checking the .send_event flag on the event these fake moves can be filtered out, it is always True if the event is produced by XSendEvent), then when the real mouse move from XWarpPointer comes in immediately after the fake one, it produces no delta because the "last known" position is already the same. This is the basic mode of operation of all Linux games that require delta movement when DGA is not available.