diff --git a/include/SDL_video.h b/include/SDL_video.h index 8a7b3ccdf..65fd6437e 100644 --- a/include/SDL_video.h +++ b/include/SDL_video.h @@ -1010,6 +1010,21 @@ extern DECLSPEC void SDLCALL SDL_SetWindowBordered(SDL_Window * window, extern DECLSPEC void SDLCALL SDL_SetWindowResizable(SDL_Window * window, SDL_bool resizable); +/** + * \brief Set the window to always be above the others. + * + * This will add or remove the window's `SDL_WINDOW_ALWAYS_ON_TOP` + * flag. This will bring the window to the front and keep the window above + * the rest. + * + * \param window The window of which to change the always on top state. + * \param on_top SDL_TRUE to set the window always on top, SDL_FALSE to disable. + * + * \sa SDL_SetWindowAlwaysOnTop + */ + +extern DECLSPEC void SDLCALL SDL_SetWindowAlwaysOnTop(SDL_Window * window, + SDL_bool on_top); /** * Show a window. * diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 2d35d5f9b..157730806 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -810,3 +810,4 @@ #define SDL_AndroidShowToast SDL_AndroidShowToast_REAL #define SDL_GetAudioDeviceSpec SDL_GetAudioDeviceSpec_REAL #define SDL_TLSCleanup SDL_TLSCleanup_REAL +#define SDL_SetWindowAlwaysOnTop SDL_SetWindowAlwaysOnTop_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 6d89825f0..a3113d1da 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -875,3 +875,4 @@ SDL_DYNAPI_PROC(int,SDL_AndroidShowToast,(const char *a, int b, int c, int d, in #endif SDL_DYNAPI_PROC(int,SDL_GetAudioDeviceSpec,(int a, int b, SDL_AudioSpec *c),(a,b,c),return) SDL_DYNAPI_PROC(void,SDL_TLSCleanup,(void),(),) +SDL_DYNAPI_PROC(void,SDL_SetWindowAlwaysOnTop,(SDL_Window *a, SDL_bool b),(a,b),) diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index c6f004865..682e52592 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -229,6 +229,7 @@ struct SDL_VideoDevice void (*RestoreWindow) (_THIS, SDL_Window * window); void (*SetWindowBordered) (_THIS, SDL_Window * window, SDL_bool bordered); void (*SetWindowResizable) (_THIS, SDL_Window * window, SDL_bool resizable); + void (*SetWindowAlwaysOnTop) (_THIS, SDL_Window * window, SDL_bool on_top); void (*SetWindowFullscreen) (_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen); int (*SetWindowGammaRamp) (_THIS, SDL_Window * window, const Uint16 * ramp); int (*GetWindowGammaRamp) (_THIS, SDL_Window * window, Uint16 * ramp); diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index e15afb956..a5cbe6962 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -2109,6 +2109,25 @@ SDL_SetWindowResizable(SDL_Window * window, SDL_bool resizable) } } +void +SDL_SetWindowAlwaysOnTop(SDL_Window * window, SDL_bool on_top) +{ + CHECK_WINDOW_MAGIC(window,); + if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { + const int want = (on_top != SDL_FALSE); /* normalize the flag. */ + const int have = ((window->flags & SDL_WINDOW_ALWAYS_ON_TOP) != 0); + if ((want != have) && (_this->SetWindowAlwaysOnTop)) { + if (want) { + window->flags |= SDL_WINDOW_ALWAYS_ON_TOP; + } else { + window->flags &= ~SDL_WINDOW_ALWAYS_ON_TOP; + } + + _this->SetWindowAlwaysOnTop(_this, window, (SDL_bool) want); + } + } +} + void SDL_SetWindowSize(SDL_Window * window, int w, int h) { diff --git a/src/video/cocoa/SDL_cocoavideo.m b/src/video/cocoa/SDL_cocoavideo.m index 55c6026cf..5019d3e7c 100644 --- a/src/video/cocoa/SDL_cocoavideo.m +++ b/src/video/cocoa/SDL_cocoavideo.m @@ -92,6 +92,7 @@ Cocoa_CreateDevice(int devindex) device->RestoreWindow = Cocoa_RestoreWindow; device->SetWindowBordered = Cocoa_SetWindowBordered; device->SetWindowResizable = Cocoa_SetWindowResizable; + device->SetWindowAlwaysOnTop = Cocoa_SetWindowAlwaysOnTop; device->SetWindowFullscreen = Cocoa_SetWindowFullscreen; device->SetWindowGammaRamp = Cocoa_SetWindowGammaRamp; device->GetWindowGammaRamp = Cocoa_GetWindowGammaRamp; diff --git a/src/video/cocoa/SDL_cocoawindow.h b/src/video/cocoa/SDL_cocoawindow.h index a8d1126d1..a2000d420 100644 --- a/src/video/cocoa/SDL_cocoawindow.h +++ b/src/video/cocoa/SDL_cocoawindow.h @@ -142,6 +142,7 @@ extern void Cocoa_MinimizeWindow(_THIS, SDL_Window * window); extern void Cocoa_RestoreWindow(_THIS, SDL_Window * window); extern void Cocoa_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered); extern void Cocoa_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable); +extern void Cocoa_SetWindowAlwaysOnTop(_THIS, SDL_Window * window, SDL_bool on_top); extern void Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen); extern int Cocoa_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp); extern int Cocoa_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp); diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index 802cb3abe..49bdfe834 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -1819,6 +1819,18 @@ Cocoa_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable) } }} +void +Cocoa_SetWindowAlwaysOnTop(_THIS, SDL_Window * window, SDL_bool on_top) +{ @autoreleasepool + { + NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow; + if (on_top) { + [nswindow setLevel:NSFloatingWindowLevel]; + } else { + [nswindow setLevel:kCGNormalWindowLevel]; + } + }} + void Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen) { @autoreleasepool diff --git a/src/video/windows/SDL_windowsvideo.c b/src/video/windows/SDL_windowsvideo.c index 7b7c35fbb..8eb32b2ef 100644 --- a/src/video/windows/SDL_windowsvideo.c +++ b/src/video/windows/SDL_windowsvideo.c @@ -157,6 +157,7 @@ WIN_CreateDevice(int devindex) device->RestoreWindow = WIN_RestoreWindow; device->SetWindowBordered = WIN_SetWindowBordered; device->SetWindowResizable = WIN_SetWindowResizable; + device->SetWindowAlwaysOnTop = WIN_SetWindowAlwaysOnTop; device->SetWindowFullscreen = WIN_SetWindowFullscreen; device->SetWindowGammaRamp = WIN_SetWindowGammaRamp; device->GetWindowGammaRamp = WIN_GetWindowGammaRamp; diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index 95ceaf993..51d0c1111 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -631,6 +631,18 @@ WIN_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable) SetWindowLong(hwnd, GWL_STYLE, style); } +void +WIN_SetWindowAlwaysOnTop(_THIS, SDL_Window * window, SDL_bool on_top) +{ + SDL_WindowData *data = (SDL_WindowData *)window->driverdata; + HWND hwnd = data->hwnd; + if (on_top) { + SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + } else { + SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + } +} + void WIN_RestoreWindow(_THIS, SDL_Window * window) { diff --git a/src/video/windows/SDL_windowswindow.h b/src/video/windows/SDL_windowswindow.h index c83f06d05..fe7f825ff 100644 --- a/src/video/windows/SDL_windowswindow.h +++ b/src/video/windows/SDL_windowswindow.h @@ -73,6 +73,7 @@ extern void WIN_MinimizeWindow(_THIS, SDL_Window * window); extern void WIN_RestoreWindow(_THIS, SDL_Window * window); extern void WIN_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered); extern void WIN_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable); +extern void WIN_SetWindowAlwaysOnTop(_THIS, SDL_Window * window, SDL_bool on_top); extern void WIN_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen); extern int WIN_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp); extern int WIN_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp);