Add support for the custom initial screen for the main window, fix primary screen detection.

This commit is contained in:
bruvzg 2023-01-05 00:00:02 +02:00
parent 163f6f5fe8
commit 2718a7b7d3
No known key found for this signature in database
GPG key ID: 7960FCF39844EC38
27 changed files with 506 additions and 205 deletions

View file

@ -1240,6 +1240,14 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF_BASIC("display/window/size/mode", 0);
custom_prop_info["display/window/size/mode"] = PropertyInfo(Variant::INT, "display/window/size/mode", PROPERTY_HINT_ENUM, "Windowed,Minimized,Maximized,Fullscreen,Exclusive Fullscreen");
// Keep the enum values in sync with the `DisplayServer::SCREEN_` enum.
GLOBAL_DEF_BASIC("display/window/size/initial_screen", -2);
String screen_hints = "Primary Monitor:-2"; // Note: Main Window Monitor:-1 is not used for the main window, skip it.
for (int i = 0; i < 64; i++) {
screen_hints += ",Monitor " + itos(i + 1) + ":" + itos(i);
}
custom_prop_info["display/window/size/initial_screen"] = PropertyInfo(Variant::INT, "display/window/size/initial_screen", PROPERTY_HINT_ENUM, screen_hints);
GLOBAL_DEF_BASIC("display/window/size/resizable", true);
GLOBAL_DEF_BASIC("display/window/size/borderless", false);
GLOBAL_DEF("display/window/size/always_on_top", false);

View file

@ -130,12 +130,25 @@
The names of built-in display servers are [code]Windows[/code], [code]macOS[/code], [code]X11[/code] (Linux), [code]Android[/code], [code]iOS[/code], [code]web[/code] (HTML5) and [code]headless[/code] (when started with the [code]--headless[/code] [url=$DOCS_URL/tutorials/editor/command_line_tutorial.html]command line argument[/url]).
</description>
</method>
<method name="get_primary_screen" qualifiers="const">
<return type="int" />
<description>
Returns index of the primary screen.
</description>
</method>
<method name="get_screen_count" qualifiers="const">
<return type="int" />
<description>
Returns the number of displays available.
</description>
</method>
<method name="get_screen_from_rect" qualifiers="const">
<return type="int" />
<param index="0" name="rect" type="Rect2" />
<description>
Returns index of the screen which contains specified rectangle.
</description>
</method>
<method name="get_swap_cancel_ok">
<return type="bool" />
<description>
@ -1521,6 +1534,9 @@
<constant name="MOUSE_MODE_CONFINED_HIDDEN" value="4" enum="MouseMode">
Confines the mouse cursor to the game window, and make it hidden.
</constant>
<constant name="SCREEN_PRIMARY" value="-2">
Represents the primary screen.
</constant>
<constant name="SCREEN_OF_MAIN_WINDOW" value="-1">
Represents the screen where the main window is located. This is usually the default value in functions that allow specifying one of several screens.
</constant>

View file

@ -596,6 +596,9 @@
Main window content is expanded to the full size of the window. Unlike a borderless window, the frame is left intact and can be used to resize the window, and the title bar is transparent, but has minimize/maximize/close buttons.
[b]Note:[/b] This setting is implemented only on macOS.
</member>
<member name="display/window/size/initial_screen" type="int" setter="" getter="" default="-2">
Main window initial screen.
</member>
<member name="display/window/size/mode" type="int" setter="" getter="" default="0">
Main window mode. See [enum DisplayServer.WindowMode] for possible values and how each mode behaves.
</member>

View file

@ -503,7 +503,7 @@
<member name="content_scale_size" type="Vector2i" setter="set_content_scale_size" getter="get_content_scale_size" default="Vector2i(0, 0)">
Base size of the content (i.e. nodes that are drawn inside the window). If non-zero, [Window]'s content will be scaled when the window is resized to a different size.
</member>
<member name="current_screen" type="int" setter="set_current_screen" getter="get_current_screen" default="0">
<member name="current_screen" type="int" setter="set_current_screen" getter="get_current_screen">
The screen the window is currently on.
</member>
<member name="exclusive" type="bool" setter="set_exclusive" getter="is_exclusive" default="false">
@ -513,6 +513,8 @@
<member name="extend_to_title" type="bool" setter="set_flag" getter="get_flag" default="false">
If [code]true[/code], the [Window] contents is expanded to the full size of the window, window title bar is transparent.
</member>
<member name="initial_position" type="int" setter="set_initial_position" getter="get_initial_position" enum="Window.WindowInitialPosition" default="0">
</member>
<member name="max_size" type="Vector2i" setter="set_max_size" getter="get_max_size" default="Vector2i(0, 0)">
If non-zero, the [Window] can't be resized to be bigger than this size.
[b]Note:[/b] This property will be ignored if the value is lower than [member min_size].
@ -732,6 +734,10 @@
<constant name="LAYOUT_DIRECTION_RTL" value="3" enum="LayoutDirection">
Right-to-left layout direction.
</constant>
<constant name="WINDOW_INITIAL_POSITION_ABSOLUTE" value="0" enum="WindowInitialPosition">
</constant>
<constant name="WINDOW_INITIAL_POSITION_CENTER_SCREEN" value="1" enum="WindowInitialPosition">
</constant>
</constants>
<theme_items>
<theme_item name="title_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)">

View file

@ -93,30 +93,24 @@ Error EditorRun::run(const String &p_scene, const String &p_write_movie) {
}
int screen = EDITOR_GET("run/window_placement/screen");
if (screen == 0) {
if (screen == -5) {
// Same as editor
screen = DisplayServer::get_singleton()->window_get_current_screen();
} else if (screen == 1) {
} else if (screen == -4) {
// Previous monitor (wrap to the other end if needed)
screen = Math::wrapi(
DisplayServer::get_singleton()->window_get_current_screen() - 1,
0,
DisplayServer::get_singleton()->get_screen_count());
} else if (screen == 2) {
} else if (screen == -3) {
// Next monitor (wrap to the other end if needed)
screen = Math::wrapi(
DisplayServer::get_singleton()->window_get_current_screen() + 1,
0,
DisplayServer::get_singleton()->get_screen_count());
} else {
// Fixed monitor ID
// There are 3 special options, so decrement the option ID by 3 to get the monitor ID
screen -= 3;
}
Rect2 screen_rect;
screen_rect.position = DisplayServer::get_singleton()->screen_get_position(screen);
screen_rect.size = DisplayServer::get_singleton()->screen_get_size(screen);
Rect2 screen_rect = DisplayServer::get_singleton()->screen_get_usable_rect(screen);
int window_placement = EDITOR_GET("run/window_placement/rect");
if (screen_rect != Rect2()) {
@ -169,13 +163,13 @@ Error EditorRun::run(const String &p_scene, const String &p_write_movie) {
args.push_back(itos(pos.x) + "," + itos(pos.y));
} break;
case 3: { // force maximized
Vector2 pos = screen_rect.position;
Vector2 pos = screen_rect.position + screen_rect.size / 2;
args.push_back("--position");
args.push_back(itos(pos.x) + "," + itos(pos.y));
args.push_back("--maximized");
} break;
case 4: { // force fullscreen
Vector2 pos = screen_rect.position;
Vector2 pos = screen_rect.position + screen_rect.size / 2;
args.push_back("--position");
args.push_back(itos(pos.x) + "," + itos(pos.y));
args.push_back("--fullscreen");

View file

@ -697,12 +697,13 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
// Window placement
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "run/window_placement/rect", 1, "Top Left,Centered,Custom Position,Force Maximized,Force Fullscreen")
String screen_hints = "Same as Editor,Previous Monitor,Next Monitor";
// Keep the enum values in sync with the `DisplayServer::SCREEN_` enum.
String screen_hints = "Same as Editor:-5,Previous Monitor:-4,Next Monitor:-3,Primary Monitor:-2"; // Note: Main Window Screen:-1 is not used for the main window.
for (int i = 0; i < DisplayServer::get_singleton()->get_screen_count(); i++) {
screen_hints += ",Monitor " + itos(i + 1);
screen_hints += ",Monitor " + itos(i + 1) + ":" + itos(i);
}
_initial_set("run/window_placement/rect_custom_position", Vector2());
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "run/window_placement/screen", 0, screen_hints)
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "run/window_placement/screen", -5, screen_hints)
// Auto save
_initial_set("run/auto_save/save_before_running", true);

View file

