From a0a5da5d91b4316c2ca60f5dfce3b5963ef89d24 Mon Sep 17 00:00:00 2001
From: Joseph Lyncheski <[EMAIL REDACTED]>
Date: Mon, 19 Apr 2021 07:13:38 -0400
Subject: [PATCH] Add SDL_SetWindowAlwaysOnTop()
---
include/SDL_video.h | 15 +++++++++++++++
src/dynapi/SDL_dynapi_overrides.h | 1 +
src/dynapi/SDL_dynapi_procs.h | 1 +
src/video/SDL_sysvideo.h | 1 +
src/video/SDL_video.c | 19 +++++++++++++++++++
src/video/cocoa/SDL_cocoavideo.m | 1 +
src/video/cocoa/SDL_cocoawindow.h | 1 +
src/video/cocoa/SDL_cocoawindow.m | 12 ++++++++++++
src/video/windows/SDL_windowsvideo.c | 1 +
src/video/windows/SDL_windowswindow.c | 12 ++++++++++++
src/video/windows/SDL_windowswindow.h | 1 +
11 files changed, 65 insertions(+)
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 @@
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 @@ - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
}
}}
+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);