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