Mercurial > sdl-ios-xcode
annotate src/video/x11/SDL_x11mouse.c @ 1158:ec446adf8cb2
POSIX clock_gettime() isn't available on Linux before 2.6, and the symbol may
just be flat out missing from glibc, so force use of previous gettimeofday()
behaviour for now.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Tue, 11 Oct 2005 20:05:54 +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 } |