@ -3014,16 +3014,15 @@ ProjectManager::ProjectManager() {
float scale_factor = MAX(1, EDSCALE);
if (scale_factor > 1.0) {
Vector2i window_size = DisplayServer::get_singleton()->window_get_size();
Vector2i screen_size = DisplayServer::get_singleton()->screen_get_size();
Vector2i screen_position = DisplayServer::get_singleton()->screen_get_position();
Rect2i screen_rect = DisplayServer::get_singleton()->screen_get_usable_rect(DisplayServer::get_singleton()->window_get_current_screen());
window_size *= scale_factor;
DisplayServer::get_singleton()->window_set_size(window_size);
if (screen_size != Vector2i()) {
if (screen_rect.size != Vector2i()) {
Vector2i window_position;
window_position.x = screen_position.x + (screen_size.x - window_size.x) / 2;
window_position.y = screen_position.y + (screen_size.y - window_size.y) / 2;
window_position.x = screen_rect.position.x + (screen_rect.size.x - window_size.x) / 2;
window_position.y = screen_rect.position.y + (screen_rect.size.y - window_size.y) / 2;
DisplayServer::get_singleton()->window_set_position(window_position);
}
}

View file

@ -179,7 +179,7 @@ static DisplayServer::VSyncMode window_vsync_mode = DisplayServer::VSYNC_ENABLED
static uint32_t window_flags = 0;
static Size2i window_size = Size2i(1152, 648);
static int init_screen = -1;
static int init_screen = DisplayServer::SCREEN_PRIMARY;
static bool init_fullscreen = false;
static bool init_maximized = false;
static bool init_windowed = false;
@ -377,7 +377,8 @@ void Main::print_help(const char *p_binary) {
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(" --position <X>,<Y> Request window position (if set, screen argument is ignored).\n");
OS::get_singleton()->print(" --screen <N> Request window screen.\n");
OS::get_singleton()->print(" --single-window Use a single window (no separate subwindows).\n");
OS::get_singleton()->print(" --xr-mode <mode> Select XR (Extended Reality) mode ['default', 'off', 'on'].\n");
OS::get_singleton()->print("\n");
@ -959,6 +960,17 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
goto error;
}
} else if (I->get() == "--screen") { // set window screen
if (I->next()) {
init_screen = I->next()->get().to_int();
N = I->next()->next();
} else {
OS::get_singleton()->print("Missing screen argument, aborting.\n");
goto error;
}
} else if (I->get() == "--position") { // set window position
if (I->next()) {
@ -1658,6 +1670,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
window_flags |= DisplayServer::WINDOW_FLAG_NO_FOCUS_BIT;
}
window_mode = (DisplayServer::WindowMode)(GLOBAL_GET("display/window/size/mode").operator int());
init_screen = GLOBAL_GET("display/window/size/initial_screen").operator int();
}
GLOBAL_DEF("internationalization/locale/include_text_server_data", false);
@ -1909,7 +1922,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
// rendering_driver now held in static global String in main and initialized in setup()
Error err;
display_server = DisplayServer::create(display_driver_idx, rendering_driver, window_mode, window_vsync_mode, window_flags, window_position, window_size, err);
display_server = DisplayServer::create(display_driver_idx, rendering_driver, window_mode, window_vsync_mode, window_flags, window_position, window_size, init_screen, err);
if (err != OK || display_server == nullptr) {
// We can't use this display server, try other ones as fallback.
// Skip headless (always last registered) because that's not what users
@ -1918,7 +1931,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
if (i == display_driver_idx) {
continue; // Don't try the same twice.
}
display_server = DisplayServer::create(i, rendering_driver, window_mode, window_vsync_mode, window_flags, window_position, window_size, err);
display_server = DisplayServer::create(i, rendering_driver, window_mode, window_vsync_mode, window_flags, window_position, window_size, init_screen, err);
if (err == OK && display_server != nullptr) {
break;
}
@ -2015,10 +2028,6 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
print_line(" "); //add a blank line for readability
if (init_use_custom_pos) {
display_server->window_set_position(init_custom_pos);
}
// right moment to create and initialize the audio server
audio_server = memnew(AudioServer);
@ -2037,9 +2046,6 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
bool show_logo = true;
#endif
if (init_screen != -1) {
DisplayServer::get_singleton()->window_set_current_screen(init_screen);
}
if (init_windowed) {
//do none..
} else if (init_maximized) {

View file

@ -184,6 +184,10 @@ int DisplayServerAndroid::get_screen_count() const {
return 1;
}
int DisplayServerAndroid::get_primary_screen() const {
return 0;
}
Point2i DisplayServerAndroid::screen_get_position(int p_screen) const {
return Point2i(0, 0);
}
@ -459,8 +463,8 @@ Vector<String> DisplayServerAndroid::get_rendering_drivers_func() {
return drivers;
}
DisplayServer *DisplayServerAndroid::create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error) {
DisplayServer *ds = memnew(DisplayServerAndroid(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, r_error));
DisplayServer *DisplayServerAndroid::create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) {
DisplayServer *ds = memnew(DisplayServerAndroid(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, p_screen, r_error));
if (r_error != OK) {
OS::get_singleton()->alert("Your video card driver does not support any of the supported Vulkan versions.", "Unable to initialize Video driver");
if (p_rendering_driver == "vulkan") {
@ -512,7 +516,7 @@ void DisplayServerAndroid::notify_surface_changed(int p_width, int p_height) {
rect_changed_callback.callp(reinterpret_cast<const Variant **>(&sizep), 1, ret, ce);
}
DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error) {
DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) {
rendering_driver = p_rendering_driver;
keep_screen_on = GLOBAL_GET("display/window/energy_saving/keep_screen_on");

View file

@ -115,6 +115,7 @@ public:
virtual ScreenOrientation screen_get_orientation(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual int get_screen_count() const override;
virtual int get_primary_screen() const override;
virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
@ -198,7 +199,7 @@ public:
virtual void mouse_set_mode(MouseMode p_mode) override;
virtual MouseMode mouse_get_mode() const override;
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error);
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error);
static Vector<String> get_rendering_drivers_func();
static void register_android_driver();
@ -215,7 +216,7 @@ public:
virtual void set_native_icon(const String &p_filename) override;
virtual void set_icon(const Ref<Image> &p_icon) override;
DisplayServerAndroid(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error);
DisplayServerAndroid(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error);
~DisplayServerAndroid();
};

View file

@ -75,7 +75,7 @@ class DisplayServerIOS : public DisplayServer {
void perform_event(const Ref<InputEvent> &p_event);
DisplayServerIOS(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error);
DisplayServerIOS(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error);
~DisplayServerIOS();
public:
@ -84,7 +84,7 @@ public:
static DisplayServerIOS *get_singleton();
static void register_ios_driver();
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error);
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error);
static Vector<String> get_rendering_drivers_func();
// MARK: - Events
@ -139,6 +139,7 @@ public:
virtual Rect2i get_display_safe_area() const override;
virtual int get_screen_count() const override;
virtual int get_primary_screen() const override;
virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;

View file

@ -49,7 +49,7 @@ DisplayServerIOS *DisplayServerIOS::get_singleton() {
return (DisplayServerIOS *)DisplayServer::get_singleton();
}
DisplayServerIOS::DisplayServerIOS(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error) {
DisplayServerIOS::DisplayServerIOS(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) {
rendering_driver = p_rendering_driver;
// Init TTS
@ -151,8 +151,8 @@ DisplayServerIOS::~DisplayServerIOS() {
#endif
}
DisplayServer *DisplayServerIOS::create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error) {
return memnew(DisplayServerIOS(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, r_error));
DisplayServer *DisplayServerIOS::create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) {
return memnew(DisplayServerIOS(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, p_screen, r_error));
}
Vector<String> DisplayServerIOS::get_rendering_drivers_func() {
@ -379,6 +379,10 @@ int DisplayServerIOS::get_screen_count() const {
return 1;
}
int DisplayServerIOS::get_primary_screen() const {
return 0;
}
Point2i DisplayServerIOS::screen_get_position(int p_screen) const {
return Size2i();
}

View file

@ -751,11 +751,22 @@ int DisplayServerX11::get_screen_count() const {
return count;
}
int DisplayServerX11::get_primary_screen() const {
return XDefaultScreen(x11_display);
}
Rect2i DisplayServerX11::_screen_get_rect(int p_screen) const {
Rect2i rect(0, 0, 0, 0);
if (p_screen == SCREEN_OF_MAIN_WINDOW) {
p_screen = window_get_current_screen();
switch (p_screen) {
case SCREEN_PRIMARY: {
p_screen = get_primary_screen();
} break;
case SCREEN_OF_MAIN_WINDOW: {
p_screen = window_get_current_screen(MAIN_WINDOW_ID);
} break;
default:
break;
}
ERR_FAIL_COND_V(p_screen < 0, rect);
@ -822,8 +833,15 @@ int bad_window_error_handler(Display *display, XErrorEvent *error) {
Rect2i DisplayServerX11::screen_get_usable_rect(int p_screen) const {
_THREAD_SAFE_METHOD_
if (p_screen == SCREEN_OF_MAIN_WINDOW) {
p_screen = window_get_current_screen();
switch (p_screen) {
case SCREEN_PRIMARY: {
p_screen = get_primary_screen();
} break;
case SCREEN_OF_MAIN_WINDOW: {
p_screen = window_get_current_screen(MAIN_WINDOW_ID);
} break;
default:
break;
}
int screen_count = get_screen_count();
@ -1102,8 +1120,15 @@ Rect2i DisplayServerX11::screen_get_usable_rect(int p_screen) const {
int DisplayServerX11::screen_get_dpi(int p_screen) const {
_THREAD_SAFE_METHOD_
if (p_screen == SCREEN_OF_MAIN_WINDOW) {
p_screen = window_get_current_screen();
switch (p_screen) {
case SCREEN_PRIMARY: {
p_screen = get_primary_screen();
} break;
case SCREEN_OF_MAIN_WINDOW: {
p_screen = window_get_current_screen(MAIN_WINDOW_ID);
} break;
default:
break;
}
//invalid screen?
@ -1147,8 +1172,15 @@ int DisplayServerX11::screen_get_dpi(int p_screen) const {
float DisplayServerX11::screen_get_refresh_rate(int p_screen) const {
_THREAD_SAFE_METHOD_
if (p_screen == SCREEN_OF_MAIN_WINDOW) {
p_screen = window_get_current_screen();
switch (p_screen) {
case SCREEN_PRIMARY: {
p_screen = get_primary_screen();
} break;
case SCREEN_OF_MAIN_WINDOW: {
p_screen = window_get_current_screen(MAIN_WINDOW_ID);
} break;
default:
break;
}
//invalid screen?
@ -1235,10 +1267,10 @@ Vector<DisplayServer::WindowID> DisplayServerX11::get_window_list() const {
return ret;
}
DisplayServer::WindowID DisplayServerX11::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, int p_screen) {
DisplayServer::WindowID DisplayServerX11::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
_THREAD_SAFE_METHOD_
WindowID id = _create_window(p_mode, p_vsync_mode, p_flags, p_rect, p_screen);
WindowID id = _create_window(p_mode, p_vsync_mode, p_flags, p_rect);
for (int i = 0; i < WINDOW_FLAG_MAX; i++) {
if (p_flags & (1 << i)) {
window_set_flag(WindowFlags(i), true, id);
@ -1500,8 +1532,15 @@ void DisplayServerX11::window_set_current_screen(int p_screen, WindowID p_window
ERR_FAIL_COND(!windows.has(p_window));
WindowData &wd = windows[p_window];
if (p_screen == SCREEN_OF_MAIN_WINDOW) {
p_screen = window_get_current_screen();
switch (p_screen) {
case SCREEN_PRIMARY: {
p_screen = get_primary_screen();
} break;
case SCREEN_OF_MAIN_WINDOW: {
p_screen = window_get_current_screen(MAIN_WINDOW_ID);
} break;
default:
break;
}
// Check if screen is valid
@ -1521,9 +1560,10 @@ void DisplayServerX11::window_set_current_screen(int p_screen, WindowID p_window
Point2i wpos = window_get_position(p_window) - screen_get_position(window_get_current_screen(p_window));
Size2i wsize = window_get_size(p_window);
wpos += srect.position;
wpos.x = CLAMP(wpos.x, srect.position.x, srect.position.x + srect.size.width - wsize.width / 3);
wpos.y = CLAMP(wpos.y, srect.position.y, srect.position.y + srect.size.height - wsize.height / 3);
if (srect != Rect2i()) {
wpos.x = CLAMP(wpos.x, srect.position.x, srect.position.x + srect.size.width - wsize.width / 3);
wpos.y = CLAMP(wpos.y, srect.position.y, srect.position.y + srect.size.height - wsize.height / 3);
}
window_set_position(wpos, p_window);
}
}
@ -4519,8 +4559,8 @@ Vector<String> DisplayServerX11::get_rendering_drivers_func() {
return drivers;
}
DisplayServer *DisplayServerX11::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error) {
DisplayServer *ds = memnew(DisplayServerX11(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, r_error));
DisplayServer *DisplayServerX11::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) {
DisplayServer *ds = memnew(DisplayServerX11(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, p_screen, r_error));
if (r_error != OK) {
if (p_rendering_driver == "vulkan") {
String executable_name = OS::get_singleton()->get_executable_path().get_file();
@ -4541,7 +4581,7 @@ DisplayServer *DisplayServerX11::create_func(const String &p_rendering_driver, W
return ds;
}
DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, int p_screen) {
DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
//Create window
XVisualInfo visualInfo;
@ -4617,30 +4657,19 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
valuemask |= CWOverrideRedirect | CWSaveUnder;
}
int rq_screen = get_screen_from_rect(p_rect);
if (rq_screen < 0) {
rq_screen = get_primary_screen(); // Requested window rect is outside any screen bounds.
}
Rect2i win_rect = p_rect;
if (p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
Rect2i screen_rect = Rect2i(screen_get_position(p_screen), screen_get_size(p_screen));
Rect2i screen_rect = Rect2i(screen_get_position(rq_screen), screen_get_size(rq_screen));
win_rect = screen_rect;
} else {
int nearest_area = 0;
int pos_screen = -1;
for (int i = 0; i < get_screen_count(); i++) {
Rect2i r;
r.position = screen_get_position(i);
r.size = screen_get_size(i);
Rect2 inters = r.intersection(p_rect);
int area = inters.size.width * inters.size.height;
if (area > nearest_area) {
pos_screen = i;
nearest_area = area;
}
}
Rect2i srect = screen_get_usable_rect(p_screen);
Point2i wpos = p_rect.position - ((pos_screen >= 0) ? screen_get_position(pos_screen) : Vector2i());
wpos += srect.position;
Rect2i srect = screen_get_usable_rect(rq_screen);
Point2i wpos = p_rect.position;
wpos.x = CLAMP(wpos.x, srect.position.x, srect.position.x + srect.size.width - p_rect.size.width / 3);
wpos.y = CLAMP(wpos.y, srect.position.y, srect.position.y + srect.size.height - p_rect.size.height / 3);
@ -4811,7 +4840,7 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
return id;
}
DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error) {
DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) {
#ifdef DEBUG_ENABLED
int dylibloader_verbose = 1;
#else
@ -5075,16 +5104,17 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
ERR_FAIL_MSG("Video driver not found");
}
Point2i window_position(
(screen_get_size(0).width - p_resolution.width) / 2,
(screen_get_size(0).height - p_resolution.height) / 2);
window_position += screen_get_position(0);
Point2i window_position;
if (p_position != nullptr) {
window_position = *p_position;
} else {
if (p_screen == SCREEN_OF_MAIN_WINDOW) {
p_screen = SCREEN_PRIMARY;
}
window_position = screen_get_position(p_screen) + (screen_get_size(p_screen) - p_resolution) / 2;
}
WindowID main_window = _create_window(p_mode, p_vsync_mode, p_flags, Rect2i(window_position, p_resolution), 0);
WindowID main_window = _create_window(p_mode, p_vsync_mode, p_flags, Rect2i(window_position, p_resolution));
if (main_window == INVALID_WINDOW_ID) {
r_error = ERR_CANT_CREATE;
return;

View file

@ -185,7 +185,7 @@ class DisplayServerX11 : public DisplayServer {
WindowID last_focused_window = INVALID_WINDOW_ID;
WindowID window_id_counter = MAIN_WINDOW_ID;
WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, int p_screen);
WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect);
String internal_clipboard;
String internal_clipboard_primary;
@ -352,6 +352,7 @@ public:
virtual String clipboard_get_primary() const override;
virtual int get_screen_count() const override;
virtual int get_primary_screen() const override;
virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
@ -365,7 +366,7 @@ public:
virtual Vector<DisplayServer::WindowID> get_window_list() const override;
virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i(), int p_screen = 0) override;
virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()) override;
virtual void show_window(WindowID p_id) override;
virtual void delete_sub_window(WindowID p_id) override;
@ -453,12 +454,12 @@ public:
virtual void set_native_icon(const String &p_filename) override;
virtual void set_icon(const Ref<Image> &p_icon) override;
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error);
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error);
static Vector<String> get_rendering_drivers_func();
static void register_x11_driver();
DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error);
DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error);
~DisplayServerX11();
};

View file

@ -191,7 +191,7 @@ private:
const NSMenu *_get_menu_root(const String &p_menu_root) const;
NSMenu *_get_menu_root(const String &p_menu_root);
WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, const Rect2i &p_rect, int p_screen);
WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, const Rect2i &p_rect);
void _update_window_style(WindowData p_wd);
void _set_window_per_pixel_transparency_enabled(bool p_enabled, WindowID p_window);
@ -324,6 +324,7 @@ public:
virtual String clipboard_get() const override;
virtual int get_screen_count() const override;
virtual int get_primary_screen() const override;
virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
@ -336,7 +337,7 @@ public:
virtual Vector<int> get_window_list() const override;
virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i(), int p_screen = 0) override;
virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()) override;
virtual void show_window(WindowID p_id) override;
virtual void delete_sub_window(WindowID p_id) override;
@ -435,12 +436,12 @@ public:
virtual void set_native_icon(const String &p_filename) override;
virtual void set_icon(const Ref<Image> &p_icon) override;
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error);
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error);
static Vector<String> get_rendering_drivers_func();
static void register_macos_driver();
DisplayServerMacOS(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error);
DisplayServerMacOS(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error);
~DisplayServerMacOS();
};

View file

@ -109,7 +109,7 @@ NSMenu *DisplayServerMacOS::_get_menu_root(const String &p_menu_root) {
return menu;
}
DisplayServerMacOS::WindowID DisplayServerMacOS::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, const Rect2i &p_rect, int p_screen) {
DisplayServerMacOS::WindowID DisplayServerMacOS::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, const Rect2i &p_rect) {
WindowID id;
const float scale = screen_get_max_scale();
{
@ -119,36 +119,30 @@ DisplayServerMacOS::WindowID DisplayServerMacOS::_create_window(WindowMode p_mod
ERR_FAIL_COND_V_MSG(wd.window_delegate == nil, INVALID_WINDOW_ID, "Can't create a window delegate");
[wd.window_delegate setWindowID:window_id_counter];
int nearest_area = 0;
int pos_screen = -1;
for (int i = 0; i < get_screen_count(); i++) {
Rect2i r = screen_get_usable_rect(i);
Rect2 inters = r.intersection(p_rect);
int area = inters.size.width * inters.size.height;
if (area > nearest_area && area > 0) {
pos_screen = i;
nearest_area = area;
}
int rq_screen = get_screen_from_rect(p_rect);
if (rq_screen < 0) {
rq_screen = get_primary_screen(); // Requested window rect is outside any screen bounds.
}
Rect2i srect = screen_get_usable_rect(p_screen);
Point2i wpos = p_rect.position - ((pos_screen >= 0) ? screen_get_position(pos_screen) : Vector2i());
wpos += srect.position;
wpos.x = CLAMP(wpos.x, srect.position.x, srect.position.x + srect.size.width - p_rect.size.width / 3);
wpos.y = CLAMP(wpos.y, srect.position.y, srect.position.y + srect.size.height - p_rect.size.height / 3);
Rect2i srect = screen_get_usable_rect(rq_screen);
Point2i wpos = p_rect.position;
if (srect != Rect2i()) {
wpos.x = CLAMP(wpos.x, srect.position.x, srect.position.x + srect.size.width - p_rect.size.width / 3);
wpos.y = CLAMP(wpos.y, srect.position.y, srect.position.y + srect.size.height - p_rect.size.height / 3);
}
// OS X native y-coordinate relative to _get_screens_origin() is negative,
// Godot passes a positive value.
wpos.y *= -1;
wpos += _get_screens_origin();
wpos /= scale;
// initWithContentRect uses bottom-left corner of the windows frame as origin.
wd.window_object = [[GodotWindow alloc]
initWithContentRect:NSMakeRect(0, 0, p_rect.size.width / scale, p_rect.size.height / scale)
initWithContentRect:NSMakeRect(100, 100, p_rect.size.width / scale, p_rect.size.height / scale)
styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable
backing:NSBackingStoreBuffered
defer:NO];
ERR_FAIL_COND_V_MSG(wd.window_object == nil, INVALID_WINDOW_ID, "Can't create a window");
[wd.window_object setFrameTopLeftPoint:NSMakePoint(wpos.x / scale, wpos.y / scale)];
[wd.window_object setWindowID:window_id_counter];
wd.window_view = [[GodotContentView alloc] init];
@ -186,6 +180,16 @@ DisplayServerMacOS::WindowID DisplayServerMacOS::_create_window(WindowMode p_mod
window_set_vsync_mode(p_vsync_mode, window_id_counter);
#endif
[wd.window_view updateLayerDelegate];
const NSRect contentRect = [wd.window_view frame];
const NSRect windowRect = [wd.window_object frame];
const NSRect nsrect = [wd.window_object convertRectToScreen:contentRect];
Point2i offset;
offset.x = (nsrect.origin.x - windowRect.origin.x);
offset.y = (nsrect.origin.y + nsrect.size.height);
offset.y -= (windowRect.origin.y + windowRect.size.height);
[wd.window_object setFrameTopLeftPoint:NSMakePoint(wpos.x - offset.x, wpos.y - offset.y)];
id = window_id_counter++;
windows[id] = wd;
}
@ -2077,11 +2081,22 @@ int DisplayServerMacOS::get_screen_count() const {
return [screenArray count];
}
int DisplayServerMacOS::get_primary_screen() const {
return 0;
}
Point2i DisplayServerMacOS::screen_get_position(int p_screen) const {
_THREAD_SAFE_METHOD_
if (p_screen == SCREEN_OF_MAIN_WINDOW) {
p_screen = window_get_current_screen();
switch (p_screen) {
case SCREEN_PRIMARY: {
p_screen = get_primary_screen();
} break;
case SCREEN_OF_MAIN_WINDOW: {
p_screen = window_get_current_screen(MAIN_WINDOW_ID);
} break;
default:
break;
}
Point2i position = _get_native_screen_position(p_screen) - _get_screens_origin();
@ -2094,8 +2109,15 @@ Point2i DisplayServerMacOS::screen_get_position(int p_screen) const {
Size2i DisplayServerMacOS::screen_get_size(int p_screen) const {
_THREAD_SAFE_METHOD_
if (p_screen == SCREEN_OF_MAIN_WINDOW) {
p_screen = window_get_current_screen();
switch (p_screen) {
case SCREEN_PRIMARY: {
p_screen = get_primary_screen();
} break;
case SCREEN_OF_MAIN_WINDOW: {
p_screen = window_get_current_screen(MAIN_WINDOW_ID);
} break;
default:
break;
}
NSArray *screenArray = [NSScreen screens];
@ -2111,8 +2133,15 @@ Size2i DisplayServerMacOS::screen_get_size(int p_screen) const {
int DisplayServerMacOS::screen_get_dpi(int p_screen) const {
_THREAD_SAFE_METHOD_
if (p_screen == SCREEN_OF_MAIN_WINDOW) {
p_screen = window_get_current_screen();
switch (p_screen) {
case SCREEN_PRIMARY: {
p_screen = get_primary_screen();
} break;
case SCREEN_OF_MAIN_WINDOW: {
p_screen = window_get_current_screen(MAIN_WINDOW_ID);
} break;
default:
break;
}
NSArray *screenArray = [NSScreen screens];
@ -2135,9 +2164,17 @@ int DisplayServerMacOS::screen_get_dpi(int p_screen) const {
float DisplayServerMacOS::screen_get_scale(int p_screen) const {
_THREAD_SAFE_METHOD_
if (p_screen == SCREEN_OF_MAIN_WINDOW) {
p_screen = window_get_current_screen();
switch (p_screen) {
case SCREEN_PRIMARY: {
p_screen = get_primary_screen();
} break;
case SCREEN_OF_MAIN_WINDOW: {
p_screen = window_get_current_screen(MAIN_WINDOW_ID);
} break;
default:
break;
}
if (OS::get_singleton()->is_hidpi_allowed()) {
NSArray *screenArray = [NSScreen screens];
if ((NSUInteger)p_screen < [screenArray count]) {
@ -2160,8 +2197,15 @@ float DisplayServerMacOS::screen_get_max_scale() const {
Rect2i DisplayServerMacOS::screen_get_usable_rect(int p_screen) const {
_THREAD_SAFE_METHOD_
if (p_screen == SCREEN_OF_MAIN_WINDOW) {
p_screen = window_get_current_screen();
switch (p_screen) {
case SCREEN_PRIMARY: {
p_screen = get_primary_screen();
} break;
case SCREEN_OF_MAIN_WINDOW: {
p_screen = window_get_current_screen(MAIN_WINDOW_ID);
} break;
default:
break;
}
NSArray *screenArray = [NSScreen screens];
@ -2182,8 +2226,15 @@ Rect2i DisplayServerMacOS::screen_get_usable_rect(int p_screen) const {
float DisplayServerMacOS::screen_get_refresh_rate(int p_screen) const {
_THREAD_SAFE_METHOD_
if (p_screen == SCREEN_OF_MAIN_WINDOW) {
p_screen = window_get_current_screen();
switch (p_screen) {
case SCREEN_PRIMARY: {
p_screen = get_primary_screen();
} break;
case SCREEN_OF_MAIN_WINDOW: {
p_screen = window_get_current_screen(MAIN_WINDOW_ID);
} break;
default:
break;
}
NSArray *screenArray = [NSScreen screens];
@ -2225,10 +2276,10 @@ Vector<DisplayServer::WindowID> DisplayServerMacOS::get_window_list() const {
return ret;
}
DisplayServer::WindowID DisplayServerMacOS::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, int p_screen) {
DisplayServer::WindowID DisplayServerMacOS::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
_THREAD_SAFE_METHOD_
WindowID id = _create_window(p_mode, p_vsync_mode, p_rect, p_screen);
WindowID id = _create_window(p_mode, p_vsync_mode, p_rect);
for (int i = 0; i < WINDOW_FLAG_MAX; i++) {
if (p_flags & (1 << i)) {
window_set_flag(WindowFlags(i), true, id);
@ -3520,8 +3571,8 @@ void DisplayServerMacOS::set_icon(const Ref<Image> &p_icon) {
[NSApp setApplicationIconImage:nsimg];
}
DisplayServer *DisplayServerMacOS::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error) {
DisplayServer *ds = memnew(DisplayServerMacOS(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, r_error));
DisplayServer *DisplayServerMacOS::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) {
DisplayServer *ds = memnew(DisplayServerMacOS(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, p_screen, r_error));
if (r_error != OK) {
if (p_rendering_driver == "vulkan") {
String executable_command;
@ -3690,7 +3741,7 @@ bool DisplayServerMacOS::mouse_process_popups(bool p_close) {
return closed;
}
DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error) {
DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) {
Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events);
r_error = OK;
@ -3796,15 +3847,17 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM
}
#endif
Point2i window_position(
screen_get_position(0).x + (screen_get_size(0).width - p_resolution.width) / 2,
screen_get_position(0).y + (screen_get_size(0).height - p_resolution.height) / 2);
Point2i window_position;
if (p_position != nullptr) {
window_position = *p_position;
} else {
if (p_screen == SCREEN_OF_MAIN_WINDOW) {
p_screen = SCREEN_PRIMARY;
}
window_position = screen_get_position(p_screen) + (screen_get_size(p_screen) - p_resolution) / 2;
}
WindowID main_window = _create_window(p_mode, p_vsync_mode, Rect2i(window_position, p_resolution), 0);
WindowID main_window = _create_window(p_mode, p_vsync_mode, Rect2i(window_position, p_resolution));
ERR_FAIL_COND(main_window == INVALID_WINDOW_ID);
for (int i = 0; i < WINDOW_FLAG_MAX; i++) {
if (p_flags & (1 << i)) {

View file

@ -746,11 +746,11 @@ void DisplayServerWeb::_dispatch_input_event(const Ref<InputEvent> &p_event) {
}
}
DisplayServer *DisplayServerWeb::create_func(const String &p_rendering_driver, WindowMode p_window_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Point2i *p_position, const Size2i &p_resolution, Error &r_error) {
return memnew(DisplayServerWeb(p_rendering_driver, p_window_mode, p_vsync_mode, p_flags, p_position, p_resolution, r_error));
DisplayServer *DisplayServerWeb::create_func(const String &p_rendering_driver, WindowMode p_window_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Point2i *p_position, const Size2i &p_resolution, int p_screen, Error &r_error) {
return memnew(DisplayServerWeb(p_rendering_driver, p_window_mode, p_vsync_mode, p_flags, p_position, p_resolution, p_screen, r_error));
}
DisplayServerWeb::DisplayServerWeb(const String &p_rendering_driver, WindowMode p_window_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Point2i *p_position, const Size2i &p_resolution, Error &r_error) {
DisplayServerWeb::DisplayServerWeb(const String &p_rendering_driver, WindowMode p_window_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Point2i *p_position, const Size2i &p_resolution, int p_screen, Error &r_error) {
r_error = OK; // Always succeeds for now.
// Ensure the canvas ID.
@ -864,6 +864,10 @@ int DisplayServerWeb::get_screen_count() const {
return 1;
}
int DisplayServerWeb::get_primary_screen() const {
return 0;
}
Point2i DisplayServerWeb::screen_get_position(int p_screen) const {
return Point2i(); // TODO offsetX/Y?
}

View file

@ -97,7 +97,7 @@ private:
static void _js_utterance_callback(int p_event, int p_id, int p_pos);
static Vector<String> get_rendering_drivers_func();
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_window_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error);
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_window_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error);
static void _dispatch_input_event(const Ref<InputEvent> &p_event);
@ -151,6 +151,7 @@ public:
// screen
virtual int get_screen_count() const override;
virtual int get_primary_screen() const override;
virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
@ -223,7 +224,7 @@ public:
virtual void swap_buffers() override;
static void register_web_driver();
DisplayServerWeb(const String &p_rendering_driver, WindowMode p_window_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Point2i *p_position, const Size2i &p_resolution, Error &r_error);
DisplayServerWeb(const String &p_rendering_driver, WindowMode p_window_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Point2i *p_position, const Size2i &p_resolution, int p_screen, Error &r_error);
~DisplayServerWeb();
};

View file

@ -254,7 +254,7 @@ void DisplayServerWindows::warp_mouse(const Point2i &p_position) {
Point2i DisplayServerWindows::mouse_get_position() const {
POINT p;
GetCursorPos(&p);
return Point2i(p.x, p.y);
return Point2i(p.x, p.y) - _get_screens_origin();
}
MouseButton DisplayServerWindows::mouse_get_button_state() const {
@ -346,6 +346,19 @@ typedef struct {
HMONITOR monitor;
} EnumScreenData;
static BOOL CALLBACK _MonitorEnumProcPrim(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
EnumScreenData *data = (EnumScreenData *)dwData;
if (data->monitor == hMonitor) {
if ((lprcMonitor->left == 0) && (lprcMonitor->top == 0)) {
data->screen = data->count;
return FALSE;
}
}
data->count++;
return TRUE;
}
static BOOL CALLBACK _MonitorEnumProcScreen(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
EnumScreenData *data = (EnumScreenData *)dwData;
if (data->monitor == hMonitor) {
@ -370,6 +383,12 @@ int DisplayServerWindows::get_screen_count() const {
return data;
}
int DisplayServerWindows::get_primary_screen() const {
EnumScreenData data = { 0, 0, 0 };
EnumDisplayMonitors(nullptr, nullptr, _MonitorEnumProcPrim, (LPARAM)&data);
return data.screen;
}
typedef struct {
int count;
int screen;
@ -387,12 +406,39 @@ static BOOL CALLBACK _MonitorEnumProcPos(HMONITOR hMonitor, HDC hdcMonitor, LPRE
return TRUE;
}
static BOOL CALLBACK _MonitorEnumProcOrigin(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
EnumPosData *data = (EnumPosData *)dwData;
data->pos.x = MIN(data->pos.x, lprcMonitor->left);
data->pos.y = MIN(data->pos.y, lprcMonitor->top);
return TRUE;
}
Point2i DisplayServerWindows::_get_screens_origin() const {
_THREAD_SAFE_METHOD_
EnumPosData data = { 0, 0, Point2() };
EnumDisplayMonitors(nullptr, nullptr, _MonitorEnumProcOrigin, (LPARAM)&data);
return data.pos;
}
Point2i DisplayServerWindows::screen_get_position(int p_screen) const {
_THREAD_SAFE_METHOD_
EnumPosData data = { 0, p_screen == SCREEN_OF_MAIN_WINDOW ? window_get_current_screen() : p_screen, Point2() };
switch (p_screen) {
case SCREEN_PRIMARY: {
p_screen = get_primary_screen();
} break;
case SCREEN_OF_MAIN_WINDOW: {
p_screen = window_get_current_screen(MAIN_WINDOW_ID);
} break;
default:
break;
}
EnumPosData data = { 0, p_screen, Point2() };
EnumDisplayMonitors(nullptr, nullptr, _MonitorEnumProcPos, (LPARAM)&data);
return data.pos;
return data.pos - _get_screens_origin();
}
typedef struct {
@ -427,7 +473,18 @@ static BOOL CALLBACK _MonitorEnumProcSize(HMONITOR hMonitor, HDC hdcMonitor, LPR
Size2i DisplayServerWindows::screen_get_size(int p_screen) const {
_THREAD_SAFE_METHOD_
EnumSizeData data = { 0, p_screen == SCREEN_OF_MAIN_WINDOW ? window_get_current_screen() : p_screen, Size2() };
switch (p_screen) {
case SCREEN_PRIMARY: {
p_screen = get_primary_screen();
} break;
case SCREEN_OF_MAIN_WINDOW: {
p_screen = window_get_current_screen(MAIN_WINDOW_ID);
} break;
default:
break;
}
EnumSizeData data = { 0, p_screen, Size2() };
EnumDisplayMonitors(nullptr, nullptr, _MonitorEnumProcSize, (LPARAM)&data);
return data.size;
}
@ -473,8 +530,20 @@ static BOOL CALLBACK _MonitorEnumProcRefreshRate(HMONITOR hMonitor, HDC hdcMonit
Rect2i DisplayServerWindows::screen_get_usable_rect(int p_screen) const {
_THREAD_SAFE_METHOD_
EnumRectData data = { 0, p_screen == SCREEN_OF_MAIN_WINDOW ? window_get_current_screen() : p_screen, Rect2i() };
switch (p_screen) {
case SCREEN_PRIMARY: {
p_screen = get_primary_screen();
} break;
case SCREEN_OF_MAIN_WINDOW: {
p_screen = window_get_current_screen(MAIN_WINDOW_ID);
} break;
default:
break;
}
EnumRectData data = { 0, p_screen, Rect2i() };
EnumDisplayMonitors(nullptr, nullptr, _MonitorEnumProcUsableSize, (LPARAM)&data);
data.rect.position -= _get_screens_origin();
return data.rect;
}
@ -549,14 +618,36 @@ static BOOL CALLBACK _MonitorEnumProcDpi(HMONITOR hMonitor, HDC hdcMonitor, LPRE
int DisplayServerWindows::screen_get_dpi(int p_screen) const {
_THREAD_SAFE_METHOD_
EnumDpiData data = { 0, p_screen == SCREEN_OF_MAIN_WINDOW ? window_get_current_screen() : p_screen, 72 };
switch (p_screen) {
case SCREEN_PRIMARY: {
p_screen = get_primary_screen();
} break;
case SCREEN_OF_MAIN_WINDOW: {
p_screen = window_get_current_screen(MAIN_WINDOW_ID);
} break;
default:
break;
}
EnumDpiData data = { 0, p_screen, 72 };
EnumDisplayMonitors(nullptr, nullptr, _MonitorEnumProcDpi, (LPARAM)&data);
return data.dpi;
}
float DisplayServerWindows::screen_get_refresh_rate(int p_screen) const {
_THREAD_SAFE_METHOD_
EnumRefreshRateData data = { 0, p_screen == SCREEN_OF_MAIN_WINDOW ? window_get_current_screen() : p_screen, SCREEN_REFRESH_RATE_FALLBACK };
switch (p_screen) {
case SCREEN_PRIMARY: {
p_screen = get_primary_screen();
} break;
case SCREEN_OF_MAIN_WINDOW: {
p_screen = window_get_current_screen(MAIN_WINDOW_ID);
} break;
default:
break;
}
EnumRefreshRateData data = { 0, p_screen, SCREEN_REFRESH_RATE_FALLBACK };
EnumDisplayMonitors(nullptr, nullptr, _MonitorEnumProcRefreshRate, (LPARAM)&data);
return data.rate;
}
@ -612,9 +703,10 @@ Vector<DisplayServer::WindowID> DisplayServerWindows::get_window_list() const {
}
DisplayServer::WindowID DisplayServerWindows::get_window_at_screen_position(const Point2i &p_position) const {
Point2i offset = _get_screens_origin();
POINT p;
p.x = p_position.x;
p.y = p_position.y;
p.x = p_position.x + offset.x;
p.y = p_position.y + offset.y;
HWND hwnd = WindowFromPoint(p);
for (const KeyValue<WindowID, WindowData> &E : windows) {
if (E.value.hWnd == hwnd) {
@ -625,10 +717,10 @@ DisplayServer::WindowID DisplayServerWindows::get_window_at_screen_position(cons
return INVALID_WINDOW_ID;
}
DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, int p_screen) {
DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
_THREAD_SAFE_METHOD_
WindowID window_id = _create_window(p_mode, p_vsync_mode, p_flags, p_rect, p_screen);
WindowID window_id = _create_window(p_mode, p_vsync_mode, p_flags, p_rect);
ERR_FAIL_COND_V_MSG(window_id == INVALID_WINDOW_ID, INVALID_WINDOW_ID, "Failed to create sub window.");
WindowData &wd = windows[window_id];
@ -870,7 +962,7 @@ void DisplayServerWindows::window_set_current_screen(int p_screen, WindowID p_wi
}
const WindowData &wd = windows[p_window];
if (wd.fullscreen) {
Point2 pos = screen_get_position(p_screen);
Point2 pos = screen_get_position(p_screen) + _get_screens_origin();
Size2 size = screen_get_size(p_screen);
MoveWindow(wd.hWnd, pos.x, pos.y, size.width, size.height, TRUE);
@ -911,7 +1003,7 @@ Point2i DisplayServerWindows::window_get_position(WindowID p_window) const {
ClientToScreen(wd.hWnd, &point);
return Point2i(point.x, point.y);
return Point2i(point.x, point.y) - _get_screens_origin();
}
Point2i DisplayServerWindows::window_get_position_with_decorations(WindowID p_window) const {
@ -926,7 +1018,7 @@ Point2i DisplayServerWindows::window_get_position_with_decorations(WindowID p_wi
RECT r;
if (GetWindowRect(wd.hWnd, &r)) {
return Point2i(r.left, r.top);
return Point2i(r.left, r.top) - _get_screens_origin();
}
return Point2i();
@ -956,11 +1048,13 @@ void DisplayServerWindows::window_set_position(const Point2i &p_position, Window
return;
}
Point2i offset = _get_screens_origin();
RECT rc;
rc.left = p_position.x;
rc.right = p_position.x + wd.width;
rc.bottom = p_position.y + wd.height;
rc.top = p_position.y;
rc.left = p_position.x + offset.x;
rc.right = p_position.x + wd.width + offset.x;
rc.bottom = p_position.y + wd.height + offset.y;
rc.top = p_position.y + offset.y;
const DWORD style = GetWindowLongPtr(wd.hWnd, GWL_STYLE);
const DWORD exStyle = GetWindowLongPtr(wd.hWnd, GWL_EXSTYLE);
@ -1296,7 +1390,7 @@ void DisplayServerWindows::window_set_mode(WindowMode p_mode, WindowID p_window)
}
int cs = window_get_current_screen(p_window);
Point2 pos = screen_get_position(cs);
Point2 pos = screen_get_position(cs) + _get_screens_origin();
Size2 size = screen_get_size(cs);
wd.fullscreen = true;
@ -2277,7 +2371,7 @@ LRESULT DisplayServerWindows::MouseProc(int code, WPARAM wParam, LPARAM lParam)
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN: {
MOUSEHOOKSTRUCT *ms = (MOUSEHOOKSTRUCT *)lParam;
Point2i pos = Point2i(ms->pt.x, ms->pt.y);
Point2i pos = Point2i(ms->pt.x, ms->pt.y) - _get_screens_origin();
List<WindowID>::Element *C = nullptr;
List<WindowID>::Element *E = popup_list.back();
// Find top popup to close.
@ -3130,10 +3224,12 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
ClientToScreen(hWnd, (POINT *)&rect.left);
ClientToScreen(hWnd, (POINT *)&rect.right);
window_client_rect = Rect2i(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
window_client_rect.position -= _get_screens_origin();
RECT wrect;
GetWindowRect(hWnd, &wrect);
window_rect = Rect2i(wrect.left, wrect.top, wrect.right - wrect.left, wrect.bottom - wrect.top);
window_rect.position -= _get_screens_origin();
}
WINDOWPOS *window_pos_params = (WINDOWPOS *)lParam;
@ -3539,7 +3635,7 @@ void DisplayServerWindows::_update_tablet_ctx(const String &p_old_driver, const
}
}
DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, int p_screen) {
DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
DWORD dwExStyle;
DWORD dwStyle;
@ -3552,40 +3648,38 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
WindowRect.top = p_rect.position.y;
WindowRect.bottom = p_rect.position.y + p_rect.size.y;
int rq_screen = get_screen_from_rect(p_rect);
if (rq_screen < 0) {
rq_screen = get_primary_screen(); // Requested window rect is outside any screen bounds.
}
if (p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
Rect2i screen_rect = Rect2i(screen_get_position(p_screen), screen_get_size(p_screen));
Rect2i screen_rect = Rect2i(screen_get_position(rq_screen), screen_get_size(rq_screen));
WindowRect.left = screen_rect.position.x;
WindowRect.right = screen_rect.position.x + screen_rect.size.x;
WindowRect.top = screen_rect.position.y;
WindowRect.bottom = screen_rect.position.y + screen_rect.size.y;
} else {
int nearest_area = 0;
int pos_screen = -1;
for (int i = 0; i < get_screen_count(); i++) {
Rect2i r;
r.position = screen_get_position(i);
r.size = screen_get_size(i);
Rect2 inters = r.intersection(p_rect);
int area = inters.size.width * inters.size.height;
if (area > nearest_area) {
pos_screen = i;
nearest_area = area;
}
Rect2i srect = screen_get_usable_rect(rq_screen);
Point2i wpos = p_rect.position;
if (srect != Rect2i()) {
wpos.x = CLAMP(wpos.x, srect.position.x, srect.position.x + srect.size.width - p_rect.size.width / 3);
wpos.y = CLAMP(wpos.y, srect.position.y, srect.position.y + srect.size.height - p_rect.size.height / 3);
}
Rect2i srect = screen_get_usable_rect(p_screen);
Point2i wpos = p_rect.position - ((pos_screen >= 0) ? screen_get_position(pos_screen) : Vector2i());
wpos += srect.position;
wpos.x = CLAMP(wpos.x, srect.position.x, srect.position.x + srect.size.width - p_rect.size.width / 3);
wpos.y = CLAMP(wpos.y, srect.position.y, srect.position.y + srect.size.height - p_rect.size.height / 3);
WindowRect.left = wpos.x;
WindowRect.right = wpos.x + p_rect.size.x;
WindowRect.top = wpos.y;
WindowRect.bottom = wpos.y + p_rect.size.y;
}
Point2i offset = _get_screens_origin();
WindowRect.left += offset.x;
WindowRect.right += offset.x;
WindowRect.top += offset.y;
WindowRect.bottom += offset.y;
AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);
WindowID id = window_id_counter;
@ -3794,7 +3888,7 @@ void DisplayServerWindows::tablet_set_current_driver(const String &p_driver) {
}
}
DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error) {
DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) {
drop_events = false;
key_event_pos = 0;
@ -3941,15 +4035,17 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
mouse_monitor = SetWindowsHookEx(WH_MOUSE, ::MouseProc, nullptr, GetCurrentThreadId());
Point2i window_position(
(screen_get_size(0).width - p_resolution.width) / 2,
(screen_get_size(0).height - p_resolution.height) / 2);
Point2i window_position;
if (p_position != nullptr) {
window_position = *p_position;
} else {
if (p_screen == SCREEN_OF_MAIN_WINDOW) {
p_screen = SCREEN_PRIMARY;
}
window_position = screen_get_position(p_screen) + (screen_get_size(p_screen) - p_resolution) / 2;
}
WindowID main_window = _create_window(p_mode, p_vsync_mode, 0, Rect2i(window_position, p_resolution), 0);
WindowID main_window = _create_window(p_mode, p_vsync_mode, 0, Rect2i(window_position, p_resolution));
ERR_FAIL_COND_MSG(main_window == INVALID_WINDOW_ID, "Failed to create main window.");
joypad = new JoypadWindows(&windows[MAIN_WINDOW_ID].hWnd);
@ -4012,8 +4108,8 @@ Vector<String> DisplayServerWindows::get_rendering_drivers_func() {
return drivers;
}
DisplayServer *DisplayServerWindows::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error) {
DisplayServer *ds = memnew(DisplayServerWindows(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, r_error));
DisplayServer *DisplayServerWindows::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) {
DisplayServer *ds = memnew(DisplayServerWindows(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, p_screen, r_error));
if (r_error != OK) {
if (p_rendering_driver == "vulkan") {
String executable_name = OS::get_singleton()->get_executable_path().get_file();

View file

@ -426,7 +426,7 @@ class DisplayServerWindows : public DisplayServer {
uint64_t time_since_popup = 0;
Ref<Image> icon;
WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, int p_screen);
WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect);
WindowID window_id_counter = MAIN_WINDOW_ID;
RBMap<WindowID, WindowData> windows;
@ -476,6 +476,7 @@ class DisplayServerWindows : public DisplayServer {
void _dispatch_input_event(const Ref<InputEvent> &p_event);
LRESULT _handle_early_window_message(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
Point2i _get_screens_origin() const;
public:
LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
@ -511,6 +512,7 @@ public:
virtual String clipboard_get() const override;
virtual int get_screen_count() const override;
virtual int get_primary_screen() const override;
virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
@ -522,7 +524,7 @@ public:
virtual Vector<DisplayServer::WindowID> get_window_list() const override;
virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i(), int p_screen = 0) override;
virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()) override;
virtual void show_window(WindowID p_window) override;
virtual void delete_sub_window(WindowID p_window) override;
@ -623,11 +625,11 @@ public:
virtual void set_context(Context p_context) override;
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error);
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error);
static Vector<String> get_rendering_drivers_func();
static void register_windows_driver();
DisplayServerWindows(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error);
DisplayServerWindows(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error);
~DisplayServerWindows();
};

View file

@ -1298,7 +1298,6 @@ void Viewport::_gui_show_tooltip() {
r.position.y = vr.position.y;
}
gui.tooltip_popup->set_current_screen(window->get_current_screen());
gui.tooltip_popup->set_position(r.position);
gui.tooltip_popup->set_size(r.size);

View file

@ -223,6 +223,14 @@ void Window::_get_property_list(List<PropertyInfo> *p_list) const {
}
void Window::_validate_property(PropertyInfo &p_property) const {
if (p_property.name == "position" && initial_position != WINDOW_INITIAL_POSITION_ABSOLUTE) {
p_property.usage = PROPERTY_USAGE_NONE;
}
if (p_property.name == "current_screen" && initial_position != WINDOW_INITIAL_POSITION_CENTER_SCREEN) {
p_property.usage = PROPERTY_USAGE_NONE;
}
if (p_property.name == "theme_type_variation") {
List<StringName> names;
@ -275,6 +283,15 @@ String Window::get_title() const {
return title;
}
void Window::set_initial_position(Window::WindowInitialPosition p_initial_position) {
initial_position = p_initial_position;
notify_property_list_changed();
}
Window::WindowInitialPosition Window::get_initial_position() const {
return initial_position;
}
void Window::set_current_screen(int p_screen) {
current_screen = p_screen;
if (window_id == DisplayServer::INVALID_WINDOW_ID) {
@ -462,7 +479,13 @@ void Window::_make_window() {
}
DisplayServer::VSyncMode vsync_mode = DisplayServer::get_singleton()->window_get_vsync_mode(DisplayServer::MAIN_WINDOW_ID);
window_id = DisplayServer::get_singleton()->create_sub_window(DisplayServer::WindowMode(mode), vsync_mode, f, Rect2i(position, size), current_screen);
Rect2i window_rect;
if (initial_position == WINDOW_INITIAL_POSITION_ABSOLUTE) {
window_rect = Rect2i(position, size);
} else if (initial_position == WINDOW_INITIAL_POSITION_CENTER_SCREEN) {
window_rect = Rect2i(DisplayServer::get_singleton()->screen_get_position(current_screen) + (DisplayServer::get_singleton()->screen_get_size(current_screen) - size) / 2, size);
}
window_id = DisplayServer::get_singleton()->create_sub_window(DisplayServer::WindowMode(mode), vsync_mode, f, window_rect);
ERR_FAIL_COND(window_id == DisplayServer::INVALID_WINDOW_ID);
DisplayServer::get_singleton()->window_set_max_size(Size2i(), window_id);
DisplayServer::get_singleton()->window_set_min_size(Size2i(), window_id);
@ -2068,6 +2091,9 @@ void Window::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_title", "title"), &Window::set_title);
ClassDB::bind_method(D_METHOD("get_title"), &Window::get_title);
ClassDB::bind_method(D_METHOD("set_initial_position", "initial_position"), &Window::set_initial_position);
ClassDB::bind_method(D_METHOD("get_initial_position"), &Window::get_initial_position);
ClassDB::bind_method(D_METHOD("set_current_screen", "index"), &Window::set_current_screen);
ClassDB::bind_method(D_METHOD("get_current_screen"), &Window::get_current_screen);
@ -2204,11 +2230,18 @@ void Window::_bind_methods() {
ClassDB::bind_method(D_METHOD("popup_centered", "minsize"), &Window::popup_centered, DEFVAL(Size2i()));
ClassDB::bind_method(D_METHOD("popup_centered_clamped", "minsize", "fallback_ratio"), &Window::popup_centered_clamped, DEFVAL(Size2i()), DEFVAL(0.75));
ADD_PROPERTY(PropertyInfo(Variant::INT, "initial_position", PROPERTY_HINT_ENUM, "Absolute,Screen Center"), "set_initial_position", "get_initial_position");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "position", PROPERTY_HINT_NONE, "suffix:px"), "set_position", "get_position");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size", PROPERTY_HINT_NONE, "suffix:px"), "set_size", "get_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Windowed,Minimized,Maximized,Fullscreen"), "set_mode", "get_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "current_screen"), "set_current_screen", "get_current_screen");
// Keep the enum values in sync with the `DisplayServer::SCREEN_` enum.
String screen_hints = "Primary Monitor:-2,Main Window Monitor:-1";
for (int i = 0; i < 64; i++) {
screen_hints += ",Monitor " + itos(i + 1) + ":" + itos(i);
}
ADD_PROPERTY(PropertyInfo(Variant::INT, "current_screen", PROPERTY_HINT_ENUM, screen_hints), "set_current_screen", "get_current_screen");
ADD_GROUP("Flags", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible");
@ -2285,6 +2318,9 @@ void Window::_bind_methods() {
BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_LOCALE);
BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_LTR);
BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_RTL);
BIND_ENUM_CONSTANT(WINDOW_INITIAL_POSITION_ABSOLUTE);
BIND_ENUM_CONSTANT(WINDOW_INITIAL_POSITION_CENTER_SCREEN);
}
Window::Window() {

View file

@ -87,11 +87,16 @@ public:
DEFAULT_WINDOW_SIZE = 100,
};
enum WindowInitialPosition {
WINDOW_INITIAL_POSITION_ABSOLUTE,
WINDOW_INITIAL_POSITION_CENTER_SCREEN,
};
private:
DisplayServer::WindowID window_id = DisplayServer::INVALID_WINDOW_ID;
String title;
mutable int current_screen = 0;
mutable int current_screen = DisplayServer::SCREEN_PRIMARY;
mutable Vector2i position;
mutable Size2i size = Size2i(DEFAULT_WINDOW_SIZE, DEFAULT_WINDOW_SIZE);
mutable Size2i min_size;
@ -100,6 +105,7 @@ private:
mutable bool flags[FLAG_MAX] = {};
bool visible = true;
bool focused = false;
WindowInitialPosition initial_position = WINDOW_INITIAL_POSITION_ABSOLUTE;
bool use_font_oversampling = false;
bool transient = false;
@ -201,6 +207,9 @@ public:
void set_title(const String &p_title);
String get_title() const;
void set_initial_position(WindowInitialPosition p_initial_position);
WindowInitialPosition get_initial_position() const;
void set_current_screen(int p_screen);
int get_current_screen() const;
@ -369,5 +378,6 @@ VARIANT_ENUM_CAST(Window::Flags);
VARIANT_ENUM_CAST(Window::ContentScaleMode);
VARIANT_ENUM_CAST(Window::ContentScaleAspect);
VARIANT_ENUM_CAST(Window::LayoutDirection);
VARIANT_ENUM_CAST(Window::WindowInitialPosition);
#endif // WINDOW_H

View file

@ -379,7 +379,24 @@ bool DisplayServer::screen_is_kept_on() const {
return false;
}
DisplayServer::WindowID DisplayServer::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, int p_screen) {
int DisplayServer::get_screen_from_rect(const Rect2 &p_rect) const {
int nearest_area = 0;
int pos_screen = -1;
for (int i = 0; i < get_screen_count(); i++) {
Rect2i r;
r.position = screen_get_position(i);
r.size = screen_get_size(i);
Rect2 inters = r.intersection(p_rect);
int area = inters.size.width * inters.size.height;
if (area > nearest_area) {
pos_screen = i;
nearest_area = area;
}
}
return pos_screen;
}
DisplayServer::WindowID DisplayServer::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Sub-windows not supported by this display server.");
}
@ -612,6 +629,8 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_display_safe_area"), &DisplayServer::get_display_safe_area);
ClassDB::bind_method(D_METHOD("get_screen_count"), &DisplayServer::get_screen_count);
ClassDB::bind_method(D_METHOD("get_primary_screen"), &DisplayServer::get_primary_screen);
ClassDB::bind_method(D_METHOD("get_screen_from_rect", "rect"), &DisplayServer::get_screen_from_rect);
ClassDB::bind_method(D_METHOD("screen_get_position", "screen"), &DisplayServer::screen_get_position, DEFVAL(SCREEN_OF_MAIN_WINDOW));
ClassDB::bind_method(D_METHOD("screen_get_size", "screen"), &DisplayServer::screen_get_size, DEFVAL(SCREEN_OF_MAIN_WINDOW));
ClassDB::bind_method(D_METHOD("screen_get_usable_rect", "screen"), &DisplayServer::screen_get_usable_rect, DEFVAL(SCREEN_OF_MAIN_WINDOW));
@ -754,7 +773,9 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(MOUSE_MODE_CONFINED);
BIND_ENUM_CONSTANT(MOUSE_MODE_CONFINED_HIDDEN);
BIND_CONSTANT(SCREEN_PRIMARY);
BIND_CONSTANT(SCREEN_OF_MAIN_WINDOW);
BIND_CONSTANT(MAIN_WINDOW_ID);
BIND_CONSTANT(INVALID_WINDOW_ID);
@ -858,9 +879,9 @@ Vector<String> DisplayServer::get_create_function_rendering_drivers(int p_index)
return server_create_functions[p_index].get_rendering_drivers_function();
}
DisplayServer *DisplayServer::create(int p_index, const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error) {
DisplayServer *DisplayServer::create(int p_index, const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) {
ERR_FAIL_INDEX_V(p_index, server_create_count, nullptr);
return server_create_functions[p_index].create_function(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, r_error);
return server_create_functions[p_index].create_function(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, p_screen, r_error);
}
void DisplayServer::_input_set_mouse_mode(Input::MouseMode p_mode) {

View file

@ -73,7 +73,7 @@ public:
OPENGL_CONTEXT,
};
typedef DisplayServer *(*CreateFunction)(const String &, WindowMode, VSyncMode, uint32_t, const Point2i *, const Size2i &, Error &r_error);
typedef DisplayServer *(*CreateFunction)(const String &, WindowMode, VSyncMode, uint32_t, const Point2i *, const Size2i &, int p_screen, Error &r_error);
typedef Vector<String> (*GetRenderingDriversFunction)();
private:
@ -242,12 +242,15 @@ public:
virtual Rect2i get_display_safe_area() const { return screen_get_usable_rect(); }
enum {
SCREEN_OF_MAIN_WINDOW = -1
SCREEN_PRIMARY = -2,
SCREEN_OF_MAIN_WINDOW = -1, // Note: for the main window, determine screen from position.
};
const float SCREEN_REFRESH_RATE_FALLBACK = -1.0; // Returned by screen_get_refresh_rate if the method fails.
virtual int get_screen_count() const = 0;
virtual int get_primary_screen() const = 0;
virtual int get_screen_from_rect(const Rect2 &p_rect) const;
virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0;
virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0;
virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0;
@ -312,7 +315,7 @@ public:
WINDOW_FLAG_EXTEND_TO_TITLE_BIT = (1 << WINDOW_FLAG_EXTEND_TO_TITLE),
};
virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i(), int p_screen = 0);
virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i());
virtual void show_window(WindowID p_id);
virtual void delete_sub_window(WindowID p_id);
@ -485,7 +488,7 @@ public:
static int get_create_function_count();
static const char *get_create_function_name(int p_index);
static Vector<String> get_create_function_rendering_drivers(int p_index);
static DisplayServer *create(int p_index, const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error);
static DisplayServer *create(int p_index, const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error);
DisplayServer();
~DisplayServer();

View file

@ -45,7 +45,7 @@ private:
return drivers;
}
static DisplayServer *create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error) {
static DisplayServer *create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) {
r_error = OK;
RasterizerDummy::make_current();
return memnew(DisplayServerHeadless());
@ -56,6 +56,7 @@ public:
String get_name() const override { return "headless"; }
int get_screen_count() const override { return 0; }
int get_primary_screen() const override { return 0; };
Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override { return Point2i(); }
Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override { return Size2i(); }
Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override { return Rect2i(); }
@ -66,7 +67,7 @@ public:
Vector<DisplayServer::WindowID> get_window_list() const override { return Vector<DisplayServer::WindowID>(); }
WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i(), int p_screen = 0) override { return 0; }
WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()) override { return 0; }
void show_window(WindowID p_id) override {}
void delete_sub_window(WindowID p_id) override {}

View file

@ -203,7 +203,7 @@ struct GodotTestCaseListener : public doctest::IReporter {
OS::get_singleton()->set_has_server_feature_callback(nullptr);
for (int i = 0; i < DisplayServer::get_create_function_count(); i++) {
if (String("headless") == DisplayServer::get_create_function_name(i)) {
DisplayServer::create(i, "", DisplayServer::WindowMode::WINDOW_MODE_MINIMIZED, DisplayServer::VSyncMode::VSYNC_ENABLED, 0, nullptr, Vector2i(0, 0), err);
DisplayServer::create(i, "", DisplayServer::WindowMode::WINDOW_MODE_MINIMIZED, DisplayServer::VSyncMode::VSYNC_ENABLED, 0, nullptr, Vector2i(0, 0), DisplayServer::SCREEN_PRIMARY, err);
break;
}
}