Mercurial > sdl-ios-xcode
annotate src/video/x11/SDL_x11mouse.c @ 1192:54aa9aa32327
To: sdl@libsdl.org
From: Christian Walther <cwalther@gmx.ch>
Date: Fri, 18 Nov 2005 23:39:02 +0100
Subject: [SDL] Mouse position bugs on Mac OS X
The attached patch fixes a few bugs in SDL related to the mouse position
in windowed mode on Mac OS X, reproduced using the attached minimal test
program - at least here on 10.3.9, with SDL CVS from today. Could anyone
test whether the bugs exist and are fixed by the patch on 10.2 and 10.4?
1. When using OpenGL, the vertical mouse positions obtained through
events or SDL_GetMouseState() are off by one.
2. When using OpenGL, SDL_WarpMouse() inverts the y coordinate.
3. Clicks on the topmost pixel row of the window are not recognized.
1 and 2 do not occur in non-OpenGL mode, while 3 does. All three only
occur in windowed mode, not in fullscreen.
The cause for 1 and 3 is that in Cocoa, "the location of the mouse"
seems to be defined as "the location of the top left corner of the mouse
pointer's hot pixel" (this is not documented, it's just what I found out
here), which together with the fact that Cocoa's usual y coordinates
start at the bottom and increase upwards means that the y coordinate of
the mouse runs from 1 to h, not from 0 to h-1, in a window of height h.
If it does work on 10.2 and 10.4 (I'll try to test it as soon as I can,
but at the moment all I have at hand is 10.3.9), can this be applied to
the CVS?
-Christian
To: sdl@libsdl.org
From: Christian Walther <cwalther@gmx.ch>
Date: Mon, 28 Nov 2005 10:41:51 +0100
Subject: [SDL] Re: Mouse position bugs on Mac OS X
I wrote:
> I'll try to test it as soon as I can, but at the moment all I have at hand is 10.3.9
So, here are the results of my tests (with patched and unpatched
frameworks compiled with Xcode 1.5 (gcc 3.3) on 10.3.9):
On 10.1.5, my test program doesn't run because of "Undefined symbols:
SDL undefined reference to _CGMainDisplayID expected to be defined in
Carbon". I guess not supporting 10.1 was a deliberate decision then and
that's OK with me.
On 10.2.8, 10.3.9, and 10.4.0, the bugs exist as described in my
original post and are fixed by my patch. That is, there is no difference
between pre/post 10.3 and the patched version works correctly in all
combinations of GL/non-GL and windowed/fullscreen.
I therefore recommend the patch for inclusion.
-Christian
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Mon, 28 Nov 2005 13:58:26 +0000 |
parents | 045f186426e1 |
children | c9b51268668f |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
769
b8d311d90021
Updated copyright information for 2004 (Happy New Year!)
Sam Lantinga <slouken@libsdl.org>
parents:
527
diff
changeset
|
3 Copyright (C) 1997-2004 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 of the License, or (at your option) any later version. | |
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 | |
13 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
80
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 #include <stdlib.h> | |
29 #include <stdio.h> | |
30 #include <string.h> | |
31 | |
32 #include <X11/Xlib.h> | |
33 #include <X11/Xutil.h> | |
34 | |
35 #include "SDL_error.h" | |
36 #include "SDL_mouse.h" | |
37 #include "SDL_events_c.h" | |
38 #include "SDL_cursor_c.h" | |
39 #include "SDL_x11dga_c.h" | |
40 #include "SDL_x11mouse_c.h" | |
41 | |
42 | |
43 /* The implementation dependent data for the window manager cursor */ | |
44 struct WMcursor { | |
45 Cursor x_cursor; | |
46 }; | |
47 | |
48 | |
49 void X11_FreeWMCursor(_THIS, WMcursor *cursor) | |
50 { | |
51 if ( SDL_Display != NULL ) { | |
52 SDL_Lock_EventThread(); | |
1168
045f186426e1
Dynamically load X11 libraries like we currently do for alsa, esd, etc.
Ryan C. Gordon <icculus@icculus.org>
parents:
888
diff
changeset
|
53 pXFreeCursor(SDL_Display, cursor->x_cursor); |
045f186426e1
Dynamically load X11 libraries like we currently do for alsa, esd, etc.
Ryan C. Gordon <icculus@icculus.org>
parents:
888
diff
changeset
|
54 pXSync(SDL_Display, False); |
0 | 55 SDL_Unlock_EventThread(); |
56 } | |
57 free(cursor); | |
58 } | |
59 | |
60 WMcursor *X11_CreateWMCursor(_THIS, | |
61 Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) | |
62 { | |
63 WMcursor *cursor; | |
64 XGCValues GCvalues; | |
65 GC GCcursor; | |
66 XImage *data_image, *mask_image; | |
67 Pixmap data_pixmap, mask_pixmap; | |
68 int clen, i; | |
69 char *x_data, *x_mask; | |
70 static XColor black = { 0, 0, 0, 0 }; | |
71 static XColor white = { 0xffff, 0xffff, 0xffff, 0xffff }; | |
72 | |
73 /* Allocate the cursor memory */ | |
74 cursor = (WMcursor *)malloc(sizeof(WMcursor)); | |
75 if ( cursor == NULL ) { | |
76 SDL_OutOfMemory(); | |
77 return(NULL); | |
78 } | |
79 | |
80 /* Mix the mask and the data */ | |
81 clen = (w/8)*h; | |
82 x_data = (char *)malloc(clen); | |
83 if ( x_data == NULL ) { | |
84 free(cursor); | |
85 SDL_OutOfMemory(); | |
86 return(NULL); | |
87 } | |
88 x_mask = (char *)malloc(clen); | |
89 if ( x_mask == NULL ) { | |
90 free(cursor); | |
91 free(x_data); | |
92 SDL_OutOfMemory(); | |
93 return(NULL); | |
94 } | |
95 for ( i=0; i<clen; ++i ) { | |
96 /* The mask is OR'd with the data to turn inverted color | |
97 pixels black since inverted color cursors aren't supported | |
98 under X11. | |
99 */ | |
100 x_mask[i] = data[i] | mask[i]; | |
101 x_data[i] = data[i]; | |
102 } | |
103 | |
104 /* Prevent the event thread from running while we use the X server */ | |
105 SDL_Lock_EventThread(); | |
106 | |
107 /* Create the data image */ | |
1168
045f186426e1
Dynamically load X11 libraries like we currently do for alsa, esd, etc.
Ryan C. Gordon <icculus@icculus.org>
parents:
888
diff
changeset
|
108 data_image = pXCreateImage(SDL_Display, |
0 | 109 DefaultVisual(SDL_Display, SDL_Screen), |
110 1, XYBitmap, 0, x_data, w, h, 8, w/8); | |
111 data_image->byte_order = MSBFirst; | |
112 data_image->bitmap_bit_order = MSBFirst; | |
1168
045f186426e1
Dynamically load X11 libraries like we currently do for alsa, esd, etc.
Ryan C. Gordon <icculus@icculus.org>
parents:
888
diff
changeset
|
113 data_pixmap = pXCreatePixmap(SDL_Display, SDL_Root, w, h, 1); |
0 | 114 |
115 /* Create the data mask */ | |
1168
045f186426e1
Dynamically load X11 libraries like we currently do for alsa, esd, etc.
Ryan C. Gordon <icculus@icculus.org>
parents:
888
diff
changeset
|
116 mask_image = pXCreateImage(SDL_Display, |
0 | 117 DefaultVisual(SDL_Display, SDL_Screen), |
118 1, XYBitmap, 0, x_mask, w, h, 8, w/8); | |
119 mask_image->byte_order = MSBFirst; | |
120 mask_image->bitmap_bit_order = MSBFirst; | |
1168
045f186426e1
Dynamically load X11 libraries like we currently do for alsa, esd, etc.
Ryan C. Gordon <icculus@icculus.org>
parents:
888
diff
changeset
|
121 mask_pixmap = pXCreatePixmap(SDL_Display, SDL_Root, w, h, 1); |
0 | 122 |
123 /* Create the graphics context */ | |
124 GCvalues.function = GXcopy; | |
125 GCvalues.foreground = ~0; | |
126 GCvalues.background = 0; | |
127 GCvalues.plane_mask = AllPlanes; | |
1168
045f186426e1
Dynamically load X11 libraries like we currently do for alsa, esd, etc.
Ryan C. Gordon <icculus@icculus.org>
parents:
888
diff
changeset
|
128 GCcursor = pXCreateGC(SDL_Display, data_pixmap, |
0 | 129 (GCFunction|GCForeground|GCBackground|GCPlaneMask), |
130 &GCvalues); | |
131 | |
132 /* Blit the images to the pixmaps */ | |
1168
045f186426e1
Dynamically load X11 libraries like we currently do for alsa, esd, etc.
Ryan C. Gordon <icculus@icculus.org>
parents:
888
diff
changeset
|
133 pXPutImage(SDL_Display, data_pixmap, GCcursor, data_image, |
0 | 134 0, 0, 0, 0, w, h); |
1168
045f186426e1
Dynamically load X11 libraries like we currently do for alsa, esd, etc.
Ryan C. Gordon <icculus@icculus.org>
parents:
888
diff
changeset
|
135 pXPutImage(SDL_Display, mask_pixmap, GCcursor, mask_image, |
0 | 136 0, 0, 0, 0, w, h); |
1168
045f186426e1
Dynamically load X11 libraries like we currently do for alsa, esd, etc.
Ryan C. Gordon <icculus@icculus.org>
parents:
888
diff
changeset
|
137 pXFreeGC(SDL_Display, GCcursor); |
0 | 138 /* These free the x_data and x_mask memory pointers */ |
1168
045f186426e1
Dynamically load X11 libraries like we currently do for alsa, esd, etc.
Ryan C. Gordon <icculus@icculus.org>
parents:
888
diff
changeset
|
139 pXDestroyImage(data_image); |
045f186426e1
Dynamically load X11 libraries like we currently do for alsa, esd, etc.
Ryan C. Gordon <icculus@icculus.org>
parents:
888
diff
changeset
|
140 pXDestroyImage(mask_image); |
0 | 141 |
142 /* Create the cursor */ | |
1168
045f186426e1
Dynamically load X11 libraries like we currently do for alsa, esd, etc.
Ryan C. Gordon <icculus@icculus.org>
parents:
888
diff
changeset
|
143 cursor->x_cursor = pXCreatePixmapCursor(SDL_Display, data_pixmap, |
0 | 144 mask_pixmap, &black, &white, hot_x, hot_y); |
1168
045f186426e1
Dynamically load X11 libraries like we currently do for alsa, esd, etc.
Ryan C. Gordon <icculus@icculus.org>
parents:
888
diff
changeset
|
145 pXFreePixmap(SDL_Display, data_pixmap); |
045f186426e1
Dynamically load X11 libraries like we currently do for alsa, esd, etc.
Ryan C. Gordon <icculus@icculus.org>
parents:
888
diff
changeset
|
146 pXFreePixmap(SDL_Display, mask_pixmap); |
0 | 147 |
148 /* Release the event thread */ | |
1168
045f186426e1
Dynamically load X11 libraries like we currently do for alsa, esd, etc.
Ryan C. Gordon <icculus@icculus.org>
parents:
888
diff
changeset
|
149 pXSync(SDL_Display, False); |
0 | 150 SDL_Unlock_EventThread(); |
151 | |
152 return(cursor); | |
153 } | |
154 | |
155 int X11_ShowWMCursor(_THIS, WMcursor *cursor) | |
156 { | |
157 /* Don't do anything if the display is gone */ | |
158 if ( SDL_Display == NULL ) { | |
159 return(0); | |
160 } | |
161 | |
162 /* Set the X11 cursor cursor, or blank if cursor is NULL */ | |
163 if ( SDL_Window ) { | |
164 SDL_Lock_EventThread(); | |
165 if ( cursor == NULL ) { | |
166 if ( SDL_BlankCursor != NULL ) { | |
1168
045f186426e1
Dynamically load X11 libraries like we currently do for alsa, esd, etc.
Ryan C. Gordon <icculus@icculus.org>
parents:
888
diff
changeset
|
167 pXDefineCursor(SDL_Display, SDL_Window, |
0 | 168 SDL_BlankCursor->x_cursor); |
169 } | |
170 } else { | |
1168
045f186426e1
Dynamically load X11 libraries like we currently do for alsa, esd, etc.
Ryan C. Gordon <icculus@icculus.org>
parents:
888
diff
changeset
|
171 pXDefineCursor(SDL_Display, SDL_Window, cursor->x_cursor); |
0 | 172 } |
1168
045f186426e1
Dynamically load X11 libraries like we currently do for alsa, esd, etc.
Ryan C. Gordon <icculus@icculus.org>
parents:
888
diff
changeset
|
173 pXSync(SDL_Display, False); |
0 | 174 SDL_Unlock_EventThread(); |
175 } | |
176 return(1); | |
177 } | |
178 | |
179 void X11_WarpWMCursor(_THIS, Uint16 x, Uint16 y) | |
180 { | |
181 if ( using_dga & DGA_MOUSE ) { | |
527
5c74ac147358
Fixed mouse warp position bug with offset video modes
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
182 SDL_PrivateMouseMotion(0, 0, x, y); |
5c74ac147358
Fixed mouse warp position bug with offset video modes
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
183 } else if ( mouse_relative) { |
5c74ac147358
Fixed mouse warp position bug with offset video modes
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
184 /* RJR: March 28, 2000 |
5c74ac147358
Fixed mouse warp position bug with offset video modes
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
185 leave physical cursor at center of screen if |
5c74ac147358
Fixed mouse warp position bug with offset video modes
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
186 mouse hidden and grabbed */ |
0 | 187 SDL_PrivateMouseMotion(0, 0, x, y); |
188 } else { | |
189 SDL_Lock_EventThread(); | |
1168
045f186426e1
Dynamically load X11 libraries like we currently do for alsa, esd, etc.
Ryan C. Gordon <icculus@icculus.org>
parents:
888
diff
changeset
|
190 pXWarpPointer(SDL_Display, None, SDL_Window, 0, 0, 0, 0, x, y); |
045f186426e1
Dynamically load X11 libraries like we currently do for alsa, esd, etc.
Ryan C. Gordon <icculus@icculus.org>
parents:
888
diff
changeset
|
191 pXSync(SDL_Display, False); |
0 | 192 SDL_Unlock_EventThread(); |
193 } | |
194 } | |
195 | |
196 /* Sets the mouse acceleration from a string of the form: | |
197 2/1/0 | |
198 The first number is the numerator, followed by the acceleration | |
199 denumenator and threshold. | |
200 */ | |
201 static void SetMouseAccel(_THIS, const char *accel_param) | |
202 { | |
203 int i; | |
204 int accel_value[3]; | |
205 char *mouse_param, *mouse_param_buf, *pin; | |
206 | |
207 mouse_param_buf = (char *)malloc(strlen(accel_param)+1); | |
208 if ( ! mouse_param_buf ) { | |
209 return; | |
210 } | |
211 strcpy(mouse_param_buf, accel_param); | |
212 mouse_param = mouse_param_buf; | |
213 | |
214 for ( i=0; (i < 3) && mouse_param; ++i ) { | |
215 pin = strchr(mouse_param, '/'); | |
216 if ( pin ) { | |
217 *pin = '\0'; | |
218 } | |
219 accel_value[i] = atoi(mouse_param); | |
220 if ( pin ) { | |
221 mouse_param = pin+1; | |
222 } else { | |
223 mouse_param = NULL; | |
224 } | |
225 } | |
226 if ( mouse_param_buf ) { | |
1168
045f186426e1
Dynamically load X11 libraries like we currently do for alsa, esd, etc.
Ryan C. Gordon <icculus@icculus.org>
parents:
888
diff
changeset
|
227 pXChangePointerControl(SDL_Display, True, True, |
0 | 228 accel_value[0], accel_value[1], accel_value[2]); |
229 free(mouse_param_buf); | |
230 } | |
231 } | |
232 | |
233 /* Check to see if we need to enter or leave mouse relative mode */ | |
234 void X11_CheckMouseModeNoLock(_THIS) | |
235 { | |
79
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
236 char *env_override; |
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
237 int enable_relative = 1; |
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
238 |
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
239 /* Allow the user to override the relative mouse mode. |
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
240 They almost never want to do this, as it seriously affects |
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
241 applications that rely on continuous relative mouse motion. |
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
242 */ |
80
8806bc1eb80e
Oops, reversed the logic of the variable
Sam Lantinga <slouken@lokigames.com>
parents:
79
diff
changeset
|
243 env_override = getenv("SDL_MOUSE_RELATIVE"); |
79
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
244 if ( env_override ) { |
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
245 enable_relative = atoi(env_override); |
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
246 } |
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
247 |
0 | 248 /* If the mouse is hidden and input is grabbed, we use relative mode */ |
79
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
249 if ( enable_relative && |
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
250 !(SDL_cursorstate & CURSOR_VISIBLE) && |
0 | 251 (this->input_grab != SDL_GRAB_OFF) && |
79
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
252 (SDL_GetAppState() & SDL_APPACTIVE) ) { |
0 | 253 if ( ! mouse_relative ) { |
254 X11_EnableDGAMouse(this); | |
255 if ( ! (using_dga & DGA_MOUSE) ) { | |
256 char *xmouse_accel; | |
257 | |
258 SDL_GetMouseState(&mouse_last.x, &mouse_last.y); | |
259 /* Use as raw mouse mickeys as possible */ | |
1168
045f186426e1
Dynamically load X11 libraries like we currently do for alsa, esd, etc.
Ryan C. Gordon <icculus@icculus.org>
parents:
888
diff
changeset
|
260 pXGetPointerControl(SDL_Display, |
0 | 261 &mouse_accel.numerator, |
262 &mouse_accel.denominator, | |
263 &mouse_accel.threshold); | |
264 xmouse_accel=getenv("SDL_VIDEO_X11_MOUSEACCEL"); | |
265 if ( xmouse_accel ) { | |
266 SetMouseAccel(this, xmouse_accel); | |
267 } | |
268 } | |
269 mouse_relative = 1; | |
270 } | |
271 } else { | |
272 if ( mouse_relative ) { | |
273 if ( using_dga & DGA_MOUSE ) { | |
274 X11_DisableDGAMouse(this); | |
275 } else { | |
1168
045f186426e1
Dynamically load X11 libraries like we currently do for alsa, esd, etc.
Ryan C. Gordon <icculus@icculus.org>
parents:
888
diff
changeset
|
276 pXChangePointerControl(SDL_Display, True, True, |
0 | 277 mouse_accel.numerator, |
278 mouse_accel.denominator, | |
279 mouse_accel.threshold); | |
280 } | |
281 mouse_relative = 0; | |
282 } | |
283 } | |
284 } | |
285 void X11_CheckMouseMode(_THIS) | |
286 { | |
287 SDL_Lock_EventThread(); | |
288 X11_CheckMouseModeNoLock(this); | |
289 SDL_Unlock_EventThread(); | |
290 } |