From dbbd206084d4b80e19050ef2b8d4f3e40ac71a68 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 2 Nov 2012 15:22:37 -0400 Subject: [PATCH] X11: Handle _NET_WM_PING protocol, so window manager knows when app is hung up. --- src/video/x11/SDL_x11events.c | 24 ++++++++++++++++++++++++ src/video/x11/SDL_x11video.c | 1 + src/video/x11/SDL_x11video.h | 1 + src/video/x11/SDL_x11window.c | 10 ++++++++-- 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 47ba10d63..cfae4bcaa 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -387,10 +387,34 @@ X11_DispatchEvent(_THIS) /* Have we been requested to quit (or another client message?) */ case ClientMessage:{ if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) && + (xevent.xclient.format == 32) && + (xevent.xclient.data.l[0] == videodata->_NET_WM_PING)) { + + SDL_DisplayData *dpydata; + Window root; + +#ifdef DEBUG_XEVENTS + printf("window %p: _NET_WM_PING\n", data); +#endif + + dpydata = (SDL_DisplayData *) + SDL_GetDisplayForWindow(data->window); + root = RootWindow(display, dpydata->screen); + xevent.xclient.window = root; + XSendEvent(display, root, False, SubstructureRedirectMask | SubstructureNotifyMask, &xevent); + break; + } + + else if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) && (xevent.xclient.format == 32) && (xevent.xclient.data.l[0] == videodata->WM_DELETE_WINDOW)) { +#ifdef DEBUG_XEVENTS + printf("window %p: WM_DELETE_WINDOW\n", data); +#endif + SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0); + break; } } break; diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index 637e2b6e1..52a996a53 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -383,6 +383,7 @@ X11_VideoInit(_THIS) GET_ATOM(_NET_WM_NAME); GET_ATOM(_NET_WM_ICON_NAME); GET_ATOM(_NET_WM_ICON); + GET_ATOM(_NET_WM_PING); GET_ATOM(UTF8_STRING); /* Detect the window manager */ diff --git a/src/video/x11/SDL_x11video.h b/src/video/x11/SDL_x11video.h index 6ed951462..5c092048f 100644 --- a/src/video/x11/SDL_x11video.h +++ b/src/video/x11/SDL_x11video.h @@ -93,6 +93,7 @@ typedef struct SDL_VideoData Atom _NET_WM_NAME; Atom _NET_WM_ICON_NAME; Atom _NET_WM_ICON; + Atom _NET_WM_PING; Atom UTF8_STRING; SDL_Scancode key_layout[256]; diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index ba4ecc24a..2c883a573 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -536,8 +536,14 @@ X11_CreateWindow(_THIS, SDL_Window * window) PropModeReplace, (unsigned char *)&_NET_WM_WINDOW_TYPE_NORMAL, 1); - /* Allow the window to be deleted by the window manager */ - XSetWMProtocols(display, w, &data->WM_DELETE_WINDOW, 1); + + { + Atom protocols[] = { + data->WM_DELETE_WINDOW, /* Allow window to be deleted by the WM */ + data->_NET_WM_PING, /* Respond so WM knows we're alive */ + }; + XSetWMProtocols(display, w, protocols, sizeof (protocols) / sizeof (protocols[0])); + } if (SetupWindowData(_this, window, w, SDL_TRUE) < 0) { XDestroyWindow(display, w);