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