Merge pull request #70624 from bruvzg/cur_sc

Improve `window_set_current_screen` and fix secondary window initial mode and positions.
This commit is contained in:
Rémi Verschelde 2023-01-03 15:56:05 +01:00
commit 8791e333da
No known key found for this signature in database
GPG Key ID: C3336907360768E1
13 changed files with 189 additions and 89 deletions

View File

@ -1235,10 +1235,10 @@ Vector<DisplayServer::WindowID> DisplayServerX11::get_window_list() const {
return ret; return ret;
} }
DisplayServer::WindowID DisplayServerX11::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) { DisplayServer::WindowID DisplayServerX11::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, int p_screen) {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_
WindowID id = _create_window(p_mode, p_vsync_mode, p_flags, p_rect); WindowID id = _create_window(p_mode, p_vsync_mode, p_flags, p_rect, p_screen);
for (int i = 0; i < WINDOW_FLAG_MAX; i++) { for (int i = 0; i < WINDOW_FLAG_MAX; i++) {
if (p_flags & (1 << i)) { if (p_flags & (1 << i)) {
window_set_flag(WindowFlags(i), true, id); window_set_flag(WindowFlags(i), true, id);
@ -1257,6 +1257,8 @@ void DisplayServerX11::show_window(WindowID p_id) {
DEBUG_LOG_X11("show_window: %lu (%u) \n", wd.x11_window, p_id); DEBUG_LOG_X11("show_window: %lu (%u) \n", wd.x11_window, p_id);
XMapWindow(x11_display, wd.x11_window); XMapWindow(x11_display, wd.x11_window);
XSync(x11_display, False);
_validate_mode_on_map(p_id);
} }
void DisplayServerX11::delete_sub_window(WindowID p_id) { void DisplayServerX11::delete_sub_window(WindowID p_id) {
@ -1505,16 +1507,24 @@ void DisplayServerX11::window_set_current_screen(int p_screen, WindowID p_window
// Check if screen is valid // Check if screen is valid
ERR_FAIL_INDEX(p_screen, get_screen_count()); ERR_FAIL_INDEX(p_screen, get_screen_count());
if (window_get_current_screen(p_window) == p_screen) {
return;
}
if (window_get_mode(p_window) == WINDOW_MODE_FULLSCREEN) { if (window_get_mode(p_window) == WINDOW_MODE_FULLSCREEN) {
Point2i position = screen_get_position(p_screen); Point2i position = screen_get_position(p_screen);
Size2i size = screen_get_size(p_screen); Size2i size = screen_get_size(p_screen);
XMoveResizeWindow(x11_display, wd.x11_window, position.x, position.y, size.x, size.y); XMoveResizeWindow(x11_display, wd.x11_window, position.x, position.y, size.x, size.y);
} else { } else {
if (p_screen != window_get_current_screen(p_window)) { Rect2i srect = screen_get_usable_rect(p_screen);
Vector2 ofs = window_get_position(p_window) - screen_get_position(window_get_current_screen(p_window)); Point2i wpos = window_get_position(p_window) - screen_get_position(window_get_current_screen(p_window));
window_set_position(ofs + screen_get_position(p_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);
window_set_position(wpos, p_window);
} }
} }
@ -4531,7 +4541,7 @@ DisplayServer *DisplayServerX11::create_func(const String &p_rendering_driver, W
return ds; return ds;
} }
DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) { DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, int p_screen) {
//Create window //Create window
XVisualInfo visualInfo; XVisualInfo visualInfo;
@ -4607,8 +4617,38 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
valuemask |= CWOverrideRedirect | CWSaveUnder; valuemask |= CWOverrideRedirect | CWSaveUnder;
} }
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));
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;
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);
win_rect.position = wpos;
}
{ {
wd.x11_window = XCreateWindow(x11_display, RootWindow(x11_display, visualInfo.screen), p_rect.position.x, p_rect.position.y, p_rect.size.width > 0 ? p_rect.size.width : 1, p_rect.size.height > 0 ? p_rect.size.height : 1, 0, visualInfo.depth, InputOutput, visualInfo.visual, valuemask, &windowAttributes); wd.x11_window = XCreateWindow(x11_display, RootWindow(x11_display, visualInfo.screen), win_rect.position.x, win_rect.position.y, win_rect.size.width > 0 ? win_rect.size.width : 1, win_rect.size.height > 0 ? win_rect.size.height : 1, 0, visualInfo.depth, InputOutput, visualInfo.visual, valuemask, &windowAttributes);
// Enable receiving notification when the window is initialized (MapNotify) // Enable receiving notification when the window is initialized (MapNotify)
// so the focus can be set at the right time. // so the focus can be set at the right time.
@ -4729,13 +4769,13 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
#if defined(VULKAN_ENABLED) #if defined(VULKAN_ENABLED)
if (context_vulkan) { if (context_vulkan) {
Error err = context_vulkan->window_create(id, p_vsync_mode, wd.x11_window, x11_display, p_rect.size.width, p_rect.size.height); Error err = context_vulkan->window_create(id, p_vsync_mode, wd.x11_window, x11_display, win_rect.size.width, win_rect.size.height);
ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create a Vulkan window"); ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create a Vulkan window");
} }
#endif #endif
#ifdef GLES3_ENABLED #ifdef GLES3_ENABLED
if (gl_manager) { if (gl_manager) {
Error err = gl_manager->window_create(id, wd.x11_window, x11_display, p_rect.size.width, p_rect.size.height); Error err = gl_manager->window_create(id, wd.x11_window, x11_display, win_rect.size.width, win_rect.size.height);
ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create an OpenGL window"); ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create an OpenGL window");
window_set_vsync_mode(p_vsync_mode, id); window_set_vsync_mode(p_vsync_mode, id);
} }
@ -5038,12 +5078,13 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
Point2i window_position( Point2i window_position(
(screen_get_size(0).width - p_resolution.width) / 2, (screen_get_size(0).width - p_resolution.width) / 2,
(screen_get_size(0).height - p_resolution.height) / 2); (screen_get_size(0).height - p_resolution.height) / 2);
window_position += screen_get_position(0);
if (p_position != nullptr) { if (p_position != nullptr) {
window_position = *p_position; window_position = *p_position;
} }
WindowID main_window = _create_window(p_mode, p_vsync_mode, p_flags, Rect2i(window_position, p_resolution)); WindowID main_window = _create_window(p_mode, p_vsync_mode, p_flags, Rect2i(window_position, p_resolution), 0);
if (main_window == INVALID_WINDOW_ID) { if (main_window == INVALID_WINDOW_ID) {
r_error = ERR_CANT_CREATE; r_error = ERR_CANT_CREATE;
return; return;
@ -5054,8 +5095,6 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
} }
} }
show_window(main_window); show_window(main_window);
XSync(x11_display, False);
_validate_mode_on_map(main_window);
#if defined(VULKAN_ENABLED) #if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") { if (rendering_driver == "vulkan") {

