src/video/gem/SDL_gemevents.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 10 Jul 2006 21:04:37 +0000
changeset 1895 c121d94672cb
parent 1857 417f2af2bd52
child 2019 d20f4510c718
permissions -rw-r--r--
SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
     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 /*
    25  * GEM SDL video driver implementation
    26  * inspired from the Dummy SDL driver
    27  * 
    28  * Patrice Mandin
    29  * and work from
    30  * Olivier Landemarre, Johan Klockars, Xavier Joubert, Claude Attard
    31  */
    32 
    33 #include <gem.h>
    34 
    35 #include "../../events/SDL_sysevents.h"
    36 #include "../../events/SDL_events_c.h"
    37 #include "SDL_gemvideo.h"
    38 #include "SDL_gemevents_c.h"
    39 #include "../ataricommon/SDL_atarikeys.h"       /* for keyboard scancodes */
    40 #include "../ataricommon/SDL_atarievents_c.h"
    41 #include "../ataricommon/SDL_xbiosevents_c.h"
    42 #include "../ataricommon/SDL_ataridevmouse_c.h"
    43 
    44 /* Defines */
    45 
    46 #define ATARIBIOS_MAXKEYS 128
    47 
    48 /* Variables */
    49 
    50 static unsigned char gem_currentkeyboard[ATARIBIOS_MAXKEYS];
    51 static unsigned char gem_previouskeyboard[ATARIBIOS_MAXKEYS];
    52 static unsigned char gem_currentascii[ATARIBIOS_MAXKEYS];
    53 
    54 /* The translation tables from a console scancode to a SDL keysym */
    55 static SDLKey keymap[ATARIBIOS_MAXKEYS];
    56 
    57 /* Functions prototypes */
    58 
    59 static SDL_keysym *TranslateKey(int scancode, int asciicode,
    60                                 SDL_keysym * keysym, SDL_bool pressed);
    61 static int do_messages(_THIS, short *message);
    62 static void do_keyboard(short kc, short ks);
    63 static void do_mouse(_THIS, short mx, short my, short mb, short ks);
    64 
    65 /* Functions */
    66 
    67 static SDL_keysym *
    68 TranslateKey(int scancode, int asciicode, SDL_keysym * keysym,
    69              SDL_bool pressed)
    70 {
    71     /* Set the keysym information */
    72     keysym->scancode = scancode;
    73 
    74     if (asciicode)
    75         keysym->sym = asciicode;
    76     else
    77         keysym->sym = keymap[scancode];
    78 
    79     keysym->mod = KMOD_NONE;
    80     keysym->unicode = 0;
    81     if (SDL_TranslateUNICODE && pressed) {
    82         keysym->unicode = SDL_AtariToUnicodeTable[asciicode];
    83     }
    84 
    85     return (keysym);
    86 }
    87 
    88 void
    89 GEM_InitOSKeymap(_THIS)
    90 {
    91     int i;
    92 
    93     SDL_memset(gem_currentkeyboard, 0, sizeof(gem_currentkeyboard));
    94     SDL_memset(gem_previouskeyboard, 0, sizeof(gem_previouskeyboard));
    95     SDL_memset(gem_currentascii, 0, sizeof(gem_currentascii));
    96 
    97     /* Initialize keymap */
    98     for (i = 0; i < sizeof(keymap); i++)
    99         keymap[i] = SDLK_UNKNOWN;
   100 
   101     /* Functions keys */
   102     for (i = 0; i < 10; i++)
   103         keymap[SCANCODE_F1 + i] = SDLK_F1 + i;
   104 
   105     /* Cursor keypad */
   106     keymap[SCANCODE_HELP] = SDLK_HELP;
   107     keymap[SCANCODE_UNDO] = SDLK_UNDO;
   108     keymap[SCANCODE_INSERT] = SDLK_INSERT;
   109     keymap[SCANCODE_CLRHOME] = SDLK_HOME;
   110     keymap[SCANCODE_UP] = SDLK_UP;
   111     keymap[SCANCODE_DOWN] = SDLK_DOWN;
   112     keymap[SCANCODE_RIGHT] = SDLK_RIGHT;
   113     keymap[SCANCODE_LEFT] = SDLK_LEFT;
   114 
   115     /* Special keys */
   116     keymap[SCANCODE_ESCAPE] = SDLK_ESCAPE;
   117     keymap[SCANCODE_BACKSPACE] = SDLK_BACKSPACE;
   118     keymap[SCANCODE_TAB] = SDLK_TAB;
   119     keymap[SCANCODE_ENTER] = SDLK_RETURN;
   120     keymap[SCANCODE_DELETE] = SDLK_DELETE;
   121     keymap[SCANCODE_LEFTCONTROL] = SDLK_LCTRL;
   122     keymap[SCANCODE_LEFTSHIFT] = SDLK_LSHIFT;
   123     keymap[SCANCODE_RIGHTSHIFT] = SDLK_RSHIFT;
   124     keymap[SCANCODE_LEFTALT] = SDLK_LALT;
   125     keymap[SCANCODE_CAPSLOCK] = SDLK_CAPSLOCK;
   126 
   127     /* Mouse init */
   128     GEM_mouse_relative = SDL_FALSE;
   129 }
   130 
   131 void
   132 GEM_PumpEvents(_THIS)
   133 {
   134     short mousex, mousey, mouseb, dummy;
   135     short kstate, prevkc, prevks;
   136     int i;
   137     SDL_keysym keysym;
   138 
   139     SDL_memset(gem_currentkeyboard, 0, sizeof(gem_currentkeyboard));
   140     prevkc = prevks = 0;
   141 
   142     for (;;) {
   143         int quit, resultat, event_mask, mouse_event;
   144         short buffer[8], kc;
   145         short x2, y2, w2, h2;
   146 
   147         quit = mouse_event = x2 = y2 = w2 = h2 = 0;
   148 
   149         event_mask = MU_MESAG | MU_TIMER | MU_KEYBD;
   150         if (!GEM_fullscreen && (GEM_handle >= 0)) {
   151             wind_get(GEM_handle, WF_WORKXYWH, &x2, &y2, &w2, &h2);
   152             event_mask |= MU_M1;
   153             if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS)) {
   154                 mouse_event = MO_LEAVE;
   155             } else {
   156                 mouse_event = MO_ENTER;
   157             }
   158         }
   159 
   160         resultat = evnt_multi(event_mask,
   161                               0, 0, 0,
   162                               mouse_event, x2, y2, w2, h2,
   163                               0, 0, 0, 0, 0,
   164                               buffer,
   165                               10,
   166                               &dummy, &dummy, &dummy, &kstate, &kc, &dummy);
   167 
   168         /* Message event ? */
   169         if (resultat & MU_MESAG)
   170             quit = do_messages(this, buffer);
   171 
   172         /* Keyboard event ? */
   173         if (resultat & MU_KEYBD) {
   174             if ((prevkc != kc) || (prevks != kstate)) {
   175                 do_keyboard(kc, kstate);
   176             } else {
   177                 /* Avoid looping, if repeating same key */
   178                 break;
   179             }
   180         }
   181 
   182         /* Mouse entering/leaving window */
   183         if (resultat & MU_M1) {
   184             if (this->input_grab == SDL_GRAB_OFF) {
   185                 if (SDL_GetAppState() & SDL_APPMOUSEFOCUS) {
   186                     SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
   187                 } else {
   188                     SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
   189                 }
   190             }
   191         }
   192 
   193         /* Timer event ? */
   194         if ((resultat & MU_TIMER) || quit)
   195             break;
   196     }
   197 
   198     /* Update mouse */
   199     graf_mkstate(&mousex, &mousey, &mouseb, &kstate);
   200     do_mouse(this, mousex, mousey, mouseb, kstate);
   201 
   202     /* Now generate keyboard events */
   203     for (i = 0; i < ATARIBIOS_MAXKEYS; i++) {
   204         /* Key pressed ? */
   205         if (gem_currentkeyboard[i] && !gem_previouskeyboard[i])
   206             SDL_PrivateKeyboard(SDL_PRESSED,
   207                                 TranslateKey(i, gem_currentascii[i],
   208                                              &keysym, SDL_TRUE));
   209 
   210         /* Key unpressed ? */
   211         if (gem_previouskeyboard[i] && !gem_currentkeyboard[i])
   212             SDL_PrivateKeyboard(SDL_RELEASED,
   213                                 TranslateKey(i, gem_currentascii[i],
   214                                              &keysym, SDL_FALSE));
   215     }
   216 
   217     SDL_memcpy(gem_previouskeyboard, gem_currentkeyboard,
   218                sizeof(gem_previouskeyboard));
   219 
   220     /* Refresh window name ? */
   221     if (GEM_refresh_name) {
   222         if (SDL_GetAppState() & SDL_APPACTIVE) {
   223             /* Fullscreen/windowed */
   224             if (GEM_title_name) {
   225                 wind_set(GEM_handle, WF_NAME,
   226                          (short) (((unsigned long) GEM_title_name) >>
   227                                   16),
   228                          (short) (((unsigned long) GEM_title_name) &
   229                                   0xffff), 0, 0);
   230             }
   231         } else {
   232             /* Iconified */
   233             if (GEM_icon_name) {
   234                 wind_set(GEM_handle, WF_NAME,
   235                          (short) (((unsigned long) GEM_icon_name) >>
   236                                   16),
   237                          (short) (((unsigned long) GEM_icon_name) &
   238                                   0xffff), 0, 0);
   239             }
   240         }
   241         GEM_refresh_name = SDL_FALSE;
   242     }
   243 }
   244 
   245 static int
   246 do_messages(_THIS, short *message)
   247 {
   248     int quit, posted;
   249     short x2, y2, w2, h2;
   250 
   251     quit = 0;
   252     switch (message[0]) {
   253     case WM_CLOSED:
   254     case AP_TERM:
   255         posted = SDL_PrivateQuit();
   256         quit = 1;
   257         break;
   258     case WM_MOVED:
   259         wind_set(message[3], WF_CURRXYWH, message[4], message[5],
   260                  message[6], message[7]);
   261         break;
   262     case WM_TOPPED:
   263         wind_set(message[3], WF_TOP, message[4], 0, 0, 0);
   264         /* Continue with TOP event processing */
   265     case WM_ONTOP:
   266         SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS);
   267         if (VDI_setpalette) {
   268             VDI_setpalette(this, VDI_curpalette);
   269         }
   270         break;
   271     case WM_REDRAW:
   272         if (!GEM_lock_redraw) {
   273             GEM_wind_redraw(this, message[3], &message[4]);
   274         }
   275         break;
   276     case WM_ICONIFY:
   277     case WM_ALLICONIFY:
   278         wind_set(message[3], WF_ICONIFY, message[4], message[5],
   279                  message[6], message[7]);
   280         /* If we're active, make ourselves inactive */
   281         if (SDL_GetAppState() & SDL_APPACTIVE) {
   282             /* Send an internal deactivate event */
   283             SDL_PrivateAppActive(0, SDL_APPACTIVE);
   284         }
   285         /* Update window title */
   286         if (GEM_refresh_name && GEM_icon_name) {
   287             wind_set(GEM_handle, WF_NAME,
   288                      (short) (((unsigned long) GEM_icon_name) >> 16),
   289                      (short) (((unsigned long) GEM_icon_name) & 0xffff),
   290                      0, 0);
   291             GEM_refresh_name = SDL_FALSE;
   292         }
   293         break;
   294     case WM_UNICONIFY:
   295         wind_set(message[3], WF_UNICONIFY, message[4], message[5],
   296                  message[6], message[7]);
   297         /* If we're not active, make ourselves active */
   298         if (!(SDL_GetAppState() & SDL_APPACTIVE)) {
   299             /* Send an internal activate event */
   300             SDL_PrivateAppActive(1, SDL_APPACTIVE);
   301         }
   302         if (GEM_refresh_name && GEM_title_name) {
   303             wind_set(GEM_handle, WF_NAME,
   304                      (short) (((unsigned long) GEM_title_name) >> 16),
   305                      (short) (((unsigned long) GEM_title_name) & 0xffff),
   306                      0, 0);
   307             GEM_refresh_name = SDL_FALSE;
   308         }
   309         break;
   310     case WM_SIZED:
   311         wind_set(message[3], WF_CURRXYWH, message[4], message[5],
   312                  message[6], message[7]);
   313         wind_get(message[3], WF_WORKXYWH, &x2, &y2, &w2, &h2);
   314         GEM_win_fulled = SDL_FALSE;     /* Cancel maximized flag */
   315         GEM_lock_redraw = SDL_TRUE;     /* Prevent redraw till buffers resized */
   316         SDL_PrivateResize(w2, h2);
   317         break;
   318     case WM_FULLED:
   319         {
   320             short x, y, w, h;
   321 
   322             if (GEM_win_fulled) {
   323                 wind_get(message[3], WF_PREVXYWH, &x, &y, &w, &h);
   324                 GEM_win_fulled = SDL_FALSE;
   325             } else {
   326                 x = GEM_desk_x;
   327                 y = GEM_desk_y;
   328                 w = GEM_desk_w;
   329                 h = GEM_desk_h;
   330                 GEM_win_fulled = SDL_TRUE;
   331             }
   332             wind_set(message[3], WF_CURRXYWH, x, y, w, h);
   333             wind_get(message[3], WF_WORKXYWH, &x2, &y2, &w2, &h2);
   334             GEM_lock_redraw = SDL_TRUE; /* Prevent redraw till buffers resized */
   335             SDL_PrivateResize(w2, h2);
   336         }
   337         break;
   338     case WM_BOTTOMED:
   339         wind_set(message[3], WF_BOTTOM, 0, 0, 0, 0);
   340         /* Continue with BOTTOM event processing */
   341     case WM_UNTOPPED:
   342         SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS);
   343         if (VDI_setpalette) {
   344             VDI_setpalette(this, VDI_oldpalette);
   345         }
   346         break;
   347     }
   348 
   349     return quit;
   350 }
   351 
   352 static void
   353 do_keyboard(short kc, short ks)
   354 {
   355     int scancode, asciicode;
   356 
   357     if (kc) {
   358         scancode = (kc >> 8) & 127;
   359         asciicode = kc & 255;
   360 
   361         gem_currentkeyboard[scancode] = 0xFF;
   362         gem_currentascii[scancode] = asciicode;
   363     }
   364 
   365     /* Read special keys */
   366     if (ks & K_RSHIFT)
   367         gem_currentkeyboard[SCANCODE_RIGHTSHIFT] = 0xFF;
   368     if (ks & K_LSHIFT)
   369         gem_currentkeyboard[SCANCODE_LEFTSHIFT] = 0xFF;
   370     if (ks & K_CTRL)
   371         gem_currentkeyboard[SCANCODE_LEFTCONTROL] = 0xFF;
   372     if (ks & K_ALT)
   373         gem_currentkeyboard[SCANCODE_LEFTALT] = 0xFF;
   374 }
   375 
   376 static void
   377 do_mouse(_THIS, short mx, short my, short mb, short ks)
   378 {
   379     static short prevmousex = 0, prevmousey = 0, prevmouseb = 0;
   380     short x2, y2, w2, h2;
   381 
   382     /* Don't return mouse events if out of window */
   383     if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS) == 0) {
   384         return;
   385     }
   386 
   387     /* Retrieve window coords, and generate mouse events accordingly */
   388     x2 = y2 = 0;
   389     w2 = VDI_w;
   390     h2 = VDI_h;
   391     if ((!GEM_fullscreen) && (GEM_handle >= 0)) {
   392         wind_get(GEM_handle, WF_WORKXYWH, &x2, &y2, &w2, &h2);
   393 
   394         /* Do not generate mouse button event if out of window working area */
   395         if ((mx < x2) || (mx >= x2 + w2) || (my < y2) || (my >= y2 + h2)) {
   396             mb = prevmouseb;
   397         }
   398     }
   399 
   400     /* Mouse motion ? */
   401     if (GEM_mouse_relative) {
   402         if (GEM_usedevmouse) {
   403             SDL_AtariDevMouse_PostMouseEvents(this, SDL_FALSE);
   404         } else {
   405             SDL_AtariXbios_PostMouseEvents(this, SDL_FALSE);
   406         }
   407     } else {
   408         if ((prevmousex != mx) || (prevmousey != my)) {
   409             int posx, posy;
   410 
   411             /* Give mouse position relative to window position */
   412             posx = mx - x2;
   413             if (posx < 0)
   414                 posx = 0;
   415             if (posx > w2)
   416                 posx = w2 - 1;
   417             posy = my - y2;
   418             if (posy < 0)
   419                 posy = 0;
   420             if (posy > h2)
   421                 posy = h2 - 1;
   422 
   423             SDL_PrivateMouseMotion(0, 0, posx, posy);
   424         }
   425         prevmousex = mx;
   426         prevmousey = my;
   427     }
   428 
   429     /* Mouse button ? */
   430     if (prevmouseb != mb) {
   431         int i;
   432 
   433         for (i = 0; i < 2; i++) {
   434             int curbutton, prevbutton;
   435 
   436             curbutton = mb & (1 << i);
   437             prevbutton = prevmouseb & (1 << i);
   438 
   439             if (curbutton && !prevbutton) {
   440                 SDL_PrivateMouseButton(SDL_PRESSED, i + 1, 0, 0);
   441             }
   442             if (!curbutton && prevbutton) {
   443                 SDL_PrivateMouseButton(SDL_RELEASED, i + 1, 0, 0);
   444             }
   445         }
   446         prevmouseb = mb;
   447     }
   448 
   449     /* Read special keys */
   450     if (ks & K_RSHIFT)
   451         gem_currentkeyboard[SCANCODE_RIGHTSHIFT] = 0xFF;
   452     if (ks & K_LSHIFT)
   453         gem_currentkeyboard[SCANCODE_LEFTSHIFT] = 0xFF;
   454     if (ks & K_CTRL)
   455         gem_currentkeyboard[SCANCODE_LEFTCONTROL] = 0xFF;
   456     if (ks & K_ALT)
   457         gem_currentkeyboard[SCANCODE_LEFTALT] = 0xFF;
   458 }
   459 
   460 /* vi: set ts=4 sw=4 expandtab: */