x11: Support _NET_WM_USER_TIME and give _NET_ACTIVE_WINDOW a valid timestamp.
authorRyan C. Gordon <icculus@icculus.org>
Mon, 04 Jan 2016 16:25:27 -0500
changeset 100065229da175b57
parent 10005 dea345d3b00a
child 10007 61058b90b9ae
x11: Support _NET_WM_USER_TIME and give _NET_ACTIVE_WINDOW a valid timestamp.

Fixes Bugzilla #3056.
src/video/x11/SDL_x11events.c
src/video/x11/SDL_x11video.c
src/video/x11/SDL_x11video.h
src/video/x11/SDL_x11window.c
src/video/x11/SDL_x11window.h
     1.1 --- a/src/video/x11/SDL_x11events.c	Sun Jan 03 21:48:17 2016 -0500
     1.2 +++ b/src/video/x11/SDL_x11events.c	Mon Jan 04 16:25:27 2016 -0500
     1.3 @@ -513,6 +513,23 @@
     1.4  }
     1.5  
     1.6  static void
     1.7 +X11_UpdateUserTime(SDL_WindowData *data, const unsigned long latest)
     1.8 +{
     1.9 +    if (latest && (latest != data->user_time)) {
    1.10 +        SDL_VideoData *videodata = data->videodata;
    1.11 +        Display *display = videodata->display;
    1.12 +        X11_XChangeProperty(display, data->xwindow, videodata->_NET_WM_USER_TIME,
    1.13 +                            XA_CARDINAL, 32, PropModeReplace,
    1.14 +                            (const unsigned char *) &latest, 1);
    1.15 +        #if DEBUG_XEVENTS
    1.16 +        printf("window %p: updating _NET_WM_USER_TIME to %lu\n", data, latest);
    1.17 +        #endif
    1.18 +        data->user_time = latest;
    1.19 +    }
    1.20 +}
    1.21 +
    1.22 +
    1.23 +static void
    1.24  X11_DispatchEvent(_THIS)
    1.25  {
    1.26      SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
    1.27 @@ -773,6 +790,7 @@
    1.28                  }
    1.29              }
    1.30  
    1.31 +            X11_UpdateUserTime(data, xevent.xkey.time);
    1.32          }
    1.33          break;
    1.34  
    1.35 @@ -1001,6 +1019,7 @@
    1.36                  }
    1.37                  SDL_SendMouseButton(data->window, 0, SDL_PRESSED, button);
    1.38              }
    1.39 +            X11_UpdateUserTime(data, xevent.xbutton.time);
    1.40          }
    1.41          break;
    1.42  
    1.43 @@ -1027,7 +1046,7 @@
    1.44  
    1.45              char *name = X11_XGetAtomName(display, xevent.xproperty.atom);
    1.46              if (name) {
    1.47 -                printf("window %p: PropertyNotify: %s %s\n", data, name, (xevent.xproperty.state == PropertyDelete) ? "deleted" : "changed");
    1.48 +                printf("window %p: PropertyNotify: %s %s time=%lu\n", data, name, (xevent.xproperty.state == PropertyDelete) ? "deleted" : "changed", xevent.xproperty.time);
    1.49                  X11_XFree(name);
    1.50              }
    1.51  
    1.52 @@ -1095,6 +1114,17 @@
    1.53              }
    1.54  #endif /* DEBUG_XEVENTS */
    1.55  
    1.56 +            /* Take advantage of this moment to make sure user_time has a
    1.57 +                valid timestamp from the X server, so if we later try to
    1.58 +                raise/restore this window, _NET_ACTIVE_WINDOW can have a
    1.59 +                non-zero timestamp, even if there's never been a mouse or
    1.60 +                key press to this window so far. Note that we don't try to
    1.61 +                set _NET_WM_USER_TIME here, though. That's only for legit
    1.62 +                user interaction with the window. */
    1.63 +            if (!data->user_time) {
    1.64 +                data->user_time = xevent.xproperty.time;
    1.65 +            }
    1.66 +
    1.67              if (xevent.xproperty.atom == data->videodata->_NET_WM_STATE) {
    1.68                  /* Get the new state from the window manager.
    1.69                     Compositing window managers can alter visibility of windows
     2.1 --- a/src/video/x11/SDL_x11video.c	Sun Jan 03 21:48:17 2016 -0500
     2.2 +++ b/src/video/x11/SDL_x11video.c	Mon Jan 04 16:25:27 2016 -0500
     2.3 @@ -397,6 +397,7 @@
     2.4      GET_ATOM(_NET_WM_ICON_NAME);
     2.5      GET_ATOM(_NET_WM_ICON);
     2.6      GET_ATOM(_NET_WM_PING);
     2.7 +    GET_ATOM(_NET_WM_USER_TIME);
     2.8      GET_ATOM(_NET_ACTIVE_WINDOW);
     2.9      GET_ATOM(UTF8_STRING);
    2.10      GET_ATOM(PRIMARY);
     3.1 --- a/src/video/x11/SDL_x11video.h	Sun Jan 03 21:48:17 2016 -0500
     3.2 +++ b/src/video/x11/SDL_x11video.h	Mon Jan 04 16:25:27 2016 -0500
     3.3 @@ -100,6 +100,7 @@
     3.4      Atom _NET_WM_ICON_NAME;
     3.5      Atom _NET_WM_ICON;
     3.6      Atom _NET_WM_PING;
     3.7 +    Atom _NET_WM_USER_TIME;
     3.8      Atom _NET_ACTIVE_WINDOW;
     3.9      Atom UTF8_STRING;
    3.10      Atom PRIMARY;
     4.1 --- a/src/video/x11/SDL_x11window.c	Sun Jan 03 21:48:17 2016 -0500
     4.2 +++ b/src/video/x11/SDL_x11window.c	Mon Jan 04 16:25:27 2016 -0500
     4.3 @@ -944,6 +944,8 @@
     4.4      Atom _NET_ACTIVE_WINDOW = data->videodata->_NET_ACTIVE_WINDOW;
     4.5  
     4.6      if (X11_IsWindowMapped(_this, window)) {
     4.7 +        SDL_assert(data->user_time != 0);  /* should be set by _some_ event by now. */
     4.8 +        /*printf("SDL Window %p: sending _NET_ACTIVE_WINDOW with timestamp %lu\n", window, data->user_time);*/
     4.9          XEvent e;
    4.10  
    4.11          SDL_zero(e);
    4.12 @@ -952,7 +954,7 @@
    4.13          e.xclient.format = 32;
    4.14          e.xclient.window = data->xwindow;
    4.15          e.xclient.data.l[0] = 1;  /* source indication. 1 = application */
    4.16 -        e.xclient.data.l[1] = CurrentTime;
    4.17 +        e.xclient.data.l[1] = data->user_time;
    4.18          e.xclient.data.l[2] = 0;
    4.19  
    4.20          X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0,
     5.1 --- a/src/video/x11/SDL_x11window.h	Sun Jan 03 21:48:17 2016 -0500
     5.2 +++ b/src/video/x11/SDL_x11window.h	Mon Jan 04 16:25:27 2016 -0500
     5.3 @@ -60,6 +60,7 @@
     5.4      Uint32 pending_focus_time;
     5.5      XConfigureEvent last_xconfigure;
     5.6      struct SDL_VideoData *videodata;
     5.7 +    unsigned long user_time;
     5.8      Atom xdnd_req;
     5.9      Window xdnd_source;
    5.10  #if SDL_VIDEO_OPENGL_EGL