Mercurial > sdl-ios-xcode
comparison src/video/x11/SDL_x11events.c @ 1951:7177581dc9fa
Initial work on X11 window code in.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Thu, 27 Jul 2006 06:53:23 +0000 |
parents | |
children | da8332c8f480 |
comparison
equal
deleted
inserted
replaced
1950:a344e42bce3b | 1951:7177581dc9fa |
---|---|
1 /* | |
2 SDL - Simple DirectMedia Layer | |
3 Copyright (C) 1997-2006 Sam Lantinga | |
4 | |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Lesser General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2.1 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 Lesser General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Lesser General Public | |
16 License along with this library; if not, write to the Free Software | |
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
18 | |
19 Sam Lantinga | |
20 slouken@libsdl.org | |
21 */ | |
22 #include "SDL_config.h" | |
23 | |
24 #include "SDL_syswm.h" | |
25 #include "SDL_x11video.h" | |
26 #include "../../events/SDL_events_c.h" | |
27 | |
28 | |
29 static void | |
30 X11_DispatchEvent(_THIS) | |
31 { | |
32 SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; | |
33 SDL_WindowData *data; | |
34 XEvent xevent; | |
35 int i; | |
36 | |
37 SDL_zero(xevent); /* valgrind fix. --ryan. */ | |
38 XNextEvent(videodata->display, &xevent); | |
39 | |
40 /* Send a SDL_SYSWMEVENT if the application wants them */ | |
41 if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) { | |
42 SDL_SysWMmsg wmmsg; | |
43 | |
44 SDL_VERSION(&wmmsg.version); | |
45 wmmsg.subsystem = SDL_SYSWM_X11; | |
46 wmmsg.event.xevent = xevent; | |
47 SDL_SendSysWMEvent(&wmmsg); | |
48 } | |
49 | |
50 data = NULL; | |
51 for (i = 0; i < videodata->numwindows; ++i) { | |
52 if (videodata->windowlist[i]->window == xevent.xany.window) { | |
53 data = videodata->windowlist[i]; | |
54 } | |
55 } | |
56 if (!data) { | |
57 return; | |
58 } | |
59 | |
60 switch (xevent.type) { | |
61 | |
62 /* Gaining mouse coverage? */ | |
63 case EnterNotify:{ | |
64 #ifdef DEBUG_XEVENTS | |
65 printf("EnterNotify! (%d,%d)\n", xevent.xcrossing.x, | |
66 xevent.xcrossing.y); | |
67 if (xevent.xcrossing.mode == NotifyGrab) | |
68 printf("Mode: NotifyGrab\n"); | |
69 if (xevent.xcrossing.mode == NotifyUngrab) | |
70 printf("Mode: NotifyUngrab\n"); | |
71 #endif | |
72 if ((xevent.xcrossing.mode != NotifyGrab) && | |
73 (xevent.xcrossing.mode != NotifyUngrab)) { | |
74 SDL_SetMouseFocus(videodata->mouse, data->windowID); | |
75 SDL_SendMouseMotion(videodata->mouse, 0, xevent.xcrossing.x, | |
76 xevent.xcrossing.y); | |
77 } | |
78 } | |
79 break; | |
80 | |
81 /* Losing mouse coverage? */ | |
82 case LeaveNotify:{ | |
83 #ifdef DEBUG_XEVENTS | |
84 printf("LeaveNotify! (%d,%d)\n", xevent.xcrossing.x, | |
85 xevent.xcrossing.y); | |
86 if (xevent.xcrossing.mode == NotifyGrab) | |
87 printf("Mode: NotifyGrab\n"); | |
88 if (xevent.xcrossing.mode == NotifyUngrab) | |
89 printf("Mode: NotifyUngrab\n"); | |
90 #endif | |
91 if ((xevent.xcrossing.mode != NotifyGrab) && | |
92 (xevent.xcrossing.mode != NotifyUngrab) && | |
93 (xevent.xcrossing.detail != NotifyInferior)) { | |
94 SDL_SendMouseMotion(videodata->mouse, 0, | |
95 xevent.xcrossing.x, xevent.xcrossing.y); | |
96 SDL_SetMouseFocus(videodata->mouse, 0); | |
97 } | |
98 } | |
99 break; | |
100 | |
101 /* Gaining input focus? */ | |
102 case FocusIn:{ | |
103 #ifdef DEBUG_XEVENTS | |
104 printf("FocusIn!\n"); | |
105 #endif | |
106 SDL_SetKeyboardFocus(videodata->keyboard, data->windowID); | |
107 #ifdef X_HAVE_UTF8_STRING | |
108 if (data->ic) { | |
109 XSetICFocus(data->ic); | |
110 } | |
111 #endif | |
112 } | |
113 break; | |
114 | |
115 /* Losing input focus? */ | |
116 case FocusOut:{ | |
117 #ifdef DEBUG_XEVENTS | |
118 printf("FocusOut!\n"); | |
119 #endif | |
120 SDL_SetKeyboardFocus(videodata->keyboard, 0); | |
121 #ifdef X_HAVE_UTF8_STRING | |
122 if (data->ic) { | |
123 XUnsetICFocus(data->ic); | |
124 } | |
125 #endif | |
126 } | |
127 break; | |
128 | |
129 /* Generated upon EnterWindow and FocusIn */ | |
130 case KeymapNotify:{ | |
131 #ifdef DEBUG_XEVENTS | |
132 printf("KeymapNotify!\n"); | |
133 #endif | |
134 /* FIXME: | |
135 X11_SetKeyboardState(SDL_Display, xevent.xkeymap.key_vector); | |
136 */ | |
137 } | |
138 break; | |
139 | |
140 /* Mouse motion? */ | |
141 case MotionNotify:{ | |
142 #ifdef DEBUG_MOTION | |
143 printf("X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y); | |
144 #endif | |
145 SDL_SendMouseMotion(videodata->mouse, 0, xevent.xmotion.x, | |
146 xevent.xmotion.y); | |
147 } | |
148 break; | |
149 | |
150 /* Mouse button press? */ | |
151 case ButtonPress:{ | |
152 SDL_SendMouseButton(videodata->mouse, SDL_PRESSED, | |
153 xevent.xbutton.button); | |
154 } | |
155 break; | |
156 | |
157 /* Mouse button release? */ | |
158 case ButtonRelease:{ | |
159 SDL_SendMouseButton(videodata->mouse, SDL_RELEASED, | |
160 xevent.xbutton.button); | |
161 } | |
162 break; | |
163 | |
164 /* Key press? */ | |
165 case KeyPress:{ | |
166 #if 0 /* FIXME */ | |
167 static SDL_keysym saved_keysym; | |
168 SDL_keysym keysym; | |
169 KeyCode keycode = xevent.xkey.keycode; | |
170 | |
171 #ifdef DEBUG_XEVENTS | |
172 printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode); | |
173 #endif | |
174 /* Get the translated SDL virtual keysym */ | |
175 if (keycode) { | |
176 keysym.scancode = keycode; | |
177 keysym.sym = X11_TranslateKeycode(SDL_Display, keycode); | |
178 keysym.mod = KMOD_NONE; | |
179 keysym.unicode = 0; | |
180 } else { | |
181 keysym = saved_keysym; | |
182 } | |
183 | |
184 /* If we're not doing translation, we're done! */ | |
185 if (!SDL_TranslateUNICODE) { | |
186 posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym); | |
187 break; | |
188 } | |
189 | |
190 if (XFilterEvent(&xevent, None)) { | |
191 if (xevent.xkey.keycode) { | |
192 posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym); | |
193 } else { | |
194 /* Save event to be associated with IM text | |
195 In 1.3 we'll have a text event instead.. */ | |
196 saved_keysym = keysym; | |
197 } | |
198 break; | |
199 } | |
200 | |
201 /* Look up the translated value for the key event */ | |
202 #ifdef X_HAVE_UTF8_STRING | |
203 if (data->ic != NULL) { | |
204 static Status state; | |
205 /* A UTF-8 character can be at most 6 bytes */ | |
206 char keybuf[6]; | |
207 if (Xutf8LookupString(data->ic, &xevent.xkey, | |
208 keybuf, sizeof(keybuf), NULL, &state)) { | |
209 keysym.unicode = Utf8ToUcs4((Uint8 *) keybuf); | |
210 } | |
211 } else | |
212 #endif | |
213 { | |
214 static XComposeStatus state; | |
215 char keybuf[32]; | |
216 | |
217 if (XLookupString(&xevent.xkey, | |
218 keybuf, sizeof(keybuf), NULL, &state)) { | |
219 /* | |
220 * FIXME: XLookupString() may yield more than one | |
221 * character, so we need a mechanism to allow for | |
222 * this (perhaps null keypress events with a | |
223 * unicode value) | |
224 */ | |
225 keysym.unicode = (Uint8) keybuf[0]; | |
226 } | |
227 } | |
228 posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym); | |
229 #endif // 0 | |
230 } | |
231 break; | |
232 | |
233 /* Key release? */ | |
234 case KeyRelease:{ | |
235 #if 0 /* FIXME */ | |
236 SDL_keysym keysym; | |
237 KeyCode keycode = xevent.xkey.keycode; | |
238 | |
239 #ifdef DEBUG_XEVENTS | |
240 printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode); | |
241 #endif | |
242 /* Check to see if this is a repeated key */ | |
243 if (X11_KeyRepeat(SDL_Display, &xevent)) { | |
244 break; | |
245 } | |
246 | |
247 /* Get the translated SDL virtual keysym */ | |
248 keysym.scancode = keycode; | |
249 keysym.sym = X11_TranslateKeycode(SDL_Display, keycode); | |
250 keysym.mod = KMOD_NONE; | |
251 keysym.unicode = 0; | |
252 | |
253 posted = SDL_PrivateKeyboard(SDL_RELEASED, &keysym); | |
254 #endif // 0 | |
255 } | |
256 break; | |
257 | |
258 /* Have we been iconified? */ | |
259 case UnmapNotify:{ | |
260 #ifdef DEBUG_XEVENTS | |
261 printf("UnmapNotify!\n"); | |
262 #endif | |
263 SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_HIDDEN, 0, 0); | |
264 SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_MINIMIZED, 0, | |
265 0); | |
266 } | |
267 break; | |
268 | |
269 /* Have we been restored? */ | |
270 case MapNotify:{ | |
271 #ifdef DEBUG_XEVENTS | |
272 printf("MapNotify!\n"); | |
273 #endif | |
274 SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_SHOWN, 0, 0); | |
275 SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_RESTORED, 0, | |
276 0); | |
277 } | |
278 break; | |
279 | |
280 /* Have we been resized or moved? */ | |
281 case ConfigureNotify:{ | |
282 #ifdef DEBUG_XEVENTS | |
283 printf("ConfigureNotify! (resize: %dx%d)\n", | |
284 xevent.xconfigure.width, xevent.xconfigure.height); | |
285 #endif | |
286 SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_MOVED, | |
287 xevent.xconfigure.x, xevent.xconfigure.y); | |
288 SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_RESIZED, | |
289 xevent.xconfigure.width, | |
290 xevent.xconfigure.height); | |
291 } | |
292 break; | |
293 | |
294 /* Have we been requested to quit (or another client message?) */ | |
295 case ClientMessage:{ | |
296 if ((xevent.xclient.format == 32) && | |
297 (xevent.xclient.data.l[0] == videodata->WM_DELETE_WINDOW)) { | |
298 | |
299 SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_CLOSE, 0, | |
300 0); | |
301 } | |
302 } | |
303 break; | |
304 | |
305 /* Do we need to refresh ourselves? */ | |
306 case Expose:{ | |
307 #ifdef DEBUG_XEVENTS | |
308 printf("Expose (count = %d)\n", xevent.xexpose.count); | |
309 #endif | |
310 SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_EXPOSED, 0, | |
311 0); | |
312 } | |
313 break; | |
314 | |
315 default:{ | |
316 #ifdef DEBUG_XEVENTS | |
317 printf("Unhandled event %d\n", xevent.type); | |
318 #endif | |
319 } | |
320 break; | |
321 } | |
322 } | |
323 | |
324 /* Ack! XPending() actually performs a blocking read if no events available */ | |
325 int | |
326 X11_Pending(Display * display) | |
327 { | |
328 /* Flush the display connection and look to see if events are queued */ | |
329 XFlush(display); | |
330 if (XEventsQueued(display, QueuedAlready)) { | |
331 return (1); | |
332 } | |
333 | |
334 /* More drastic measures are required -- see if X is ready to talk */ | |
335 { | |
336 static struct timeval zero_time; /* static == 0 */ | |
337 int x11_fd; | |
338 fd_set fdset; | |
339 | |
340 x11_fd = ConnectionNumber(display); | |
341 FD_ZERO(&fdset); | |
342 FD_SET(x11_fd, &fdset); | |
343 if (select(x11_fd + 1, &fdset, NULL, NULL, &zero_time) == 1) { | |
344 return (XPending(display)); | |
345 } | |
346 } | |
347 | |
348 /* Oh well, nothing is ready .. */ | |
349 return (0); | |
350 } | |
351 | |
352 void | |
353 X11_PumpEvents(_THIS) | |
354 { | |
355 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; | |
356 | |
357 /* Keep processing pending events */ | |
358 while (X11_Pending(data->display)) { | |
359 X11_DispatchEvent(_this); | |
360 } | |
361 } | |
362 | |
363 void | |
364 X11_SaveScreenSaver(Display * display, int *saved_timeout, BOOL * dpms) | |
365 { | |
366 int timeout, interval, prefer_blank, allow_exp; | |
367 XGetScreenSaver(display, &timeout, &interval, &prefer_blank, &allow_exp); | |
368 *saved_timeout = timeout; | |
369 | |
370 #if SDL_VIDEO_DRIVER_X11_DPMS | |
371 if (SDL_X11_HAVE_DPMS) { | |
372 int dummy; | |
373 if (DPMSQueryExtension(display, &dummy, &dummy)) { | |
374 CARD16 state; | |
375 DPMSInfo(display, &state, dpms); | |
376 } | |
377 } | |
378 #else | |
379 *dpms = 0; | |
380 #endif /* SDL_VIDEO_DRIVER_X11_DPMS */ | |
381 } | |
382 | |
383 void | |
384 X11_DisableScreenSaver(Display * display) | |
385 { | |
386 int timeout, interval, prefer_blank, allow_exp; | |
387 XGetScreenSaver(display, &timeout, &interval, &prefer_blank, &allow_exp); | |
388 timeout = 0; | |
389 XSetScreenSaver(display, timeout, interval, prefer_blank, allow_exp); | |
390 | |
391 #if SDL_VIDEO_DRIVER_X11_DPMS | |
392 if (SDL_X11_HAVE_DPMS) { | |
393 int dummy; | |
394 if (DPMSQueryExtension(display, &dummy, &dummy)) { | |
395 DPMSDisable(display); | |
396 } | |
397 } | |
398 #endif /* SDL_VIDEO_DRIVER_X11_DPMS */ | |
399 } | |
400 | |
401 void | |
402 X11_RestoreScreenSaver(Display * display, int saved_timeout, BOOL dpms) | |
403 { | |
404 int timeout, interval, prefer_blank, allow_exp; | |
405 XGetScreenSaver(display, &timeout, &interval, &prefer_blank, &allow_exp); | |
406 timeout = saved_timeout; | |
407 XSetScreenSaver(display, timeout, interval, prefer_blank, allow_exp); | |
408 | |
409 #if SDL_VIDEO_DRIVER_X11_DPMS | |
410 if (SDL_X11_HAVE_DPMS) { | |
411 int dummy; | |
412 if (DPMSQueryExtension(display, &dummy, &dummy)) { | |
413 if (dpms) { | |
414 DPMSEnable(display); | |
415 } | |
416 } | |
417 } | |
418 #endif /* SDL_VIDEO_DRIVER_X11_DPMS */ | |
419 } | |
420 | |
421 /* vi: set ts=4 sw=4 expandtab: */ |