mirror of
https://github.com/godotengine/godot.git
synced 2025-10-19 16:03:29 +00:00
Merge pull request #107583 from bruvzg/non_ex_fs
[3.x] Backport nonexclusive fullscreen mode.
This commit is contained in:
commit
5aed565de5
9 changed files with 113 additions and 11 deletions
|
@ -403,6 +403,14 @@ bool _OS::is_window_fullscreen() const {
|
|||
return OS::get_singleton()->is_window_fullscreen();
|
||||
}
|
||||
|
||||
void _OS::set_window_use_nonexclusive_fullscreen(bool p_enabled) {
|
||||
OS::get_singleton()->set_window_use_nonexclusive_fullscreen(p_enabled);
|
||||
}
|
||||
|
||||
bool _OS::is_window_use_nonexclusive_fullscreen() const {
|
||||
return OS::get_singleton()->is_window_use_nonexclusive_fullscreen();
|
||||
}
|
||||
|
||||
void _OS::set_window_resizable(bool p_enabled) {
|
||||
OS::get_singleton()->set_window_resizable(p_enabled);
|
||||
}
|
||||
|
@ -1371,6 +1379,8 @@ void _OS::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_display_cutouts"), &_OS::get_display_cutouts);
|
||||
ClassDB::bind_method(D_METHOD("set_window_fullscreen", "enabled"), &_OS::set_window_fullscreen);
|
||||
ClassDB::bind_method(D_METHOD("is_window_fullscreen"), &_OS::is_window_fullscreen);
|
||||
ClassDB::bind_method(D_METHOD("set_window_use_nonexclusive_fullscreen", "enabled"), &_OS::set_window_use_nonexclusive_fullscreen);
|
||||
ClassDB::bind_method(D_METHOD("is_window_use_nonexclusive_fullscreen"), &_OS::is_window_use_nonexclusive_fullscreen);
|
||||
ClassDB::bind_method(D_METHOD("set_window_resizable", "enabled"), &_OS::set_window_resizable);
|
||||
ClassDB::bind_method(D_METHOD("is_window_resizable"), &_OS::is_window_resizable);
|
||||
ClassDB::bind_method(D_METHOD("set_window_minimized", "enabled"), &_OS::set_window_minimized);
|
||||
|
@ -1568,6 +1578,7 @@ void _OS::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_borderless"), "set_borderless_window", "get_borderless_window");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_per_pixel_transparency_enabled"), "set_window_per_pixel_transparency_enabled", "get_window_per_pixel_transparency_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_fullscreen"), "set_window_fullscreen", "is_window_fullscreen");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_use_nonexclusive_fullscreen"), "set_window_use_nonexclusive_fullscreen", "is_window_use_nonexclusive_fullscreen");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_maximized"), "set_window_maximized", "is_window_maximized");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_minimized"), "set_window_minimized", "is_window_minimized");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_resizable"), "set_window_resizable", "is_window_resizable");
|
||||
|
|
|
@ -225,6 +225,8 @@ public:
|
|||
virtual void set_window_size(const Size2 &p_size);
|
||||
virtual void set_window_fullscreen(bool p_enabled);
|
||||
virtual bool is_window_fullscreen() const;
|
||||
virtual void set_window_use_nonexclusive_fullscreen(bool p_enabled);
|
||||
virtual bool is_window_use_nonexclusive_fullscreen() const;
|
||||
virtual void set_window_resizable(bool p_enabled);
|
||||
virtual bool is_window_resizable() const;
|
||||
virtual void set_window_minimized(bool p_enabled);
|
||||
|
|
|
@ -107,6 +107,7 @@ public:
|
|||
struct VideoMode {
|
||||
int width, height;
|
||||
bool fullscreen;
|
||||
bool non_ex_fs;
|
||||
bool resizable;
|
||||
bool borderless_window;
|
||||
bool maximized;
|
||||
|
@ -126,6 +127,7 @@ public:
|
|||
use_vsync = p_use_vsync;
|
||||
vsync_via_compositor = p_vsync_via_compositor;
|
||||
layered = false;
|
||||
non_ex_fs = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -282,6 +284,8 @@ public:
|
|||
virtual void set_window_size(const Size2 p_size) {}
|
||||
virtual void set_window_fullscreen(bool p_enabled) {}
|
||||
virtual bool is_window_fullscreen() const { return true; }
|
||||
virtual void set_window_use_nonexclusive_fullscreen(bool p_enabled) {}
|
||||
virtual bool is_window_use_nonexclusive_fullscreen() const { return false; }
|
||||
virtual void set_window_resizable(bool p_enabled) {}
|
||||
virtual bool is_window_resizable() const { return false; }
|
||||
virtual void set_window_minimized(bool p_enabled) {}
|
||||
|
|
|
@ -1082,6 +1082,7 @@ ProjectSettings::ProjectSettings() {
|
|||
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/use_nonexclusive_fullscreen", false);
|
||||
GLOBAL_DEF("display/window/size/always_on_top", false);
|
||||
GLOBAL_DEF("display/window/size/test_width", 0);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/test_width", PropertyInfo(Variant::INT, "display/window/size/test_width", PROPERTY_HINT_RANGE, "0,7680,1,or_greater")); // 8K resolution
|
||||
|
|
|
@ -1211,7 +1211,7 @@
|
|||
[b]Note:[/b] Setting [code]window_borderless[/code] to [code]false[/code] disables per-pixel transparency.
|
||||
</member>
|
||||
<member name="window_fullscreen" type="bool" setter="set_window_fullscreen" getter="is_window_fullscreen" default="false">
|
||||
If [code]true[/code], the window is fullscreen.
|
||||
If [code]true[/code], the window is fullscreen. See also [member window_use_nonexclusive_fullscreen].
|
||||
</member>
|
||||
<member name="window_maximized" type="bool" setter="set_window_maximized" getter="is_window_maximized" default="false">
|
||||
If [code]true[/code], the window is maximized.
|
||||
|
@ -1234,6 +1234,11 @@
|
|||
<member name="window_size" type="Vector2" setter="set_window_size" getter="get_window_size" default="Vector2( 0, 0 )">
|
||||
The size of the window (without counting window manager decorations).
|
||||
</member>
|
||||
<member name="window_use_nonexclusive_fullscreen" type="bool" setter="set_window_use_nonexclusive_fullscreen" getter="is_window_use_nonexclusive_fullscreen" default="false">
|
||||
If [code]true[/code] and [member window_fullscreen] is set, a full screen mode with full multi-window support is used.
|
||||
If [code]false[/code] and [member window_fullscreen] is set, a single window fullscreen mode is used, this mode has less overhead, but only one window can be open on a given screen at a time (opening a application switching will trigger a full screen transition). This mode might not work with screen recording software.
|
||||
[b]Note:[/b] This property is only implemented on Windows.
|
||||
</member>
|
||||
</members>
|
||||
<constants>
|
||||
<constant name="VIDEO_DRIVER_GLES2" value="1" enum="VideoDriver">
|
||||
|
|
|
@ -539,8 +539,9 @@
|
|||
[b]Note:[/b] This setting is ignored on iOS, Android, and HTML5.
|
||||
</member>
|
||||
<member name="display/window/size/fullscreen" type="bool" setter="" getter="" default="false">
|
||||
Sets the main window to full screen when the project starts. Note that this is not [i]exclusive[/i] fullscreen. On Windows and Linux, a borderless window is used to emulate fullscreen. On macOS, a new desktop is used to display the running project.
|
||||
Sets the main window to full screen when the project starts. The display's video mode is not changed. See also [member display/window/size/use_nonexclusive_fullscreen].
|
||||
Regardless of the platform, enabling fullscreen will change the window size to match the monitor's size. Therefore, make sure your project supports [url=$DOCS_URL/tutorials/rendering/multiple_resolutions.html]multiple resolutions[/url] when enabling fullscreen mode.
|
||||
[b]Note:[/b] On macOS, a new desktop is used to display the running project.
|
||||
[b]Note:[/b] This setting is ignored on iOS, Android, and HTML5.
|
||||
</member>
|
||||
<member name="display/window/size/height" type="int" setter="" getter="" default="600">
|
||||
|
@ -556,6 +557,11 @@
|
|||
<member name="display/window/size/test_width" type="int" setter="" getter="" default="0">
|
||||
If greater than zero, overrides the window width when running the game. Useful for testing stretch modes.
|
||||
</member>
|
||||
<member name="display/window/size/use_nonexclusive_fullscreen" type="bool" setter="" getter="" default="false">
|
||||
If [code]true[/code] and [member display/window/size/fullscreen] is set, a full screen mode with full multi-window support is used.
|
||||
If [code]false[/code] and [member display/window/size/fullscreen] is set, a single window fullscreen mode is used, this mode has less overhead, but only one window can be open on a given screen at a time (opening a application switching will trigger a full screen transition). This mode might not work with screen recording software.
|
||||
[b]Note:[/b] This property is only implemented on Windows.
|
||||
</member>
|
||||
<member name="display/window/size/width" type="int" setter="" getter="" default="1024">
|
||||
Sets the game's main viewport width. On desktop platforms, this is the default window size. Stretch mode settings also use this as a reference when enabled.
|
||||
</member>
|
||||
|
|
|
@ -151,6 +151,7 @@ HashMap<Main::CLIScope, Vector<String>> forwardable_cli_arguments;
|
|||
static OS::VideoMode video_mode;
|
||||
static int init_screen = -1;
|
||||
static bool init_fullscreen = false;
|
||||
static bool init_non_ex_fs = false;
|
||||
static bool init_maximized = false;
|
||||
static bool init_windowed = false;
|
||||
static bool init_always_on_top = false;
|
||||
|
@ -641,6 +642,10 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
} else if (I->get() == "-f" || I->get() == "--fullscreen") { // force fullscreen
|
||||
|
||||
init_fullscreen = true;
|
||||
} else if (I->get() == "--nonexclusive-fullscreen") { // force fullscreen
|
||||
|
||||
init_fullscreen = true;
|
||||
init_non_ex_fs = true;
|
||||
} else if (I->get() == "-m" || I->get() == "--maximized") { // force maximized window
|
||||
|
||||
init_maximized = true;
|
||||
|
@ -1141,6 +1146,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
if (editor || project_manager) {
|
||||
Engine::get_singleton()->set_editor_hint(true);
|
||||
use_custom_res = false;
|
||||
init_non_ex_fs = true;
|
||||
input_map->load_default(); //keys for editor
|
||||
} else {
|
||||
input_map->load_from_globals(); //keys for game
|
||||
|
@ -1192,6 +1198,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.non_ex_fs = GLOBAL_GET("display/window/size/use_nonexclusive_fullscreen");
|
||||
video_mode.always_on_top = GLOBAL_GET("display/window/size/always_on_top");
|
||||
}
|
||||
|
||||
|
@ -1487,6 +1494,9 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
|
|||
if (init_screen != -1) {
|
||||
OS::get_singleton()->set_current_screen(init_screen);
|
||||
}
|
||||
if (init_non_ex_fs) {
|
||||
OS::get_singleton()->set_window_use_nonexclusive_fullscreen(true);
|
||||
}
|
||||
if (init_windowed) {
|
||||
//do none..
|
||||
} else if (init_maximized) {
|
||||
|
|
|
@ -71,6 +71,8 @@ __declspec(dllexport) void NoHotPatch() {} // Disable Nahimic code injection.
|
|||
#define GetProcAddress (void *)GetProcAddress
|
||||
#endif
|
||||
|
||||
int constexpr FS_TRANSP_BORDER = 2;
|
||||
|
||||
typedef struct {
|
||||
int count;
|
||||
int screen;
|
||||
|
@ -1430,6 +1432,7 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
|
|||
WindowRect.bottom = current.dmPelsHeight;
|
||||
|
||||
*/
|
||||
int off_x = video_mode.non_ex_fs ? FS_TRANSP_BORDER : 0;
|
||||
|
||||
// Get the primary monitor without providing hwnd
|
||||
// Solution from https://devblogs.microsoft.com/oldnewthing/20070809-00/?p=25643
|
||||
|
@ -1440,7 +1443,7 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
|
|||
EnumSizeData data = { 0, primary_data.screen, Size2() };
|
||||
EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcSize, (LPARAM)&data);
|
||||
|
||||
WindowRect.right = data.size.width;
|
||||
WindowRect.right = data.size.width + off_x;
|
||||
WindowRect.bottom = data.size.height;
|
||||
|
||||
/* DEVMODE dmScreenSettings;
|
||||
|
@ -1706,6 +1709,7 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
|
|||
}
|
||||
|
||||
update_real_mouse_position();
|
||||
_update_window_mouse_passthrough();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
@ -1869,9 +1873,11 @@ void OS_Windows::set_mouse_mode(MouseMode p_mode) {
|
|||
|
||||
void OS_Windows::_set_mouse_mode_impl(MouseMode p_mode) {
|
||||
if (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_CONFINED || p_mode == MOUSE_MODE_CONFINED_HIDDEN) {
|
||||
int off_x = (video_mode.fullscreen && video_mode.non_ex_fs) ? FS_TRANSP_BORDER : 0;
|
||||
// Mouse is grabbed (captured or confined).
|
||||
RECT clipRect;
|
||||
GetClientRect(hWnd, &clipRect);
|
||||
clipRect.right -= off_x;
|
||||
ClientToScreen(hWnd, (POINT *)&clipRect.left);
|
||||
ClientToScreen(hWnd, (POINT *)&clipRect.right);
|
||||
ClipCursor(&clipRect);
|
||||
|
@ -1952,7 +1958,16 @@ void OS_Windows::set_window_mouse_passthrough(const PoolVector2Array &p_region)
|
|||
|
||||
void OS_Windows::_update_window_mouse_passthrough() {
|
||||
if (mpath.size() == 0) {
|
||||
if (video_mode.non_ex_fs && video_mode.fullscreen) {
|
||||
int cs = get_current_screen();
|
||||
Size2 size = get_screen_size(cs);
|
||||
|
||||
HRGN region = CreateRectRgn(0, 0, size.width, size.height);
|
||||
SetWindowRgn(hWnd, region, FALSE);
|
||||
DeleteObject(region);
|
||||
} else {
|
||||
SetWindowRgn(hWnd, NULL, TRUE);
|
||||
}
|
||||
} else {
|
||||
POINT *points = (POINT *)memalloc(sizeof(POINT) * mpath.size());
|
||||
for (int i = 0; i < mpath.size(); i++) {
|
||||
|
@ -1966,7 +1981,15 @@ void OS_Windows::_update_window_mouse_passthrough() {
|
|||
}
|
||||
|
||||
HRGN region = CreatePolygonRgn(points, mpath.size(), ALTERNATE);
|
||||
SetWindowRgn(hWnd, region, TRUE);
|
||||
if (video_mode.non_ex_fs && video_mode.fullscreen) {
|
||||
int cs = get_current_screen();
|
||||
Size2 size = get_screen_size(cs);
|
||||
|
||||
HRGN region_clip = CreateRectRgn(0, 0, size.width, size.height);
|
||||
CombineRgn(region, region, region_clip, RGN_AND);
|
||||
DeleteObject(region_clip);
|
||||
}
|
||||
SetWindowRgn(hWnd, region, FALSE);
|
||||
DeleteObject(region);
|
||||
memfree(points);
|
||||
}
|
||||
|
@ -2007,8 +2030,9 @@ void OS_Windows::set_current_screen(int p_screen) {
|
|||
}
|
||||
Point2 pos = get_screen_position(p_screen);
|
||||
Size2 size = get_screen_size(p_screen);
|
||||
int off_x = (video_mode.non_ex_fs) ? FS_TRANSP_BORDER : 0;
|
||||
|
||||
MoveWindow(hWnd, pos.x, pos.y, size.width, size.height, TRUE);
|
||||
MoveWindow(hWnd, pos.x, pos.y, size.width + off_x, size.height, TRUE);
|
||||
} else {
|
||||
Vector2 ofs = get_window_position() - get_screen_position(get_current_screen());
|
||||
set_window_position(ofs + get_screen_position(p_screen));
|
||||
|
@ -2137,7 +2161,9 @@ Size2 OS_Windows::get_window_size() const {
|
|||
|
||||
RECT r;
|
||||
if (GetClientRect(hWnd, &r)) { // Only area inside of window border
|
||||
return Size2(r.right - r.left, r.bottom - r.top);
|
||||
int off_x = (video_mode.fullscreen && video_mode.non_ex_fs) ? FS_TRANSP_BORDER : 0;
|
||||
|
||||
return Size2(r.right - r.left - off_x, r.bottom - r.top);
|
||||
}
|
||||
return Size2();
|
||||
}
|
||||
|
@ -2169,7 +2195,9 @@ void OS_Windows::set_max_window_size(const Size2 p_size) {
|
|||
Size2 OS_Windows::get_real_window_size() const {
|
||||
RECT r;
|
||||
if (GetWindowRect(hWnd, &r)) { // Includes area of the window border
|
||||
return Size2(r.right - r.left, r.bottom - r.top);
|
||||
int off_x = (video_mode.fullscreen && video_mode.non_ex_fs) ? FS_TRANSP_BORDER : 0;
|
||||
|
||||
return Size2(r.right - r.left - off_x, r.bottom - r.top);
|
||||
}
|
||||
return Size2();
|
||||
}
|
||||
|
@ -2208,8 +2236,9 @@ void OS_Windows::set_window_size(const Size2 p_size) {
|
|||
}
|
||||
}
|
||||
void OS_Windows::set_window_fullscreen(bool p_enabled) {
|
||||
if (video_mode.fullscreen == p_enabled)
|
||||
if (video_mode.fullscreen == p_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (layered_window)
|
||||
set_window_per_pixel_transparency_enabled(false);
|
||||
|
@ -2228,8 +2257,9 @@ void OS_Windows::set_window_fullscreen(bool p_enabled) {
|
|||
video_mode.fullscreen = true;
|
||||
|
||||
_update_window_style(false);
|
||||
int off_x = (video_mode.non_ex_fs) ? FS_TRANSP_BORDER : 0;
|
||||
|
||||
MoveWindow(hWnd, pos.x, pos.y, size.width, size.height, TRUE);
|
||||
MoveWindow(hWnd, pos.x, pos.y, size.width + off_x, size.height, TRUE);
|
||||
|
||||
SystemParametersInfoA(SPI_GETMOUSETRAILS, 0, &restore_mouse_trails, 0);
|
||||
if (restore_mouse_trails > 1) {
|
||||
|
@ -2259,10 +2289,39 @@ void OS_Windows::set_window_fullscreen(bool p_enabled) {
|
|||
SystemParametersInfoA(SPI_SETMOUSETRAILS, restore_mouse_trails, 0, 0);
|
||||
}
|
||||
}
|
||||
_update_window_mouse_passthrough();
|
||||
}
|
||||
|
||||
void OS_Windows::set_window_use_nonexclusive_fullscreen(bool p_enabled) {
|
||||
if (video_mode.non_ex_fs == p_enabled) {
|
||||
return;
|
||||
}
|
||||
video_mode.non_ex_fs = p_enabled;
|
||||
|
||||
if (video_mode.fullscreen) {
|
||||
int cs = get_current_screen();
|
||||
Point2 pos = get_screen_position(cs);
|
||||
Size2 size = get_screen_size(cs);
|
||||
|
||||
video_mode.fullscreen = true;
|
||||
|
||||
_update_window_style(false);
|
||||
int off_x = (video_mode.non_ex_fs) ? FS_TRANSP_BORDER : 0;
|
||||
|
||||
MoveWindow(hWnd, pos.x, pos.y, size.width + off_x, size.height, TRUE);
|
||||
|
||||
_update_window_mouse_passthrough();
|
||||
}
|
||||
}
|
||||
|
||||
bool OS_Windows::is_window_fullscreen() const {
|
||||
return video_mode.fullscreen;
|
||||
}
|
||||
|
||||
bool OS_Windows::is_window_use_nonexclusive_fullscreen() const {
|
||||
return video_mode.non_ex_fs;
|
||||
}
|
||||
|
||||
void OS_Windows::set_window_resizable(bool p_enabled) {
|
||||
if (video_mode.resizable == p_enabled)
|
||||
return;
|
||||
|
@ -2402,7 +2461,8 @@ void OS_Windows::_update_window_style(bool p_repaint, bool p_maximized) {
|
|||
if (p_repaint) {
|
||||
RECT rect;
|
||||
GetWindowRect(hWnd, &rect);
|
||||
MoveWindow(hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE);
|
||||
int off_x = (video_mode.fullscreen && video_mode.non_ex_fs) ? FS_TRANSP_BORDER : 0;
|
||||
MoveWindow(hWnd, rect.left, rect.top, rect.right - rect.left + off_x, rect.bottom - rect.top, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -344,6 +344,7 @@ class OS_Windows : public OS {
|
|||
|
||||
Size2 window_rect;
|
||||
VideoMode video_mode;
|
||||
bool non_ex_fs = false;
|
||||
bool preserve_window_size = false;
|
||||
|
||||
MainLoop *main_loop;
|
||||
|
@ -486,6 +487,8 @@ public:
|
|||
virtual void set_window_size(const Size2 p_size);
|
||||
virtual void set_window_fullscreen(bool p_enabled);
|
||||
virtual bool is_window_fullscreen() const;
|
||||
virtual void set_window_use_nonexclusive_fullscreen(bool p_enabled);
|
||||
virtual bool is_window_use_nonexclusive_fullscreen() const;
|
||||
virtual void set_window_resizable(bool p_enabled);
|
||||
virtual bool is_window_resizable() const;
|
||||
virtual void set_window_minimized(bool p_enabled);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue