src/video/photon/SDL_ph_events.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 20 Jan 2003 01:38:37 +0000
changeset 571 8e3ce997621c
parent 320 66f815c147ed
child 663 8bedd6d61642
permissions -rw-r--r--
Date: Thu, 16 Jan 2003 13:48:31 +0200
From: "Mike Gorchak"
Subject: All QNX patches

whole patches concerning QNX. Almost all code has been rewritten by Julian
and me. Added initial support for hw overlays in QNX and many many others
fixes.

P.S. This patches has been reviewed by Dave Rempel from QSSL and included in
SDL 1.2.5 distribution, which coming on 3rd party CD for newest 6.2.1
version of QNX, which will be available soon.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  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@libsdl.org
    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 #define DISABLE_X11
    31 
    32 #include <Ph.h>
    33 #include <stdio.h>
    34 #include <setjmp.h>
    35 #include <photon/PkKeyDef.h>
    36 #include <sys/time.h>
    37 
    38 #include "SDL.h"
    39 #include "SDL_syswm.h"
    40 #include "SDL_sysevents.h"
    41 #include "SDL_sysvideo.h"
    42 #include "SDL_events_c.h"
    43 #include "SDL_ph_video.h"
    44 #include "SDL_ph_modes_c.h"
    45 #include "SDL_ph_image_c.h"
    46 #include "SDL_ph_events_c.h"
    47 
    48 
    49 /* The translation tables from a photon keysym to a SDL keysym */
    50 static SDLKey ODD_keymap[256];
    51 static SDLKey MISC_keymap[0xFF + 1];
    52 SDL_keysym *ph_TranslateKey(PhKeyEvent_t *key, SDL_keysym *keysym);
    53 
    54 /* Check to see if this is a repeated key.
    55    (idea shamelessly lifted from GII -- thanks guys! :)
    56  */
    57 
    58 static int ph_WarpedMotion(_THIS, PhEvent_t *winEvent)
    59 {
    60     PhRect_t *rect = PhGetRects( winEvent );
    61 
    62     int centre_x, centre_y;
    63     int dx, dy;
    64     short abs_x, abs_y;
    65     int posted;
    66 
    67     centre_x = SDL_VideoSurface->w / 2;
    68     centre_y = SDL_VideoSurface->h / 2;
    69 
    70     dx = rect->ul.x - centre_x;
    71     dy = rect->ul.y - centre_y;
    72 
    73     posted = SDL_PrivateMouseMotion( 0, 1, dx, dy );
    74 
    75     /* Move mouse cursor to middle of the window */
    76     PtGetAbsPosition( window, &abs_x, &abs_y );
    77     PhMoveCursorAbs(PhInputGroup(NULL), abs_x + centre_x, abs_y + centre_y);
    78 
    79     return (posted);
    80 }
    81 
    82 /* Control which motion flags the window has set, a flags value of -1 sets
    83  * MOTION_BUTTON and MOTION_NOBUTTON */
    84 
    85 static void set_motion_sensitivity(_THIS, unsigned int flags)
    86 {
    87     int rid;
    88     int fields = Ph_EV_PTR_MOTION_BUTTON | Ph_EV_PTR_MOTION_NOBUTTON;
    89     PhRegion_t region;
    90 
    91     if( window )
    92     {
    93         rid = PtWidgetRid( window );
    94         if( rid != 0 && PhRegionQuery( rid, &region, NULL, NULL, 0 ) == 0 )
    95         {
    96             region.events_sense=(region.events_sense & ~fields)|(flags & fields);
    97             PhRegionChange(Ph_REGION_EV_SENSE, 0, &region, NULL, NULL);
    98         }
    99     }
   100 }
   101 
   102 /* Convert the photon button state value to an SDL value */
   103 static Uint8 ph2sdl_mousebutton(unsigned short button_state)
   104 {
   105     Uint8 mouse_button = 0;
   106 
   107     if (button_state & Ph_BUTTON_SELECT)
   108         mouse_button |= SDL_BUTTON_LEFT;
   109     if (button_state & Ph_BUTTON_MENU)
   110         mouse_button |= SDL_BUTTON_RIGHT;
   111     if (button_state & Ph_BUTTON_ADJUST)
   112         mouse_button |= SDL_BUTTON_MIDDLE;
   113 
   114     return (mouse_button);
   115 }
   116 
   117 static int ph_DispatchEvent(_THIS)
   118 {
   119     int posted;
   120     PhRect_t* rect;
   121     PhPointerEvent_t* pointerEvent;
   122     PhKeyEvent_t* keyEvent;
   123     PhWindowEvent_t* winEvent;
   124     int i, buttons;
   125     SDL_Rect sdlrects[50]; 
   126 	
   127     posted = 0;
   128 	
   129     switch (event->type)
   130     {
   131         case Ph_EV_BOUNDARY:
   132         {
   133             if (event->subtype == Ph_EV_PTR_ENTER)
   134             {
   135                 posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
   136             }
   137             else if (event->subtype ==Ph_EV_PTR_LEAVE)
   138             {
   139                 posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);	
   140             }
   141         }
   142         break;
   143 
   144         case Ph_EV_PTR_MOTION_BUTTON:
   145         case Ph_EV_PTR_MOTION_NOBUTTON:
   146         {
   147             if (SDL_VideoSurface)
   148             {
   149                 pointerEvent = PhGetData(event);
   150                 rect = PhGetRects(event);
   151 
   152                 if (mouse_relative)
   153                 {
   154                     posted = ph_WarpedMotion(this, event);
   155                 }
   156                 else
   157                 {
   158                     posted = SDL_PrivateMouseMotion(0, 0, rect->ul.x, rect->ul.y);
   159                 }
   160             }
   161         }
   162         break;
   163 
   164         case Ph_EV_BUT_PRESS:
   165         {
   166             pointerEvent = PhGetData( event );
   167             buttons = ph2sdl_mousebutton( pointerEvent->buttons );
   168             if (buttons != 0)
   169             {
   170                 posted = SDL_PrivateMouseButton(SDL_PRESSED, buttons, 0, 0);
   171             }
   172         }
   173         break;
   174 
   175         case Ph_EV_BUT_RELEASE:
   176         {
   177             pointerEvent = PhGetData(event);
   178             buttons = ph2sdl_mousebutton(pointerEvent->buttons);
   179             if (event->subtype == Ph_EV_RELEASE_REAL && buttons != 0)
   180             {
   181                 posted = SDL_PrivateMouseButton(SDL_RELEASED, buttons, 0, 0);
   182             }
   183             else if(event->subtype == Ph_EV_RELEASE_PHANTOM)
   184             {
   185                 /* If the mouse is outside the window,
   186                  * only a phantom release event is sent, so
   187                  * check if the window doesn't have mouse focus.
   188                  * Not perfect, maybe checking the mouse button
   189                  * state for Ph_EV_BOUNDARY events would be
   190                  * better. */
   191                 if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS) == 0)
   192 		{
   193                     posted = SDL_PrivateMouseButton(SDL_RELEASED, buttons, 0, 0);
   194                 }
   195             }
   196         }
   197         break;
   198 
   199         case Ph_EV_WM:
   200         {
   201             winEvent = PhGetData(event);
   202 
   203             /* losing focus */
   204             if ((winEvent->event_f==Ph_WM_FOCUS) && (winEvent->event_state==Ph_WM_EVSTATE_FOCUSLOST))
   205             {
   206                 set_motion_sensitivity(this, Ph_EV_PTR_MOTION_BUTTON);
   207                 posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS);	
   208             }
   209             /* gaining focus */
   210             else if ((winEvent->event_f==Ph_WM_FOCUS) && (winEvent->event_state==Ph_WM_EVSTATE_FOCUS))
   211             {
   212                 set_motion_sensitivity(this, -1);
   213                 posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS);
   214             }
   215             /* request to quit */
   216             else if (winEvent->event_f==Ph_WM_CLOSE)
   217             {
   218                 posted = SDL_PrivateQuit();
   219             }
   220             /* request to resize */
   221             else if (winEvent->event_f==Ph_WM_RESIZE)
   222             {
   223                 SDL_PrivateResize(winEvent->size.w, winEvent->size.h);
   224             }
   225             /* request to maximize */
   226             else if (winEvent->event_f==Ph_WM_MAX)
   227             {
   228                 /* TODO: get screen resolution, set window pos to 0, 0 and resize it ! */
   229             }
   230         }
   231         break;
   232 
   233         /* window has been resized, moved or removed */
   234         case Ph_EV_EXPOSE:
   235         {
   236             if (SDL_VideoSurface)
   237             {
   238                 rect = PhGetRects(event);
   239 
   240                 for(i=0;i<event->num_rects;i++)
   241                 {
   242                     sdlrects[i].x = rect[i].ul.x;
   243                     sdlrects[i].y = rect[i].ul.y;
   244                     sdlrects[i].w = rect[i].lr.x - rect[i].ul.x + 1;
   245                     sdlrects[i].h = rect[i].lr.y - rect[i].ul.y + 1;
   246                 }
   247 
   248                 this->UpdateRects(this, event->num_rects, sdlrects);
   249             }
   250         }
   251 	break;
   252 
   253         case Ph_EV_KEY:
   254         {
   255             SDL_keysym keysym;
   256 
   257             posted = 0;
   258 
   259             keyEvent = PhGetData( event );
   260 
   261             if (Pk_KF_Key_Down & keyEvent->key_flags)
   262             {
   263                 posted = SDL_PrivateKeyboard(SDL_PRESSED, ph_TranslateKey(keyEvent, &keysym));
   264             }
   265             else /* must be key release */
   266             {
   267                  /* Ignore repeated key release events */
   268                  /* if (! Pk_KF_Key_Repeat & keyEvent->key_flags ) */
   269 
   270                 posted = SDL_PrivateKeyboard(SDL_RELEASED, ph_TranslateKey( keyEvent, &keysym));
   271             }
   272         }
   273         break;
   274     }
   275 
   276     return(posted);
   277 }
   278 
   279 /* perform a blocking read if no events available */
   280 int ph_Pending(_THIS)
   281 {
   282     /* Flush the display connection and look to see if events are queued */
   283     PgFlush();
   284 
   285     while( 1 )
   286     {   /* note this is a non-blocking call */
   287         switch( PhEventPeek( event, EVENT_SIZE ) )
   288         {
   289             case Ph_EVENT_MSG:
   290                  return 1;
   291                  break;
   292             case -1:
   293                  perror("ph_Pending(): PhEventNext failed");
   294                  break;
   295             default:
   296                  return 0;
   297         }
   298     }
   299 
   300     /* Oh well, nothing is ready .. */
   301     return(0);
   302 }
   303 
   304 void ph_PumpEvents(_THIS)
   305 {
   306     /* Flush the display connection and look to see if events are queued */
   307     PgFlush();
   308 
   309     while (ph_Pending(this))
   310     {
   311         ph_DispatchEvent(this);
   312     }
   313 }
   314 
   315 void ph_InitKeymap(void)
   316 {
   317     int i;
   318 
   319     /* Odd keys used in international keyboards */
   320     for (i=0; i<SDL_TABLESIZE(ODD_keymap); ++i)
   321         ODD_keymap[i] = SDLK_UNKNOWN;
   322 
   323     /* Map the miscellaneous keys */
   324     for (i=0; i<SDL_TABLESIZE(MISC_keymap); ++i)
   325         MISC_keymap[i] = SDLK_UNKNOWN;
   326 
   327     MISC_keymap[Pk_BackSpace&0xFF] = SDLK_BACKSPACE;
   328     MISC_keymap[Pk_Tab&0xFF] = SDLK_TAB;
   329     MISC_keymap[Pk_Clear&0xFF] = SDLK_CLEAR;
   330     MISC_keymap[Pk_Return&0xFF] = SDLK_RETURN;
   331     MISC_keymap[Pk_Pause&0xFF] = SDLK_PAUSE;
   332     MISC_keymap[Pk_Escape&0xFF] = SDLK_ESCAPE;
   333     MISC_keymap[Pk_Delete&0xFF] = SDLK_DELETE;
   334 
   335     MISC_keymap[Pk_KP_0&0xFF] = SDLK_KP0;
   336     MISC_keymap[Pk_KP_1&0xFF] = SDLK_KP1;
   337     MISC_keymap[Pk_KP_2&0xFF] = SDLK_KP2;
   338     MISC_keymap[Pk_KP_3&0xFF] = SDLK_KP3;
   339     MISC_keymap[Pk_KP_4&0xFF] = SDLK_KP4;
   340     MISC_keymap[Pk_KP_5&0xFF] = SDLK_KP5;
   341     MISC_keymap[Pk_KP_6&0xFF] = SDLK_KP6;
   342     MISC_keymap[Pk_KP_7&0xFF] = SDLK_KP7;
   343     MISC_keymap[Pk_KP_8&0xFF] = SDLK_KP8;
   344     MISC_keymap[Pk_KP_9&0xFF] = SDLK_KP9;
   345 
   346     MISC_keymap[Pk_KP_Decimal&0xFF] = SDLK_KP_PERIOD;
   347     MISC_keymap[Pk_KP_Divide&0xFF] = SDLK_KP_DIVIDE;
   348     MISC_keymap[Pk_KP_Multiply&0xFF] = SDLK_KP_MULTIPLY;
   349     MISC_keymap[Pk_KP_Subtract&0xFF] = SDLK_KP_MINUS;
   350     MISC_keymap[Pk_KP_Add&0xFF] = SDLK_KP_PLUS;
   351     MISC_keymap[Pk_KP_Enter&0xFF] = SDLK_KP_ENTER;
   352     MISC_keymap[Pk_KP_Equal&0xFF] = SDLK_KP_EQUALS;
   353 
   354     MISC_keymap[Pk_Up&0xFF] = SDLK_UP;
   355     MISC_keymap[Pk_Down&0xFF] = SDLK_DOWN;
   356     MISC_keymap[Pk_Right&0xFF] = SDLK_RIGHT;
   357     MISC_keymap[Pk_Left&0xFF] = SDLK_LEFT;
   358     MISC_keymap[Pk_Insert&0xFF] = SDLK_INSERT;
   359     MISC_keymap[Pk_Home&0xFF] = SDLK_HOME;
   360     MISC_keymap[Pk_End&0xFF] = SDLK_END;
   361     MISC_keymap[Pk_Pg_Up&0xFF] = SDLK_PAGEUP;
   362     MISC_keymap[Pk_Pg_Down&0xFF] = SDLK_PAGEDOWN;
   363 
   364     MISC_keymap[Pk_F1&0xFF] = SDLK_F1;
   365     MISC_keymap[Pk_F2&0xFF] = SDLK_F2;
   366     MISC_keymap[Pk_F3&0xFF] = SDLK_F3;
   367     MISC_keymap[Pk_F4&0xFF] = SDLK_F4;
   368     MISC_keymap[Pk_F5&0xFF] = SDLK_F5;
   369     MISC_keymap[Pk_F6&0xFF] = SDLK_F6;
   370     MISC_keymap[Pk_F7&0xFF] = SDLK_F7;
   371     MISC_keymap[Pk_F8&0xFF] = SDLK_F8;
   372     MISC_keymap[Pk_F9&0xFF] = SDLK_F9;
   373     MISC_keymap[Pk_F10&0xFF] = SDLK_F10;
   374     MISC_keymap[Pk_F11&0xFF] = SDLK_F11;
   375     MISC_keymap[Pk_F12&0xFF] = SDLK_F12;
   376     MISC_keymap[Pk_F13&0xFF] = SDLK_F13;
   377     MISC_keymap[Pk_F14&0xFF] = SDLK_F14;
   378     MISC_keymap[Pk_F15&0xFF] = SDLK_F15;
   379 
   380     MISC_keymap[Pk_Num_Lock&0xFF] = SDLK_NUMLOCK;
   381     MISC_keymap[Pk_Caps_Lock&0xFF] = SDLK_CAPSLOCK;
   382     MISC_keymap[Pk_Scroll_Lock&0xFF] = SDLK_SCROLLOCK;
   383     MISC_keymap[Pk_Shift_R&0xFF] = SDLK_RSHIFT;
   384     MISC_keymap[Pk_Shift_L&0xFF] = SDLK_LSHIFT;
   385     MISC_keymap[Pk_Control_R&0xFF] = SDLK_RCTRL;
   386     MISC_keymap[Pk_Control_L&0xFF] = SDLK_LCTRL;
   387     MISC_keymap[Pk_Alt_R&0xFF] = SDLK_RALT;
   388     MISC_keymap[Pk_Alt_L&0xFF] = SDLK_LALT;
   389     MISC_keymap[Pk_Meta_R&0xFF] = SDLK_RMETA;
   390     MISC_keymap[Pk_Meta_L&0xFF] = SDLK_LMETA;
   391     MISC_keymap[Pk_Super_L&0xFF] = SDLK_LSUPER;   /* Left "Windows"  */
   392     MISC_keymap[Pk_Super_R&0xFF] = SDLK_RSUPER;   /* Right "Windows" */
   393     MISC_keymap[Pk_Mode_switch&0xFF] = SDLK_MODE; /* "Alt Gr" key    */
   394 
   395     MISC_keymap[Pk_Help&0xFF] = SDLK_HELP;
   396     MISC_keymap[Pk_Print&0xFF] = SDLK_PRINT;
   397     MISC_keymap[Pk_Break&0xFF] = SDLK_BREAK;
   398     MISC_keymap[Pk_Menu&0xFF] = SDLK_MENU;
   399     MISC_keymap[Pk_Hyper_R&0xFF] = SDLK_MENU;   /* Windows "Menu" key */
   400 }
   401 
   402 static unsigned long cap;
   403 
   404 SDL_keysym *ph_TranslateKey(PhKeyEvent_t *key, SDL_keysym *keysym)
   405 {
   406     /* 'sym' is set to the value of the key with modifiers applied to it.
   407        This member is valid only if Pk_KF_Sym_Valid is set in the key_flags.
   408        We will assume it is valid. */
   409 
   410     /* FIXME: This needs to check whether the cap & scancode is valid */
   411 
   412     cap = key->key_cap;
   413 
   414     switch (cap>>8)
   415     {
   416         case 0x00:  /* Latin 1 */
   417         case 0x01:  /* Latin 2 */
   418         case 0x02:  /* Latin 3 */
   419         case 0x03:  /* Latin 4 */
   420         case 0x04:  /* Katakana */
   421         case 0x05:  /* Arabic */
   422         case 0x06:  /* Cyrillic */
   423         case 0x07:  /* Greek */
   424         case 0x08:  /* Technical */
   425         case 0x0A:  /* Publishing */
   426         case 0x0C:  /* Hebrew */
   427         case 0x0D:  /* Thai */
   428                    keysym->sym = (SDLKey)(cap&0xFF);
   429                    /* Map capital letter syms to lowercase */
   430                    if ((keysym->sym >= 'A')&&(keysym->sym <= 'Z'))
   431                        keysym->sym += ('a'-'A');
   432                    break;
   433         case 0xF0:
   434                    keysym->sym = MISC_keymap[cap&0xFF];
   435                    break;
   436         default:
   437                    keysym->sym = SDLK_UNKNOWN;                
   438                    break;
   439     }
   440 
   441     keysym->scancode = key->key_scan;
   442     keysym->unicode = 0;
   443 
   444     if (SDL_TranslateUNICODE)
   445     {
   446         char utf8[MB_CUR_MAX];
   447         int utf8len;
   448         wchar_t unicode;
   449 
   450         utf8len = PhKeyToMb(utf8, key);
   451         if (utf8len > 0)
   452         {
   453             utf8len = mbtowc(&unicode, utf8, utf8len);
   454             if (utf8len > 0)
   455                 keysym->unicode = unicode;
   456         }
   457     }
   458 
   459     return (keysym);
   460 }
   461 
   462 void ph_InitOSKeymap(_THIS)
   463 {
   464     ph_InitKeymap();
   465 }