View File

@ -185,7 +185,7 @@ class DisplayServerX11 : public DisplayServer {
WindowID last_focused_window = INVALID_WINDOW_ID; WindowID last_focused_window = INVALID_WINDOW_ID;
WindowID window_id_counter = MAIN_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); WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, int p_screen);
String internal_clipboard; String internal_clipboard;
String internal_clipboard_primary; String internal_clipboard_primary;
@ -365,7 +365,7 @@ public:
virtual Vector<DisplayServer::WindowID> get_window_list() const override; 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()) 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 void show_window(WindowID p_id) override; virtual void show_window(WindowID p_id) override;
virtual void delete_sub_window(WindowID p_id) override; virtual void delete_sub_window(WindowID p_id) override;

View File

@ -99,6 +99,8 @@ public:
Callable drop_files_callback; Callable drop_files_callback;
ObjectID instance_id; ObjectID instance_id;
bool fs_transition = false;
bool initial_size = true;
WindowID transient_parent = INVALID_WINDOW_ID; WindowID transient_parent = INVALID_WINDOW_ID;
bool exclusive = false; bool exclusive = false;
@ -189,7 +191,7 @@ private:
const NSMenu *_get_menu_root(const String &p_menu_root) const; const NSMenu *_get_menu_root(const String &p_menu_root) const;
NSMenu *_get_menu_root(const String &p_menu_root); NSMenu *_get_menu_root(const String &p_menu_root);
WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, const Rect2i &p_rect); WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, const Rect2i &p_rect, int p_screen);
void _update_window_style(WindowData p_wd); void _update_window_style(WindowData p_wd);
void _set_window_per_pixel_transparency_enabled(bool p_enabled, WindowID p_window); void _set_window_per_pixel_transparency_enabled(bool p_enabled, WindowID p_window);
@ -334,7 +336,7 @@ public:
virtual Vector<int> get_window_list() const override; 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()) 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 void show_window(WindowID p_id) override; virtual void show_window(WindowID p_id) override;
virtual void delete_sub_window(WindowID p_id) override; virtual void delete_sub_window(WindowID p_id) override;

View File

@ -109,7 +109,7 @@ NSMenu *DisplayServerMacOS::_get_menu_root(const String &p_menu_root) {
return menu; return menu;
} }
DisplayServerMacOS::WindowID DisplayServerMacOS::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, const Rect2i &p_rect) { DisplayServerMacOS::WindowID DisplayServerMacOS::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, const Rect2i &p_rect, int p_screen) {
WindowID id; WindowID id;
const float scale = screen_get_max_scale(); const float scale = screen_get_max_scale();
{ {
@ -119,19 +119,36 @@ 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"); 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]; [wd.window_delegate setWindowID:window_id_counter];
Point2i position = p_rect.position; 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;
}
}
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);
// OS X native y-coordinate relative to _get_screens_origin() is negative, // OS X native y-coordinate relative to _get_screens_origin() is negative,
// Godot passes a positive value. // Godot passes a positive value.
position.y *= -1; wpos.y *= -1;
position += _get_screens_origin(); wpos += _get_screens_origin();
// initWithContentRect uses bottom-left corner of the windows frame as origin. // initWithContentRect uses bottom-left corner of the windows frame as origin.
wd.window_object = [[GodotWindow alloc] wd.window_object = [[GodotWindow alloc]
initWithContentRect:NSMakeRect(position.x / scale, (position.y - p_rect.size.height) / scale, p_rect.size.width / scale, p_rect.size.height / scale) initWithContentRect:NSMakeRect(0, 0, p_rect.size.width / scale, p_rect.size.height / scale)
styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable
backing:NSBackingStoreBuffered backing:NSBackingStoreBuffered
defer:NO]; defer:NO];
ERR_FAIL_COND_V_MSG(wd.window_object == nil, INVALID_WINDOW_ID, "Can't create a window"); 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_object setWindowID:window_id_counter];
wd.window_view = [[GodotContentView alloc] init]; wd.window_view = [[GodotContentView alloc] init];
@ -2208,10 +2225,10 @@ Vector<DisplayServer::WindowID> DisplayServerMacOS::get_window_list() const {
return ret; return ret;
} }
DisplayServer::WindowID DisplayServerMacOS::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) { DisplayServer::WindowID DisplayServerMacOS::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, int p_screen) {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_
WindowID id = _create_window(p_mode, p_vsync_mode, p_rect); WindowID id = _create_window(p_mode, p_vsync_mode, p_rect, p_screen);
for (int i = 0; i < WINDOW_FLAG_MAX; i++) { for (int i = 0; i < WINDOW_FLAG_MAX; i++) {
if (p_flags & (1 << i)) { if (p_flags & (1 << i)) {
window_set_flag(WindowFlags(i), true, id); window_set_flag(WindowFlags(i), true, id);
@ -2328,8 +2345,14 @@ void DisplayServerMacOS::window_set_current_screen(int p_screen, WindowID p_wind
was_fullscreen = true; was_fullscreen = true;
} }
Rect2i srect = screen_get_usable_rect(p_screen);
Point2i wpos = window_get_position(p_window) - screen_get_position(window_get_current_screen(p_window)); Point2i wpos = window_get_position(p_window) - screen_get_position(window_get_current_screen(p_window));
window_set_position(wpos + screen_get_position(p_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);
window_set_position(wpos, p_window);
if (was_fullscreen) { if (was_fullscreen) {
// Re-enter fullscreen mode. // Re-enter fullscreen mode.
@ -3781,7 +3804,7 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM
window_position = *p_position; window_position = *p_position;
} }
WindowID main_window = _create_window(p_mode, p_vsync_mode, Rect2i(window_position, p_resolution)); WindowID main_window = _create_window(p_mode, p_vsync_mode, Rect2i(window_position, p_resolution), 0);
ERR_FAIL_COND(main_window == INVALID_WINDOW_ID); ERR_FAIL_COND(main_window == INVALID_WINDOW_ID);
for (int i = 0; i < WINDOW_FLAG_MAX; i++) { for (int i = 0; i < WINDOW_FLAG_MAX; i++) {
if (p_flags & (1 << i)) { if (p_flags & (1 << i)) {

View File

@ -65,16 +65,28 @@
if (ds && ds->has_window(window_id)) { if (ds && ds->has_window(window_id)) {
DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
NSRect frameRect = [wd.window_object frame]; NSRect frameRect = [wd.window_object frame];
bool left = (wd.last_frame_rect.origin.x != frameRect.origin.x); if (wd.fs_transition || wd.initial_size) {
bool top = (wd.last_frame_rect.origin.y == frameRect.origin.y); self.layerContentsPlacement = NSViewLayerContentsPlacementScaleAxesIndependently;
if (left && top) { wd.initial_size = false;
self.layerContentsPlacement = NSViewLayerContentsPlacementBottomRight;
} else if (left && !top) {
self.layerContentsPlacement = NSViewLayerContentsPlacementTopRight;
} else if (!left && top) {
self.layerContentsPlacement = NSViewLayerContentsPlacementBottomLeft;
} else { } else {
self.layerContentsPlacement = NSViewLayerContentsPlacementTopLeft; bool left = (wd.last_frame_rect.origin.x != frameRect.origin.x);
bool bottom = (wd.last_frame_rect.origin.y != frameRect.origin.y);
bool right = (wd.last_frame_rect.origin.x + wd.last_frame_rect.size.width != frameRect.origin.x + frameRect.size.width);
bool top = (wd.last_frame_rect.origin.y + wd.last_frame_rect.size.height != frameRect.origin.y + frameRect.size.height);
if (left && top) {
self.layerContentsPlacement = NSViewLayerContentsPlacementBottomRight;
} else if (left && bottom) {
self.layerContentsPlacement = NSViewLayerContentsPlacementTopRight;
} else if (left) {
self.layerContentsPlacement = NSViewLayerContentsPlacementRight;
} else if (right && top) {
self.layerContentsPlacement = NSViewLayerContentsPlacementBottomLeft;
} else if (right && bottom) {
self.layerContentsPlacement = NSViewLayerContentsPlacementTopLeft;
} else if (right) {
self.layerContentsPlacement = NSViewLayerContentsPlacementLeft;
}
} }
wd.last_frame_rect = frameRect; wd.last_frame_rect = frameRect;
} }

View File

@ -38,8 +38,6 @@
@interface GodotWindowDelegate : NSObject <NSWindowDelegate> { @interface GodotWindowDelegate : NSObject <NSWindowDelegate> {
DisplayServer::WindowID window_id; DisplayServer::WindowID window_id;
NSRect old_frame;
NSWindowStyleMask old_style_mask;
} }
- (void)setWindowID:(DisplayServer::WindowID)wid; - (void)setWindowID:(DisplayServer::WindowID)wid;

View File

@ -70,24 +70,24 @@
ds->window_destroy(window_id); ds->window_destroy(window_id);
} }
- (NSArray<NSWindow *> *)customWindowsToEnterFullScreenForWindow:(NSWindow *)window { - (void)windowWillEnterFullScreen:(NSNotification *)notification {
DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) { if (!ds || !ds->has_window(window_id)) {
return nullptr; return;
} }
old_frame = [window frame]; DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
old_style_mask = [window styleMask]; wd.fs_transition = true;
NSMutableArray<NSWindow *> *windows = [[NSMutableArray alloc] init];
[windows addObject:window];
return windows;
} }
- (void)window:(NSWindow *)window startCustomAnimationToEnterFullScreenWithDuration:(NSTimeInterval)duration { - (void)windowDidFailToEnterFullScreen:(NSWindow *)window {
[(GodotWindow *)window setAnimDuration:duration]; DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
[window setFrame:[[window screen] frame] display:YES animate:YES]; if (!ds || !ds->has_window(window_id)) {
return;
}
DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
wd.fs_transition = false;
} }
- (void)windowDidEnterFullScreen:(NSNotification *)notification { - (void)windowDidEnterFullScreen:(NSNotification *)notification {
@ -98,29 +98,31 @@
DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
wd.fullscreen = true; wd.fullscreen = true;
wd.fs_transition = false;
// Reset window size limits. // Reset window size limits.
[wd.window_object setContentMinSize:NSMakeSize(0, 0)]; [wd.window_object setContentMinSize:NSMakeSize(0, 0)];
[wd.window_object setContentMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)]; [wd.window_object setContentMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];
[(GodotWindow *)wd.window_object setAnimDuration:-1.0f];
// Reset custom window buttons. // Reset custom window buttons.
if ([wd.window_object styleMask] & NSWindowStyleMaskFullSizeContentView) { if ([wd.window_object styleMask] & NSWindowStyleMaskFullSizeContentView) {
ds->window_set_custom_window_buttons(wd, false); ds->window_set_custom_window_buttons(wd, false);
} }
// Force window resize event.
[self windowDidResize:notification];
ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_TITLEBAR_CHANGE); ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_TITLEBAR_CHANGE);
// Force window resize event and redraw.
[self windowDidResize:notification];
} }
- (NSArray<NSWindow *> *)customWindowsToExitFullScreenForWindow:(NSWindow *)window { - (void)windowWillExitFullScreen:(NSNotification *)notification {
DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) { if (!ds || !ds->has_window(window_id)) {
return nullptr; return;
} }
DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
wd.fs_transition = true;
// Restore custom window buttons. // Restore custom window buttons.
if ([wd.window_object styleMask] & NSWindowStyleMaskFullSizeContentView) { if ([wd.window_object styleMask] & NSWindowStyleMaskFullSizeContentView) {
@ -128,16 +130,22 @@
} }
ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_TITLEBAR_CHANGE); ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_TITLEBAR_CHANGE);
NSMutableArray<NSWindow *> *windows = [[NSMutableArray alloc] init];
[windows addObject:wd.window_object];
return windows;
} }
- (void)window:(NSWindow *)window startCustomAnimationToExitFullScreenWithDuration:(NSTimeInterval)duration { - (void)windowDidFailToExitFullScreen:(NSWindow *)window {
[(GodotWindow *)window setAnimDuration:duration]; DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
[window setStyleMask:old_style_mask]; if (!ds || !ds->has_window(window_id)) {
[window setFrame:old_frame display:YES animate:YES]; return;
}
DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
wd.fs_transition = false;
if ([wd.window_object styleMask] & NSWindowStyleMaskFullSizeContentView) {
ds->window_set_custom_window_buttons(wd, false);
}
ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_TITLEBAR_CHANGE);
} }
- (void)windowDidExitFullScreen:(NSNotification *)notification { - (void)windowDidExitFullScreen:(NSNotification *)notification {
@ -153,8 +161,7 @@
wd.fullscreen = false; wd.fullscreen = false;
wd.exclusive_fullscreen = false; wd.exclusive_fullscreen = false;
wd.fs_transition = false;
[(GodotWindow *)wd.window_object setAnimDuration:-1.0f];
// Set window size limits. // Set window size limits.
const float scale = ds->screen_get_max_scale(); const float scale = ds->screen_get_max_scale();
@ -177,7 +184,7 @@
[wd.window_object setLevel:NSFloatingWindowLevel]; [wd.window_object setLevel:NSFloatingWindowLevel];
} }
// Force window resize event. // Force window resize event and redraw.
[self windowDidResize:notification]; [self windowDidResize:notification];
} }
@ -305,6 +312,8 @@
ds->update_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream]); ds->update_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream]);
} }
[self windowDidResize:notification]; // Emit resize event, to ensure content is resized if the window was resized while it was hidden.
ds->set_last_focused_window(window_id); ds->set_last_focused_window(window_id);
ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_FOCUS_IN); ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_FOCUS_IN);
} }

