From dc532c70e8086030b67794c62bc41922c3d5386c Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 5 Jan 2016 02:27:50 -0500 Subject: [PATCH] Added SDL_WINDOWEVENT_TAKE_FOCUS. This is for corner cases where a multi-window app is activated and wants to make a decision about where focus should go. This patch came from Unreal Engine 4's fork of SDL, compliments of Epic Games. --- include/SDL_video.h | 3 ++- src/video/x11/SDL_x11events.c | 10 ++++++++++ src/video/x11/SDL_x11video.c | 1 + src/video/x11/SDL_x11video.h | 1 + src/video/x11/SDL_x11window.c | 11 +++++------ 5 files changed, 19 insertions(+), 7 deletions(-) diff --git a/include/SDL_video.h b/include/SDL_video.h index 8e9c1002b90df..17bbbe8fce21d 100644 --- a/include/SDL_video.h +++ b/include/SDL_video.h @@ -161,7 +161,8 @@ typedef enum SDL_WINDOWEVENT_FOCUS_GAINED, /**< Window has gained keyboard focus */ SDL_WINDOWEVENT_FOCUS_LOST, /**< Window has lost keyboard focus */ SDL_WINDOWEVENT_CLOSE, /**< The window manager requests that the window be closed */ - SDL_WINDOWEVENT_HIT_TEST /** Window had a hit test that wasn't SDL_HITTEST_NORMAL. */ + SDL_WINDOWEVENT_TAKE_FOCUS, /**< Window is being offered a focus (should SetWindowInputFocus() on itself or a subwindow, or ignore) */ + SDL_WINDOWEVENT_HIT_TEST /**< Window had a hit test that wasn't SDL_HITTEST_NORMAL. */ } SDL_WindowEventID; /** diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 6a5ea1115af65..e5952dcb05184 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -979,6 +979,16 @@ X11_DispatchEvent(_THIS) SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0); break; } + else if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) && + (xevent.xclient.format == 32) && + (xevent.xclient.data.l[0] == videodata->WM_TAKE_FOCUS)) { + +#ifdef DEBUG_XEVENTS + printf("window %p: WM_TAKE_FOCUS\n", data); +#endif + SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_TAKE_FOCUS, 0, 0); + break; + } } break; diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index 1ad548f716f88..ba5e872f31b79 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -395,6 +395,7 @@ X11_VideoInit(_THIS) #define GET_ATOM(X) data->X = X11_XInternAtom(data->display, #X, False) GET_ATOM(WM_PROTOCOLS); GET_ATOM(WM_DELETE_WINDOW); + GET_ATOM(WM_TAKE_FOCUS); GET_ATOM(_NET_WM_STATE); GET_ATOM(_NET_WM_STATE_HIDDEN); GET_ATOM(_NET_WM_STATE_FOCUSED); diff --git a/src/video/x11/SDL_x11video.h b/src/video/x11/SDL_x11video.h index 9bd37f457c2b7..5ffc5793383f8 100644 --- a/src/video/x11/SDL_x11video.h +++ b/src/video/x11/SDL_x11video.h @@ -89,6 +89,7 @@ typedef struct SDL_VideoData /* Useful atoms */ Atom WM_PROTOCOLS; Atom WM_DELETE_WINDOW; + Atom WM_TAKE_FOCUS; Atom _NET_WM_STATE; Atom _NET_WM_STATE_HIDDEN; Atom _NET_WM_STATE_FOCUSED; diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index b5c2168066a3f..8856f7bfffc1a 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -574,18 +574,17 @@ X11_CreateWindow(_THIS, SDL_Window * window) (unsigned char *)&compositor, 1); { - Atom protocols[2]; + Atom protocols[3]; int proto_count = 0; const char *ping_hint; - protocols[proto_count] = data->WM_DELETE_WINDOW; /* Allow window to be deleted by the WM */ - proto_count++; - + protocols[proto_count++] = data->WM_DELETE_WINDOW; /* Allow window to be deleted by the WM */ + protocols[proto_count++] = data->WM_TAKE_FOCUS; /* Since we will want to set input focus explicitly */ + ping_hint = SDL_GetHint(SDL_HINT_VIDEO_X11_NET_WM_PING); /* Default to using ping if there is no hint */ if (!ping_hint || SDL_atoi(ping_hint)) { - protocols[proto_count] = data->_NET_WM_PING; /* Respond so WM knows we're alive */ - proto_count++; + protocols[proto_count++] = data->_NET_WM_PING; /* Respond so WM knows we're alive */ } SDL_assert(proto_count <= sizeof(protocols) / sizeof(protocols[0]));