comparison src/video/photon/SDL_ph_events.c @ 0:74212992fb08

Initial revision
author Sam Lantinga <slouken@lokigames.com>
date Thu, 26 Apr 2001 16:45:43 +0000
parents
children 8cc4dbfab9ab
comparison
equal deleted inserted replaced
-1:000000000000 0:74212992fb08
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 /* Handle the event stream, converting photon events into SDL events */
29
30 #include <Ph.h>
31 #include <stdio.h>
32 #include <setjmp.h>
33 #include <photon/PkKeyDef.h>
34 #include <sys/time.h>
35
36 #include "SDL.h"
37 #include "SDL_syswm.h"
38 #include "SDL_sysevents.h"
39 #include "SDL_sysvideo.h"
40 #include "SDL_events_c.h"
41 #include "SDL_ph_video.h"
42 #include "SDL_ph_modes_c.h"
43 #include "SDL_ph_image_c.h"
44 #include "SDL_ph_events_c.h"
45
46
47 /* The translation tables from a photon keysym to a SDL keysym */
48 static SDLKey ODD_keymap[256];
49 static SDLKey MISC_keymap[0xFF + 1];
50 SDL_keysym *ph_TranslateKey(PhKeyEvent_t *key, SDL_keysym *keysym);
51
52 /* Check to see if this is a repeated key.
53 (idea shamelessly lifted from GII -- thanks guys! :)
54 */
55
56 static int ph_KeyRepeat(_THIS, PhKeyEvent_t* keyevent)
57 {
58 PhEvent_t* peekevent;
59 PhKeyEvent_t* keyEvent;
60 int repeated;
61
62 repeated = 0;
63 switch (PhEventPeek( peekevent, EVENT_SIZE ))
64 {
65 case Ph_EVENT_MSG: {
66 if(peekevent->type == Ph_EV_KEY)
67 {
68 keyEvent = PhGetData( peekevent );
69 if ( !(Pk_KF_Key_Down & keyEvent->key_flags) &&
70 (keyEvent->key_cap == keyevent->key_cap) &&
71 (peekevent->timestamp == event->timestamp)
72 ) {
73 repeated = 1;
74 //PhEventNext( peekevent, EVENT_SIZE );
75 }
76 }
77 }
78 break;
79
80 case -1: {
81 perror( "PhEventPeek failed" );
82 }
83 break;
84
85 default: /* no events pending */
86 }
87 return(repeated);
88 }
89
90 /* Note: The X server buffers and accumulates mouse motion events, so
91 the motion event generated by the warp may not appear exactly as we
92 expect it to. We work around this (and improve performance) by only
93 warping the pointer when it reaches the edge, and then wait for it.
94 */
95 /*
96 #define MOUSE_FUDGE_FACTOR 8
97
98 static inline int X11_WarpedMotion(_THIS, XEvent *xevent)
99 {
100 int w, h, i;
101 int deltax, deltay;
102 int posted;
103
104 w = SDL_VideoSurface->w;
105 h = SDL_VideoSurface->h;
106 deltax = xevent->xmotion.x - mouse_last.x;
107 deltay = xevent->xmotion.y - mouse_last.y;
108 #ifdef DEBUG_MOTION
109 printf("Warped mouse motion: %d,%d\n", deltax, deltay);
110 #endif
111 mouse_last.x = xevent->xmotion.x;
112 mouse_last.y = xevent->xmotion.y;
113 posted = SDL_PrivateMouseMotion(0, 1, deltax, deltay);
114
115 if ( (xevent->xmotion.x < MOUSE_FUDGE_FACTOR) ||
116 (xevent->xmotion.x > (w-MOUSE_FUDGE_FACTOR)) ||
117 (xevent->xmotion.y < MOUSE_FUDGE_FACTOR) ||
118 (xevent->xmotion.y > (h-MOUSE_FUDGE_FACTOR)) ) {
119 /* Get the events that have accumulated */
120 /* while ( XCheckTypedEvent(SDL_Display, MotionNotify, xevent) ) {
121 deltax = xevent->xmotion.x - mouse_last.x;
122 deltay = xevent->xmotion.y - mouse_last.y;
123 #ifdef DEBUG_MOTION
124 printf("Extra mouse motion: %d,%d\n", deltax, deltay);
125 #endif
126 mouse_last.x = xevent->xmotion.x;
127 mouse_last.y = xevent->xmotion.y;
128 posted += SDL_PrivateMouseMotion(0, 1, deltax, deltay);
129 }
130 mouse_last.x = w/2;
131 mouse_last.y = h/2;
132 XWarpPointer(SDL_Display, None, SDL_Window, 0, 0, 0, 0,
133 mouse_last.x, mouse_last.y);
134 for ( i=0; i<10; ++i ) {
135 XMaskEvent(SDL_Display, PointerMotionMask, xevent);
136 if ( (xevent->xmotion.x >
137 (mouse_last.x-MOUSE_FUDGE_FACTOR)) &&
138 (xevent->xmotion.x <
139 (mouse_last.x+MOUSE_FUDGE_FACTOR)) &&
140 (xevent->xmotion.y >
141 (mouse_last.y-MOUSE_FUDGE_FACTOR)) &&
142 (xevent->xmotion.y <
143 (mouse_last.y+MOUSE_FUDGE_FACTOR)) ) {
144 break;
145 }
146 #ifdef DEBUG_XEVENTS
147 printf("Lost mouse motion: %d,%d\n", xevent->xmotion.x, xevent->xmotion.y);
148 #endif
149 }
150 #ifdef DEBUG_XEVENTS
151 if ( i == 10 ) {
152 printf("Warning: didn't detect mouse warp motion\n");
153 }
154 #endif
155 }
156 return(posted);
157 }
158 */
159
160 static int ph_DispatchEvent(_THIS)
161 {
162 int posted;
163 PhRect_t* rect;
164 PhPointerEvent_t* pointerEvent;
165 PhKeyEvent_t* keyEvent;
166 PhWindowEvent_t* winEvent;
167 int i;
168 SDL_Rect sdlrects[50];
169
170 posted = 0;
171
172 switch (event->type) {
173 case Ph_EV_BOUNDARY:
174 {
175
176 if (event->subtype == Ph_EV_PTR_ENTER)
177 posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
178 else if (event->subtype ==Ph_EV_PTR_LEAVE)
179 posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
180 }
181 break;
182
183 case Ph_EV_PTR_MOTION_BUTTON:
184 case Ph_EV_PTR_MOTION_NOBUTTON:
185 {
186
187 if ( SDL_VideoSurface ) {
188 pointerEvent = PhGetData( event );
189 rect = PhGetRects( event );
190 posted = SDL_PrivateMouseMotion(0, 1,
191 pointerEvent->pos.x - rect[0].ul.x,
192 pointerEvent->pos.y - rect[0].ul.y);
193 }
194 }
195 break;
196
197 case Ph_EV_BUT_PRESS:
198 {
199
200 pointerEvent = PhGetData( event );
201 /* TODO: is 'buttons' the right mapping? */
202 posted = SDL_PrivateMouseButton(SDL_PRESSED,
203 pointerEvent->buttons, 0, 0);
204 }
205 break;
206
207 case Ph_EV_BUT_RELEASE:
208 {
209
210 pointerEvent = PhGetData( event );
211 posted = SDL_PrivateMouseButton(SDL_RELEASED,
212 pointerEvent->buttons, 0, 0);
213 }
214 break;
215
216 case Ph_EV_WM:
217 {
218
219
220 winEvent = PhGetData( event );
221
222 /* losing focus */
223 if ((winEvent->event_f==Ph_WM_FOCUS)&&
224 (winEvent->event_state==Ph_WM_EVSTATE_FOCUSLOST))
225 {
226 posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS);
227
228 /* Queue leaving fullscreen mode */
229 switch_waiting = 0x01;
230 switch_time = SDL_GetTicks() + 200;
231 }
232
233 /* gaining focus */
234 else if ((winEvent->event_f==Ph_WM_FOCUS)&&
235 (winEvent->event_state==Ph_WM_EVSTATE_FOCUS))
236 {
237 posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS);
238
239 /* Queue entry into fullscreen mode */
240 switch_waiting = 0x01 | SDL_FULLSCREEN;
241 switch_time = SDL_GetTicks() + 1500;
242 }
243
244 /* request to quit */
245 else if (winEvent->event_f==Ph_WM_CLOSE)
246 {
247 posted = SDL_PrivateQuit();
248 }
249 }
250 break;
251
252 /* window has been resized, moved or removed */
253 case Ph_EV_EXPOSE:
254 {
255
256 if (SDL_VideoSurface)
257 {
258
259
260 rect = PhGetRects( event );
261
262 //PgSetClipping(1, rect );
263 for(i=0;i<event->num_rects;i++)
264 {
265 sdlrects[i].x = rect[i].ul.x;
266 sdlrects[i].y = rect[i].ul.y;
267 sdlrects[i].w = rect[i].lr.x - rect[i].ul.x;
268 sdlrects[i].h = rect[i].lr.y - rect[i].ul.y;
269
270 }
271
272 this->UpdateRects(this, event->num_rects, sdlrects);
273
274 }
275 }
276 break;
277
278 case Ph_EV_KEY:
279 {
280
281 SDL_keysym keysym;
282
283 posted = 0;
284
285 keyEvent = PhGetData( event );
286
287 if (Pk_KF_Key_Down & keyEvent->key_flags)
288 {
289
290 posted = SDL_PrivateKeyboard(SDL_PRESSED,
291 ph_TranslateKey( keyEvent, &keysym));
292 }
293 else /* must be key release */
294 {
295 /* Ignore repeated key release events */
296 /*if (! Pk_KF_Key_Repeat & keyEvent->key_flags )*/
297
298 posted = SDL_PrivateKeyboard(SDL_RELEASED,
299 ph_TranslateKey( keyEvent, &keysym));
300 /*}*/
301 }
302 }
303 break;
304 }
305
306
307
308 return(posted);
309 }
310
311 /* perform a blocking read if no events available */
312 int ph_Pending(_THIS)
313 {
314
315 /* Flush the display connection and look to see if events are queued */
316
317 PgFlush();
318
319 while( 1 )
320 { //note this is a non-blocking call
321 switch( PhEventPeek( event, EVENT_SIZE ) )
322 {
323 case Ph_EVENT_MSG:
324
325 return 1;
326 break;
327 case -1:
328 perror( "PhEventNext failed" );
329 break;
330 default:
331
332 return 0;
333 }
334 }
335
336 /* Oh well, nothing is ready .. */
337 return(0);
338 }
339
340 /*
341 SAMPLE EVENT PUMP
342 =================
343 static void update( int block ){
344
345 int ch,fl;
346 PhKeyEvent_t *key;
347
348 for( ;; ){
349
350 if( block ){
351 do{
352 fl=PhEventNext( event,EVENT_SIZE );
353 }while( fl!=Ph_EVENT_MSG );
354 block=0;
355 }else{
356 do{
357 fl=PhEventPeek( event,EVENT_SIZE );
358 if( !fl ) return;
359 }while( fl!=Ph_EVENT_MSG );
360 }
361
362 switch( event->type ){
363 case Ph_EV_KEY:
364 key=PhGetData( event );
365 ch=key->key_cap; // & 127;
366 fl=key->key_flags;
367 if( ch<32 || ch>127 ) break;
368 if( fl & Pk_KF_Key_Down ){
369 if( !(fl & Pk_KF_Key_Repeat) ){
370 if( queput-queget<QUE_SIZE ) keyque[ queput++ & QUE_MASK ]=ch;
371 keyMatrix[ch]=1;
372 }
373 }else{
374 keyMatrix[ch]=0;
375 }
376 break;
377 default:
378 PtEventHandler( event );
379 }
380 }
381 }
382 */
383
384 void ph_PumpEvents(_THIS)
385 {
386 int pending;
387
388 /* Keep processing pending events */
389 pending = 0;
390 while ( ph_Pending(this) ) {
391 ph_DispatchEvent(this);
392 ++pending;
393 }
394 if ( switch_waiting ) {
395 Uint32 now;
396
397 now = SDL_GetTicks();
398 if ( pending || !SDL_VideoSurface ) {
399 /* Try again later... */
400 if ( switch_waiting & SDL_FULLSCREEN ) {
401 switch_time = now + 1500;
402 } else {
403 switch_time = now + 200;
404 }
405 } else if ( now >= switch_time ) {
406 Uint32 go_fullscreen;
407
408 go_fullscreen = switch_waiting & SDL_FULLSCREEN;
409 switch_waiting = 0;
410 if ( SDL_VideoSurface->flags & SDL_FULLSCREEN ) {
411 if ( go_fullscreen ) {
412 ph_EnterFullScreen(this);
413 } else {
414 ph_LeaveFullScreen(this);
415 }
416 }
417 /* Handle focus in/out when grabbed */
418 /*
419 if ( go_fullscreen ) {
420 ph_GrabInputNoLock(this, this->input_grab);
421 } else {
422 ph_GrabInputNoLock(this, SDL_GRAB_OFF);
423 }
424 */
425 }
426 }
427 }
428
429 void ph_InitKeymap(void)
430 {
431 int i;
432
433 /* Odd keys used in international keyboards */
434 for ( i=0; i<SDL_TABLESIZE(ODD_keymap); ++i )
435 ODD_keymap[i] = SDLK_UNKNOWN;
436
437 /* Map the miscellaneous keys */
438 for ( i=0; i<SDL_TABLESIZE(MISC_keymap); ++i )
439 MISC_keymap[i] = SDLK_UNKNOWN;
440
441 MISC_keymap[Pk_BackSpace&0xFF] = SDLK_BACKSPACE;
442 MISC_keymap[Pk_Tab&0xFF] = SDLK_TAB;
443 MISC_keymap[Pk_Clear&0xFF] = SDLK_CLEAR;
444 MISC_keymap[Pk_Return&0xFF] = SDLK_RETURN;
445 MISC_keymap[Pk_Pause&0xFF] = SDLK_PAUSE;
446 MISC_keymap[Pk_Escape&0xFF] = SDLK_ESCAPE;
447 MISC_keymap[Pk_Delete&0xFF] = SDLK_DELETE;
448
449 MISC_keymap[Pk_KP_0&0xFF] = SDLK_KP0;
450 MISC_keymap[Pk_KP_1&0xFF] = SDLK_KP1;
451 MISC_keymap[Pk_KP_2&0xFF] = SDLK_KP2;
452 MISC_keymap[Pk_KP_3&0xFF] = SDLK_KP3;
453 MISC_keymap[Pk_KP_4&0xFF] = SDLK_KP4;
454 MISC_keymap[Pk_KP_5&0xFF] = SDLK_KP5;
455 MISC_keymap[Pk_KP_6&0xFF] = SDLK_KP6;
456 MISC_keymap[Pk_KP_7&0xFF] = SDLK_KP7;
457 MISC_keymap[Pk_KP_8&0xFF] = SDLK_KP8;
458 MISC_keymap[Pk_KP_9&0xFF] = SDLK_KP9;
459
460 MISC_keymap[Pk_KP_Decimal&0xFF] = SDLK_KP_PERIOD;
461 MISC_keymap[Pk_KP_Divide&0xFF] = SDLK_KP_DIVIDE;
462 MISC_keymap[Pk_KP_Multiply&0xFF] = SDLK_KP_MULTIPLY;
463 MISC_keymap[Pk_KP_Subtract&0xFF] = SDLK_KP_MINUS;
464 MISC_keymap[Pk_KP_Add&0xFF] = SDLK_KP_PLUS;
465 MISC_keymap[Pk_KP_Enter&0xFF] = SDLK_KP_ENTER;
466 MISC_keymap[Pk_KP_Equal&0xFF] = SDLK_KP_EQUALS;
467
468 MISC_keymap[Pk_Up&0xFF] = SDLK_UP;
469 MISC_keymap[Pk_Down&0xFF] = SDLK_DOWN;
470 MISC_keymap[Pk_Right&0xFF] = SDLK_RIGHT;
471 MISC_keymap[Pk_Left&0xFF] = SDLK_LEFT;
472 MISC_keymap[Pk_Insert&0xFF] = SDLK_INSERT;
473 MISC_keymap[Pk_Home&0xFF] = SDLK_HOME;
474 MISC_keymap[Pk_End&0xFF] = SDLK_END;
475 MISC_keymap[Pk_Pg_Up&0xFF] = SDLK_PAGEUP;
476 MISC_keymap[Pk_Pg_Down&0xFF] = SDLK_PAGEDOWN;
477
478 MISC_keymap[Pk_F1&0xFF] = SDLK_F1;
479 MISC_keymap[Pk_F2&0xFF] = SDLK_F2;
480 MISC_keymap[Pk_F3&0xFF] = SDLK_F3;
481 MISC_keymap[Pk_F4&0xFF] = SDLK_F4;
482 MISC_keymap[Pk_F5&0xFF] = SDLK_F5;
483 MISC_keymap[Pk_F6&0xFF] = SDLK_F6;
484 MISC_keymap[Pk_F7&0xFF] = SDLK_F7;
485 MISC_keymap[Pk_F8&0xFF] = SDLK_F8;
486 MISC_keymap[Pk_F9&0xFF] = SDLK_F9;
487 MISC_keymap[Pk_F10&0xFF] = SDLK_F10;
488 MISC_keymap[Pk_F11&0xFF] = SDLK_F11;
489 MISC_keymap[Pk_F12&0xFF] = SDLK_F12;
490 MISC_keymap[Pk_F13&0xFF] = SDLK_F13;
491 MISC_keymap[Pk_F14&0xFF] = SDLK_F14;
492 MISC_keymap[Pk_F15&0xFF] = SDLK_F15;
493
494 MISC_keymap[Pk_Num_Lock&0xFF] = SDLK_NUMLOCK;
495 MISC_keymap[Pk_Caps_Lock&0xFF] = SDLK_CAPSLOCK;
496 MISC_keymap[Pk_Scroll_Lock&0xFF] = SDLK_SCROLLOCK;
497 MISC_keymap[Pk_Shift_R&0xFF] = SDLK_RSHIFT;
498 MISC_keymap[Pk_Shift_L&0xFF] = SDLK_LSHIFT;
499 MISC_keymap[Pk_Control_R&0xFF] = SDLK_RCTRL;
500 MISC_keymap[Pk_Control_L&0xFF] = SDLK_LCTRL;
501 MISC_keymap[Pk_Alt_R&0xFF] = SDLK_RALT;
502 MISC_keymap[Pk_Alt_L&0xFF] = SDLK_LALT;
503 MISC_keymap[Pk_Meta_R&0xFF] = SDLK_RMETA;
504 MISC_keymap[Pk_Meta_L&0xFF] = SDLK_LMETA;
505 MISC_keymap[Pk_Super_L&0xFF] = SDLK_LSUPER; /* Left "Windows" */
506 MISC_keymap[Pk_Super_R&0xFF] = SDLK_RSUPER; /* Right "Windows */
507 MISC_keymap[Pk_Mode_switch&0xFF] = SDLK_MODE; /* "Alt Gr" key */
508
509 MISC_keymap[Pk_Help&0xFF] = SDLK_HELP;
510 MISC_keymap[Pk_Print&0xFF] = SDLK_PRINT;
511 // MISC_keymap[Pk_Sys_Req] = SDLK_SYSREQ;
512 MISC_keymap[Pk_Break&0xFF] = SDLK_BREAK;
513 MISC_keymap[Pk_Menu&0xFF] = SDLK_MENU;
514 MISC_keymap[Pk_Hyper_R&0xFF] = SDLK_MENU; /* Windows "Menu" key */
515 }
516
517 static unsigned long cap;
518
519 SDL_keysym *ph_TranslateKey(PhKeyEvent_t *key, SDL_keysym *keysym)
520 {
521 /*
522 'sym' is set to the value of the key with modifiers applied to it.
523 This member is valid only if Pk_KF_Sym_Valid is set in the key_flags.
524 We will assume it is valid.
525 */
526 cap = key->key_cap;
527 switch (cap>>8) {
528 case 0x00: /* Latin 1 */
529 case 0x01: /* Latin 2 */
530 case 0x02: /* Latin 3 */
531 case 0x03: /* Latin 4 */
532 case 0x04: /* Katakana */
533 case 0x05: /* Arabic */
534 case 0x06: /* Cyrillic */
535 case 0x07: /* Greek */
536 case 0x08: /* Technical */
537 case 0x0A: /* Publishing */
538 case 0x0C: /* Hebrew */
539 case 0x0D: /* Thai */
540 keysym->sym = (SDLKey)(cap&0xFF);
541 /* Map capital letter syms to lowercase */
542 if ((keysym->sym >= 'A')&&(keysym->sym <= 'Z'))
543 keysym->sym += ('a'-'A');
544 break;
545 // case 0xFE:
546 // keysym->sym = ODD_keymap[sym&0xFF];
547 // break;
548 case 0xF0:
549 keysym->sym = MISC_keymap[cap&0xFF];
550 break;
551 default:
552 fprintf(stderr,"Photon: Unknown key_cap, cap = 0x%.4x\n", (unsigned int)cap);
553 break;
554 }
555 return (keysym);
556 }
557
558 void ph_InitOSKeymap(_THIS)
559 {
560
561 ph_InitKeymap();
562 }
563