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.

This commit is contained in:
Sam Lantinga 2012-09-28 14:01:55 -07:00
parent b40f346c7e
commit 2c196568a8
2 changed files with 93 additions and 29 deletions

View file

@ -28,6 +28,7 @@
#include <unistd.h>
#include <limits.h> /* 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;