From 754d392775e3868abe7e342d1002157a095d4c92 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 28 Sep 2012 14:01:55 -0700 Subject: [PATCH] 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 | 106 ++++++++++++++++++++++++---------- src/video/x11/SDL_x11window.h | 16 +++++ 2 files changed, 93 insertions(+), 29 deletions(-) diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 8755dcac8..821176333 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -28,6 +28,7 @@ #include #include /* For INT_MAX */ +#include "SDL_x11video.h" #include "SDL_x11video.h" #include "SDL_x11touch.h" #include "SDL_x11xinput2.h" @@ -109,6 +110,34 @@ static void X11_HandleGenericEvent(SDL_VideoData *videodata,XEvent event) #endif /* SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS */ +static void +X11_DispatchFocusIn(SDL_WindowData *data) +{ +#ifdef DEBUG_XEVENTS + printf("window %p: Dispatching FocusIn\n", data); +#endif + SDL_SetKeyboardFocus(data->window); +#ifdef X_HAVE_UTF8_STRING + if (data->ic) { + XSetICFocus(data->ic); + } +#endif +} + +static void +X11_DispatchFocusOut(SDL_WindowData *data) +{ +#ifdef DEBUG_XEVENTS + printf("window %p: Dispatching FocusOut\n", data); +#endif + SDL_SetKeyboardFocus(NULL); +#ifdef X_HAVE_UTF8_STRING + if (data->ic) { + XUnsetICFocus(data->ic); + } +#endif +} + static void X11_DispatchMapNotify(SDL_WindowData *data) { @@ -186,7 +215,7 @@ X11_DispatchEvent(_THIS) /* Gaining mouse coverage? */ case EnterNotify:{ #ifdef DEBUG_XEVENTS - printf("EnterNotify! (%d,%d,%d)\n", + printf("window %p: EnterNotify! (%d,%d,%d)\n", data, xevent.xcrossing.x, xevent.xcrossing.y, xevent.xcrossing.mode); @@ -201,7 +230,7 @@ X11_DispatchEvent(_THIS) /* Losing mouse coverage? */ case LeaveNotify:{ #ifdef DEBUG_XEVENTS - printf("LeaveNotify! (%d,%d,%d)\n", + printf("window %p: LeaveNotify! (%d,%d,%d)\n", data, xevent.xcrossing.x, xevent.xcrossing.y, xevent.xcrossing.mode); @@ -221,35 +250,27 @@ X11_DispatchEvent(_THIS) /* Gaining input focus? */ case FocusIn:{ #ifdef DEBUG_XEVENTS - printf("FocusIn!\n"); -#endif - SDL_SetKeyboardFocus(data->window); -#ifdef X_HAVE_UTF8_STRING - if (data->ic) { - XSetICFocus(data->ic); - } + printf("window %p: FocusIn!\n", data); #endif + data->pending_focus = PENDING_FOCUS_IN; + data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_IN_TIME; } break; /* Losing input focus? */ case FocusOut:{ #ifdef DEBUG_XEVENTS - printf("FocusOut!\n"); -#endif - SDL_SetKeyboardFocus(NULL); -#ifdef X_HAVE_UTF8_STRING - if (data->ic) { - XUnsetICFocus(data->ic); - } + printf("window %p: FocusOut!\n", data); #endif + data->pending_focus = PENDING_FOCUS_OUT; + data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_OUT_TIME; } break; /* Generated upon EnterWindow and FocusIn */ case KeymapNotify:{ #ifdef DEBUG_XEVENTS - printf("KeymapNotify!\n"); + printf("window %p: KeymapNotify!\n", data); #endif /* FIXME: X11_SetKeyboardState(SDL_Display, xevent.xkeymap.key_vector); @@ -260,7 +281,7 @@ X11_DispatchEvent(_THIS) /* Has the keyboard layout changed? */ case MappingNotify:{ #ifdef DEBUG_XEVENTS - printf("MappingNotify!\n"); + printf("window %p: MappingNotify!\n", data); #endif X11_UpdateKeymap(_this); } @@ -274,7 +295,7 @@ X11_DispatchEvent(_THIS) Status status = 0; #ifdef DEBUG_XEVENTS - printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode); + printf("window %p: KeyPress (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode); #endif SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]); #if 1 @@ -313,7 +334,7 @@ X11_DispatchEvent(_THIS) KeyCode keycode = xevent.xkey.keycode; #ifdef DEBUG_XEVENTS - printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode); + printf("window %p: KeyRelease (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode); #endif if (X11_KeyRepeat(display, &xevent)) { /* We're about to get a repeated key down, ignore the key up */ @@ -326,7 +347,7 @@ X11_DispatchEvent(_THIS) /* Have we been iconified? */ case UnmapNotify:{ #ifdef DEBUG_XEVENTS - printf("UnmapNotify!\n"); + printf("window %p: UnmapNotify!\n", data); #endif X11_DispatchUnmapNotify(data); } @@ -335,7 +356,7 @@ X11_DispatchEvent(_THIS) /* Have we been restored? */ case MapNotify:{ #ifdef DEBUG_XEVENTS - printf("MapNotify!\n"); + printf("window %p: MapNotify!\n", data); #endif X11_DispatchMapNotify(data); } @@ -344,7 +365,7 @@ X11_DispatchEvent(_THIS) /* Have we been resized or moved? */ case ConfigureNotify:{ #ifdef DEBUG_XEVENTS - printf("ConfigureNotify! (resize: %dx%d)\n", + printf("window %p: ConfigureNotify! (resize: %dx%d)\n", data, xevent.xconfigure.width, xevent.xconfigure.height); #endif SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED, @@ -368,7 +389,7 @@ X11_DispatchEvent(_THIS) /* Do we need to refresh ourselves? */ case Expose:{ #ifdef DEBUG_XEVENTS - printf("Expose (count = %d)\n", xevent.xexpose.count); + printf("window %p: Expose (count = %d)\n", data, xevent.xexpose.count); #endif SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED, 0, 0); } @@ -378,7 +399,7 @@ X11_DispatchEvent(_THIS) SDL_Mouse *mouse = SDL_GetMouse(); if(!mouse->relative_mode) { #ifdef DEBUG_MOTION - printf("X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y); + printf("window %p: X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y); #endif SDL_SendMouseMotion(data->window, 0, xevent.xmotion.x, xevent.xmotion.y); @@ -411,7 +432,7 @@ X11_DispatchEvent(_THIS) char *name = XGetAtomName(display, xevent.xproperty.atom); if (name) { - printf("PropertyNotify: %s %s\n", name, (xevent.xproperty.state == PropertyDelete) ? "deleted" : "changed"); + printf("window %p: PropertyNotify: %s %s\n", data, name, (xevent.xproperty.state == PropertyDelete) ? "deleted" : "changed"); XFree(name); } @@ -508,7 +529,7 @@ X11_DispatchEvent(_THIS) req = &xevent.xselectionrequest; #ifdef DEBUG_XEVENTS - printf("SelectionRequest (requestor = %ld, target = %ld)\n", + printf("window %p: SelectionRequest (requestor = %ld, target = %ld)\n", data, req->requestor, req->target); #endif @@ -538,7 +559,7 @@ X11_DispatchEvent(_THIS) case SelectionNotify: { #ifdef DEBUG_XEVENTS - printf("SelectionNotify (requestor = %ld, target = %ld)\n", + printf("window %p: SelectionNotify (requestor = %ld, target = %ld)\n", data, xevent.xselection.requestor, xevent.xselection.target); #endif videodata->selection_waiting = SDL_FALSE; @@ -547,13 +568,36 @@ X11_DispatchEvent(_THIS) default:{ #ifdef DEBUG_XEVENTS - printf("Unhandled event %d\n", xevent.type); + printf("window %p: Unhandled event %d\n", data, xevent.type); #endif } break; } } +static void +X11_HandleFocusChanges(_THIS) +{ + SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; + int i; + + if (videodata && videodata->windowlist) { + for (i = 0; i < videodata->numwindows; ++i) { + SDL_WindowData *data = videodata->windowlist[i]; + if (data && data->pending_focus != PENDING_FOCUS_NONE) { + Uint32 now = SDL_GetTicks(); + if ( (int)(data->pending_focus_time-now) <= 0 ) { + if ( data->pending_focus == PENDING_FOCUS_IN ) { + X11_DispatchFocusIn(data); + } else { + X11_DispatchFocusOut(data); + } + data->pending_focus = PENDING_FOCUS_NONE; + } + } + } + } +} /* Ack! XPending() actually performs a blocking read if no events available */ static int X11_Pending(Display * display) @@ -606,6 +650,10 @@ X11_PumpEvents(_THIS) while (X11_Pending(data->display)) { X11_DispatchEvent(_this); } + + /* FIXME: Only need to do this when there are pending focus changes */ + X11_HandleFocusChanges(_this); + /*Dont process evtouch events if XInput2 multitouch is supported*/ if(X11_Xinput2IsMultitouchSupported()) { return; diff --git a/src/video/x11/SDL_x11window.h b/src/video/x11/SDL_x11window.h index 60c818459..8ff9a4dd7 100644 --- a/src/video/x11/SDL_x11window.h +++ b/src/video/x11/SDL_x11window.h @@ -23,6 +23,20 @@ #ifndef _SDL_x11window_h #define _SDL_x11window_h +/* 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. +*/ +#define PENDING_FOCUS_IN_TIME 200 +#define PENDING_FOCUS_OUT_TIME 200 + +typedef enum +{ + PENDING_FOCUS_NONE, + PENDING_FOCUS_IN, + PENDING_FOCUS_OUT +} PendingFocusEnum; + typedef struct { SDL_Window *window; @@ -39,6 +53,8 @@ typedef struct GC gc; XIC ic; SDL_bool created; + PendingFocusEnum pending_focus; + Uint32 pending_focus_time; struct SDL_VideoData *videodata; } SDL_WindowData;