View File

@ -625,10 +625,10 @@ DisplayServer::WindowID DisplayServerWindows::get_window_at_screen_position(cons
return INVALID_WINDOW_ID; 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) { DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, int p_screen) {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_
WindowID window_id = _create_window(p_mode, p_vsync_mode, p_flags, p_rect); WindowID window_id = _create_window(p_mode, p_vsync_mode, p_flags, p_rect, p_screen);
ERR_FAIL_COND_V_MSG(window_id == INVALID_WINDOW_ID, INVALID_WINDOW_ID, "Failed to create sub window."); ERR_FAIL_COND_V_MSG(window_id == INVALID_WINDOW_ID, INVALID_WINDOW_ID, "Failed to create sub window.");
WindowData &wd = windows[window_id]; WindowData &wd = windows[window_id];
@ -865,19 +865,24 @@ void DisplayServerWindows::window_set_current_screen(int p_screen, WindowID p_wi
ERR_FAIL_COND(!windows.has(p_window)); ERR_FAIL_COND(!windows.has(p_window));
ERR_FAIL_INDEX(p_screen, get_screen_count()); ERR_FAIL_INDEX(p_screen, get_screen_count());
if (window_get_current_screen(p_window) == p_screen) {
return;
}
const WindowData &wd = windows[p_window]; const WindowData &wd = windows[p_window];
if (wd.fullscreen) { if (wd.fullscreen) {
int cs = window_get_current_screen(p_window);
if (cs == p_screen) {
return;
}
Point2 pos = screen_get_position(p_screen); Point2 pos = screen_get_position(p_screen);
Size2 size = screen_get_size(p_screen); Size2 size = screen_get_size(p_screen);
MoveWindow(wd.hWnd, pos.x, pos.y, size.width, size.height, TRUE); MoveWindow(wd.hWnd, pos.x, pos.y, size.width, size.height, TRUE);
} else { } else {
Vector2 ofs = window_get_position(p_window) - screen_get_position(window_get_current_screen(p_window)); Rect2i srect = screen_get_usable_rect(p_screen);
window_set_position(ofs + screen_get_position(p_screen), 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);
window_set_position(wpos, p_window);
} }
// Don't let the mouse leave the window when resizing to a smaller resolution. // Don't let the mouse leave the window when resizing to a smaller resolution.
@ -3534,7 +3539,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) { DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, int p_screen) {
DWORD dwExStyle; DWORD dwExStyle;
DWORD dwStyle; DWORD dwStyle;
@ -3548,24 +3553,37 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
WindowRect.bottom = p_rect.position.y + p_rect.size.y; WindowRect.bottom = p_rect.position.y + p_rect.size.y;
if (p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN) { 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));
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 nearest_area = 0;
Rect2i screen_rect; int pos_screen = -1;
for (int i = 0; i < get_screen_count(); i++) { for (int i = 0; i < get_screen_count(); i++) {
Rect2i r; Rect2i r;
r.position = screen_get_position(i); r.position = screen_get_position(i);
r.size = screen_get_size(i); r.size = screen_get_size(i);
Rect2 inters = r.intersection(p_rect); Rect2 inters = r.intersection(p_rect);
int area = inters.size.width * inters.size.height; int area = inters.size.width * inters.size.height;
if (area >= nearest_area) { if (area > nearest_area) {
screen_rect = r; pos_screen = i;
nearest_area = area; nearest_area = area;
} }
} }
WindowRect.left = screen_rect.position.x; Rect2i srect = screen_get_usable_rect(p_screen);
WindowRect.right = screen_rect.position.x + screen_rect.size.x; Point2i wpos = p_rect.position - ((pos_screen >= 0) ? screen_get_position(pos_screen) : Vector2i());
WindowRect.top = screen_rect.position.y; wpos += srect.position;
WindowRect.bottom = screen_rect.position.y + screen_rect.size.y; 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;
} }
AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);
@ -3931,7 +3949,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
window_position = *p_position; window_position = *p_position;
} }
WindowID main_window = _create_window(p_mode, p_vsync_mode, 0, Rect2i(window_position, p_resolution)); WindowID main_window = _create_window(p_mode, p_vsync_mode, 0, Rect2i(window_position, p_resolution), 0);
ERR_FAIL_COND_MSG(main_window == INVALID_WINDOW_ID, "Failed to create main window."); ERR_FAIL_COND_MSG(main_window == INVALID_WINDOW_ID, "Failed to create main window.");
joypad = new JoypadWindows(&windows[MAIN_WINDOW_ID].hWnd); joypad = new JoypadWindows(&windows[MAIN_WINDOW_ID].hWnd);

