Added special window type flags.
authorRyan C. Gordon <icculus@icculus.org>
Tue, 05 Jan 2016 01:30:40 -0500
changeset 100213beca914a2ad
parent 10020 08b9e569e1ce
child 10022 30807689ca1b
Added special window type flags.

Specifically: always on top, skip taskbar, tooltip, utility, and popup menu.

This is currently only implemented for X11.

This patch is based on work in Unreal Engine 4's fork of SDL,
compliments of Epic Games.
include/SDL_video.h
src/video/SDL_video.c
src/video/x11/SDL_x11video.c
src/video/x11/SDL_x11video.h
src/video/x11/SDL_x11window.c
     1.1 --- a/include/SDL_video.h	Tue Jan 05 02:26:45 2016 -0500
     1.2 +++ b/include/SDL_video.h	Tue Jan 05 01:30:40 2016 -0500
     1.3 @@ -110,7 +110,12 @@
     1.4      SDL_WINDOW_FULLSCREEN_DESKTOP = ( SDL_WINDOW_FULLSCREEN | 0x00001000 ),
     1.5      SDL_WINDOW_FOREIGN = 0x00000800,            /**< window not created by SDL */
     1.6      SDL_WINDOW_ALLOW_HIGHDPI = 0x00002000,      /**< window should be created in high-DPI mode if supported */
     1.7 -    SDL_WINDOW_MOUSE_CAPTURE = 0x00004000       /**< window has mouse captured (unrelated to INPUT_GRABBED) */
     1.8 +    SDL_WINDOW_MOUSE_CAPTURE = 0x00004000,      /**< window has mouse captured (unrelated to INPUT_GRABBED) */
     1.9 +    SDL_WINDOW_ALWAYS_ON_TOP = 0x00008000,      /**< window should always be above others */
    1.10 +    SDL_WINDOW_SKIP_TASKBAR  = 0x00010000,      /**< window should not be added to the taskbar */
    1.11 +    SDL_WINDOW_UTILITY       = 0x00020000,      /**< window should be treated as a utility window */
    1.12 +    SDL_WINDOW_TOOLTIP       = 0x00040000,      /**< window should be treated as a tooltip */
    1.13 +    SDL_WINDOW_POPUP_MENU    = 0x00080000       /**< window should be treated as a popup menu */
    1.14  } SDL_WindowFlags;
    1.15  
    1.16  /**
     2.1 --- a/src/video/SDL_video.c	Tue Jan 05 02:26:45 2016 -0500
     2.2 +++ b/src/video/SDL_video.c	Tue Jan 05 01:30:40 2016 -0500
     2.3 @@ -1304,7 +1304,7 @@
     2.4  }
     2.5  
     2.6  #define CREATE_FLAGS \
     2.7 -    (SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI)
     2.8 +    (SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_SKIP_TASKBAR | SDL_WINDOW_POPUP_MENU | SDL_WINDOW_UTILITY | SDL_WINDOW_TOOLTIP)
     2.9  
    2.10  static void
    2.11  SDL_FinishWindowCreation(SDL_Window *window, Uint32 flags)
    2.12 @@ -1344,6 +1344,11 @@
    2.13          }
    2.14      }
    2.15  
    2.16 +    if ( (((flags & SDL_WINDOW_UTILITY) != 0) + ((flags & SDL_WINDOW_TOOLTIP) != 0) + ((flags & SDL_WINDOW_POPUP_MENU) != 0)) > 1 ) {
    2.17 +        SDL_SetError("Conflicting window flags specified");
    2.18 +        return NULL;
    2.19 +    }
    2.20 +
    2.21      /* Some platforms can't create zero-sized windows */
    2.22      if (w < 1) {
    2.23          w = 1;
     3.1 --- a/src/video/x11/SDL_x11video.c	Tue Jan 05 02:26:45 2016 -0500
     3.2 +++ b/src/video/x11/SDL_x11video.c	Tue Jan 05 01:30:40 2016 -0500
     3.3 @@ -394,6 +394,9 @@
     3.4      GET_ATOM(_NET_WM_STATE_MAXIMIZED_VERT);
     3.5      GET_ATOM(_NET_WM_STATE_MAXIMIZED_HORZ);
     3.6      GET_ATOM(_NET_WM_STATE_FULLSCREEN);
     3.7 +    GET_ATOM(_NET_WM_STATE_ABOVE);
     3.8 +    GET_ATOM(_NET_WM_STATE_SKIP_TASKBAR);
     3.9 +    GET_ATOM(_NET_WM_STATE_SKIP_PAGER);
    3.10      GET_ATOM(_NET_WM_ALLOWED_ACTIONS);
    3.11      GET_ATOM(_NET_WM_ACTION_FULLSCREEN);
    3.12      GET_ATOM(_NET_WM_NAME);
     4.1 --- a/src/video/x11/SDL_x11video.h	Tue Jan 05 02:26:45 2016 -0500
     4.2 +++ b/src/video/x11/SDL_x11video.h	Tue Jan 05 01:30:40 2016 -0500
     4.3 @@ -94,6 +94,9 @@
     4.4      Atom _NET_WM_STATE_MAXIMIZED_VERT;
     4.5      Atom _NET_WM_STATE_MAXIMIZED_HORZ;
     4.6      Atom _NET_WM_STATE_FULLSCREEN;
     4.7 +    Atom _NET_WM_STATE_ABOVE;
     4.8 +    Atom _NET_WM_STATE_SKIP_TASKBAR;
     4.9 +    Atom _NET_WM_STATE_SKIP_PAGER;
    4.10      Atom _NET_WM_ALLOWED_ACTIONS;
    4.11      Atom _NET_WM_ACTION_FULLSCREEN;
    4.12      Atom _NET_WM_NAME;
     5.1 --- a/src/video/x11/SDL_x11window.c	Tue Jan 05 02:26:45 2016 -0500
     5.2 +++ b/src/video/x11/SDL_x11window.c	Tue Jan 05 01:30:40 2016 -0500
     5.3 @@ -137,7 +137,10 @@
     5.4      Atom _NET_WM_STATE_MAXIMIZED_VERT = videodata->_NET_WM_STATE_MAXIMIZED_VERT;
     5.5      Atom _NET_WM_STATE_MAXIMIZED_HORZ = videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
     5.6      Atom _NET_WM_STATE_FULLSCREEN = videodata->_NET_WM_STATE_FULLSCREEN;
     5.7 -    Atom atoms[5];
     5.8 +    Atom _NET_WM_STATE_ABOVE = videodata->_NET_WM_STATE_ABOVE;
     5.9 +    Atom _NET_WM_STATE_SKIP_TASKBAR = videodata->_NET_WM_STATE_SKIP_TASKBAR;
    5.10 +    Atom _NET_WM_STATE_SKIP_PAGER = videodata->_NET_WM_STATE_SKIP_PAGER;
    5.11 +    Atom atoms[16];
    5.12      int count = 0;
    5.13  
    5.14      /* The window manager sets this property, we shouldn't set it.
    5.15 @@ -148,6 +151,14 @@
    5.16          atoms[count++] = _NET_WM_STATE_HIDDEN;
    5.17      }
    5.18      */
    5.19 +
    5.20 +    if (flags & SDL_WINDOW_ALWAYS_ON_TOP) {
    5.21 +        atoms[count++] = _NET_WM_STATE_ABOVE;
    5.22 +    }
    5.23 +    if (flags & SDL_WINDOW_SKIP_TASKBAR) {
    5.24 +        atoms[count++] = _NET_WM_STATE_SKIP_TASKBAR;
    5.25 +        atoms[count++] = _NET_WM_STATE_SKIP_PAGER;
    5.26 +    }
    5.27      if (flags & SDL_WINDOW_INPUT_FOCUS) {
    5.28          atoms[count++] = _NET_WM_STATE_FOCUSED;
    5.29      }
    5.30 @@ -158,6 +169,9 @@
    5.31      if (flags & SDL_WINDOW_FULLSCREEN) {
    5.32          atoms[count++] = _NET_WM_STATE_FULLSCREEN;
    5.33      }
    5.34 +
    5.35 +    SDL_assert(count <= SDL_arraysize(atoms));
    5.36 +
    5.37      if (count > 0) {
    5.38          X11_XChangeProperty(display, xwindow, _NET_WM_STATE, XA_ATOM, 32,
    5.39                          PropModeReplace, (unsigned char *)atoms, count);
    5.40 @@ -358,10 +372,11 @@
    5.41      XSizeHints *sizehints;
    5.42      XWMHints *wmhints;
    5.43      XClassHint *classhints;
    5.44 -    const long _NET_WM_BYPASS_COMPOSITOR_HINT_ON = 1;
    5.45      Atom _NET_WM_BYPASS_COMPOSITOR;
    5.46      Atom _NET_WM_WINDOW_TYPE;
    5.47 -    Atom _NET_WM_WINDOW_TYPE_NORMAL;
    5.48 +    Atom wintype;
    5.49 +    const char *wintype_name = NULL;
    5.50 +    int compositor = 1;
    5.51      Atom _NET_WM_PID;
    5.52      Atom XdndAware, xdnd_version = 5;
    5.53      long fevent = 0;
    5.54 @@ -399,7 +414,7 @@
    5.55          depth = displaydata->depth;
    5.56      }
    5.57  
    5.58 -    xattr.override_redirect = False;
    5.59 +    xattr.override_redirect = ((window->flags & SDL_WINDOW_TOOLTIP) || (window->flags & SDL_WINDOW_POPUP_MENU)) ? True : False;
    5.60      xattr.background_pixmap = None;
    5.61      xattr.border_pixel = 0;
    5.62  
    5.63 @@ -533,17 +548,29 @@
    5.64      /* Set the window manager state */
    5.65      X11_SetNetWMState(_this, w, window->flags);
    5.66  
    5.67 -    /* Let the window manager know we're a "normal" window */
    5.68 +    compositor = 2;  /* don't disable compositing except for "normal" windows */
    5.69 +
    5.70 +    if (window->flags & SDL_WINDOW_UTILITY) {
    5.71 +        wintype_name = "_NET_WM_WINDOW_TYPE_UTILITY";
    5.72 +    } else if (window->flags & SDL_WINDOW_TOOLTIP) {
    5.73 +        wintype_name = "_NET_WM_WINDOW_TYPE_TOOLTIP";
    5.74 +    } else if (window->flags & SDL_WINDOW_POPUP_MENU) {
    5.75 +        wintype_name = "_NET_WM_WINDOW_TYPE_POPUP_MENU";
    5.76 +    } else {
    5.77 +        wintype_name = "_NET_WM_WINDOW_TYPE_NORMAL";
    5.78 +        compositor = 1;  /* disable compositing for "normal" windows */
    5.79 +    }
    5.80 +
    5.81 +    /* Let the window manager know what type of window we are. */
    5.82      _NET_WM_WINDOW_TYPE = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
    5.83 -    _NET_WM_WINDOW_TYPE_NORMAL = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE_NORMAL", False);
    5.84 +    wintype = X11_XInternAtom(display, wintype_name, False);
    5.85      X11_XChangeProperty(display, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32,
    5.86 -                    PropModeReplace,
    5.87 -                    (unsigned char *)&_NET_WM_WINDOW_TYPE_NORMAL, 1);
    5.88 +                    PropModeReplace, (unsigned char *)&wintype, 1);
    5.89  
    5.90      _NET_WM_BYPASS_COMPOSITOR = X11_XInternAtom(display, "_NET_WM_BYPASS_COMPOSITOR", False);
    5.91      X11_XChangeProperty(display, w, _NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32,
    5.92                      PropModeReplace,
    5.93 -                    (unsigned char *)&_NET_WM_BYPASS_COMPOSITOR_HINT_ON, 1);
    5.94 +                    (unsigned char *)&compositor, 1);
    5.95  
    5.96      {
    5.97          Atom protocols[2];