We need to queue the focus in/out changes because they may occur during video mode changes and we can respond to them by triggering more mode changes.
authorSam Lantinga
Fri, 28 Sep 2012 14:01:55 -0700
changeset 6504100c49578dba
parent 6503 8ff31baded38
child 6505 ce7abf273d8c
We need to queue the focus in/out changes because they may occur during video mode changes and we can respond to them by triggering more mode changes.
src/video/x11/SDL_x11events.c
src/video/x11/SDL_x11window.h
     1.1 --- a/src/video/x11/SDL_x11events.c	Fri Sep 28 14:00:43 2012 -0700
     1.2 +++ b/src/video/x11/SDL_x11events.c	Fri Sep 28 14:01:55 2012 -0700
     1.3 @@ -29,6 +29,7 @@
     1.4  #include <limits.h> /* For INT_MAX */
     1.5  
     1.6  #include "SDL_x11video.h"
     1.7 +#include "SDL_x11video.h"
     1.8  #include "SDL_x11touch.h"
     1.9  #include "SDL_x11xinput2.h"
    1.10  #include "../../events/SDL_events_c.h"
    1.11 @@ -110,6 +111,34 @@
    1.12  
    1.13  
    1.14  static void
    1.15 +X11_DispatchFocusIn(SDL_WindowData *data)
    1.16 +{
    1.17 +#ifdef DEBUG_XEVENTS
    1.18 +    printf("window %p: Dispatching FocusIn\n", data);
    1.19 +#endif
    1.20 +    SDL_SetKeyboardFocus(data->window);
    1.21 +#ifdef X_HAVE_UTF8_STRING
    1.22 +    if (data->ic) {
    1.23 +        XSetICFocus(data->ic);
    1.24 +    }
    1.25 +#endif
    1.26 +}
    1.27 +
    1.28 +static void
    1.29 +X11_DispatchFocusOut(SDL_WindowData *data)
    1.30 +{
    1.31 +#ifdef DEBUG_XEVENTS
    1.32 +    printf("window %p: Dispatching FocusOut\n", data);
    1.33 +#endif
    1.34 +    SDL_SetKeyboardFocus(NULL);
    1.35 +#ifdef X_HAVE_UTF8_STRING
    1.36 +    if (data->ic) {
    1.37 +        XUnsetICFocus(data->ic);
    1.38 +    }
    1.39 +#endif
    1.40 +}
    1.41 +
    1.42 +static void
    1.43  X11_DispatchMapNotify(SDL_WindowData *data)
    1.44  {
    1.45      SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
    1.46 @@ -186,7 +215,7 @@
    1.47          /* Gaining mouse coverage? */
    1.48      case EnterNotify:{
    1.49  #ifdef DEBUG_XEVENTS
    1.50 -            printf("EnterNotify! (%d,%d,%d)\n", 
    1.51 +            printf("window %p: EnterNotify! (%d,%d,%d)\n", data,
    1.52                     xevent.xcrossing.x,
    1.53                     xevent.xcrossing.y,
    1.54                     xevent.xcrossing.mode);
    1.55 @@ -201,7 +230,7 @@
    1.56          /* Losing mouse coverage? */
    1.57      case LeaveNotify:{
    1.58  #ifdef DEBUG_XEVENTS
    1.59 -            printf("LeaveNotify! (%d,%d,%d)\n", 
    1.60 +            printf("window %p: LeaveNotify! (%d,%d,%d)\n", data,
    1.61                     xevent.xcrossing.x,
    1.62                     xevent.xcrossing.y,
    1.63                     xevent.xcrossing.mode);
    1.64 @@ -221,35 +250,27 @@
    1.65          /* Gaining input focus? */
    1.66      case FocusIn:{
    1.67  #ifdef DEBUG_XEVENTS
    1.68 -            printf("FocusIn!\n");
    1.69 +            printf("window %p: FocusIn!\n", data);
    1.70  #endif
    1.71 -            SDL_SetKeyboardFocus(data->window);
    1.72 -#ifdef X_HAVE_UTF8_STRING
    1.73 -            if (data->ic) {
    1.74 -                XSetICFocus(data->ic);
    1.75 -            }
    1.76 -#endif
    1.77 +            data->pending_focus = PENDING_FOCUS_IN;
    1.78 +            data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_IN_TIME;
    1.79          }
    1.80          break;
    1.81  
    1.82          /* Losing input focus? */
    1.83      case FocusOut:{
    1.84  #ifdef DEBUG_XEVENTS
    1.85 -            printf("FocusOut!\n");
    1.86 +            printf("window %p: FocusOut!\n", data);
    1.87  #endif
    1.88 -            SDL_SetKeyboardFocus(NULL);
    1.89 -#ifdef X_HAVE_UTF8_STRING
    1.90 -            if (data->ic) {
    1.91 -                XUnsetICFocus(data->ic);
    1.92 -            }
    1.93 -#endif
    1.94 +            data->pending_focus = PENDING_FOCUS_OUT;
    1.95 +            data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_OUT_TIME;
    1.96          }
    1.97          break;
    1.98  
    1.99          /* Generated upon EnterWindow and FocusIn */
   1.100      case KeymapNotify:{
   1.101  #ifdef DEBUG_XEVENTS
   1.102 -            printf("KeymapNotify!\n");
   1.103 +            printf("window %p: KeymapNotify!\n", data);
   1.104  #endif
   1.105              /* FIXME:
   1.106                 X11_SetKeyboardState(SDL_Display, xevent.xkeymap.key_vector);
   1.107 @@ -260,7 +281,7 @@
   1.108          /* Has the keyboard layout changed? */
   1.109      case MappingNotify:{
   1.110  #ifdef DEBUG_XEVENTS
   1.111 -            printf("MappingNotify!\n");
   1.112 +            printf("window %p: MappingNotify!\n", data);
   1.113  #endif
   1.114              X11_UpdateKeymap(_this);
   1.115          }
   1.116 @@ -274,7 +295,7 @@
   1.117              Status status = 0;
   1.118  
   1.119  #ifdef DEBUG_XEVENTS
   1.120 -            printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
   1.121 +            printf("window %p: KeyPress (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode);
   1.122  #endif
   1.123              SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]);
   1.124  #if 1
   1.125 @@ -313,7 +334,7 @@
   1.126              KeyCode keycode = xevent.xkey.keycode;
   1.127  
   1.128  #ifdef DEBUG_XEVENTS
   1.129 -            printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
   1.130 +            printf("window %p: KeyRelease (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode);
   1.131  #endif
   1.132              if (X11_KeyRepeat(display, &xevent)) {
   1.133                  /* We're about to get a repeated key down, ignore the key up */
   1.134 @@ -326,7 +347,7 @@
   1.135          /* Have we been iconified? */
   1.136      case UnmapNotify:{
   1.137  #ifdef DEBUG_XEVENTS
   1.138 -            printf("UnmapNotify!\n");
   1.139 +            printf("window %p: UnmapNotify!\n", data);
   1.140  #endif
   1.141              X11_DispatchUnmapNotify(data);
   1.142          }
   1.143 @@ -335,7 +356,7 @@
   1.144          /* Have we been restored? */
   1.145      case MapNotify:{
   1.146  #ifdef DEBUG_XEVENTS
   1.147 -            printf("MapNotify!\n");
   1.148 +            printf("window %p: MapNotify!\n", data);
   1.149  #endif
   1.150              X11_DispatchMapNotify(data);
   1.151          }
   1.152 @@ -344,7 +365,7 @@
   1.153          /* Have we been resized or moved? */
   1.154      case ConfigureNotify:{
   1.155  #ifdef DEBUG_XEVENTS
   1.156 -            printf("ConfigureNotify! (resize: %dx%d)\n",
   1.157 +            printf("window %p: ConfigureNotify! (resize: %dx%d)\n", data,
   1.158                     xevent.xconfigure.width, xevent.xconfigure.height);
   1.159  #endif
   1.160              SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED,
   1.161 @@ -368,7 +389,7 @@
   1.162          /* Do we need to refresh ourselves? */
   1.163      case Expose:{
   1.164  #ifdef DEBUG_XEVENTS
   1.165 -            printf("Expose (count = %d)\n", xevent.xexpose.count);
   1.166 +            printf("window %p: Expose (count = %d)\n", data, xevent.xexpose.count);
   1.167  #endif
   1.168              SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED, 0, 0);
   1.169          }
   1.170 @@ -378,7 +399,7 @@
   1.171              SDL_Mouse *mouse = SDL_GetMouse();  
   1.172              if(!mouse->relative_mode) {
   1.173  #ifdef DEBUG_MOTION
   1.174 -                printf("X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y);
   1.175 +                printf("window %p: X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y);
   1.176  #endif
   1.177  
   1.178                  SDL_SendMouseMotion(data->window, 0, xevent.xmotion.x, xevent.xmotion.y);
   1.179 @@ -411,7 +432,7 @@
   1.180  
   1.181              char *name = XGetAtomName(display, xevent.xproperty.atom);
   1.182              if (name) {
   1.183 -                printf("PropertyNotify: %s %s\n", name, (xevent.xproperty.state == PropertyDelete) ? "deleted" : "changed");
   1.184 +                printf("window %p: PropertyNotify: %s %s\n", data, name, (xevent.xproperty.state == PropertyDelete) ? "deleted" : "changed");
   1.185                  XFree(name);
   1.186              }
   1.187  
   1.188 @@ -508,7 +529,7 @@
   1.189  
   1.190              req = &xevent.xselectionrequest;
   1.191  #ifdef DEBUG_XEVENTS
   1.192 -            printf("SelectionRequest (requestor = %ld, target = %ld)\n",
   1.193 +            printf("window %p: SelectionRequest (requestor = %ld, target = %ld)\n", data,
   1.194                  req->requestor, req->target);
   1.195  #endif
   1.196  
   1.197 @@ -538,7 +559,7 @@
   1.198  
   1.199      case SelectionNotify: {
   1.200  #ifdef DEBUG_XEVENTS
   1.201 -            printf("SelectionNotify (requestor = %ld, target = %ld)\n",
   1.202 +            printf("window %p: SelectionNotify (requestor = %ld, target = %ld)\n", data,
   1.203                  xevent.xselection.requestor, xevent.xselection.target);
   1.204  #endif
   1.205              videodata->selection_waiting = SDL_FALSE;
   1.206 @@ -547,13 +568,36 @@
   1.207  
   1.208      default:{
   1.209  #ifdef DEBUG_XEVENTS
   1.210 -            printf("Unhandled event %d\n", xevent.type);
   1.211 +            printf("window %p: Unhandled event %d\n", data, xevent.type);
   1.212  #endif
   1.213          }
   1.214          break;
   1.215      }
   1.216  }
   1.217  
   1.218 +static void
   1.219 +X11_HandleFocusChanges(_THIS)
   1.220 +{
   1.221 +    SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
   1.222 +    int i;
   1.223 +
   1.224 +    if (videodata && videodata->windowlist) {
   1.225 +        for (i = 0; i < videodata->numwindows; ++i) {
   1.226 +            SDL_WindowData *data = videodata->windowlist[i];
   1.227 +            if (data && data->pending_focus != PENDING_FOCUS_NONE) {
   1.228 +                Uint32 now = SDL_GetTicks();
   1.229 +                if ( (int)(data->pending_focus_time-now) <= 0 ) {
   1.230 +                    if ( data->pending_focus == PENDING_FOCUS_IN ) {
   1.231 +                        X11_DispatchFocusIn(data);
   1.232 +                    } else {
   1.233 +                        X11_DispatchFocusOut(data);
   1.234 +                    }
   1.235 +                    data->pending_focus = PENDING_FOCUS_NONE;
   1.236 +                }
   1.237 +            }
   1.238 +        }
   1.239 +    }
   1.240 +}
   1.241  /* Ack!  XPending() actually performs a blocking read if no events available */
   1.242  static int
   1.243  X11_Pending(Display * display)
   1.244 @@ -606,6 +650,10 @@
   1.245      while (X11_Pending(data->display)) {
   1.246          X11_DispatchEvent(_this);
   1.247      }
   1.248 +
   1.249 +    /* FIXME: Only need to do this when there are pending focus changes */
   1.250 +    X11_HandleFocusChanges(_this);
   1.251 +
   1.252      /*Dont process evtouch events if XInput2 multitouch is supported*/
   1.253      if(X11_Xinput2IsMultitouchSupported()) {
   1.254          return;
     2.1 --- a/src/video/x11/SDL_x11window.h	Fri Sep 28 14:00:43 2012 -0700
     2.2 +++ b/src/video/x11/SDL_x11window.h	Fri Sep 28 14:01:55 2012 -0700
     2.3 @@ -23,6 +23,20 @@
     2.4  #ifndef _SDL_x11window_h
     2.5  #define _SDL_x11window_h
     2.6  
     2.7 +/* We need to queue the focus in/out changes because they may occur during
     2.8 +   video mode changes and we can respond to them by triggering more mode
     2.9 +   changes.
    2.10 +*/
    2.11 +#define PENDING_FOCUS_IN_TIME   200
    2.12 +#define PENDING_FOCUS_OUT_TIME  200
    2.13 +
    2.14 +typedef enum
    2.15 +{
    2.16 +    PENDING_FOCUS_NONE,
    2.17 +    PENDING_FOCUS_IN,
    2.18 +    PENDING_FOCUS_OUT
    2.19 +} PendingFocusEnum;
    2.20 +
    2.21  typedef struct
    2.22  {
    2.23      SDL_Window *window;
    2.24 @@ -39,6 +53,8 @@
    2.25      GC gc;
    2.26      XIC ic;
    2.27      SDL_bool created;
    2.28 +    PendingFocusEnum pending_focus;
    2.29 +    Uint32 pending_focus_time;
    2.30      struct SDL_VideoData *videodata;
    2.31  } SDL_WindowData;
    2.32