Mercurial > sdl-ios-xcode
annotate src/video/wincommon/SDL_sysmouse.c @ 4167:a6f635e5eaa6 SDL-1.2
Fixed bug #611
From Tim Angus 2008-08-12 11:18:06
I'm one of the maintainers of ioquake3.org, an updated version of the
Quake 3 engine. Relatively recently, we moved ioq3 to use SDL as a
replacement for 95% of the platform specific code that was there. On the
whole it's doing a great job but unfortunately since the move we've been
getting complaints about the quality of the mouse input on the Windows
platform to the point where for many the game is unplayable. Put in
other terms, the current stable SDL 1.2 is basically not fit for purpose
if you need high quality mouse input as you do in a first person shooter.
Over the weekend I decided to pull my finger out and actually figure out
what's going on. There are basically two major problems. Firstly, when
using the "windib" driver, mouse input is gathered via the WM_MOUSEMOVE
message. Googling for this indicates that often this is known to result
in "spurious" and/or "missing" mouse movement events; this is the
primary cause of the poor mouse input. The second problem is that the
"directx" driver does not work at all in combination with OpenGL meaning
that you can't use DirectInput if your application also uses OpenGL. In
other words you're locked into using the "windib" driver and its poor
mouse input.
In order to address these problems I've done the following:
* Remove WM_MOUSEMOVE based motion event generation and replace with
calls to GetCursorPos which seems much more reliable. In order to
achieve this I've moved mouse motion out into a separate function that
is called once per DIB_PumpEvents.
* Remove the restriction on the "directx" driver being inoperable in
combination with OpenGL. There is a bug for this issues that I've
hijacked to a certain extent
(http://bugzilla.libsdl.org/show_bug.cgi?id=265). I'm the first to admit
I don't really understand why this restriction is there in the first
place. The commit message for the bug fix that introduced this
restriction (r581) isn't very elaborate and I couldn't see any other bug
tracking the issue. If anyone has more information on the bug that was
avoided by r581 it would be helpful as I/someone could then look into
addressing the problem without disabling the "directx" driver.
* I've also removed the restriction on not being allowed to use
DirectInput in windowed mode. I couldn't see any reason for this, at
least not from our perspective. I have my suspicions that it'll be
something like matching up the cursor with the mouse coordinates...
* I bumped up the DirectInput API used to version 7 in order to get
access to mouse buttons 4-7. I've had to inject a little bit of the DX7
headers into SDL there as the MinGW ones aren't up to date in this respect.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Thu, 02 Apr 2009 04:43:36 +0000 |
parents | a1b03ba2fcd0 |
children |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
4159 | 3 Copyright (C) 1997-2009 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1251
diff
changeset
|
6 modify it under the terms of the GNU Lesser General Public |
0 | 7 License as published by the Free Software Foundation; either |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1251
diff
changeset
|
8 version 2.1 of the License, or (at your option) any later version. |
0 | 9 |
10 This library is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1251
diff
changeset
|
13 Lesser General Public License for more details. |
0 | 14 |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1251
diff
changeset
|
15 You should have received a copy of the GNU Lesser General Public |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1251
diff
changeset
|
16 License along with this library; if not, write to the Free Software |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1251
diff
changeset
|
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
0 | 18 |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
13
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
1402
d910939febfa
Use consistent identifiers for the various platforms we support.
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
22 #include "SDL_config.h" |
0 | 23 |
1433
bb6839704ed6
SDL_windows.h is no longer necessary
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
24 #define WIN32_LEAN_AND_MEAN |
bb6839704ed6
SDL_windows.h is no longer necessary
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
25 #include <windows.h> |
0 | 26 |
27 #include "SDL_mouse.h" | |
1361
19418e4422cb
New configure-based build system. Still work in progress, but much improved
Sam Lantinga <slouken@libsdl.org>
parents:
1358
diff
changeset
|
28 #include "../../events/SDL_events_c.h" |
19418e4422cb
New configure-based build system. Still work in progress, but much improved
Sam Lantinga <slouken@libsdl.org>
parents:
1358
diff
changeset
|
29 #include "../SDL_cursor_c.h" |
0 | 30 #include "SDL_sysmouse_c.h" |
31 #include "SDL_lowvideo.h" | |
32 | |
33 #ifdef _WIN32_WCE | |
34 #define USE_STATIC_CURSOR | |
35 #endif | |
36 | |
37 HCURSOR SDL_hcursor = NULL; /* Exported for SDL_eventloop.c */ | |
38 | |
39 /* The implementation dependent data for the window manager cursor */ | |
40 /* For some reason when creating a windows cursor, the ands and xors memory | |
41 is not copied, so we need to keep track of it and free it when we are done | |
42 with the cursor. If we free the memory prematurely, the app crashes. :-} | |
43 */ | |
44 struct WMcursor { | |
45 HCURSOR curs; | |
46 #ifndef USE_STATIC_CURSOR | |
47 Uint8 *ands; | |
48 Uint8 *xors; | |
49 #endif | |
50 }; | |
51 | |
52 /* Convert bits to padded bytes */ | |
53 #define PAD_BITS(bits) ((bits+7)/8) | |
54 | |
55 #ifdef CURSOR_DEBUG | |
56 static void PrintBITMAP(FILE *out, char *bits, int w, int h) | |
57 { | |
58 int i; | |
59 unsigned char ch; | |
60 | |
61 while ( h-- > 0 ) { | |
62 for ( i=0; i<w; ++i ) { | |
63 if ( (i%8) == 0 ) | |
64 ch = *bits++; | |
65 if ( ch&0x80 ) | |
66 fprintf(out, "X"); | |
67 else | |
68 fprintf(out, " "); | |
69 ch <<= 1; | |
70 } | |
71 fprintf(out, "\n"); | |
72 } | |
73 } | |
74 #endif | |
75 | |
76 #ifndef USE_STATIC_CURSOR | |
77 /* Local functions to convert the SDL cursor mask into Windows format */ | |
78 static void memnot(Uint8 *dst, Uint8 *src, int len) | |
79 { | |
80 while ( len-- > 0 ) | |
81 *dst++ = ~*src++; | |
82 } | |
83 static void memxor(Uint8 *dst, Uint8 *src1, Uint8 *src2, int len) | |
84 { | |
85 while ( len-- > 0 ) | |
86 *dst++ = (*src1++)^(*src2++); | |
87 } | |
88 #endif /* !USE_STATIC_CURSOR */ | |
89 | |
90 void WIN_FreeWMCursor(_THIS, WMcursor *cursor) | |
91 { | |
92 #ifndef USE_STATIC_CURSOR | |
506
f097dba83975
Fixed cursor resource leak in Windows (thanks Huib-Jan Imbens!)
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
93 if ( cursor->curs == GetCursor() ) |
f097dba83975
Fixed cursor resource leak in Windows (thanks Huib-Jan Imbens!)
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
94 SetCursor(NULL); |
0 | 95 if ( cursor->curs != NULL ) |
96 DestroyCursor(cursor->curs); | |
97 if ( cursor->ands != NULL ) | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
98 SDL_free(cursor->ands); |
0 | 99 if ( cursor->xors != NULL ) |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
100 SDL_free(cursor->xors); |
0 | 101 #endif /* !USE_STATIC_CURSOR */ |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
102 SDL_free(cursor); |
0 | 103 } |
104 | |
105 WMcursor *WIN_CreateWMCursor(_THIS, | |
106 Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) | |
107 { | |
108 #ifdef USE_STATIC_CURSOR | |
109 WMcursor *cursor; | |
110 | |
111 /* Allocate the cursor */ | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
112 cursor = (WMcursor *)SDL_malloc(sizeof(*cursor)); |
0 | 113 if ( cursor ) { |
114 cursor->curs = LoadCursor(NULL, IDC_ARROW); | |
115 } | |
116 return(cursor); | |
117 #else | |
118 WMcursor *cursor; | |
119 int allowed_x; | |
120 int allowed_y; | |
121 int run, pad, i; | |
122 Uint8 *aptr, *xptr; | |
123 | |
124 /* Check to make sure the cursor size is okay */ | |
125 allowed_x = GetSystemMetrics(SM_CXCURSOR); | |
126 allowed_y = GetSystemMetrics(SM_CYCURSOR); | |
127 if ( (w > allowed_x) || (h > allowed_y) ) { | |
128 SDL_SetError("Only cursors of dimension (%dx%d) are allowed", | |
129 allowed_x, allowed_y); | |
130 return(NULL); | |
131 } | |
132 | |
133 /* Allocate the cursor */ | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
134 cursor = (WMcursor *)SDL_malloc(sizeof(*cursor)); |
0 | 135 if ( cursor == NULL ) { |
136 SDL_SetError("Out of memory"); | |
137 return(NULL); | |
138 } | |
139 cursor->curs = NULL; | |
140 cursor->ands = NULL; | |
141 cursor->xors = NULL; | |
142 | |
143 /* Pad out to the normal cursor size */ | |
144 run = PAD_BITS(w); | |
145 pad = PAD_BITS(allowed_x)-run; | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
146 aptr = cursor->ands = (Uint8 *)SDL_malloc((run+pad)*allowed_y); |
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
147 xptr = cursor->xors = (Uint8 *)SDL_malloc((run+pad)*allowed_y); |
0 | 148 if ( (aptr == NULL) || (xptr == NULL) ) { |
149 WIN_FreeWMCursor(NULL, cursor); | |
150 SDL_OutOfMemory(); | |
151 return(NULL); | |
152 } | |
153 for ( i=0; i<h; ++i ) { | |
154 memxor(xptr, data, mask, run); | |
155 xptr += run; | |
156 data += run; | |
157 memnot(aptr, mask, run); | |
158 mask += run; | |
159 aptr += run; | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
160 SDL_memset(xptr, 0, pad); |
0 | 161 xptr += pad; |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
162 SDL_memset(aptr, ~0, pad); |
0 | 163 aptr += pad; |
164 } | |
165 pad += run; | |
166 for ( ; i<allowed_y; ++i ) { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
167 SDL_memset(xptr, 0, pad); |
0 | 168 xptr += pad; |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
169 SDL_memset(aptr, ~0, pad); |
0 | 170 aptr += pad; |
171 } | |
172 | |
173 /* Create the cursor */ | |
174 cursor->curs = CreateCursor( | |
1472
4aac8563c296
Fixed more Win64 portability issues
Sam Lantinga <slouken@libsdl.org>
parents:
1456
diff
changeset
|
175 (HINSTANCE)GetWindowLongPtr(SDL_Window, GWLP_HINSTANCE), |
0 | 176 hot_x, hot_y, allowed_x, allowed_y, |
177 cursor->ands, cursor->xors); | |
178 if ( cursor->curs == NULL ) { | |
179 WIN_FreeWMCursor(NULL, cursor); | |
180 SDL_SetError("Windows couldn't create the requested cursor"); | |
181 return(NULL); | |
182 } | |
183 return(cursor); | |
184 #endif /* USE_STATIC_CURSOR */ | |
185 } | |
186 | |
187 int WIN_ShowWMCursor(_THIS, WMcursor *cursor) | |
188 { | |
189 POINT mouse_pos; | |
190 | |
4167 | 191 if ( !this->screen ) { |
0 | 192 return(0); |
193 } | |
194 | |
195 /* Set the window cursor to our cursor, if applicable */ | |
196 if ( cursor != NULL ) { | |
197 SDL_hcursor = cursor->curs; | |
198 } else { | |
199 SDL_hcursor = NULL; | |
200 } | |
201 GetCursorPos(&mouse_pos); | |
202 if ( PtInRect(&SDL_bounds, mouse_pos) ) { | |
203 SetCursor(SDL_hcursor); | |
204 } | |
205 return(1); | |
206 } | |
207 | |
208 void WIN_WarpWMCursor(_THIS, Uint16 x, Uint16 y) | |
209 { | |
4167 | 210 if ( mouse_relative) { |
0 | 211 /* RJR: March 28, 2000 |
212 leave physical cursor at center of screen if | |
213 mouse hidden and grabbed */ | |
214 SDL_PrivateMouseMotion(0, 0, x, y); | |
215 } else { | |
527
5c74ac147358
Fixed mouse warp position bug with offset video modes
Sam Lantinga <slouken@libsdl.org>
parents:
506
diff
changeset
|
216 POINT pt; |
4167 | 217 |
218 /* With DirectInput the position doesn't follow | |
219 * the cursor, so it is set manually */ | |
220 if ( DINPUT() ) { | |
221 SDL_PrivateMouseMotion(0, 0, x, y); | |
222 } | |
223 | |
0 | 224 pt.x = x; |
225 pt.y = y; | |
226 ClientToScreen(SDL_Window, &pt); | |
227 SetCursorPos(pt.x, pt.y); | |
228 } | |
229 } | |
230 | |
231 /* Update the current mouse state and position */ | |
232 void WIN_UpdateMouse(_THIS) | |
233 { | |
234 POINT pt; | |
235 | |
4167 | 236 /* Always unset SDL_APPMOUSEFOCUS to give the WM_MOUSEMOVE event |
237 * handler a chance to install a TRACKMOUSEEVENT */ | |
238 SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); | |
239 | |
240 GetCursorPos(&pt); | |
241 ScreenToClient(SDL_Window, &pt); | |
242 SDL_PrivateMouseMotion(0,0, (Sint16)pt.x, (Sint16)pt.y); | |
0 | 243 } |
244 | |
245 /* Check to see if we need to enter or leave mouse relative mode */ | |
246 void WIN_CheckMouseMode(_THIS) | |
247 { | |
1251
86d0d01290ea
Updated Windows CE/PocketPC support...adds GAPI driver, landscape mode,
Ryan C. Gordon <icculus@icculus.org>
parents:
527
diff
changeset
|
248 #ifndef _WIN32_WCE |
0 | 249 /* If the mouse is hidden and input is grabbed, we use relative mode */ |
250 if ( !(SDL_cursorstate & CURSOR_VISIBLE) && | |
251 (this->input_grab != SDL_GRAB_OFF) ) { | |
252 mouse_relative = 1; | |
253 } else { | |
254 mouse_relative = 0; | |
255 } | |
1251
86d0d01290ea
Updated Windows CE/PocketPC support...adds GAPI driver, landscape mode,
Ryan C. Gordon <icculus@icculus.org>
parents:
527
diff
changeset
|
256 #else |
86d0d01290ea
Updated Windows CE/PocketPC support...adds GAPI driver, landscape mode,
Ryan C. Gordon <icculus@icculus.org>
parents:
527
diff
changeset
|
257 mouse_relative = 0; |
86d0d01290ea
Updated Windows CE/PocketPC support...adds GAPI driver, landscape mode,
Ryan C. Gordon <icculus@icculus.org>
parents:
527
diff
changeset
|
258 #endif |
0 | 259 } |