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