src/video/x11/SDL_x11events.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 28 May 2006 13:04:16 +0000
branchSDL-1.3
changeset 1662 782fd950bd46
parent 1659 14717b52abc0
child 1668 4da1ee79c9af
permissions -rw-r--r--
Revamp of the video system in progress - adding support for multiple displays, multiple windows, and a full video mode selection API.

WARNING: None of the video drivers have been updated for the new API yet! The API is still under design and very fluid.

The code is now run through a consistent indent format:
indent -i4 -nut -nsc -br -ce

The headers are being converted to automatically generate doxygen documentation.
     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 /* Handle the event stream, converting X11 events into SDL events */
    25 
    26 #include <setjmp.h>
    27 #include <X11/Xlib.h>
    28 #include <X11/Xutil.h>
    29 #include <X11/keysym.h>
    30 #ifdef __SVR4
    31 #include <X11/Sunkeysym.h>
    32 #endif
    33 #include <sys/types.h>
    34 #include <sys/time.h>
    35 #include <unistd.h>
    36 
    37 #include "SDL_timer.h"
    38 #include "SDL_syswm.h"
    39 #include "../SDL_sysvideo.h"
    40 #include "../../events/SDL_sysevents.h"
    41 #include "../../events/SDL_events_c.h"
    42 #include "SDL_x11video.h"
    43 #include "SDL_x11dga_c.h"
    44 #include "SDL_x11modes_c.h"
    45 #include "SDL_x11image_c.h"
    46 #include "SDL_x11gamma_c.h"
    47 #include "SDL_x11wm_c.h"
    48 #include "SDL_x11mouse_c.h"
    49 #include "SDL_x11events_c.h"
    50 
    51 
    52 /* Define this if you want to debug X11 events */
    53 /*#define DEBUG_XEVENTS*/
    54 
    55 /* The translation tables from an X11 keysym to a SDL keysym */
    56 static SDLKey ODD_keymap[256];
    57 static SDLKey MISC_keymap[256];
    58 SDLKey X11_TranslateKeycode (Display * display, KeyCode kc);
    59 
    60 
    61 #ifdef X_HAVE_UTF8_STRING
    62 Uint32
    63 Utf8ToUcs4 (const Uint8 * utf8)
    64 {
    65     Uint32 c;
    66     int i = 1;
    67     int noOctets = 0;
    68     int firstOctetMask = 0;
    69     unsigned char firstOctet = utf8[0];
    70     if (firstOctet < 0x80) {
    71         /*
    72            Characters in the range:
    73            00000000 to 01111111 (ASCII Range)
    74            are stored in one octet:
    75            0xxxxxxx (The same as its ASCII representation)
    76            The least 6 significant bits of the first octet is the most 6 significant nonzero bits
    77            of the UCS4 representation.
    78          */
    79         noOctets = 1;
    80         firstOctetMask = 0x7F;  /* 0(1111111) - The most significant bit is ignored */
    81     } else if ((firstOctet & 0xE0)      /* get the most 3 significant bits by AND'ing with 11100000 */
    82                == 0xC0) {       /* see if those 3 bits are 110. If so, the char is in this range */
    83         /*
    84            Characters in the range:
    85            00000000 10000000 to 00000111 11111111
    86            are stored in two octets:
    87            110xxxxx 10xxxxxx
    88            The least 5 significant bits of the first octet is the most 5 significant nonzero bits
    89            of the UCS4 representation.
    90          */
    91         noOctets = 2;
    92         firstOctetMask = 0x1F;  /* 000(11111) - The most 3 significant bits are ignored */
    93     } else if ((firstOctet & 0xF0)      /* get the most 4 significant bits by AND'ing with 11110000 */
    94                == 0xE0) {       /* see if those 4 bits are 1110. If so, the char is in this range */
    95         /*
    96            Characters in the range:
    97            00001000 00000000 to 11111111 11111111
    98            are stored in three octets:
    99            1110xxxx 10xxxxxx 10xxxxxx
   100            The least 4 significant bits of the first octet is the most 4 significant nonzero bits
   101            of the UCS4 representation.
   102          */
   103         noOctets = 3;
   104         firstOctetMask = 0x0F;  /* 0000(1111) - The most 4 significant bits are ignored */
   105     } else if ((firstOctet & 0xF8)      /* get the most 5 significant bits by AND'ing with 11111000 */
   106                == 0xF0) {       /* see if those 5 bits are 11110. If so, the char is in this range */
   107         /*
   108            Characters in the range:
   109            00000001 00000000 00000000 to 00011111 11111111 11111111
   110            are stored in four octets:
   111            11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
   112            The least 3 significant bits of the first octet is the most 3 significant nonzero bits
   113            of the UCS4 representation.
   114          */
   115         noOctets = 4;
   116         firstOctetMask = 0x07;  /* 11110(111) - The most 5 significant bits are ignored */
   117     } else if ((firstOctet & 0xFC)      /* get the most 6 significant bits by AND'ing with 11111100 */
   118                == 0xF8) {       /* see if those 6 bits are 111110. If so, the char is in this range */
   119         /*
   120            Characters in the range:
   121            00000000 00100000 00000000 00000000 to
   122            00000011 11111111 11111111 11111111
   123            are stored in five octets:
   124            111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
   125            The least 2 significant bits of the first octet is the most 2 significant nonzero bits
   126            of the UCS4 representation.
   127          */
   128         noOctets = 5;
   129         firstOctetMask = 0x03;  /* 111110(11) - The most 6 significant bits are ignored */
   130     } else if ((firstOctet & 0xFE)      /* get the most 7 significant bits by AND'ing with 11111110 */
   131                == 0xFC) {       /* see if those 7 bits are 1111110. If so, the char is in this range */
   132         /*
   133            Characters in the range:
   134            00000100 00000000 00000000 00000000 to
   135            01111111 11111111 11111111 11111111
   136            are stored in six octets:
   137            1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
   138            The least significant bit of the first octet is the most significant nonzero bit
   139            of the UCS4 representation.
   140          */
   141         noOctets = 6;
   142         firstOctetMask = 0x01;  /* 1111110(1) - The most 7 significant bits are ignored */
   143     } else
   144         return 0;               /* The given chunk is not a valid UTF-8 encoded Unicode character */
   145 
   146     /*
   147        The least noOctets significant bits of the first octet is the most 2 significant nonzero bits
   148        of the UCS4 representation.
   149        The first 6 bits of the UCS4 representation is the least 8-noOctets-1 significant bits of
   150        firstOctet if the character is not ASCII. If so, it's the least 7 significant bits of firstOctet.
   151        This done by AND'ing firstOctet with its mask to trim the bits used for identifying the
   152        number of continuing octets (if any) and leave only the free bits (the x's)
   153        Sample:
   154        1-octet:    0xxxxxxx  &  01111111 = 0xxxxxxx
   155        2-octets:  110xxxxx  &  00011111 = 000xxxxx
   156      */
   157     c = firstOctet & firstOctetMask;
   158 
   159     /* Now, start filling c.ucs4 with the bits from the continuing octets from utf8. */
   160     for (i = 1; i < noOctets; i++) {
   161         /* A valid continuing octet is of the form 10xxxxxx */
   162         if ((utf8[i] & 0xC0)    /* get the most 2 significant bits by AND'ing with 11000000 */
   163             !=0x80)
   164             /* see if those 2 bits are 10. If not, the is a malformed sequence. */
   165             /*The given chunk is a partial sequence at the end of a string that could
   166                begin a valid character */
   167             return 0;
   168 
   169         /* Make room for the next 6-bits */
   170         c <<= 6;
   171 
   172         /*
   173            Take only the least 6 significance bits of the current octet (utf8[i]) and fill the created room
   174            of c.ucs4 with them.
   175            This done by AND'ing utf8[i] with 00111111 and the OR'ing the result with c.ucs4.
   176          */
   177         c |= utf8[i] & 0x3F;
   178     }
   179     return c;
   180 }
   181 #endif
   182 
   183 /* Check to see if this is a repeated key.
   184    (idea shamelessly lifted from GII -- thanks guys! :)
   185  */
   186 static int
   187 X11_KeyRepeat (Display * display, XEvent * event)
   188 {
   189     XEvent peekevent;
   190     int repeated;
   191 
   192     repeated = 0;
   193     if (XPending (display)) {
   194         XPeekEvent (display, &peekevent);
   195         if ((peekevent.type == KeyPress) &&
   196             (peekevent.xkey.keycode == event->xkey.keycode) &&
   197             ((peekevent.xkey.time - event->xkey.time) < 2)) {
   198             repeated = 1;
   199             XNextEvent (display, &peekevent);
   200         }
   201     }
   202     return (repeated);
   203 }
   204 
   205 /* Note:  The X server buffers and accumulates mouse motion events, so
   206    the motion event generated by the warp may not appear exactly as we
   207    expect it to.  We work around this (and improve performance) by only
   208    warping the pointer when it reaches the edge, and then wait for it.
   209 */
   210 #define MOUSE_FUDGE_FACTOR	8
   211 
   212 static __inline__ int
   213 X11_WarpedMotion (_THIS, XEvent * xevent)
   214 {
   215     int w, h, i;
   216     int deltax, deltay;
   217     int posted;
   218 
   219     w = SDL_VideoSurface->w;
   220     h = SDL_VideoSurface->h;
   221     deltax = xevent->xmotion.x - mouse_last.x;
   222     deltay = xevent->xmotion.y - mouse_last.y;
   223 #ifdef DEBUG_MOTION
   224     printf ("Warped mouse motion: %d,%d\n", deltax, deltay);
   225 #endif
   226     mouse_last.x = xevent->xmotion.x;
   227     mouse_last.y = xevent->xmotion.y;
   228     posted = SDL_PrivateMouseMotion (0, 1, deltax, deltay);
   229 
   230     if ((xevent->xmotion.x < MOUSE_FUDGE_FACTOR) ||
   231         (xevent->xmotion.x > (w - MOUSE_FUDGE_FACTOR)) ||
   232         (xevent->xmotion.y < MOUSE_FUDGE_FACTOR) ||
   233         (xevent->xmotion.y > (h - MOUSE_FUDGE_FACTOR))) {
   234         /* Get the events that have accumulated */
   235         while (XCheckTypedEvent (SDL_Display, MotionNotify, xevent)) {
   236             deltax = xevent->xmotion.x - mouse_last.x;
   237             deltay = xevent->xmotion.y - mouse_last.y;
   238 #ifdef DEBUG_MOTION
   239             printf ("Extra mouse motion: %d,%d\n", deltax, deltay);
   240 #endif
   241             mouse_last.x = xevent->xmotion.x;
   242             mouse_last.y = xevent->xmotion.y;
   243             posted += SDL_PrivateMouseMotion (0, 1, deltax, deltay);
   244         }
   245         mouse_last.x = w / 2;
   246         mouse_last.y = h / 2;
   247         XWarpPointer (SDL_Display, None, SDL_Window, 0, 0, 0, 0,
   248                       mouse_last.x, mouse_last.y);
   249         for (i = 0; i < 10; ++i) {
   250             XMaskEvent (SDL_Display, PointerMotionMask, xevent);
   251             if ((xevent->xmotion.x >
   252                  (mouse_last.x - MOUSE_FUDGE_FACTOR)) &&
   253                 (xevent->xmotion.x <
   254                  (mouse_last.x + MOUSE_FUDGE_FACTOR)) &&
   255                 (xevent->xmotion.y >
   256                  (mouse_last.y - MOUSE_FUDGE_FACTOR)) &&
   257                 (xevent->xmotion.y < (mouse_last.y + MOUSE_FUDGE_FACTOR))) {
   258                 break;
   259             }
   260 #ifdef DEBUG_XEVENTS
   261             printf ("Lost mouse motion: %d,%d\n", xevent->xmotion.x,
   262                     xevent->xmotion.y);
   263 #endif
   264         }
   265 #ifdef DEBUG_XEVENTS
   266         if (i == 10) {
   267             printf ("Warning: didn't detect mouse warp motion\n");
   268         }
   269 #endif
   270     }
   271     return (posted);
   272 }
   273 
   274 static int
   275 X11_DispatchEvent (_THIS)
   276 {
   277     int posted;
   278     XEvent xevent;
   279 
   280     SDL_memset (&xevent, '\0', sizeof (XEvent));        /* valgrind fix. --ryan. */
   281     XNextEvent (SDL_Display, &xevent);
   282 
   283     posted = 0;
   284     switch (xevent.type) {
   285 
   286         /* Gaining mouse coverage? */
   287     case EnterNotify:
   288         {
   289 #ifdef DEBUG_XEVENTS
   290             printf ("EnterNotify! (%d,%d)\n", xevent.xcrossing.x,
   291                     xevent.xcrossing.y);
   292             if (xevent.xcrossing.mode == NotifyGrab)
   293                 printf ("Mode: NotifyGrab\n");
   294             if (xevent.xcrossing.mode == NotifyUngrab)
   295                 printf ("Mode: NotifyUngrab\n");
   296 #endif
   297             if ((xevent.xcrossing.mode != NotifyGrab) &&
   298                 (xevent.xcrossing.mode != NotifyUngrab)) {
   299                 if (SDL_CurrentWindow.input_grab == SDL_GRAB_OFF) {
   300                     posted = SDL_PrivateAppActive (1, SDL_APPMOUSEFOCUS);
   301                 }
   302                 posted = SDL_PrivateMouseMotion (0, 0,
   303                                                  xevent.xcrossing.x,
   304                                                  xevent.xcrossing.y);
   305             }
   306         }
   307         break;
   308 
   309         /* Losing mouse coverage? */
   310     case LeaveNotify:
   311         {
   312 #ifdef DEBUG_XEVENTS
   313             printf ("LeaveNotify! (%d,%d)\n", xevent.xcrossing.x,
   314                     xevent.xcrossing.y);
   315             if (xevent.xcrossing.mode == NotifyGrab)
   316                 printf ("Mode: NotifyGrab\n");
   317             if (xevent.xcrossing.mode == NotifyUngrab)
   318                 printf ("Mode: NotifyUngrab\n");
   319 #endif
   320             if ((xevent.xcrossing.mode != NotifyGrab) &&
   321                 (xevent.xcrossing.mode != NotifyUngrab) &&
   322                 (xevent.xcrossing.detail != NotifyInferior)) {
   323                 if (SDL_CurrentWindow.input_grab == SDL_GRAB_OFF) {
   324                     posted = SDL_PrivateAppActive (0, SDL_APPMOUSEFOCUS);
   325                 } else {
   326                     posted = SDL_PrivateMouseMotion (0, 0,
   327                                                      xevent.xcrossing.x,
   328                                                      xevent.xcrossing.y);
   329                 }
   330             }
   331         }
   332         break;
   333 
   334         /* Gaining input focus? */
   335     case FocusIn:
   336         {
   337 #ifdef DEBUG_XEVENTS
   338             printf ("FocusIn!\n");
   339 #endif
   340             posted = SDL_PrivateAppActive (1, SDL_APPINPUTFOCUS);
   341 
   342 #ifdef X_HAVE_UTF8_STRING
   343             if (SDL_IC != NULL) {
   344                 XSetICFocus (SDL_IC);
   345             }
   346 #endif
   347             /* Queue entry into fullscreen mode */
   348             switch_waiting = 0x01 | SDL_FULLSCREEN;
   349             switch_time = SDL_GetTicks () + 1500;
   350         }
   351         break;
   352 
   353         /* Losing input focus? */
   354     case FocusOut:
   355         {
   356 #ifdef DEBUG_XEVENTS
   357             printf ("FocusOut!\n");
   358 #endif
   359             posted = SDL_PrivateAppActive (0, SDL_APPINPUTFOCUS);
   360 
   361 #ifdef X_HAVE_UTF8_STRING
   362             if (SDL_IC != NULL) {
   363                 XUnsetICFocus (SDL_IC);
   364             }
   365 #endif
   366             /* Queue leaving fullscreen mode */
   367             switch_waiting = 0x01;
   368             switch_time = SDL_GetTicks () + 200;
   369         }
   370         break;
   371 
   372         /* Generated upon EnterWindow and FocusIn */
   373     case KeymapNotify:
   374         {
   375 #ifdef DEBUG_XEVENTS
   376             printf ("KeymapNotify!\n");
   377 #endif
   378             X11_SetKeyboardState (SDL_Display, xevent.xkeymap.key_vector);
   379         }
   380         break;
   381 
   382         /* Mouse motion? */
   383     case MotionNotify:
   384         {
   385             if (SDL_VideoSurface) {
   386                 if (mouse_relative) {
   387                     if (using_dga & DGA_MOUSE) {
   388 #ifdef DEBUG_MOTION
   389                         printf ("DGA motion: %d,%d\n",
   390                                 xevent.xmotion.x_root, xevent.xmotion.y_root);
   391 #endif
   392                         posted = SDL_PrivateMouseMotion (0, 1,
   393                                                          xevent.
   394                                                          xmotion.
   395                                                          x_root,
   396                                                          xevent.
   397                                                          xmotion.y_root);
   398                     } else {
   399                         posted = X11_WarpedMotion (_this, &xevent);
   400                     }
   401                 } else {
   402 #ifdef DEBUG_MOTION
   403                     printf ("X11 motion: %d,%d\n", xevent.xmotion.x,
   404                             xevent.xmotion.y);
   405 #endif
   406                     posted = SDL_PrivateMouseMotion (0, 0,
   407                                                      xevent.xmotion.x,
   408                                                      xevent.xmotion.y);
   409                 }
   410             }
   411         }
   412         break;
   413 
   414         /* Mouse button press? */
   415     case ButtonPress:
   416         {
   417             posted = SDL_PrivateMouseButton (SDL_PRESSED,
   418                                              xevent.xbutton.button, 0, 0);
   419         }
   420         break;
   421 
   422         /* Mouse button release? */
   423     case ButtonRelease:
   424         {
   425             posted = SDL_PrivateMouseButton (SDL_RELEASED,
   426                                              xevent.xbutton.button, 0, 0);
   427         }
   428         break;
   429 
   430         /* Key press? */
   431     case KeyPress:
   432         {
   433             static SDL_keysym saved_keysym;
   434             SDL_keysym keysym;
   435             KeyCode keycode = xevent.xkey.keycode;
   436 
   437 #ifdef DEBUG_XEVENTS
   438             printf ("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
   439 #endif
   440             /* Get the translated SDL virtual keysym */
   441             if (keycode) {
   442                 keysym.scancode = keycode;
   443                 keysym.sym = X11_TranslateKeycode (SDL_Display, keycode);
   444                 keysym.mod = KMOD_NONE;
   445                 keysym.unicode = 0;
   446             } else {
   447                 keysym = saved_keysym;
   448             }
   449 
   450             /* If we're not doing translation, we're done! */
   451             if (!SDL_TranslateUNICODE) {
   452                 posted = SDL_PrivateKeyboard (SDL_PRESSED, &keysym);
   453                 break;
   454             }
   455 
   456             if (XFilterEvent (&xevent, None)) {
   457                 if (xevent.xkey.keycode) {
   458                     posted = SDL_PrivateKeyboard (SDL_PRESSED, &keysym);
   459                 } else {
   460                     /* Save event to be associated with IM text
   461                        In 1.3 we'll have a text event instead.. */
   462                     saved_keysym = keysym;
   463                 }
   464                 break;
   465             }
   466 
   467             /* Look up the translated value for the key event */
   468 #ifdef X_HAVE_UTF8_STRING
   469             if (SDL_IC != NULL) {
   470                 static Status state;
   471                 /* A UTF-8 character can be at most 6 bytes */
   472                 char keybuf[6];
   473                 if (Xutf8LookupString (SDL_IC, &xevent.xkey,
   474                                        keybuf, sizeof (keybuf),
   475                                        NULL, &state)) {
   476                     keysym.unicode = Utf8ToUcs4 ((Uint8 *) keybuf);
   477                 }
   478             } else
   479 #endif
   480             {
   481                 static XComposeStatus state;
   482                 char keybuf[32];
   483 
   484                 if (XLookupString (&xevent.xkey,
   485                                    keybuf, sizeof (keybuf), NULL, &state)) {
   486                     /*
   487                      * FIXME: XLookupString() may yield more than one
   488                      * character, so we need a mechanism to allow for
   489                      * this (perhaps null keypress events with a
   490                      * unicode value)
   491                      */
   492                     keysym.unicode = (Uint8) keybuf[0];
   493                 }
   494             }
   495             posted = SDL_PrivateKeyboard (SDL_PRESSED, &keysym);
   496         }
   497         break;
   498 
   499         /* Key release? */
   500     case KeyRelease:
   501         {
   502             SDL_keysym keysym;
   503             KeyCode keycode = xevent.xkey.keycode;
   504 
   505 #ifdef DEBUG_XEVENTS
   506             printf ("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
   507 #endif
   508             /* Check to see if this is a repeated key */
   509             if (X11_KeyRepeat (SDL_Display, &xevent)) {
   510                 break;
   511             }
   512 
   513             /* Get the translated SDL virtual keysym */
   514             keysym.scancode = keycode;
   515             keysym.sym = X11_TranslateKeycode (SDL_Display, keycode);
   516             keysym.mod = KMOD_NONE;
   517             keysym.unicode = 0;
   518 
   519             posted = SDL_PrivateKeyboard (SDL_RELEASED, &keysym);
   520         }
   521         break;
   522 
   523         /* Have we been iconified? */
   524     case UnmapNotify:
   525         {
   526 #ifdef DEBUG_XEVENTS
   527             printf ("UnmapNotify!\n");
   528 #endif
   529             /* If we're active, make ourselves inactive */
   530             if (SDL_GetAppState () & SDL_APPACTIVE) {
   531                 /* Swap out the gamma before we go inactive */
   532                 X11_SwapVidModeGamma (_this);
   533 
   534                 /* Send an internal deactivate event */
   535                 posted = SDL_PrivateAppActive (0,
   536                                                SDL_APPACTIVE |
   537                                                SDL_APPINPUTFOCUS);
   538             }
   539         }
   540         break;
   541 
   542         /* Have we been restored? */
   543     case MapNotify:
   544         {
   545 #ifdef DEBUG_XEVENTS
   546             printf ("MapNotify!\n");
   547 #endif
   548             /* If we're not active, make ourselves active */
   549             if (!(SDL_GetAppState () & SDL_APPACTIVE)) {
   550                 /* Send an internal activate event */
   551                 posted = SDL_PrivateAppActive (1, SDL_APPACTIVE);
   552 
   553                 /* Now that we're active, swap the gamma back */
   554                 X11_SwapVidModeGamma (_this);
   555             }
   556 
   557             if (SDL_VideoSurface &&
   558                 (SDL_VideoSurface->flags & SDL_FULLSCREEN)) {
   559                 X11_EnterFullScreen (_this);
   560             } else {
   561                 X11_GrabInputNoLock (_this, SDL_CurrentWindow.input_grab);
   562             }
   563             X11_CheckMouseModeNoLock (_this);
   564 
   565             if (SDL_VideoSurface) {
   566                 X11_RefreshDisplay (_this);
   567             }
   568         }
   569         break;
   570 
   571         /* Have we been resized or moved? */
   572     case ConfigureNotify:
   573         {
   574 #ifdef DEBUG_XEVENTS
   575             printf ("ConfigureNotify! (resize: %dx%d)\n",
   576                     xevent.xconfigure.width, xevent.xconfigure.height);
   577 #endif
   578             if (SDL_VideoSurface) {
   579                 if ((xevent.xconfigure.width != SDL_VideoSurface->w) ||
   580                     (xevent.xconfigure.height != SDL_VideoSurface->h)) {
   581                     /* FIXME: Find a better fix for the bug with KDE 1.2 */
   582                     if (!((xevent.xconfigure.width == 32) &&
   583                           (xevent.xconfigure.height == 32))) {
   584                         SDL_PrivateResize (xevent.xconfigure.width,
   585                                            xevent.xconfigure.height);
   586                     }
   587                 } else {
   588                     /* OpenGL windows need to know about the change */
   589                     if (SDL_VideoSurface->flags & SDL_INTERNALOPENGL) {
   590                         SDL_PrivateExpose ();
   591                     }
   592                 }
   593             }
   594         }
   595         break;
   596 
   597         /* Have we been requested to quit (or another client message?) */
   598     case ClientMessage:
   599         {
   600             if ((xevent.xclient.format == 32) &&
   601                 (xevent.xclient.data.l[0] == WM_DELETE_WINDOW)) {
   602                 posted = SDL_PrivateQuit ();
   603             } else if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) {
   604                 SDL_SysWMmsg wmmsg;
   605 
   606                 SDL_VERSION (&wmmsg.version);
   607                 wmmsg.subsystem = SDL_SYSWM_X11;
   608                 wmmsg.event.xevent = xevent;
   609                 posted = SDL_PrivateSysWMEvent (&wmmsg);
   610             }
   611         }
   612         break;
   613 
   614         /* Do we need to refresh ourselves? */
   615     case Expose:
   616         {
   617 #ifdef DEBUG_XEVENTS
   618             printf ("Expose (count = %d)\n", xevent.xexpose.count);
   619 #endif
   620             if (SDL_VideoSurface && (xevent.xexpose.count == 0)) {
   621                 X11_RefreshDisplay (_this);
   622             }
   623         }
   624         break;
   625 
   626     default:
   627         {
   628 #ifdef DEBUG_XEVENTS
   629             printf ("Unhandled event %d\n", xevent.type);
   630 #endif
   631             /* Only post the event if we're watching for it */
   632             if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) {
   633                 SDL_SysWMmsg wmmsg;
   634 
   635                 SDL_VERSION (&wmmsg.version);
   636                 wmmsg.subsystem = SDL_SYSWM_X11;
   637                 wmmsg.event.xevent = xevent;
   638                 posted = SDL_PrivateSysWMEvent (&wmmsg);
   639             }
   640         }
   641         break;
   642     }
   643     return (posted);
   644 }
   645 
   646 /* Ack!  XPending() actually performs a blocking read if no events available */
   647 int
   648 X11_Pending (Display * display)
   649 {
   650     /* Flush the display connection and look to see if events are queued */
   651     XFlush (display);
   652     if (XEventsQueued (display, QueuedAlready)) {
   653         return (1);
   654     }
   655 
   656     /* More drastic measures are required -- see if X is ready to talk */
   657     {
   658         static struct timeval zero_time;        /* static == 0 */
   659         int x11_fd;
   660         fd_set fdset;
   661 
   662         x11_fd = ConnectionNumber (display);
   663         FD_ZERO (&fdset);
   664         FD_SET (x11_fd, &fdset);
   665         if (select (x11_fd + 1, &fdset, NULL, NULL, &zero_time) == 1) {
   666             return (XPending (display));
   667         }
   668     }
   669 
   670     /* Oh well, nothing is ready .. */
   671     return (0);
   672 }
   673 
   674 void
   675 X11_PumpEvents (_THIS)
   676 {
   677     int pending;
   678 
   679     /* Keep processing pending events */
   680     pending = 0;
   681     while (X11_Pending (SDL_Display)) {
   682         X11_DispatchEvent (_this);
   683         ++pending;
   684     }
   685     if (switch_waiting) {
   686         Uint32 now;
   687 
   688         now = SDL_GetTicks ();
   689         if (pending || !SDL_VideoSurface) {
   690             /* Try again later... */
   691             if (switch_waiting & SDL_FULLSCREEN) {
   692                 switch_time = now + 1500;
   693             } else {
   694                 switch_time = now + 200;
   695             }
   696         } else if ((int) (switch_time - now) <= 0) {
   697             Uint32 go_fullscreen;
   698 
   699             go_fullscreen = switch_waiting & SDL_FULLSCREEN;
   700             switch_waiting = 0;
   701             if (SDL_VideoSurface->flags & SDL_FULLSCREEN) {
   702                 if (go_fullscreen) {
   703                     X11_EnterFullScreen (_this);
   704                 } else {
   705                     X11_LeaveFullScreen (_this);
   706                 }
   707             }
   708             /* Handle focus in/out when grabbed */
   709             if (go_fullscreen) {
   710                 X11_GrabInputNoLock (_this, SDL_CurrentWindow.input_grab);
   711             } else {
   712                 X11_GrabInputNoLock (_this, SDL_GRAB_OFF);
   713             }
   714             X11_CheckMouseModeNoLock (_this);
   715         }
   716     }
   717 }
   718 
   719 void
   720 X11_InitKeymap (void)
   721 {
   722     int i;
   723 
   724     /* Odd keys used in international keyboards */
   725     for (i = 0; i < SDL_arraysize (ODD_keymap); ++i)
   726         ODD_keymap[i] = SDLK_UNKNOWN;
   727 
   728     /* Some of these might be mappable to an existing SDLK_ code */
   729     ODD_keymap[XK_dead_grave & 0xFF] = SDLK_COMPOSE;
   730     ODD_keymap[XK_dead_acute & 0xFF] = SDLK_COMPOSE;
   731     ODD_keymap[XK_dead_tilde & 0xFF] = SDLK_COMPOSE;
   732     ODD_keymap[XK_dead_macron & 0xFF] = SDLK_COMPOSE;
   733     ODD_keymap[XK_dead_breve & 0xFF] = SDLK_COMPOSE;
   734     ODD_keymap[XK_dead_abovedot & 0xFF] = SDLK_COMPOSE;
   735     ODD_keymap[XK_dead_diaeresis & 0xFF] = SDLK_COMPOSE;
   736     ODD_keymap[XK_dead_abovering & 0xFF] = SDLK_COMPOSE;
   737     ODD_keymap[XK_dead_doubleacute & 0xFF] = SDLK_COMPOSE;
   738     ODD_keymap[XK_dead_caron & 0xFF] = SDLK_COMPOSE;
   739     ODD_keymap[XK_dead_cedilla & 0xFF] = SDLK_COMPOSE;
   740     ODD_keymap[XK_dead_ogonek & 0xFF] = SDLK_COMPOSE;
   741     ODD_keymap[XK_dead_iota & 0xFF] = SDLK_COMPOSE;
   742     ODD_keymap[XK_dead_voiced_sound & 0xFF] = SDLK_COMPOSE;
   743     ODD_keymap[XK_dead_semivoiced_sound & 0xFF] = SDLK_COMPOSE;
   744     ODD_keymap[XK_dead_belowdot & 0xFF] = SDLK_COMPOSE;
   745 #ifdef XK_dead_hook
   746     ODD_keymap[XK_dead_hook & 0xFF] = SDLK_COMPOSE;
   747 #endif
   748 #ifdef XK_dead_horn
   749     ODD_keymap[XK_dead_horn & 0xFF] = SDLK_COMPOSE;
   750 #endif
   751 
   752 #ifdef XK_dead_circumflex
   753     /* These X keysyms have 0xFE as the high byte */
   754     ODD_keymap[XK_dead_circumflex & 0xFF] = SDLK_CARET;
   755 #endif
   756 #ifdef XK_ISO_Level3_Shift
   757     ODD_keymap[XK_ISO_Level3_Shift & 0xFF] = SDLK_MODE; /* "Alt Gr" key */
   758 #endif
   759 
   760     /* Map the miscellaneous keys */
   761     for (i = 0; i < SDL_arraysize (MISC_keymap); ++i)
   762         MISC_keymap[i] = SDLK_UNKNOWN;
   763 
   764     /* These X keysyms have 0xFF as the high byte */
   765     MISC_keymap[XK_BackSpace & 0xFF] = SDLK_BACKSPACE;
   766     MISC_keymap[XK_Tab & 0xFF] = SDLK_TAB;
   767     MISC_keymap[XK_Clear & 0xFF] = SDLK_CLEAR;
   768     MISC_keymap[XK_Return & 0xFF] = SDLK_RETURN;
   769     MISC_keymap[XK_Pause & 0xFF] = SDLK_PAUSE;
   770     MISC_keymap[XK_Escape & 0xFF] = SDLK_ESCAPE;
   771     MISC_keymap[XK_Delete & 0xFF] = SDLK_DELETE;
   772 
   773     MISC_keymap[XK_KP_0 & 0xFF] = SDLK_KP0;     /* Keypad 0-9 */
   774     MISC_keymap[XK_KP_1 & 0xFF] = SDLK_KP1;
   775     MISC_keymap[XK_KP_2 & 0xFF] = SDLK_KP2;
   776     MISC_keymap[XK_KP_3 & 0xFF] = SDLK_KP3;
   777     MISC_keymap[XK_KP_4 & 0xFF] = SDLK_KP4;
   778     MISC_keymap[XK_KP_5 & 0xFF] = SDLK_KP5;
   779     MISC_keymap[XK_KP_6 & 0xFF] = SDLK_KP6;
   780     MISC_keymap[XK_KP_7 & 0xFF] = SDLK_KP7;
   781     MISC_keymap[XK_KP_8 & 0xFF] = SDLK_KP8;
   782     MISC_keymap[XK_KP_9 & 0xFF] = SDLK_KP9;
   783     MISC_keymap[XK_KP_Insert & 0xFF] = SDLK_KP0;
   784     MISC_keymap[XK_KP_End & 0xFF] = SDLK_KP1;
   785     MISC_keymap[XK_KP_Down & 0xFF] = SDLK_KP2;
   786     MISC_keymap[XK_KP_Page_Down & 0xFF] = SDLK_KP3;
   787     MISC_keymap[XK_KP_Left & 0xFF] = SDLK_KP4;
   788     MISC_keymap[XK_KP_Begin & 0xFF] = SDLK_KP5;
   789     MISC_keymap[XK_KP_Right & 0xFF] = SDLK_KP6;
   790     MISC_keymap[XK_KP_Home & 0xFF] = SDLK_KP7;
   791     MISC_keymap[XK_KP_Up & 0xFF] = SDLK_KP8;
   792     MISC_keymap[XK_KP_Page_Up & 0xFF] = SDLK_KP9;
   793     MISC_keymap[XK_KP_Delete & 0xFF] = SDLK_KP_PERIOD;
   794     MISC_keymap[XK_KP_Decimal & 0xFF] = SDLK_KP_PERIOD;
   795     MISC_keymap[XK_KP_Divide & 0xFF] = SDLK_KP_DIVIDE;
   796     MISC_keymap[XK_KP_Multiply & 0xFF] = SDLK_KP_MULTIPLY;
   797     MISC_keymap[XK_KP_Subtract & 0xFF] = SDLK_KP_MINUS;
   798     MISC_keymap[XK_KP_Add & 0xFF] = SDLK_KP_PLUS;
   799     MISC_keymap[XK_KP_Enter & 0xFF] = SDLK_KP_ENTER;
   800     MISC_keymap[XK_KP_Equal & 0xFF] = SDLK_KP_EQUALS;
   801 
   802     MISC_keymap[XK_Up & 0xFF] = SDLK_UP;
   803     MISC_keymap[XK_Down & 0xFF] = SDLK_DOWN;
   804     MISC_keymap[XK_Right & 0xFF] = SDLK_RIGHT;
   805     MISC_keymap[XK_Left & 0xFF] = SDLK_LEFT;
   806     MISC_keymap[XK_Insert & 0xFF] = SDLK_INSERT;
   807     MISC_keymap[XK_Home & 0xFF] = SDLK_HOME;
   808     MISC_keymap[XK_End & 0xFF] = SDLK_END;
   809     MISC_keymap[XK_Page_Up & 0xFF] = SDLK_PAGEUP;
   810     MISC_keymap[XK_Page_Down & 0xFF] = SDLK_PAGEDOWN;
   811 
   812     MISC_keymap[XK_F1 & 0xFF] = SDLK_F1;
   813     MISC_keymap[XK_F2 & 0xFF] = SDLK_F2;
   814     MISC_keymap[XK_F3 & 0xFF] = SDLK_F3;
   815     MISC_keymap[XK_F4 & 0xFF] = SDLK_F4;
   816     MISC_keymap[XK_F5 & 0xFF] = SDLK_F5;
   817     MISC_keymap[XK_F6 & 0xFF] = SDLK_F6;
   818     MISC_keymap[XK_F7 & 0xFF] = SDLK_F7;
   819     MISC_keymap[XK_F8 & 0xFF] = SDLK_F8;
   820     MISC_keymap[XK_F9 & 0xFF] = SDLK_F9;
   821     MISC_keymap[XK_F10 & 0xFF] = SDLK_F10;
   822     MISC_keymap[XK_F11 & 0xFF] = SDLK_F11;
   823     MISC_keymap[XK_F12 & 0xFF] = SDLK_F12;
   824     MISC_keymap[XK_F13 & 0xFF] = SDLK_F13;
   825     MISC_keymap[XK_F14 & 0xFF] = SDLK_F14;
   826     MISC_keymap[XK_F15 & 0xFF] = SDLK_F15;
   827 
   828     MISC_keymap[XK_Num_Lock & 0xFF] = SDLK_NUMLOCK;
   829     MISC_keymap[XK_Caps_Lock & 0xFF] = SDLK_CAPSLOCK;
   830     MISC_keymap[XK_Scroll_Lock & 0xFF] = SDLK_SCROLLOCK;
   831     MISC_keymap[XK_Shift_R & 0xFF] = SDLK_RSHIFT;
   832     MISC_keymap[XK_Shift_L & 0xFF] = SDLK_LSHIFT;
   833     MISC_keymap[XK_Control_R & 0xFF] = SDLK_RCTRL;
   834     MISC_keymap[XK_Control_L & 0xFF] = SDLK_LCTRL;
   835     MISC_keymap[XK_Alt_R & 0xFF] = SDLK_RALT;
   836     MISC_keymap[XK_Alt_L & 0xFF] = SDLK_LALT;
   837     MISC_keymap[XK_Meta_R & 0xFF] = SDLK_RMETA;
   838     MISC_keymap[XK_Meta_L & 0xFF] = SDLK_LMETA;
   839     MISC_keymap[XK_Super_L & 0xFF] = SDLK_LSUPER;       /* Left "Windows" */
   840     MISC_keymap[XK_Super_R & 0xFF] = SDLK_RSUPER;       /* Right "Windows */
   841     MISC_keymap[XK_Mode_switch & 0xFF] = SDLK_MODE;     /* "Alt Gr" key */
   842     MISC_keymap[XK_Multi_key & 0xFF] = SDLK_COMPOSE;    /* Multi-key compose */
   843 
   844     MISC_keymap[XK_Help & 0xFF] = SDLK_HELP;
   845     MISC_keymap[XK_Print & 0xFF] = SDLK_PRINT;
   846     MISC_keymap[XK_Sys_Req & 0xFF] = SDLK_SYSREQ;
   847     MISC_keymap[XK_Break & 0xFF] = SDLK_BREAK;
   848     MISC_keymap[XK_Menu & 0xFF] = SDLK_MENU;
   849     MISC_keymap[XK_Hyper_R & 0xFF] = SDLK_MENU; /* Windows "Menu" key */
   850 }
   851 
   852 /* Get the translated SDL virtual keysym */
   853 SDLKey
   854 X11_TranslateKeycode (Display * display, KeyCode kc)
   855 {
   856     KeySym xsym;
   857     SDLKey key;
   858 
   859     xsym = XKeycodeToKeysym (display, kc, 0);
   860 #ifdef DEBUG_KEYS
   861     fprintf (stderr, "Translating key code %d -> 0x%.4x\n", kc, xsym);
   862 #endif
   863     key = SDLK_UNKNOWN;
   864     if (xsym) {
   865         switch (xsym >> 8) {
   866         case 0x1005FF:
   867 #ifdef SunXK_F36
   868             if (xsym == SunXK_F36)
   869                 key = SDLK_F11;
   870 #endif
   871 #ifdef SunXK_F37
   872             if (xsym == SunXK_F37)
   873                 key = SDLK_F12;
   874 #endif
   875             break;
   876         case 0x00:             /* Latin 1 */
   877             key = (SDLKey) (xsym & 0xFF);
   878             break;
   879         case 0x01:             /* Latin 2 */
   880         case 0x02:             /* Latin 3 */
   881         case 0x03:             /* Latin 4 */
   882         case 0x04:             /* Katakana */
   883         case 0x05:             /* Arabic */
   884         case 0x06:             /* Cyrillic */
   885         case 0x07:             /* Greek */
   886         case 0x08:             /* Technical */
   887         case 0x0A:             /* Publishing */
   888         case 0x0C:             /* Hebrew */
   889         case 0x0D:             /* Thai */
   890             /* These are wrong, but it's better than nothing */
   891             key = (SDLKey) (xsym & 0xFF);
   892             break;
   893         case 0xFE:
   894             key = ODD_keymap[xsym & 0xFF];
   895             break;
   896         case 0xFF:
   897             key = MISC_keymap[xsym & 0xFF];
   898             break;
   899         default:
   900             /*
   901                fprintf(stderr, "X11: Unhandled xsym, sym = 0x%04x\n",
   902                (unsigned int)xsym);
   903              */
   904             break;
   905         }
   906     } else {
   907         /* X11 doesn't know how to translate the key! */
   908         switch (kc) {
   909             /* Caution:
   910                These keycodes are from the Microsoft Keyboard
   911              */
   912         case 115:
   913             key = SDLK_LSUPER;
   914             break;
   915         case 116:
   916             key = SDLK_RSUPER;
   917             break;
   918         case 117:
   919             key = SDLK_MENU;
   920             break;
   921         default:
   922             /*
   923              * no point in an error message; happens for
   924              * several keys when we get a keymap notify
   925              */
   926             break;
   927         }
   928     }
   929     return key;
   930 }
   931 
   932 /* X11 modifier masks for various keys */
   933 static unsigned meta_l_mask, meta_r_mask, alt_l_mask, alt_r_mask;
   934 static unsigned num_mask, mode_switch_mask;
   935 
   936 static void
   937 get_modifier_masks (Display * display)
   938 {
   939     static unsigned got_masks;
   940     int i, j;
   941     XModifierKeymap *xmods;
   942     unsigned n;
   943 
   944     if (got_masks)
   945         return;
   946 
   947     xmods = XGetModifierMapping (display);
   948     n = xmods->max_keypermod;
   949     for (i = 3; i < 8; i++) {
   950         for (j = 0; j < n; j++) {
   951             KeyCode kc = xmods->modifiermap[i * n + j];
   952             KeySym ks = XKeycodeToKeysym (display, kc, 0);
   953             unsigned mask = 1 << i;
   954             switch (ks) {
   955             case XK_Num_Lock:
   956                 num_mask = mask;
   957                 break;
   958             case XK_Alt_L:
   959                 alt_l_mask = mask;
   960                 break;
   961             case XK_Alt_R:
   962                 alt_r_mask = mask;
   963                 break;
   964             case XK_Meta_L:
   965                 meta_l_mask = mask;
   966                 break;
   967             case XK_Meta_R:
   968                 meta_r_mask = mask;
   969                 break;
   970             case XK_Mode_switch:
   971                 mode_switch_mask = mask;
   972                 break;
   973             }
   974         }
   975     }
   976     XFreeModifiermap (xmods);
   977     got_masks = 1;
   978 }
   979 
   980 
   981 /*
   982  * This function is semi-official; it is not officially exported and should
   983  * not be considered part of the SDL API, but may be used by client code
   984  * that *really* needs it (including legacy code).
   985  * It is slow, though, and should be avoided if possible.
   986  *
   987  * Note that it isn't completely accurate either; in particular, multi-key
   988  * sequences (dead accents, compose key sequences) will not work since the
   989  * state has been irrevocably lost.
   990  */
   991 Uint16
   992 X11_KeyToUnicode (SDLKey keysym, SDLMod modifiers)
   993 {
   994     SDL_VideoDevice *_this = SDL_GetVideoDevice ();
   995     char keybuf[32];
   996     int i;
   997     KeySym xsym = 0;
   998     XKeyEvent xkey;
   999     Uint16 unicode;
  1000 
  1001     if (!_this || !SDL_Display) {
  1002         return 0;
  1003     }
  1004 
  1005     SDL_memset (&xkey, 0, sizeof (xkey));
  1006     xkey.display = SDL_Display;
  1007 
  1008     xsym = keysym;              /* last resort if not found */
  1009     for (i = 0; i < 256; ++i) {
  1010         if (MISC_keymap[i] == keysym) {
  1011             xsym = 0xFF00 | i;
  1012             break;
  1013         } else if (ODD_keymap[i] == keysym) {
  1014             xsym = 0xFE00 | i;
  1015             break;
  1016         }
  1017     }
  1018 
  1019     xkey.keycode = XKeysymToKeycode (xkey.display, xsym);
  1020 
  1021     get_modifier_masks (SDL_Display);
  1022     if (modifiers & KMOD_SHIFT)
  1023         xkey.state |= ShiftMask;
  1024     if (modifiers & KMOD_CAPS)
  1025         xkey.state |= LockMask;
  1026     if (modifiers & KMOD_CTRL)
  1027         xkey.state |= ControlMask;
  1028     if (modifiers & KMOD_MODE)
  1029         xkey.state |= mode_switch_mask;
  1030     if (modifiers & KMOD_LALT)
  1031         xkey.state |= alt_l_mask;
  1032     if (modifiers & KMOD_RALT)
  1033         xkey.state |= alt_r_mask;
  1034     if (modifiers & KMOD_LMETA)
  1035         xkey.state |= meta_l_mask;
  1036     if (modifiers & KMOD_RMETA)
  1037         xkey.state |= meta_r_mask;
  1038     if (modifiers & KMOD_NUM)
  1039         xkey.state |= num_mask;
  1040 
  1041     unicode = 0;
  1042     if (XLookupString (&xkey, keybuf, sizeof (keybuf), NULL, NULL))
  1043         unicode = (unsigned char) keybuf[0];
  1044     return (unicode);
  1045 }
  1046 
  1047 
  1048 /*
  1049  * Called when focus is regained, to read the keyboard state and generate
  1050  * synthetic keypress/release events.
  1051  * key_vec is a bit vector of keycodes (256 bits)
  1052  */
  1053 void
  1054 X11_SetKeyboardState (Display * display, const char *key_vec)
  1055 {
  1056     char keys_return[32];
  1057     int i;
  1058     Uint8 *kstate = SDL_GetKeyState (NULL);
  1059     SDLMod modstate;
  1060     Window junk_window;
  1061     int x, y;
  1062     unsigned int mask;
  1063 
  1064     /* The first time the window is mapped, we initialize key state */
  1065     if (!key_vec) {
  1066         XQueryKeymap (display, keys_return);
  1067         key_vec = keys_return;
  1068     }
  1069 
  1070     /* Get the keyboard modifier state */
  1071     modstate = 0;
  1072     get_modifier_masks (display);
  1073     if (XQueryPointer (display, DefaultRootWindow (display),
  1074                        &junk_window, &junk_window, &x, &y, &x, &y, &mask)) {
  1075         if (mask & LockMask) {
  1076             modstate |= KMOD_CAPS;
  1077         }
  1078         if (mask & mode_switch_mask) {
  1079             modstate |= KMOD_MODE;
  1080         }
  1081         if (mask & num_mask) {
  1082             modstate |= KMOD_NUM;
  1083         }
  1084     }
  1085 
  1086     /* Zero the new keyboard state and generate it */
  1087     SDL_memset (kstate, 0, SDLK_LAST);
  1088     /*
  1089      * An obvious optimisation is to check entire longwords at a time in
  1090      * both loops, but we can't be sure the arrays are aligned so it's not
  1091      * worth the extra complexity
  1092      */
  1093     for (i = 0; i < 32; i++) {
  1094         int j;
  1095         if (!key_vec[i])
  1096             continue;
  1097         for (j = 0; j < 8; j++) {
  1098             if (key_vec[i] & (1 << j)) {
  1099                 SDLKey key;
  1100                 KeyCode kc = (i << 3 | j);
  1101                 key = X11_TranslateKeycode (display, kc);
  1102                 if (key == SDLK_UNKNOWN) {
  1103                     continue;
  1104                 }
  1105                 kstate[key] = SDL_PRESSED;
  1106                 switch (key) {
  1107                 case SDLK_LSHIFT:
  1108                     modstate |= KMOD_LSHIFT;
  1109                     break;
  1110                 case SDLK_RSHIFT:
  1111                     modstate |= KMOD_RSHIFT;
  1112                     break;
  1113                 case SDLK_LCTRL:
  1114                     modstate |= KMOD_LCTRL;
  1115                     break;
  1116                 case SDLK_RCTRL:
  1117                     modstate |= KMOD_RCTRL;
  1118                     break;
  1119                 case SDLK_LALT:
  1120                     modstate |= KMOD_LALT;
  1121                     break;
  1122                 case SDLK_RALT:
  1123                     modstate |= KMOD_RALT;
  1124                     break;
  1125                 case SDLK_LMETA:
  1126                     modstate |= KMOD_LMETA;
  1127                     break;
  1128                 case SDLK_RMETA:
  1129                     modstate |= KMOD_RMETA;
  1130                     break;
  1131                 default:
  1132                     break;
  1133                 }
  1134             }
  1135         }
  1136     }
  1137 
  1138     /* Hack - set toggle key state */
  1139     if (modstate & KMOD_CAPS) {
  1140         kstate[SDLK_CAPSLOCK] = SDL_PRESSED;
  1141     } else {
  1142         kstate[SDLK_CAPSLOCK] = SDL_RELEASED;
  1143     }
  1144     if (modstate & KMOD_NUM) {
  1145         kstate[SDLK_NUMLOCK] = SDL_PRESSED;
  1146     } else {
  1147         kstate[SDLK_NUMLOCK] = SDL_RELEASED;
  1148     }
  1149 
  1150     /* Set the final modifier state */
  1151     SDL_SetModState (modstate);
  1152 }
  1153 
  1154 void
  1155 X11_InitOSKeymap (_THIS)
  1156 {
  1157     X11_InitKeymap ();
  1158 }
  1159 
  1160 void
  1161 X11_SaveScreenSaver (Display * display, int *saved_timeout, BOOL * dpms)
  1162 {
  1163     int timeout, interval, prefer_blank, allow_exp;
  1164     XGetScreenSaver (display, &timeout, &interval, &prefer_blank, &allow_exp);
  1165     *saved_timeout = timeout;
  1166 
  1167 #if SDL_VIDEO_DRIVER_X11_DPMS
  1168     if (SDL_X11_HAVE_DPMS) {
  1169         int dummy;
  1170         if (DPMSQueryExtension (display, &dummy, &dummy)) {
  1171             CARD16 state;
  1172             DPMSInfo (display, &state, dpms);
  1173         }
  1174     }
  1175 #else
  1176     *dpms = 0;
  1177 #endif /* SDL_VIDEO_DRIVER_X11_DPMS */
  1178 }
  1179 
  1180 void
  1181 X11_DisableScreenSaver (Display * display)
  1182 {
  1183     int timeout, interval, prefer_blank, allow_exp;
  1184     XGetScreenSaver (display, &timeout, &interval, &prefer_blank, &allow_exp);
  1185     timeout = 0;
  1186     XSetScreenSaver (display, timeout, interval, prefer_blank, allow_exp);
  1187 
  1188 #if SDL_VIDEO_DRIVER_X11_DPMS
  1189     if (SDL_X11_HAVE_DPMS) {
  1190         int dummy;
  1191         if (DPMSQueryExtension (display, &dummy, &dummy)) {
  1192             DPMSDisable (display);
  1193         }
  1194     }
  1195 #endif /* SDL_VIDEO_DRIVER_X11_DPMS */
  1196 }
  1197 
  1198 void
  1199 X11_RestoreScreenSaver (Display * display, int saved_timeout, BOOL dpms)
  1200 {
  1201     int timeout, interval, prefer_blank, allow_exp;
  1202     XGetScreenSaver (display, &timeout, &interval, &prefer_blank, &allow_exp);
  1203     timeout = saved_timeout;
  1204     XSetScreenSaver (display, timeout, interval, prefer_blank, allow_exp);
  1205 
  1206 #if SDL_VIDEO_DRIVER_X11_DPMS
  1207     if (SDL_X11_HAVE_DPMS) {
  1208         int dummy;
  1209         if (DPMSQueryExtension (display, &dummy, &dummy)) {
  1210             if (dpms) {
  1211                 DPMSEnable (display);
  1212             }
  1213         }
  1214     }
  1215 #endif /* SDL_VIDEO_DRIVER_X11_DPMS */
  1216 }
  1217 
  1218 /* vi: set ts=4 sw=4 expandtab: */