src/video/x11/SDL_x11events.c
author Bob Pendleton <bob@pendleton.com>
Thu, 06 Mar 2008 23:07:02 +0000
changeset 2323 4ac07ae446d3
parent 2306 1a8bab15a45d
child 2324 3202e4826c57
permissions -rw-r--r--
Fixed many valgrind errors. But, I broke testdyngl.
     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 static void
    33 X11_DispatchEvent(_THIS)
    34 {
    35     SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
    36     SDL_WindowData *data;
    37     XEvent xevent;
    38     int i;
    39 
    40     SDL_zero(xevent);           /* valgrind fix. --ryan. */
    41     XNextEvent(videodata->display, &xevent);
    42 
    43     /* Send a SDL_SYSWMEVENT if the application wants them */
    44     if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) {
    45         SDL_SysWMmsg wmmsg;
    46 
    47         SDL_VERSION(&wmmsg.version);
    48         wmmsg.subsystem = SDL_SYSWM_X11;
    49         wmmsg.event.xevent = xevent;
    50         SDL_SendSysWMEvent(&wmmsg);
    51     }
    52 
    53     data = NULL;
    54     if (videodata && 
    55         videodata->windowlist) {
    56       for (i = 0; i < videodata->numwindows; ++i) {
    57         if ((videodata->windowlist[i] != NULL) &&
    58             (videodata->windowlist[i]->window == xevent.xany.window)) {
    59           data = videodata->windowlist[i];
    60           break;
    61         }
    62       }
    63     }
    64     if (!data) {
    65         return;
    66     }
    67 
    68     switch (xevent.type) {
    69 
    70         /* Gaining mouse coverage? */
    71     case EnterNotify:{
    72 #ifdef DEBUG_XEVENTS
    73             printf("EnterNotify! (%d,%d)\n", xevent.xcrossing.x,
    74                    xevent.xcrossing.y);
    75             if (xevent.xcrossing.mode == NotifyGrab)
    76                 printf("Mode: NotifyGrab\n");
    77             if (xevent.xcrossing.mode == NotifyUngrab)
    78                 printf("Mode: NotifyUngrab\n");
    79 #endif
    80             if ((xevent.xcrossing.mode != NotifyGrab) &&
    81                 (xevent.xcrossing.mode != NotifyUngrab)) {
    82                 SDL_SetMouseFocus(videodata->mouse, data->windowID);
    83                 SDL_SendMouseMotion(videodata->mouse, 0, xevent.xcrossing.x,
    84                                     xevent.xcrossing.y);
    85             }
    86         }
    87         break;
    88 
    89         /* Losing mouse coverage? */
    90     case LeaveNotify:{
    91 #ifdef DEBUG_XEVENTS
    92             printf("LeaveNotify! (%d,%d)\n", xevent.xcrossing.x,
    93                    xevent.xcrossing.y);
    94             if (xevent.xcrossing.mode == NotifyGrab)
    95                 printf("Mode: NotifyGrab\n");
    96             if (xevent.xcrossing.mode == NotifyUngrab)
    97                 printf("Mode: NotifyUngrab\n");
    98 #endif
    99             if ((xevent.xcrossing.mode != NotifyGrab) &&
   100                 (xevent.xcrossing.mode != NotifyUngrab) &&
   101                 (xevent.xcrossing.detail != NotifyInferior)) {
   102                 SDL_SendMouseMotion(videodata->mouse, 0,
   103                                     xevent.xcrossing.x, xevent.xcrossing.y);
   104                 SDL_SetMouseFocus(videodata->mouse, 0);
   105             }
   106         }
   107         break;
   108 
   109         /* Gaining input focus? */
   110     case FocusIn:{
   111 #ifdef DEBUG_XEVENTS
   112             printf("FocusIn!\n");
   113 #endif
   114             SDL_SetKeyboardFocus(videodata->keyboard, data->windowID);
   115 #ifdef X_HAVE_UTF8_STRING
   116             if (data->ic) {
   117                 XSetICFocus(data->ic);
   118             }
   119 #endif
   120         }
   121         break;
   122 
   123         /* Losing input focus? */
   124     case FocusOut:{
   125 #ifdef DEBUG_XEVENTS
   126             printf("FocusOut!\n");
   127 #endif
   128             SDL_SetKeyboardFocus(videodata->keyboard, 0);
   129 #ifdef X_HAVE_UTF8_STRING
   130             if (data->ic) {
   131                 XUnsetICFocus(data->ic);
   132             }
   133 #endif
   134         }
   135         break;
   136 
   137         /* Generated upon EnterWindow and FocusIn */
   138     case KeymapNotify:{
   139 #ifdef DEBUG_XEVENTS
   140             printf("KeymapNotify!\n");
   141 #endif
   142             /* FIXME:
   143                X11_SetKeyboardState(SDL_Display, xevent.xkeymap.key_vector);
   144              */
   145         }
   146         break;
   147 
   148         /* Has the keyboard layout changed? */
   149     case MappingNotify:{
   150 #ifdef DEBUG_XEVENTS
   151             printf("MappingNotify!\n");
   152 #endif
   153             X11_UpdateKeymap(_this);
   154         }
   155         break;
   156 
   157         /* Mouse motion? */
   158     case MotionNotify:{
   159 #ifdef DEBUG_MOTION
   160             printf("X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y);
   161 #endif
   162             SDL_SendMouseMotion(videodata->mouse, 0, xevent.xmotion.x,
   163                                 xevent.xmotion.y);
   164         }
   165         break;
   166 
   167         /* Mouse button press? */
   168     case ButtonPress:{
   169             SDL_SendMouseButton(videodata->mouse, SDL_PRESSED,
   170                                 xevent.xbutton.button);
   171         }
   172         break;
   173 
   174         /* Mouse button release? */
   175     case ButtonRelease:{
   176             SDL_SendMouseButton(videodata->mouse, SDL_RELEASED,
   177                                 xevent.xbutton.button);
   178         }
   179         break;
   180 
   181         /* Key press? */
   182     case KeyPress:{
   183             KeyCode keycode = xevent.xkey.keycode;
   184             KeySym keysym = NoSymbol;
   185             char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
   186             Uint32 ucs4 = 0;
   187 
   188 #ifdef DEBUG_XEVENTS
   189             printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
   190 #endif
   191             SDL_SendKeyboardKey(videodata->keyboard, SDL_PRESSED,
   192                                 videodata->key_layout[keycode]);
   193 #if 1
   194             if (videodata->key_layout[keycode] == SDLK_UNKNOWN) {
   195                 int min_keycode, max_keycode;
   196                 XDisplayKeycodes(videodata->display, &min_keycode,
   197                                  &max_keycode);
   198                 keysym = XKeycodeToKeysym(videodata->display, keycode, 0);
   199                 fprintf(stderr,
   200                         "The key you just pressed is not recognized by SDL. To help get this fixed, please report this to the SDL mailing list <sdl@libsdl.org> X11 KeyCode %d (%d), X11 KeySym 0x%X (%s).\n",
   201                         keycode, keycode - min_keycode, keysym,
   202                         XKeysymToString(keysym));
   203             }
   204 #endif
   205             /* Xutf8LookupString(), works for Latin-1 */
   206             SDL_zero(text);
   207             XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL);
   208             if (*text) {
   209                 printf("Sending text event %s\n", text);
   210                 SDL_SendKeyboardText(videodata->keyboard, text);
   211             }
   212         }
   213         break;
   214 
   215         /* Key release? */
   216     case KeyRelease:{
   217             KeyCode keycode = xevent.xkey.keycode;
   218 
   219 #ifdef DEBUG_XEVENTS
   220             printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
   221 #endif
   222             SDL_SendKeyboardKey(videodata->keyboard, SDL_RELEASED,
   223                                 videodata->key_layout[keycode]);
   224         }
   225         break;
   226 
   227         /* Have we been iconified? */
   228     case UnmapNotify:{
   229 #ifdef DEBUG_XEVENTS
   230             printf("UnmapNotify!\n");
   231 #endif
   232             SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_HIDDEN, 0, 0);
   233             SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_MINIMIZED, 0,
   234                                 0);
   235         }
   236         break;
   237 
   238         /* Have we been restored? */
   239     case MapNotify:{
   240 #ifdef DEBUG_XEVENTS
   241             printf("MapNotify!\n");
   242 #endif
   243             SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_SHOWN, 0, 0);
   244             SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_RESTORED, 0,
   245                                 0);
   246         }
   247         break;
   248 
   249         /* Have we been resized or moved? */
   250     case ConfigureNotify:{
   251 #ifdef DEBUG_XEVENTS
   252             printf("ConfigureNotify! (resize: %dx%d)\n",
   253                    xevent.xconfigure.width, xevent.xconfigure.height);
   254 #endif
   255             SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_MOVED,
   256                                 xevent.xconfigure.x, xevent.xconfigure.y);
   257             SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_RESIZED,
   258                                 xevent.xconfigure.width,
   259                                 xevent.xconfigure.height);
   260         }
   261         break;
   262 
   263         /* Have we been requested to quit (or another client message?) */
   264     case ClientMessage:{
   265             if ((xevent.xclient.format == 32) &&
   266                 (xevent.xclient.data.l[0] == videodata->WM_DELETE_WINDOW)) {
   267 
   268                 SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_CLOSE, 0,
   269                                     0);
   270             }
   271         }
   272         break;
   273 
   274         /* Do we need to refresh ourselves? */
   275     case Expose:{
   276 #ifdef DEBUG_XEVENTS
   277             printf("Expose (count = %d)\n", xevent.xexpose.count);
   278 #endif
   279             SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_EXPOSED, 0,
   280                                 0);
   281         }
   282         break;
   283 
   284     default:{
   285 #ifdef DEBUG_XEVENTS
   286             printf("Unhandled event %d\n", xevent.type);
   287 #endif
   288         }
   289         break;
   290     }
   291 }
   292 
   293 /* Ack!  XPending() actually performs a blocking read if no events available */
   294 int
   295 X11_Pending(Display * display)
   296 {
   297     /* Flush the display connection and look to see if events are queued */
   298     XFlush(display);
   299     if (XEventsQueued(display, QueuedAlready)) {
   300         return (1);
   301     }
   302 
   303     /* More drastic measures are required -- see if X is ready to talk */
   304     {
   305         static struct timeval zero_time;        /* static == 0 */
   306         int x11_fd;
   307         fd_set fdset;
   308 
   309         x11_fd = ConnectionNumber(display);
   310         FD_ZERO(&fdset);
   311         FD_SET(x11_fd, &fdset);
   312         if (select(x11_fd + 1, &fdset, NULL, NULL, &zero_time) == 1) {
   313             return (XPending(display));
   314         }
   315     }
   316 
   317     /* Oh well, nothing is ready .. */
   318     return (0);
   319 }
   320 
   321 void
   322 X11_PumpEvents(_THIS)
   323 {
   324     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
   325 
   326     /* Keep processing pending events */
   327     while (X11_Pending(data->display)) {
   328         X11_DispatchEvent(_this);
   329     }
   330 }
   331 
   332 void
   333 X11_SaveScreenSaver(Display * display, int *saved_timeout, BOOL * dpms)
   334 {
   335     int timeout, interval, prefer_blank, allow_exp;
   336     XGetScreenSaver(display, &timeout, &interval, &prefer_blank, &allow_exp);
   337     *saved_timeout = timeout;
   338 
   339 #if SDL_VIDEO_DRIVER_X11_DPMS
   340     if (SDL_X11_HAVE_DPMS) {
   341         int dummy;
   342         if (DPMSQueryExtension(display, &dummy, &dummy)) {
   343             CARD16 state;
   344             DPMSInfo(display, &state, dpms);
   345         }
   346     }
   347 #else
   348     *dpms = 0;
   349 #endif /* SDL_VIDEO_DRIVER_X11_DPMS */
   350 }
   351 
   352 void
   353 X11_DisableScreenSaver(Display * display)
   354 {
   355     int timeout, interval, prefer_blank, allow_exp;
   356     XGetScreenSaver(display, &timeout, &interval, &prefer_blank, &allow_exp);
   357     timeout = 0;
   358     XSetScreenSaver(display, timeout, interval, prefer_blank, allow_exp);
   359 
   360 #if SDL_VIDEO_DRIVER_X11_DPMS
   361     if (SDL_X11_HAVE_DPMS) {
   362         int dummy;
   363         if (DPMSQueryExtension(display, &dummy, &dummy)) {
   364             DPMSDisable(display);
   365         }
   366     }
   367 #endif /* SDL_VIDEO_DRIVER_X11_DPMS */
   368 }
   369 
   370 void
   371 X11_RestoreScreenSaver(Display * display, int saved_timeout, BOOL dpms)
   372 {
   373     int timeout, interval, prefer_blank, allow_exp;
   374     XGetScreenSaver(display, &timeout, &interval, &prefer_blank, &allow_exp);
   375     timeout = saved_timeout;
   376     XSetScreenSaver(display, timeout, interval, prefer_blank, allow_exp);
   377 
   378 #if SDL_VIDEO_DRIVER_X11_DPMS
   379     if (SDL_X11_HAVE_DPMS) {
   380         int dummy;
   381         if (DPMSQueryExtension(display, &dummy, &dummy)) {
   382             if (dpms) {
   383                 DPMSEnable(display);
   384             }
   385         }
   386     }
   387 #endif /* SDL_VIDEO_DRIVER_X11_DPMS */
   388 }
   389 
   390 /* vi: set ts=4 sw=4 expandtab: */