Mercurial > sdl-ios-xcode
annotate src/video/x11/SDL_x11mouse.c @ 82:2bddc38a9f5d
When the mouse is grabbed, send the application the motion associated with
the enter/leave notify events.
author | Sam Lantinga <slouken@lokigames.com> |
---|---|
date | Tue, 26 Jun 2001 17:40:59 +0000 |
parents | 8806bc1eb80e |
children | e8157fcb3114 |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
3 Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga | |
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 | |
20 slouken@devolution.com | |
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 ) { | |
180 x += (this->screen->offset % this->screen->pitch) / | |
181 this->screen->format->BytesPerPixel; | |
182 y += (this->screen->offset / this->screen->pitch); | |
183 SDL_PrivateMouseMotion(0, 0, x, y); | |
184 } else { | |
185 SDL_Lock_EventThread(); | |
186 XWarpPointer(SDL_Display, None, SDL_Window, 0, 0, 0, 0, x, y); | |
187 XSync(SDL_Display, False); | |
188 SDL_Unlock_EventThread(); | |
189 } | |
190 } | |
191 | |
192 /* Sets the mouse acceleration from a string of the form: | |
193 2/1/0 | |
194 The first number is the numerator, followed by the acceleration | |
195 denumenator and threshold. | |
196 */ | |
197 static void SetMouseAccel(_THIS, const char *accel_param) | |
198 { | |
199 int i; | |
200 int accel_value[3]; | |
201 char *mouse_param, *mouse_param_buf, *pin; | |
202 | |
203 mouse_param_buf = (char *)malloc(strlen(accel_param)+1); | |
204 if ( ! mouse_param_buf ) { | |
205 return; | |
206 } | |
207 strcpy(mouse_param_buf, accel_param); | |
208 mouse_param = mouse_param_buf; | |
209 | |
210 for ( i=0; (i < 3) && mouse_param; ++i ) { | |
211 pin = strchr(mouse_param, '/'); | |
212 if ( pin ) { | |
213 *pin = '\0'; | |
214 } | |
215 accel_value[i] = atoi(mouse_param); | |
216 if ( pin ) { | |
217 mouse_param = pin+1; | |
218 } else { | |
219 mouse_param = NULL; | |
220 } | |
221 } | |
222 if ( mouse_param_buf ) { | |
223 XChangePointerControl(SDL_Display, True, True, | |
224 accel_value[0], accel_value[1], accel_value[2]); | |
225 free(mouse_param_buf); | |
226 } | |
227 } | |
228 | |
229 /* Check to see if we need to enter or leave mouse relative mode */ | |
230 void X11_CheckMouseModeNoLock(_THIS) | |
231 { | |
79
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
232 char *env_override; |
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
233 int enable_relative = 1; |
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
234 |
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
235 /* 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
|
236 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
|
237 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
|
238 */ |
80
8806bc1eb80e
Oops, reversed the logic of the variable
Sam Lantinga <slouken@lokigames.com>
parents:
79
diff
changeset
|
239 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
|
240 if ( env_override ) { |
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
241 enable_relative = atoi(env_override); |
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
242 } |
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
243 |
0 | 244 /* 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
|
245 if ( enable_relative && |
ffadd05de74d
Allow the user to override the relative mouse mode.
Sam Lantinga <slouken@lokigames.com>
parents:
78
diff
changeset
|
246 !(SDL_cursorstate & CURSOR_VISIBLE) && |
0 | 247 (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
|
248 (SDL_GetAppState() & SDL_APPACTIVE) ) { |
0 | 249 if ( ! mouse_relative ) { |
250 X11_EnableDGAMouse(this); | |
251 if ( ! (using_dga & DGA_MOUSE) ) { | |
252 char *xmouse_accel; | |
253 | |
254 SDL_GetMouseState(&mouse_last.x, &mouse_last.y); | |
255 /* Use as raw mouse mickeys as possible */ | |
256 XGetPointerControl(SDL_Display, | |
257 &mouse_accel.numerator, | |
258 &mouse_accel.denominator, | |
259 &mouse_accel.threshold); | |
260 xmouse_accel=getenv("SDL_VIDEO_X11_MOUSEACCEL"); | |
261 if ( xmouse_accel ) { | |
262 SetMouseAccel(this, xmouse_accel); | |
263 } | |
264 } | |
265 mouse_relative = 1; | |
266 } | |
267 } else { | |
268 if ( mouse_relative ) { | |
269 if ( using_dga & DGA_MOUSE ) { | |
270 X11_DisableDGAMouse(this); | |
271 } else { | |
272 XChangePointerControl(SDL_Display, True, True, | |
273 mouse_accel.numerator, | |
274 mouse_accel.denominator, | |
275 mouse_accel.threshold); | |
276 } | |
277 mouse_relative = 0; | |
278 } | |
279 } | |
280 } | |
281 void X11_CheckMouseMode(_THIS) | |
282 { | |
283 SDL_Lock_EventThread(); | |
284 X11_CheckMouseModeNoLock(this); | |
285 SDL_Unlock_EventThread(); | |
286 } |