Can I change the "always on top" flag somehow?

I want to change the Always On Top flag in an SDL_Window after it’s created. It can be set initially with SDL_CreateWindow as a flag, but after that, it’s not possible to change the Always On Top flag through the API

What’s more, I cannot directly use the windows API SetWindowPos() to do this myself because SDL calls it itself in a way that reverts the the topmost status of the HWND to what the flag is set to.

What should I do?

I think I solved it! I ended up changing two lines

Where ever I found

if (SDL_ShouldAllowTopmost() && (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) == (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) {

I replaced it with

if (SDL_ShouldAllowTopmost() && ((window->flags & SDL_WINDOW_ALWAYS_ON_TOP) || (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) == (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS))) {

This gets the flag to work as expected. From there, I just do the following sin to set the flag
// SDL_Window * m_window;
if(toggle){
reinterpret_cast<uint32*>(m_window)[12] |= SDL_WINDOW_ALWAYS_ON_TOP;
}else{
reinterpret_cast<uint32*>(m_window)[12] &= ~SDL_WINDOW_ALWAYS_ON_TOP;
}

You can actually set this hint in your code instead of hard-coding offsets into private memory (which will surely break someday!)

/**
 *  \brief If set to "0" then never set the top most bit on a SDL Window, even if the video mode expects it.
 *      This is a debugging aid for developers and not expected to be used by end users. The default is "1"
 *
 *  This variable can be set to the following values:
 *    "0"       - don't allow topmost
 *    "1"       - allow topmost
 */
#define SDL_HINT_ALLOW_TOPMOST "SDL_ALLOW_TOPMOST"

I looked into it, but that hint only prevents SDL from enabling the topmost zorder, when it would ordinarily do so when the window is both fullscreen and has input focus. (I’m not sure why this is, but perhaps it’s necessary for fullscreen?) Eitherway, it’s enabled by default.

The full conditional as it is in the SDL functions where it appears, is this:

if (SDL_ShouldAllowTopmost() && (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) == (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) {
    top = HWND_TOPMOST;
} else {
    top = HWND_NOTOPMOST;
}
...
SetWindowPos(hwnd, top, x, y, w, h, flags);

the “flags” argument don’t have SWP_NOZORDER specified in anyplace, so it will always set the zorder status.

I had to add the extra argument of (window->flags & SDL_WINDOW_ALWAYS_ON_TOP) || so the flag would have an effect (it doesn’t seem to be checked anywhere).

As for the bit twiddling with SDL_Window, it’s definitely goin’ to break if I update SDL aha… it’s just a cludgey hack to set the flag until an API is added later, I hope!