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.
This commit is contained in:
Ryan C. Gordon 2016-01-05 01:30:40 -05:00
parent f9b7379341
commit f2defe5e11
5 changed files with 54 additions and 11 deletions

View File

@ -110,7 +110,12 @@ typedef enum
SDL_WINDOW_FULLSCREEN_DESKTOP = ( SDL_WINDOW_FULLSCREEN | 0x00001000 ),
SDL_WINDOW_FOREIGN = 0x00000800, /**< window not created by SDL */
SDL_WINDOW_ALLOW_HIGHDPI = 0x00002000, /**< window should be created in high-DPI mode if supported */
SDL_WINDOW_MOUSE_CAPTURE = 0x00004000 /**< window has mouse captured (unrelated to INPUT_GRABBED) */
SDL_WINDOW_MOUSE_CAPTURE = 0x00004000, /**< window has mouse captured (unrelated to INPUT_GRABBED) */
SDL_WINDOW_ALWAYS_ON_TOP = 0x00008000, /**< window should always be above others */
SDL_WINDOW_SKIP_TASKBAR = 0x00010000, /**< window should not be added to the taskbar */
SDL_WINDOW_UTILITY = 0x00020000, /**< window should be treated as a utility window */
SDL_WINDOW_TOOLTIP = 0x00040000, /**< window should be treated as a tooltip */
SDL_WINDOW_POPUP_MENU = 0x00080000 /**< window should be treated as a popup menu */
} SDL_WindowFlags;
/**

View File

@ -1304,7 +1304,7 @@ SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
}
#define CREATE_FLAGS \
(SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI)
(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)
static void
SDL_FinishWindowCreation(SDL_Window *window, Uint32 flags)
@ -1344,6 +1344,11 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
}
}
if ( (((flags & SDL_WINDOW_UTILITY) != 0) + ((flags & SDL_WINDOW_TOOLTIP) != 0) + ((flags & SDL_WINDOW_POPUP_MENU) != 0)) > 1 ) {
SDL_SetError("Conflicting window flags specified");
return NULL;
}
/* Some platforms can't create zero-sized windows */
if (w < 1) {
w = 1;

View File

@ -394,6 +394,9 @@ X11_VideoInit(_THIS)
GET_ATOM(_NET_WM_STATE_MAXIMIZED_VERT);
GET_ATOM(_NET_WM_STATE_MAXIMIZED_HORZ);
GET_ATOM(_NET_WM_STATE_FULLSCREEN);
GET_ATOM(_NET_WM_STATE_ABOVE);
GET_ATOM(_NET_WM_STATE_SKIP_TASKBAR);
GET_ATOM(_NET_WM_STATE_SKIP_PAGER);
GET_ATOM(_NET_WM_ALLOWED_ACTIONS);
GET_ATOM(_NET_WM_ACTION_FULLSCREEN);
GET_ATOM(_NET_WM_NAME);

View File

@ -94,6 +94,9 @@ typedef struct SDL_VideoData
Atom _NET_WM_STATE_MAXIMIZED_VERT;
Atom _NET_WM_STATE_MAXIMIZED_HORZ;
Atom _NET_WM_STATE_FULLSCREEN;
Atom _NET_WM_STATE_ABOVE;
Atom _NET_WM_STATE_SKIP_TASKBAR;
Atom _NET_WM_STATE_SKIP_PAGER;
Atom _NET_WM_ALLOWED_ACTIONS;
Atom _NET_WM_ACTION_FULLSCREEN;
Atom _NET_WM_NAME;

View File

@ -137,7 +137,10 @@ X11_SetNetWMState(_THIS, Window xwindow, Uint32 flags)
Atom _NET_WM_STATE_MAXIMIZED_VERT = videodata->_NET_WM_STATE_MAXIMIZED_VERT;
Atom _NET_WM_STATE_MAXIMIZED_HORZ = videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
Atom _NET_WM_STATE_FULLSCREEN = videodata->_NET_WM_STATE_FULLSCREEN;
Atom atoms[5];
Atom _NET_WM_STATE_ABOVE = videodata->_NET_WM_STATE_ABOVE;
Atom _NET_WM_STATE_SKIP_TASKBAR = videodata->_NET_WM_STATE_SKIP_TASKBAR;
Atom _NET_WM_STATE_SKIP_PAGER = videodata->_NET_WM_STATE_SKIP_PAGER;
Atom atoms[16];
int count = 0;
/* The window manager sets this property, we shouldn't set it.
@ -148,6 +151,14 @@ X11_SetNetWMState(_THIS, Window xwindow, Uint32 flags)
atoms[count++] = _NET_WM_STATE_HIDDEN;
}
*/
if (flags & SDL_WINDOW_ALWAYS_ON_TOP) {
atoms[count++] = _NET_WM_STATE_ABOVE;
}
if (flags & SDL_WINDOW_SKIP_TASKBAR) {
atoms[count++] = _NET_WM_STATE_SKIP_TASKBAR;
atoms[count++] = _NET_WM_STATE_SKIP_PAGER;
}
if (flags & SDL_WINDOW_INPUT_FOCUS) {
atoms[count++] = _NET_WM_STATE_FOCUSED;
}
@ -158,6 +169,9 @@ X11_SetNetWMState(_THIS, Window xwindow, Uint32 flags)
if (flags & SDL_WINDOW_FULLSCREEN) {
atoms[count++] = _NET_WM_STATE_FULLSCREEN;
}
SDL_assert(count <= SDL_arraysize(atoms));
if (count > 0) {
X11_XChangeProperty(display, xwindow, _NET_WM_STATE, XA_ATOM, 32,
PropModeReplace, (unsigned char *)atoms, count);
@ -358,10 +372,11 @@ X11_CreateWindow(_THIS, SDL_Window * window)
XSizeHints *sizehints;
XWMHints *wmhints;
XClassHint *classhints;
const long _NET_WM_BYPASS_COMPOSITOR_HINT_ON = 1;
Atom _NET_WM_BYPASS_COMPOSITOR;
Atom _NET_WM_WINDOW_TYPE;
Atom _NET_WM_WINDOW_TYPE_NORMAL;
Atom wintype;
const char *wintype_name = NULL;
int compositor = 1;
Atom _NET_WM_PID;
Atom XdndAware, xdnd_version = 5;
long fevent = 0;
@ -399,7 +414,7 @@ X11_CreateWindow(_THIS, SDL_Window * window)
depth = displaydata->depth;
}
xattr.override_redirect = False;
xattr.override_redirect = ((window->flags & SDL_WINDOW_TOOLTIP) || (window->flags & SDL_WINDOW_POPUP_MENU)) ? True : False;
xattr.background_pixmap = None;
xattr.border_pixel = 0;
@ -533,17 +548,29 @@ X11_CreateWindow(_THIS, SDL_Window * window)
/* Set the window manager state */
X11_SetNetWMState(_this, w, window->flags);
/* Let the window manager know we're a "normal" window */
compositor = 2; /* don't disable compositing except for "normal" windows */
if (window->flags & SDL_WINDOW_UTILITY) {
wintype_name = "_NET_WM_WINDOW_TYPE_UTILITY";
} else if (window->flags & SDL_WINDOW_TOOLTIP) {
wintype_name = "_NET_WM_WINDOW_TYPE_TOOLTIP";
} else if (window->flags & SDL_WINDOW_POPUP_MENU) {
wintype_name = "_NET_WM_WINDOW_TYPE_POPUP_MENU";
} else {
wintype_name = "_NET_WM_WINDOW_TYPE_NORMAL";
compositor = 1; /* disable compositing for "normal" windows */
}
/* Let the window manager know what type of window we are. */
_NET_WM_WINDOW_TYPE = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
_NET_WM_WINDOW_TYPE_NORMAL = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE_NORMAL", False);
wintype = X11_XInternAtom(display, wintype_name, False);
X11_XChangeProperty(display, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32,
PropModeReplace,
(unsigned char *)&_NET_WM_WINDOW_TYPE_NORMAL, 1);
PropModeReplace, (unsigned char *)&wintype, 1);
_NET_WM_BYPASS_COMPOSITOR = X11_XInternAtom(display, "_NET_WM_BYPASS_COMPOSITOR", False);
X11_XChangeProperty(display, w, _NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32,
PropModeReplace,
(unsigned char *)&_NET_WM_BYPASS_COMPOSITOR_HINT_ON, 1);
(unsigned char *)&compositor, 1);
{
Atom protocols[2];