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