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