--- a/src/video/x11/SDL_x11events.c Fri Sep 28 14:17:30 2012 -0400
+++ b/src/video/x11/SDL_x11events.c Fri Sep 28 14:22:33 2012 -0700
@@ -29,6 +29,7 @@
#include <limits.h> /* For INT_MAX */
#include "SDL_x11video.h"
+#include "SDL_x11video.h"
#include "SDL_x11touch.h"
#include "SDL_x11xinput2.h"
#include "../../events/SDL_events_c.h"
@@ -110,6 +111,34 @@
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)
{
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
@@ -186,7 +215,7 @@
/* 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 @@
/* 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 @@
/* Gaining input focus? */
case FocusIn:{
#ifdef DEBUG_XEVENTS
- printf("FocusIn!\n");
+ printf("window %p: FocusIn!\n", data);
#endif
- SDL_SetKeyboardFocus(data->window);
-#ifdef X_HAVE_UTF8_STRING
- if (data->ic) {
- XSetICFocus(data->ic);
- }
-#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");
+ printf("window %p: FocusOut!\n", data);
#endif
- SDL_SetKeyboardFocus(NULL);
-#ifdef X_HAVE_UTF8_STRING
- if (data->ic) {
- XUnsetICFocus(data->ic);
- }
-#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 @@
/* 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 @@
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 @@
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 @@
/* 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 @@
/* 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 @@
/* 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 @@
/* 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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;
--- a/src/video/x11/SDL_x11modes.c Fri Sep 28 14:17:30 2012 -0400
+++ b/src/video/x11/SDL_x11modes.c Fri Sep 28 14:22:33 2012 -0700
@@ -217,6 +217,7 @@
displaydata->screen = 0;
displaydata->use_xinerama = xinerama_major * 100 + xinerama_minor;
displaydata->xinerama_info = xinerama[screen];
+ displaydata->xinerama_screen = screen;
}
else displaydata->screen = screen;
#else
@@ -637,6 +638,16 @@
#if SDL_VIDEO_DRIVER_X11_XINERAMA
if (data->use_xinerama) {
+ int screencount;
+ XineramaScreenInfo *xinerama;
+
+ /* Update the current screen layout information */
+ xinerama = XineramaQueryScreens(display, &screencount);
+ if (xinerama && data->xinerama_screen < screencount) {
+ data->xinerama_info = xinerama[data->xinerama_screen];
+ }
+ if (xinerama) XFree(xinerama);
+
*w = data->xinerama_info.width;
*h = data->xinerama_info.height;
*rate = 0;
@@ -789,21 +800,20 @@
int
X11_GetDisplayBounds(_THIS, SDL_VideoDisplay * sdl_display, SDL_Rect * rect)
{
+ Display *display = ((SDL_VideoData *) _this->driverdata)->display;
SDL_DisplayData *data = (SDL_DisplayData *) sdl_display->driverdata;
+ int real_rate;
+
+ rect->x = 0;
+ rect->y = 0;
+ get_real_resolution(display, data, &rect->w, &rect->h, &real_rate);
#if SDL_VIDEO_DRIVER_X11_XINERAMA
- if (data && data->use_xinerama) {
+ if (data->use_xinerama) {
rect->x = data->xinerama_info.x_org;
rect->y = data->xinerama_info.y_org;
- rect->w = data->xinerama_info.width;
- rect->h = data->xinerama_info.height;
- return 0;
}
#endif
- rect->x = 0;
- rect->y = 0;
- rect->w = sdl_display->current_mode.w;
- rect->h = sdl_display->current_mode.h;
return 0;
}
--- a/src/video/x11/SDL_x11modes.h Fri Sep 28 14:17:30 2012 -0400
+++ b/src/video/x11/SDL_x11modes.h Fri Sep 28 14:22:33 2012 -0700
@@ -36,6 +36,7 @@
#if SDL_VIDEO_DRIVER_X11_XINERAMA
XineramaScreenInfo xinerama_info;
+ int xinerama_screen;
#endif
#if SDL_VIDEO_DRIVER_X11_XRANDR
XRRScreenConfiguration *screen_config;
--- a/src/video/x11/SDL_x11window.c Fri Sep 28 14:17:30 2012 -0400
+++ b/src/video/x11/SDL_x11window.c Fri Sep 28 14:22:33 2012 -0700
@@ -56,14 +56,6 @@
{
return ev->type == ConfigureNotify && ev->xconfigure.window == *((Window*)win);
}
-static Bool isFocusIn(Display *dpy, XEvent *ev, XPointer win)
-{
- return ev->type == FocusIn && ev->xfocus.window == *((Window*)win);
-}
-static Bool isFocusOut(Display *dpy, XEvent *ev, XPointer win)
-{
- return ev->type == FocusOut && ev->xfocus.window == *((Window*)win);
-}
static SDL_bool
X11_IsWindowLegacyFullscreen(_THIS, SDL_Window * window)
@@ -1019,10 +1011,12 @@
XSelectInput(display, data->fswindow, StructureNotifyMask);
XSetWindowBackground(display, data->fswindow, 0);
+ XInstallColormap(display, data->colormap);
XClearWindow(display, data->fswindow);
XMapRaised(display, data->fswindow);
/* Make sure the fswindow is in view by warping mouse to the corner */
+ XUngrabPointer(display, CurrentTime);
XWarpPointer(display, None, root, 0, 0, 0, 0, rect.x, rect.y);
/* Wait to be mapped, filter Unmap event out if it arrives. */
@@ -1034,28 +1028,22 @@
XF86VidModeLockModeSwitch(display, screen, True);
}
#endif
- XInstallColormap(display, data->colormap);
SetWindowBordered(display, displaydata->screen, data->xwindow, SDL_FALSE);
/* Center actual window within our cover-the-screen window. */
- rect.x += (rect.w - window->w) / 2;
- rect.y += (rect.h - window->h) / 2;
- XReparentWindow(display, data->xwindow, data->fswindow, rect.x, rect.y);
+ XReparentWindow(display, data->xwindow, data->fswindow,
+ (rect.w - window->w) / 2, (rect.h - window->h) / 2);
- /* Center mouse in the window. */
- rect.x += (window->w / 2);
- rect.y += (window->h / 2);
+ /* Center mouse in the fullscreen window. */
+ rect.x += (rect.w / 2);
+ rect.y += (rect.h / 2);
XWarpPointer(display, None, root, 0, 0, 0, 0, rect.x, rect.y);
/* Wait to be mapped, filter Unmap event out if it arrives. */
XIfEvent(display, &ev, &isMapNotify, (XPointer)&data->xwindow);
XCheckIfEvent(display, &ev, &isUnmapNotify, (XPointer)&data->xwindow);
- /* Set the input focus because we're about to grab input */
- window->flags |= SDL_WINDOW_INPUT_FOCUS;
- SDL_SetKeyboardFocus(data->window);
-
X11_SetWindowGrab(_this, window);
}
@@ -1214,9 +1202,9 @@
/* ICCCM2.0-compliant window managers can handle fullscreen windows */
oldstyle_fullscreen = X11_IsWindowLegacyFullscreen(_this, window);
- if (((window->flags & SDL_WINDOW_INPUT_GRABBED) || oldstyle_fullscreen)
- && (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
- XEvent ev;
+ if (oldstyle_fullscreen ||
+ ((window->flags & SDL_WINDOW_INPUT_GRABBED) &&
+ (window->flags & SDL_WINDOW_INPUT_FOCUS))) {
/* Try to grab the mouse */
for (;;) {
@@ -1235,15 +1223,11 @@
/* Now grab the keyboard */
XGrabKeyboard(display, data->xwindow, True, GrabModeAsync,
GrabModeAsync, CurrentTime);
-
- /* flush these events so they don't confuse normal event handling */
- XSync(display, False);
- XCheckIfEvent(display, &ev, &isFocusIn, (XPointer)&data->xwindow);
- XCheckIfEvent(display, &ev, &isFocusOut, (XPointer)&data->xwindow);
} else {
XUngrabPointer(display, CurrentTime);
XUngrabKeyboard(display, CurrentTime);
}
+ XSync(display, False);
}
void
--- a/src/video/x11/SDL_x11window.h Fri Sep 28 14:17:30 2012 -0400
+++ b/src/video/x11/SDL_x11window.h Fri Sep 28 14:22:33 2012 -0700
@@ -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 @@
GC gc;
XIC ic;
SDL_bool created;
+ PendingFocusEnum pending_focus;
+ Uint32 pending_focus_time;
struct SDL_VideoData *videodata;
} SDL_WindowData;
--- a/test/common.c Fri Sep 28 14:17:30 2012 -0400
+++ b/test/common.c Fri Sep 28 14:22:33 2012 -0700
@@ -617,6 +617,7 @@
}
if (state->verbose & VERBOSE_MODES) {
+ SDL_Rect bounds;
SDL_DisplayMode mode;
int bpp;
Uint32 Rmask, Gmask, Bmask, Amask;
@@ -626,6 +627,10 @@
for (i = 0; i < n; ++i) {
fprintf(stderr, "Display %d:\n", i);
+ SDL_zero(bounds);
+ SDL_GetDisplayBounds(i, &bounds);
+ fprintf(stderr, "Bounds: %dx%d at %d,%d\n", bounds.w, bounds.h, bounds.x, bounds.y);
+
SDL_GetDesktopDisplayMode(i, &mode);
SDL_PixelFormatEnumToMasks(mode.format, &bpp, &Rmask, &Gmask,
&Bmask, &Amask);
@@ -736,7 +741,8 @@
return SDL_FALSE;
}
SDL_GetWindowSize(state->windows[i], &w, &h);
- if (w != state->window_w || h != state->window_h) {
+ if (!(state->window_flags & SDL_WINDOW_RESIZABLE) &&
+ (w != state->window_w || h != state->window_h)) {
printf("Window requested size %dx%d, got %dx%d\n", state->window_w, state->window_h, w, h);
state->window_w = w;
state->window_h = h;