Mercurial > sdl-ios-xcode
annotate src/video/x11/SDL_x11mouse.c @ 828:85ba077211bc
Lots of people have contributed cash. :)
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 15 Feb 2004 22:04:46 +0000 |
parents | b8d311d90021 |
children | 07def9d03315 |
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); | |
145 | |
146 /* Release the event thread */ | |
147 XSync(SDL_Display, False); | |
148 SDL_Unlock_EventThread(); | |
149 | |
150 return(cursor); | |
151 } | |
152 | |
153 int X11_ShowWMCursor(_THIS, WMcursor *cursor) | |
154 { | |
155 /* Don't do anything if the display is gone */ | |
156 if ( SDL_Display == NULL ) { | |
157 return(0); | |
158 } | |
159 | |
160 /* Set the X11 cursor cursor, or blank if cursor is NULL */ | |
161 if ( SDL_Window ) { | |
162 SDL_Lock_EventThread(); | |
163 if ( cursor == NULL ) { | |
164 if ( SDL_BlankCursor != NULL ) { | |
165 XDefineCursor(SDL_Display, SDL_Window, | |
166 SDL_BlankCursor->x_cursor); | |
167 } | |
168 } else { | |
169 XDefineCursor(SDL_Display, SDL_Window, cursor->x_cursor); | |
170 } | |
171 XSync(SDL_Display, False); | |
172 SDL_Unlock_EventThread(); | |
173 } | |
174 return(1); | |
175 } | |
176 | |
177 void X11_WarpWMCursor(_THIS, Uint16 x, Uint16 y) | |
178 { | |
179 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
|
180 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
|
181 } else if ( mouse_relative) { |
5c74ac147358
Fixed mouse warp position bug with offset video modes
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
182 /* RJR: March 28, 2000 |
5c74ac147358
Fixed mouse warp position bug with offset video modes
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
183 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
|
184 mouse hidden and grabbed */ |
0 | 185 SDL_PrivateMouseMotion(0, 0, x, y); |
186 } else { | |
187 SDL_Lock_EventThread(); | |
188 XWarpPointer(SDL_Display, None, SDL_Window, 0, 0, 0, 0, x, y); | |
189 XSync(SDL_Display, False); | |
190 SDL_Unlock_EventThread(); | |
191 } | |
192 } | |
193 | |
194 /* Sets the mouse acceleration from a string of the form: | |
195 2/1/0 | |
196 The first number is the numerator, followed by the acceleration | |
197 denumenator and threshold. | |
198 */ | |
199 static void SetMouseAccel(_THIS, const char *accel_param) | |
200 { | |
201 int i; | |
202 int accel_value[3]; | |
203 char *mouse_param, *mouse_param_buf, *pin; | |
204 | |
205 mouse_param_buf = (char *)malloc(strlen(accel_param)+1); | |
206 if ( ! mouse_param_buf ) { | |
207 return; | |
208 } | |
209 strcpy(mouse_param_buf, accel_param); | |
210 mouse_param = mouse_param_buf; | |
211 | |
212 for ( i=0; (i < 3) && mouse_param; ++i ) { | |
213 pin = strchr(mouse_param, '/'); | |
214 if ( pin ) { | |
215 *pin = '\0'; | |
216 } | |
217 accel_value[i] = atoi(mouse_param); | |
218 if ( pin ) { | |
219 mouse_param = pin+1; | |
220 } else { | |
221 mouse_param = NULL; | |
222 } | |
223 } | |
224 if ( mouse_param_buf ) { | |
225 XChangePointerControl(SDL_Display, True, True, | |
226 accel_value[0], accel_value[1], accel_value[2]); | |
227 free(mouse_param_buf); | |
228 } | |
229 } | |
230 | |
231 /* Check to see if we need to enter or leave mouse relative mode */ | |
232 void X11_CheckMouseModeNoLock(_THIS) | |
233 { | |
79
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
234 char *env_override; |
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
235 int enable_relative = 1; |
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
236 |
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
237 /* 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
|
238 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
|
239 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
|
240 */ |
80
8806bc1eb80e
Oops, reversed the logic of the variable
Sam Lantinga <slouken@lokigames.com>
parents:
79
diff
changeset
|
241 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
|
242 if ( env_override ) { |
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
243 enable_relative = atoi(env_override); |
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
244 } |
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
245 |
0 | 246 /* 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
|
247 if ( enable_relative && |
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
248 !(SDL_cursorstate & CURSOR_VISIBLE) && |
0 | 249 (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
|
250 (SDL_GetAppState() & SDL_APPACTIVE) ) { |
0 | 251 if ( ! mouse_relative ) { |
252 X11_EnableDGAMouse(this); | |
253 if ( ! (using_dga & DGA_MOUSE) ) { | |
254 char *xmouse_accel; | |
255 | |
256 SDL_GetMouseState(&mouse_last.x, &mouse_last.y); | |
257 /* Use as raw mouse mickeys as possible */ | |
258 XGetPointerControl(SDL_Display, | |
259 &mouse_accel.numerator, | |
260 &mouse_accel.denominator, | |
261 &mouse_accel.threshold); | |
262 xmouse_accel=getenv("SDL_VIDEO_X11_MOUSEACCEL"); | |
263 if ( xmouse_accel ) { | |
264 SetMouseAccel(this, xmouse_accel); | |
265 } | |
266 } | |
267 mouse_relative = 1; | |
268 } | |
269 } else { | |
270 if ( mouse_relative ) { | |
271 if ( using_dga & DGA_MOUSE ) { | |
272 X11_DisableDGAMouse(this); | |
273 } else { | |
274 XChangePointerControl(SDL_Display, True, True, | |
275 mouse_accel.numerator, | |
276 mouse_accel.denominator, | |
277 mouse_accel.threshold); | |
278 } | |
279 mouse_relative = 0; | |
280 } | |
281 } | |
282 } | |
283 void X11_CheckMouseMode(_THIS) | |
284 { | |
285 SDL_Lock_EventThread(); | |
286 X11_CheckMouseModeNoLock(this); | |
287 SDL_Unlock_EventThread(); | |
288 } |