Improve window_set_current_screen and fix secondary window initial mode and positions.

This commit is contained in:
bruvzg 2022-12-08 20:34:15 +02:00
parent a754930918
commit f7955633de
No known key found for this signature in database
GPG key ID: 7960FCF39844EC38
13 changed files with 189 additions and 89 deletions

View file

@ -99,6 +99,8 @@ public:
Callable drop_files_callback;
ObjectID instance_id;
bool fs_transition = false;
bool initial_size = true;
WindowID transient_parent = INVALID_WINDOW_ID;
bool exclusive = false;
@ -189,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);
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 _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 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 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;
}
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;
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");
[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,
// Godot passes a positive value.
position.y *= -1;
position += _get_screens_origin();
wpos.y *= -1;
wpos += _get_screens_origin();
// initWithContentRect uses bottom-left corner of the windows frame as origin.
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
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];
@ -2208,10 +2225,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) {
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_
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++) {
if (p_flags & (1 << i)) {
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;
}
Rect2i srect = screen_get_usable_rect(p_screen);
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) {
// Re-enter fullscreen mode.
@ -3781,7 +3804,7 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM
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);
for (int i = 0; i < WINDOW_FLAG_MAX; i++) {
if (p_flags & (1 << i)) {

View file

@ -65,16 +65,28 @@
if (ds && ds->has_window(window_id)) {
DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
NSRect frameRect = [wd.window_object frame];
bool left = (wd.last_frame_rect.origin.x != frameRect.origin.x);
bool top = (wd.last_frame_rect.origin.y == frameRect.origin.y);
if (left && top) {
self.layerContentsPlacement = NSViewLayerContentsPlacementBottomRight;
} else if (left && !top) {
self.layerContentsPlacement = NSViewLayerContentsPlacementTopRight;
} else if (!left && top) {
self.layerContentsPlacement = NSViewLayerContentsPlacementBottomLeft;
if (wd.fs_transition || wd.initial_size) {
self.layerContentsPlacement = NSViewLayerContentsPlacementScaleAxesIndependently;
wd.initial_size = false;
} 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;
}

View file

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

View file

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