Skip to content

Commit

Permalink
Added special window type flags.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
icculus committed Jan 5, 2016
1 parent f9b7379 commit f2defe5
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 11 deletions.
7 changes: 6 additions & 1 deletion include/SDL_video.h
Expand Up @@ -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;

/**
Expand Down
7 changes: 6 additions & 1 deletion src/video/SDL_video.c
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions src/video/x11/SDL_x11video.c
Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions src/video/x11/SDL_x11video.h
Expand Up @@ -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;
Expand Down
45 changes: 36 additions & 9 deletions src/video/x11/SDL_x11window.c
Expand Up @@ -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.
Expand All @@ -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;
}
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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];
Expand Down

0 comments on commit f2defe5

Please sign in to comment.