summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/bind/core_bind.cpp10
-rw-r--r--core/bind/core_bind.h2
-rw-r--r--core/os/os.h6
-rw-r--r--main/main.cpp10
-rw-r--r--platform/osx/os_osx.h2
-rw-r--r--platform/osx/os_osx.mm14
-rw-r--r--platform/windows/os_windows.cpp19
-rw-r--r--platform/windows/os_windows.h2
-rw-r--r--platform/x11/os_x11.cpp57
-rw-r--r--platform/x11/os_x11.h3
10 files changed, 121 insertions, 4 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 8f1a57e363..b57b24ee7d 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -304,6 +304,14 @@ bool _OS::is_window_maximized() const {
return OS::get_singleton()->is_window_maximized();
}
+void _OS::set_window_always_on_top(bool p_enabled) {
+ OS::get_singleton()->set_window_always_on_top(p_enabled);
+}
+
+bool _OS::is_window_always_on_top() const {
+ return OS::get_singleton()->is_window_always_on_top();
+}
+
void _OS::set_borderless_window(bool p_borderless) {
OS::get_singleton()->set_borderless_window(p_borderless);
}
@@ -1025,6 +1033,8 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_window_minimized"), &_OS::is_window_minimized);
ClassDB::bind_method(D_METHOD("set_window_maximized", "enabled"), &_OS::set_window_maximized);
ClassDB::bind_method(D_METHOD("is_window_maximized"), &_OS::is_window_maximized);
+ ClassDB::bind_method(D_METHOD("set_window_always_on_top", "enabled"), &_OS::set_window_always_on_top);
+ ClassDB::bind_method(D_METHOD("is_window_always_on_top"), &_OS::is_window_always_on_top);
ClassDB::bind_method(D_METHOD("request_attention"), &_OS::request_attention);
ClassDB::bind_method(D_METHOD("get_real_window_size"), &_OS::get_real_window_size);
ClassDB::bind_method(D_METHOD("center_window"), &_OS::center_window);
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index 6b688a65f8..734b57937a 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -165,6 +165,8 @@ public:
virtual bool is_window_minimized() const;
virtual void set_window_maximized(bool p_enabled);
virtual bool is_window_maximized() const;
+ virtual void set_window_always_on_top(bool p_enabled);
+ virtual bool is_window_always_on_top() const;
virtual void request_attention();
virtual void center_window();
diff --git a/core/os/os.h b/core/os/os.h
index 1ec488df06..38e55fa3b7 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -94,15 +94,17 @@ public:
bool resizable;
bool borderless_window;
bool maximized;
+ bool always_on_top;
bool use_vsync;
float get_aspect() const { return (float)width / (float)height; }
- VideoMode(int p_width = 1024, int p_height = 600, bool p_fullscreen = false, bool p_resizable = true, bool p_borderless_window = false, bool p_maximized = false, bool p_use_vsync = false) {
+ VideoMode(int p_width = 1024, int p_height = 600, bool p_fullscreen = false, bool p_resizable = true, bool p_borderless_window = false, bool p_maximized = false, bool p_always_on_top = false, bool p_use_vsync = false) {
width = p_width;
height = p_height;
fullscreen = p_fullscreen;
resizable = p_resizable;
borderless_window = p_borderless_window;
maximized = p_maximized;
+ always_on_top = p_always_on_top;
use_vsync = p_use_vsync;
}
};
@@ -192,6 +194,8 @@ public:
virtual bool is_window_minimized() const { return false; }
virtual void set_window_maximized(bool p_enabled) {}
virtual bool is_window_maximized() const { return true; }
+ virtual void set_window_always_on_top(bool p_enabled) {}
+ virtual bool is_window_always_on_top() const { return false; }
virtual void request_attention() {}
virtual void center_window();
diff --git a/main/main.cpp b/main/main.cpp
index 62d218477f..e9eca4af39 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -106,6 +106,7 @@ static OS::VideoMode video_mode;
static bool init_maximized = false;
static bool init_windowed = false;
static bool init_fullscreen = false;
+static bool init_always_on_top = false;
static bool init_use_custom_pos = false;
#ifdef DEBUG_ENABLED
static bool debug_collisions = false;
@@ -225,6 +226,7 @@ void Main::print_help(const char *p_binary) {
OS::get_singleton()->print(" -f, --fullscreen Request fullscreen mode.\n");
OS::get_singleton()->print(" -m, --maximized Request a maximized window.\n");
OS::get_singleton()->print(" -w, --windowed Request windowed mode.\n");
+ OS::get_singleton()->print(" -t, --always-on-top Request an always-on-top window.\n");
OS::get_singleton()->print(" --resolution <W>x<H> Request window resolution.\n");
OS::get_singleton()->print(" --position <X>,<Y> Request window position.\n");
OS::get_singleton()->print(" --low-dpi Force low-DPI mode (macOS and Windows only).\n");
@@ -431,6 +433,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
} else if (I->get() == "-w" || I->get() == "--windowed") { // force windowed window
init_windowed = true;
+ } else if (I->get() == "-t" || I->get() == "--always-on-top") { // force always-on-top window
+
+ init_always_on_top = true;
} else if (I->get() == "--profiling") { // enable profiling
use_debug_profiler = true;
@@ -820,6 +825,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
GLOBAL_DEF("display/window/size/resizable", true);
GLOBAL_DEF("display/window/size/borderless", false);
GLOBAL_DEF("display/window/size/fullscreen", false);
+ GLOBAL_DEF("display/window/size/always_on_top", false);
GLOBAL_DEF("display/window/size/test_width", 0);
GLOBAL_DEF("display/window/size/test_height", 0);
@@ -842,6 +848,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
video_mode.resizable = GLOBAL_GET("display/window/size/resizable");
video_mode.borderless_window = GLOBAL_GET("display/window/size/borderless");
video_mode.fullscreen = GLOBAL_GET("display/window/size/fullscreen");
+ video_mode.always_on_top = GLOBAL_GET("display/window/size/always_on_top");
}
if (!force_lowdpi) {
@@ -1047,6 +1054,9 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
} else if (init_fullscreen) {
OS::get_singleton()->set_window_fullscreen(true);
}
+ if (init_always_on_top) {
+ OS::get_singleton()->set_window_always_on_top(true);
+ }
register_server_types();
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index e5f43f9433..aa8db8f300 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -222,6 +222,8 @@ public:
virtual bool is_window_minimized() const;
virtual void set_window_maximized(bool p_enabled);
virtual bool is_window_maximized() const;
+ virtual void set_window_always_on_top(bool p_enabled);
+ virtual bool is_window_always_on_top() const;
virtual void request_attention();
virtual String get_joy_guid(int p_device) const;
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 65a168285d..4c459772aa 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -1966,6 +1966,20 @@ void OS_OSX::move_window_to_foreground() {
[window_object orderFrontRegardless];
}
+void OS_OSX::set_window_always_on_top(bool p_enabled) {
+ if (is_window_always_on_top() == p_enabled)
+ return;
+
+ if (p_enabled)
+ [window_object setLevel:NSFloatingWindowLevel];
+ else
+ [window_object setLevel:NSNormalWindowLevel];
+}
+
+bool OS_OSX::is_window_always_on_top() const {
+ return [window_object level] == NSFloatingWindowLevel;
+}
+
void OS_OSX::request_attention() {
[NSApp requestUserAttention:NSCriticalRequest];
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 5d27fae148..20129299a1 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -1075,6 +1075,10 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
}
};
+ if (video_mode.always_on_top) {
+ SetWindowPos(hWnd, video_mode.always_on_top ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ }
+
#if defined(OPENGL_ENABLED)
gl_context = memnew(ContextGL_Win(hWnd, true));
gl_context->initialize();
@@ -1614,6 +1618,19 @@ bool OS_Windows::is_window_maximized() const {
return maximized;
}
+void OS_Windows::set_window_always_on_top(bool p_enabled) {
+ if (video_mode.always_on_top == p_enabled)
+ return;
+
+ video_mode.always_on_top = p_enabled;
+
+ _update_window_style();
+}
+
+bool OS_Windows::is_window_always_on_top() const {
+ return video_mode.always_on_top;
+}
+
void OS_Windows::set_borderless_window(bool p_borderless) {
if (video_mode.borderless_window == p_borderless)
return;
@@ -1638,6 +1655,8 @@ void OS_Windows::_update_window_style(bool repaint) {
}
}
+ SetWindowPos(hWnd, video_mode.always_on_top ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+
if (repaint) {
RECT rect;
GetWindowRect(hWnd, &rect);
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 3437b8547b..4c4fbcf8f0 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -211,6 +211,8 @@ public:
virtual bool is_window_minimized() const;
virtual void set_window_maximized(bool p_enabled);
virtual bool is_window_maximized() const;
+ virtual void set_window_always_on_top(bool p_enabled);
+ virtual bool is_window_always_on_top() const;
virtual void request_attention();
virtual void set_borderless_window(bool p_borderless);
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index 8f2c1812b4..2d8e32137f 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -333,6 +333,11 @@ Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
XFree(xsh);
}
+ if (current_videomode.always_on_top) {
+ current_videomode.always_on_top = false;
+ set_window_always_on_top(true);
+ }
+
AudioDriverManager::initialize(p_audio_driver);
ERR_FAIL_COND_V(!visual_server, ERR_UNAVAILABLE);
@@ -725,9 +730,6 @@ void OS_X11::get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen) con
}
void OS_X11::set_wm_fullscreen(bool p_enabled) {
- if (current_videomode.fullscreen == p_enabled)
- return;
-
if (p_enabled && !is_window_resizable()) {
// Set the window as resizable to prevent window managers to ignore the fullscreen state flag.
XSizeHints *xsh;
@@ -788,6 +790,22 @@ void OS_X11::set_wm_fullscreen(bool p_enabled) {
}
}
+void OS_X11::set_wm_above(bool p_enabled) {
+ Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False);
+ Atom wm_above = XInternAtom(x11_display, "_NET_WM_STATE_ABOVE", False);
+
+ XClientMessageEvent xev;
+ memset(&xev, 0, sizeof(xev));
+ xev.type = ClientMessage;
+ xev.window = x11_window;
+ xev.message_type = wm_state;
+ xev.format = 32;
+ xev.data.l[0] = p_enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
+ xev.data.l[1] = wm_above;
+ xev.data.l[3] = 1;
+ XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent *)&xev);
+}
+
int OS_X11::get_screen_count() const {
// Using Xinerama Extension
int event_base, error_base;
@@ -982,7 +1000,19 @@ void OS_X11::set_window_size(const Size2 p_size) {
}
void OS_X11::set_window_fullscreen(bool p_enabled) {
+ if (current_videomode.fullscreen == p_enabled)
+ return;
+
+ if (p_enabled && current_videomode.always_on_top) {
+ // Fullscreen + Always-on-top requires a maximized window on some window managers (Metacity)
+ set_window_maximized(true);
+ }
set_wm_fullscreen(p_enabled);
+ if (!p_enabled && !current_videomode.always_on_top) {
+ // Restore
+ set_window_maximized(false);
+ }
+
current_videomode.fullscreen = p_enabled;
}
@@ -1189,6 +1219,27 @@ bool OS_X11::is_window_maximized() const {
return false;
}
+void OS_X11::set_window_always_on_top(bool p_enabled) {
+ if (is_window_always_on_top() == p_enabled)
+ return;
+
+ if (p_enabled && current_videomode.fullscreen) {
+ // Fullscreen + Always-on-top requires a maximized window on some window managers (Metacity)
+ set_window_maximized(true);
+ }
+ set_wm_above(p_enabled);
+ if (!p_enabled && !current_videomode.fullscreen) {
+ // Restore
+ set_window_maximized(false);
+ }
+
+ current_videomode.always_on_top = p_enabled;
+}
+
+bool OS_X11::is_window_always_on_top() const {
+ return current_videomode.always_on_top;
+}
+
void OS_X11::set_borderless_window(bool p_borderless) {
if (current_videomode.borderless_window == p_borderless)
diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h
index b5ceea6eaf..494845bc56 100644
--- a/platform/x11/os_x11.h
+++ b/platform/x11/os_x11.h
@@ -178,6 +178,7 @@ class OS_X11 : public OS_Unix {
bool maximized;
//void set_wm_border(bool p_enabled);
void set_wm_fullscreen(bool p_enabled);
+ void set_wm_above(bool p_enabled);
typedef xrr_monitor_info *(*xrr_get_monitors_t)(Display *dpy, Window window, Bool get_active, int *nmonitors);
typedef void (*xrr_free_monitors_t)(xrr_monitor_info *monitors);
@@ -261,6 +262,8 @@ public:
virtual bool is_window_minimized() const;
virtual void set_window_maximized(bool p_enabled);
virtual bool is_window_maximized() const;
+ virtual void set_window_always_on_top(bool p_enabled);
+ virtual bool is_window_always_on_top() const;
virtual void request_attention();
virtual void set_borderless_window(bool p_borderless);