lilium-voyager/misc/sdl-win32-mouse-fixes.diff

572 lines
17 KiB
Diff

Index: src/video/wincommon/SDL_lowvideo.h
===================================================================
--- src/video/wincommon/SDL_lowvideo.h (revision 4067)
+++ src/video/wincommon/SDL_lowvideo.h (working copy)
@@ -51,10 +51,13 @@
/* Hidden "this" pointer for the video functions */
#define _THIS SDL_VideoDevice *this
+#define FULLSCREEN() \
+ ((SDL_VideoSurface->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN)
+
#define WINDIB_FULLSCREEN() \
( \
SDL_VideoSurface && \
- ((SDL_VideoSurface->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) && \
+ FULLSCREEN() && \
(((SDL_VideoSurface->flags & SDL_OPENGL ) == SDL_OPENGL ) || \
((SDL_strcmp(this->name, "windib") == 0) || \
(SDL_strcmp(this->name, "gapi") == 0))) \
@@ -62,13 +65,19 @@
#define DDRAW_FULLSCREEN() \
( \
SDL_VideoSurface && \
- ((SDL_VideoSurface->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) && \
+ FULLSCREEN() && \
((SDL_VideoSurface->flags & SDL_OPENGL ) != SDL_OPENGL ) && \
(SDL_strcmp(this->name, "directx") == 0) \
)
-#define DINPUT_FULLSCREEN() DDRAW_FULLSCREEN()
+#define DINPUT_FULLSCREEN() \
+( \
+ FULLSCREEN() && \
+ (strcmp(this->name, "directx") == 0) \
+)
+#define DINPUT() (strcmp(this->name, "directx") == 0)
+
/* The main window -- and a function to set it for the audio */
#ifdef _WIN32_WCE
extern LPWSTR SDL_Appname;
Index: src/video/wincommon/SDL_sysevents.c
===================================================================
--- src/video/wincommon/SDL_sysevents.c (revision 4067)
+++ src/video/wincommon/SDL_sysevents.c (working copy)
@@ -335,7 +335,6 @@
{
SDL_VideoDevice *this = current_video;
static int mouse_pressed = 0;
- static int in_window = 0;
#ifdef WMMSG_DEBUG
fprintf(stderr, "Received windows message: ");
if ( msg > MAX_WMMSG ) {
@@ -411,62 +410,41 @@
break;
case WM_MOUSEMOVE: {
-
- /* Mouse is handled by DirectInput when fullscreen */
- if ( SDL_VideoSurface && ! DINPUT_FULLSCREEN() ) {
- Sint16 x, y;
- /* mouse has entered the window */
- if ( ! in_window ) {
#ifdef WM_MOUSELEAVE
+ /* No need to handle SDL_APPMOUSEFOCUS when fullscreen */
+ if ( SDL_VideoSurface && !FULLSCREEN() ) {
+ /* mouse has entered the window */
+
+ if ( !(SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) {
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = SDL_Window;
_TrackMouseEvent(&tme);
+ }
+ }
#endif /* WM_MOUSELEAVE */
- in_window = TRUE;
- posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
- }
+ /* Mouse motion is handled in DIB_PumpEvents or
+ * DX5_PumpEvents, depending on the video driver
+ * in use */
- /* mouse has moved within the window */
- x = LOWORD(lParam);
- y = HIWORD(lParam);
- if ( mouse_relative ) {
- POINT center;
- center.x = (SDL_VideoSurface->w/2);
- center.y = (SDL_VideoSurface->h/2);
- x -= (Sint16)center.x;
- y -= (Sint16)center.y;
- if ( x || y ) {
- ClientToScreen(SDL_Window, &center);
- SetCursorPos(center.x, center.y);
- posted = SDL_PrivateMouseMotion(0, 1, x, y);
- }
- } else {
-#ifdef _WIN32_WCE
- if (SDL_VideoSurface)
- GapiTransform(this->hidden->userOrientation, this->hidden->hiresFix, &x, &y);
-#endif
- posted = SDL_PrivateMouseMotion(0, 0, x, y);
- }
- }
+ posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
}
return(0);
#ifdef WM_MOUSELEAVE
case WM_MOUSELEAVE: {
- /* Mouse is handled by DirectInput when fullscreen */
- if ( SDL_VideoSurface && ! DINPUT_FULLSCREEN() ) {
+ /* No need to handle SDL_APPMOUSEFOCUS when fullscreen */
+ if ( SDL_VideoSurface && !FULLSCREEN() ) {
/* mouse has left the window */
/* or */
/* Elvis has left the building! */
posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
}
- in_window = FALSE;
}
return(0);
#endif /* WM_MOUSELEAVE */
@@ -480,7 +458,7 @@
case WM_XBUTTONDOWN:
case WM_XBUTTONUP: {
/* Mouse is handled by DirectInput when fullscreen */
- if ( SDL_VideoSurface && ! DINPUT_FULLSCREEN() ) {
+ if ( SDL_VideoSurface && ! DINPUT() ) {
WORD xbuttonval = 0;
Sint16 x, y;
Uint8 button, state;
@@ -544,20 +522,8 @@
mouse_pressed = 0;
}
}
- if ( mouse_relative ) {
- /* RJR: March 28, 2000
- report internal mouse position if in relative mode */
- x = 0; y = 0;
- } else {
- x = (Sint16)LOWORD(lParam);
- y = (Sint16)HIWORD(lParam);
-#ifdef _WIN32_WCE
- if (SDL_VideoSurface)
- GapiTransform(this->hidden->userOrientation, this->hidden->hiresFix, &x, &y);
-#endif
- }
posted = SDL_PrivateMouseButton(
- state, button, x, y);
+ state, button, 0, 0);
/*
* MSDN says:
@@ -578,7 +544,7 @@
#if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
case WM_MOUSEWHEEL:
- if ( SDL_VideoSurface && ! DINPUT_FULLSCREEN() ) {
+ if ( SDL_VideoSurface && ! DINPUT() ) {
int move = (short)HIWORD(wParam);
if ( move ) {
Uint8 button;
Index: src/video/wincommon/SDL_sysmouse.c
===================================================================
--- src/video/wincommon/SDL_sysmouse.c (revision 4067)
+++ src/video/wincommon/SDL_sysmouse.c (working copy)
@@ -208,15 +208,20 @@
void WIN_WarpWMCursor(_THIS, Uint16 x, Uint16 y)
{
- if ( DDRAW_FULLSCREEN() ) {
- SDL_PrivateMouseMotion(0, 0, x, y);
- } else if ( mouse_relative) {
+ if ( mouse_relative) {
/* RJR: March 28, 2000
leave physical cursor at center of screen if
mouse hidden and grabbed */
SDL_PrivateMouseMotion(0, 0, x, y);
} else {
POINT pt;
+
+ /* With DirectInput the position doesn't follow
+ * the cursor, so it is set manually */
+ if ( DINPUT() ) {
+ SDL_PrivateMouseMotion(0, 0, x, y);
+ }
+
pt.x = x;
pt.y = y;
ClientToScreen(SDL_Window, &pt);
@@ -227,20 +232,15 @@
/* Update the current mouse state and position */
void WIN_UpdateMouse(_THIS)
{
- RECT rect;
POINT pt;
- if ( ! DDRAW_FULLSCREEN() ) {
- GetClientRect(SDL_Window, &rect);
- GetCursorPos(&pt);
- MapWindowPoints(NULL, SDL_Window, &pt, 1);
- if (PtInRect(&rect, pt) && (WindowFromPoint(pt) == SDL_Window)){
- SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
- SDL_PrivateMouseMotion(0,0, (Sint16)pt.x, (Sint16)pt.y);
- } else {
- SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
- }
- }
+ /* Always unset SDL_APPMOUSEFOCUS to give the WM_MOUSEMOVE event
+ * handler a chance to install a TRACKMOUSEEVENT */
+ SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
+
+ GetCursorPos(&pt);
+ ScreenToClient(SDL_Window, &pt);
+ SDL_PrivateMouseMotion(0,0, (Sint16)pt.x, (Sint16)pt.y);
}
/* Check to see if we need to enter or leave mouse relative mode */
Index: src/video/windib/SDL_dibevents.c
===================================================================
--- src/video/windib/SDL_dibevents.c (revision 4067)
+++ src/video/windib/SDL_dibevents.c (working copy)
@@ -262,6 +262,36 @@
return(DefWindowProc(hwnd, msg, wParam, lParam));
}
+static void DIB_GenerateMouseMotionEvent(void)
+{
+ extern int mouse_relative;
+ extern int posted;
+
+ POINT mouse;
+ GetCursorPos( &mouse );
+
+ if ( mouse_relative ) {
+ POINT center;
+ center.x = (SDL_VideoSurface->w/2);
+ center.y = (SDL_VideoSurface->h/2);
+ ClientToScreen(SDL_Window, &center);
+
+ mouse.x -= (Sint16)center.x;
+ mouse.y -= (Sint16)center.y;
+ if ( mouse.x || mouse.y ) {
+ SetCursorPos(center.x, center.y);
+ posted = SDL_PrivateMouseMotion(0, 1, mouse.x, mouse.y);
+ }
+ } else {
+ ScreenToClient(SDL_Window, &mouse);
+#ifdef _WIN32_WCE
+ if (SDL_VideoSurface)
+ GapiTransform(this->hidden->userOrientation, this->hidden->hiresFix, &mouse.x, &mouse.y);
+#endif
+ posted = SDL_PrivateMouseMotion(0, 0, mouse.x, mouse.y);
+ }
+}
+
void DIB_PumpEvents(_THIS)
{
MSG msg;
@@ -271,6 +301,11 @@
DispatchMessage(&msg);
}
}
+
+ if ( SDL_GetAppState() & (SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS) ==
+ (SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS) ) {
+ DIB_GenerateMouseMotionEvent( );
+ }
}
static HKL hLayoutUS = NULL;
@@ -494,7 +529,7 @@
Uint16 wchars[2];
GetKeyboardState(keystate);
- if (SDL_ToUnicode((UINT)vkey, scancode, keystate, wchars, sizeof(wchars)/sizeof(wchars[0]), 0) == 1)
+ if (SDL_ToUnicode((UINT)vkey, scancode, keystate, wchars, sizeof(wchars)/sizeof(wchars[0]), 0) > 0)
{
keysym->unicode = wchars[0];
}
Index: src/video/windx5/SDL_dx5events.c
===================================================================
--- src/video/windx5/SDL_dx5events.c (revision 4067)
+++ src/video/windx5/SDL_dx5events.c (working copy)
@@ -143,7 +143,12 @@
(DISCL_FOREGROUND|DISCL_NONEXCLUSIVE),
(DISCL_FOREGROUND|DISCL_NONEXCLUSIVE), handle_keyboard },
{ "mouse",
- &GUID_SysMouse, &c_dfDIMouse,
+ &GUID_SysMouse,
+#if DIRECTINPUT_VERSION >= 0x700
+ &c_dfDIMouse2,
+#else
+ &c_dfDIMouse,
+#endif
(DISCL_FOREGROUND|DISCL_NONEXCLUSIVE),
(DISCL_FOREGROUND|DISCL_EXCLUSIVE), handle_mouse },
{ NULL, NULL, NULL, 0, 0, NULL }
@@ -285,6 +290,76 @@
}
}
}
+
+static void post_mouse_motion(int relative, Sint16 x, Sint16 y)
+{
+ extern int mouse_relative;
+
+ if ( SDL_GetAppState() & (SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS) ==
+ (SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS) ) {
+ posted = SDL_PrivateMouseMotion(
+ 0, relative, x, y);
+
+ if ( !mouse_relative ) {
+ /* As DirectInput reads raw device coordinates, it has no notion of
+ * cursors or absolute position. We must assume responsibility for
+ * keeping track of this. */
+ int current_x, current_y;
+ POINT cursor;
+ RECT trap;
+ RECT window;
+ int at_edge;
+
+ /* Get the current cursor position */
+ SDL_GetMouseState(&current_x, &current_y);
+ cursor.x = current_x;
+ cursor.y = current_y;
+ ClientToScreen(SDL_Window, &cursor);
+
+ /* Construct a 1 pixel square RECT that is used to confine the cursor
+ * pointer to a specific pixel using ClipCursor. This is used in
+ * preference to SetCursorPos as it avoids the cursor jumping around as
+ * both the OS and SDL attempt to move it simultaneously. */
+ trap.left = cursor.x;
+ trap.top = cursor.y;
+ trap.right = cursor.x + 1;
+ trap.bottom = cursor.y + 1;
+
+ GetClientRect(SDL_Window, &window);
+ window.right -= window.left; window.left = 0;
+ window.bottom -= window.top; window.top = 0;
+
+ /* As we're assuming control over the cursor, we need to know when to
+ * relinquish control of it back to the operating system. This is when
+ * the cursor reaches the edge of the window. */
+ at_edge = (current_x == window.left) ||
+ (current_x == (window.right - 1)) ||
+ (current_y == window.top) ||
+ (current_y == (window.bottom - 1));
+
+ if ( at_edge ) {
+ ClipCursor(NULL);
+ } else {
+ ClipCursor(&trap);
+ }
+ } else {
+ /* When in relative mode, warp the OS's idea of where the cursor is to
+ * the center of the screen. This isn't really necessary as DirectInput
+ * reads from the hardware itself, but in case things go wrong, the
+ * cursor will be left in a sensible place. */
+ POINT center;
+ center.x = (SDL_VideoSurface->w/2);
+ center.y = (SDL_VideoSurface->h/2);
+ ClientToScreen(SDL_Window, &center);
+ SetCursorPos(center.x, center.y);
+ }
+ } else {
+ /* No window or mouse focus, control is lost */
+ mouse_lost = 1;
+ ClipCursor(NULL);
+ }
+}
+
static void handle_mouse(const int numevents, DIDEVICEOBJECTDATA *ptrbuf)
{
int i;
@@ -298,14 +373,8 @@
return;
}
- /* If we are in windowed mode, Windows is taking care of the mouse */
- if ( (SDL_PublicSurface->flags & SDL_OPENGL) ||
- !(SDL_PublicSurface->flags & SDL_FULLSCREEN) ) {
- return;
- }
-
/* If the mouse was lost, regain some sense of mouse state */
- if ( mouse_lost ) {
+ if ( mouse_lost && (SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) {
POINT mouse_pos;
Uint8 old_state;
Uint8 new_state;
@@ -313,14 +382,17 @@
/* Set ourselves up with the current cursor position */
GetCursorPos(&mouse_pos);
ScreenToClient(SDL_Window, &mouse_pos);
- posted = SDL_PrivateMouseMotion(0, 0,
- (Sint16)mouse_pos.x, (Sint16)mouse_pos.y);
+ post_mouse_motion( 0, (Sint16)mouse_pos.x, (Sint16)mouse_pos.y);
/* Check for mouse button changes */
old_state = SDL_GetMouseState(NULL, NULL);
new_state = 0;
{ /* Get the new DirectInput button state for the mouse */
+#if DIRECTINPUT_VERSION >= 0x700
+ DIMOUSESTATE2 distate;
+#else
DIMOUSESTATE distate;
+#endif
HRESULT result;
result=IDirectInputDevice2_GetDeviceState(SDL_DIdev[1],
@@ -341,14 +413,13 @@
for ( i=0; i<8; ++i ) {
if ( (old_state&0x01) != (new_state&0x01) ) {
button = (Uint8)(i+1);
- /* Button #2 on two button mice is button 3
- (the middle button is button 2)
- */
- if ( button == 2 ) {
- button = 3;
- } else
- if ( button == 3 ) {
- button = 2;
+ /* Map DI button numbers to SDL */
+ switch ( button ) {
+ case 2: button = SDL_BUTTON_RIGHT; break;
+ case 3: button = SDL_BUTTON_MIDDLE; break;
+ case 4: button = SDL_BUTTON_X1; break;
+ case 5: button = SDL_BUTTON_X2; break;
+ default: break;
}
if ( new_state & 0x01 ) {
/* Grab mouse so we get mouse-up */
@@ -387,8 +458,7 @@
case DIMOFS_X:
if ( timestamp != ptrbuf[i].dwTimeStamp ) {
if ( xrel || yrel ) {
- posted = SDL_PrivateMouseMotion(
- 0, 1, xrel, yrel);
+ post_mouse_motion(1, xrel, yrel);
xrel = 0;
yrel = 0;
}
@@ -399,8 +469,7 @@
case DIMOFS_Y:
if ( timestamp != ptrbuf[i].dwTimeStamp ) {
if ( xrel || yrel ) {
- posted = SDL_PrivateMouseMotion(
- 0, 1, xrel, yrel);
+ post_mouse_motion(1, xrel, yrel);
xrel = 0;
yrel = 0;
}
@@ -410,8 +479,7 @@
break;
case DIMOFS_Z:
if ( xrel || yrel ) {
- posted = SDL_PrivateMouseMotion(
- 0, 1, xrel, yrel);
+ post_mouse_motion(1, xrel, yrel);
xrel = 0;
yrel = 0;
}
@@ -429,22 +497,26 @@
case DIMOFS_BUTTON1:
case DIMOFS_BUTTON2:
case DIMOFS_BUTTON3:
+#if DIRECTINPUT_VERSION >= 0x700
+ case DIMOFS_BUTTON4:
+ case DIMOFS_BUTTON5:
+ case DIMOFS_BUTTON6:
+ case DIMOFS_BUTTON7:
+#endif
if ( xrel || yrel ) {
- posted = SDL_PrivateMouseMotion(
- 0, 1, xrel, yrel);
+ post_mouse_motion(1, xrel, yrel);
xrel = 0;
yrel = 0;
}
timestamp = 0;
button = (Uint8)(ptrbuf[i].dwOfs-DIMOFS_BUTTON0)+1;
- /* Button #2 on two button mice is button 3
- (the middle button is button 2)
- */
- if ( button == 2 ) {
- button = 3;
- } else
- if ( button == 3 ) {
- button = 2;
+ /* Map DI button numbers to SDL */
+ switch ( button ) {
+ case 2: button = SDL_BUTTON_RIGHT; break;
+ case 3: button = SDL_BUTTON_MIDDLE; break;
+ case 4: button = SDL_BUTTON_X1; break;
+ case 5: button = SDL_BUTTON_X2; break;
+ default: break;
}
if ( ptrbuf[i].dwData & 0x80 ) {
/* Grab mouse so we get mouse-up */
@@ -471,7 +543,7 @@
}
}
if ( xrel || yrel ) {
- posted = SDL_PrivateMouseMotion( 0, 1, xrel, yrel);
+ post_mouse_motion(1, xrel, yrel);
}
}
@@ -840,7 +912,7 @@
keysym->unicode = vkey;
#else
GetKeyboardState(keystate);
- if (SDL_ToUnicode(vkey, scancode, keystate, wchars, sizeof(wchars)/sizeof(wchars[0]), 0) == 1)
+ if (SDL_ToUnicode(vkey, scancode, keystate, wchars, sizeof(wchars)/sizeof(wchars[0]), 0) > 0)
{
keysym->unicode = wchars[0];
}
Index: src/video/windx5/directx.h
===================================================================
--- src/video/windx5/directx.h (revision 4067)
+++ src/video/windx5/directx.h (working copy)
@@ -72,7 +72,7 @@
/* We need these defines to mark what version of DirectX API we use */
#define DIRECTDRAW_VERSION 0x0700
#define DIRECTSOUND_VERSION 0x0500
-#define DIRECTINPUT_VERSION 0x0500
+#define DIRECTINPUT_VERSION 0x0700
#ifdef __GNUC__
#define NONAMELESSUNION
@@ -81,4 +81,20 @@
#include <dsound.h>
#include <dinput.h>
+#if DIRECTINPUT_VERSION >= 0x0700 && !defined(DIMOFS_BUTTON4)
+typedef struct _DIMOUSESTATE2 {
+ LONG lX;
+ LONG lY;
+ LONG lZ;
+ BYTE rgbButtons[8];
+} DIMOUSESTATE2, *LPDIMOUSESTATE2;
+
+#define DIMOFS_BUTTON4 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 4)
+#define DIMOFS_BUTTON5 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 5)
+#define DIMOFS_BUTTON6 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 6)
+#define DIMOFS_BUTTON7 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 7)
+
+extern const DIDATAFORMAT c_dfDIMouse2;
+#endif
+
#endif /* _directx_h */
Index: configure.in
===================================================================
--- configure.in (revision 4067)
+++ configure.in (working copy)
@@ -2442,7 +2442,7 @@
# Set up the system libraries we need
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -luser32 -lgdi32 -lwinmm"
if test x$have_directx = xyes; then
- EXTRA_LDFLAGS="$EXTRA_LDFLAGS -ldxguid"
+ EXTRA_LDFLAGS="$EXTRA_LDFLAGS -ldxguid -ldinput8"
fi
# The Win32 platform requires special setup
SOURCES="$SOURCES $srcdir/src/main/win32/*.rc"