Mercurial > sdl-ios-xcode
annotate src/video/x11/SDL_x11mouse.c @ 1050:8e1815fd9777
Holding down shift while moving the mouse's scrollwheel on MacOS X makes the
OS report these are "horizontal scrollwheel" events, which confuses gaming
apps in several legitimate conditions. Now all scrollwheel events are made
to look vertical when passed to the app.
Patch by John Knottenbelt.
http://www.libsdl.org/pipermail/sdl/2005-March/067978.html
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Sun, 17 Apr 2005 10:32:41 +0000 |
parents | 07def9d03315 |
children | 045f186426e1 |
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(); | |
53 XFreeCursor(SDL_Display, cursor->x_cursor); | |
54 XSync(SDL_Display, False); | |
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 */ | |
108 data_image = XCreateImage(SDL_Display, | |
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; | |
113 data_pixmap = XCreatePixmap(SDL_Display, SDL_Root, w, h, 1); | |
114 | |
115 /* Create the data mask */ | |
116 mask_image = XCreateImage(SDL_Display, | |
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; | |
121 mask_pixmap = XCreatePixmap(SDL_Display, SDL_Root, w, h, 1); | |
122 | |
123 /* Create the graphics context */ | |
124 GCvalues.function = GXcopy; | |
125 GCvalues.foreground = ~0; | |
126 GCvalues.background = 0; | |
127 GCvalues.plane_mask = AllPlanes; | |
128 GCcursor = XCreateGC(SDL_Display, data_pixmap, | |
129 (GCFunction|GCForeground|GCBackground|GCPlaneMask), | |
130 &GCvalues); | |
131 | |
132 /* Blit the images to the pixmaps */ | |
133 XPutImage(SDL_Display, data_pixmap, GCcursor, data_image, | |
134 0, 0, 0, 0, w, h); | |
135 XPutImage(SDL_Display, mask_pixmap, GCcursor, mask_image, | |
136 0, 0, 0, 0, w, h); | |
137 XFreeGC(SDL_Display, GCcursor); | |
138 /* These free the x_data and x_mask memory pointers */ | |
139 XDestroyImage(data_image); | |
140 XDestroyImage(mask_image); | |
141 | |
142 /* Create the cursor */ | |
143 cursor->x_cursor = XCreatePixmapCursor(SDL_Display, data_pixmap, | |
144 mask_pixmap, &black, &white, hot_x, hot_y); | |
888
07def9d03315
Date: Sun, 28 Mar 2004 16:38:32 +1200
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
145 XFreePixmap(SDL_Display, data_pixmap); |
07def9d03315
Date: Sun, 28 Mar 2004 16:38:32 +1200
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
146 XFreePixmap(SDL_Display, mask_pixmap); |
0 | 147 |
148 /* Release the event thread */ | |
149 XSync(SDL_Display, False); | |
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 ) { | |
167 XDefineCursor(SDL_Display, SDL_Window, | |
168 SDL_BlankCursor->x_cursor); | |
169 } | |
170 } else { | |
171 XDefineCursor(SDL_Display, SDL_Window, cursor->x_cursor); | |
172 } | |
173 XSync(SDL_Display, False); | |
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(); | |
190 XWarpPointer(SDL_Display, None, SDL_Window, 0, 0, 0, 0, x, y); | |
191 XSync(SDL_Display, False); | |
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 ) { | |
227 XChangePointerControl(SDL_Display, True, True, | |
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 */ | |
260 XGetPointerControl(SDL_Display, | |
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 { | |
276 XChangePointerControl(SDL_Display, True, True, | |
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 } |