View File

@ -426,7 +426,7 @@ class DisplayServerWindows : public DisplayServer {
uint64_t time_since_popup = 0; uint64_t time_since_popup = 0;
Ref<Image> icon; Ref<Image> icon;
WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect); WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, int p_screen);
WindowID window_id_counter = MAIN_WINDOW_ID; WindowID window_id_counter = MAIN_WINDOW_ID;
RBMap<WindowID, WindowData> windows; RBMap<WindowID, WindowData> windows;
@ -522,7 +522,7 @@ public:
virtual Vector<DisplayServer::WindowID> get_window_list() const override; 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()) 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 void show_window(WindowID p_window) override; virtual void show_window(WindowID p_window) override;
virtual void delete_sub_window(WindowID p_window) override; virtual void delete_sub_window(WindowID p_window) override;

View File

@ -462,9 +462,8 @@ void Window::_make_window() {
} }
DisplayServer::VSyncMode vsync_mode = DisplayServer::get_singleton()->window_get_vsync_mode(DisplayServer::MAIN_WINDOW_ID); 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)); window_id = DisplayServer::get_singleton()->create_sub_window(DisplayServer::WindowMode(mode), vsync_mode, f, Rect2i(position, size), current_screen);
ERR_FAIL_COND(window_id == DisplayServer::INVALID_WINDOW_ID); ERR_FAIL_COND(window_id == DisplayServer::INVALID_WINDOW_ID);
DisplayServer::get_singleton()->window_set_current_screen(current_screen, window_id);
DisplayServer::get_singleton()->window_set_max_size(Size2i(), window_id); DisplayServer::get_singleton()->window_set_max_size(Size2i(), window_id);
DisplayServer::get_singleton()->window_set_min_size(Size2i(), window_id); DisplayServer::get_singleton()->window_set_min_size(Size2i(), window_id);
String tr_title = atr(title); String tr_title = atr(title);

View File

@ -379,7 +379,7 @@ bool DisplayServer::screen_is_kept_on() const {
return false; return false;
} }
DisplayServer::WindowID DisplayServer::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) { DisplayServer::WindowID DisplayServer::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, int p_screen) {
ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Sub-windows not supported by this display server."); ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Sub-windows not supported by this display server.");
} }

View File

@ -312,7 +312,7 @@ public:
WINDOW_FLAG_EXTEND_TO_TITLE_BIT = (1 << WINDOW_FLAG_EXTEND_TO_TITLE), 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()); 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 void show_window(WindowID p_id); virtual void show_window(WindowID p_id);
virtual void delete_sub_window(WindowID p_id); virtual void delete_sub_window(WindowID p_id);

View File

@ -66,7 +66,7 @@ public:
Vector<DisplayServer::WindowID> get_window_list() const override { return Vector<DisplayServer::WindowID>(); } 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()) override { return 0; } 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; }
void show_window(WindowID p_id) override {} void show_window(WindowID p_id) override {}
void delete_sub_window(WindowID p_id) override {} void delete_sub_window(WindowID p_id) override {}