From 4ce53cb85113956be318c12801d5663a26e3fef9 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sun, 3 Jan 2021 15:23:08 +0100 Subject: Fix: [OSX] Quitting in fullscreen mode would loose the original window size. This replicates the behaviour on e.g. Windows, which saves the original window size. --- src/video/cocoa/cocoa_v.h | 20 +++++++++++++---- src/video/cocoa/cocoa_v.mm | 53 +++++++++++++++++++++++++------------------- src/video/cocoa/cocoa_wnd.mm | 2 +- src/video/cocoa/event.mm | 18 +++++++++++---- 4 files changed, 61 insertions(+), 32 deletions(-) diff --git a/src/video/cocoa/cocoa_v.h b/src/video/cocoa/cocoa_v.h index 52d26c847..f3e484b01 100644 --- a/src/video/cocoa/cocoa_v.h +++ b/src/video/cocoa/cocoa_v.h @@ -11,10 +11,16 @@ #define VIDEO_COCOA_H #include "../video_driver.hpp" +#include "../../core/geometry_type.hpp" + extern bool _cocoa_video_started; class VideoDriver_Cocoa : public VideoDriver { +private: + bool fullscreen_on_mainloop; ///< Switch to fullscreen once the main loop is running? + Dimension orig_res; ///< Saved window size for non-fullscreen mode. + public: const char *Start(const StringList ¶m) override; @@ -59,6 +65,16 @@ public: * @return driver name */ const char *GetName() const override { return "cocoa"; } + + /* --- The following methods should be private, but can't be due to Obj-C limitations. --- */ + + /** Main game loop. */ + void GameLoop(); // In event.mm. + +private: + friend class WindowQuartzSubdriver; + + void GameSizeChanged(); }; class FVideoDriver_Cocoa : public DriverFactoryBase { @@ -190,10 +206,6 @@ extern CocoaSubdriver *_cocoa_subdriver; CocoaSubdriver *QZ_CreateWindowQuartzSubdriver(int width, int height, int bpp); -void QZ_GameSizeChanged(); - -void QZ_GameLoop(); - uint QZ_ListModes(OTTD_Point *modes, uint max_modes, CGDirectDisplayID display_id, int display_depth); #endif /* VIDEO_COCOA_H */ diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index 0f3c4c32c..c7c5a308e 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -143,25 +143,6 @@ static void QZ_UpdateVideoModes() } } -/** - * Handle a change of the display area. - */ -void QZ_GameSizeChanged() -{ - if (_cocoa_subdriver == NULL) return; - - /* Tell the game that the resolution has changed */ - _screen.width = _cocoa_subdriver->GetWidth(); - _screen.height = _cocoa_subdriver->GetHeight(); - _screen.pitch = _cocoa_subdriver->GetWidth(); - _screen.dst_ptr = _cocoa_subdriver->GetPixelBuffer(); - _fullscreen = _cocoa_subdriver->IsFullscreen(); - - BlitterFactory::GetCurrentBlitter()->PostResize(); - - GameSizeChanged(); -} - /** * Find a suitable cocoa subdriver. * @@ -175,7 +156,6 @@ void QZ_GameSizeChanged() static CocoaSubdriver *QZ_CreateSubdriver(int width, int height, int bpp, bool fullscreen, bool fallback) { CocoaSubdriver *ret = QZ_CreateWindowQuartzSubdriver(width, height, bpp); - if (ret != nullptr && fullscreen) ret->ToggleFullscreen(fullscreen); if (ret != nullptr) return ret; if (!fallback) return nullptr; @@ -219,6 +199,7 @@ const char *VideoDriver_Cocoa::Start(const StringList &parm) /* Don't create a window or enter fullscreen if we're just going to show a dialog. */ if (!CocoaSetupApplication()) return NULL; + this->orig_res = _cur_resolution; int width = _cur_resolution.width; int height = _cur_resolution.height; int bpp = BlitterFactory::GetCurrentBlitter()->GetScreenDepth(); @@ -228,13 +209,16 @@ const char *VideoDriver_Cocoa::Start(const StringList &parm) return "The cocoa quartz subdriver only supports 8 and 32 bpp."; } + /* Defer fullscreen toggle until the main loop is running, + * as otherwise a grey bar will be stuck on top of the window. */ + this->fullscreen_on_mainloop = _fullscreen; _cocoa_subdriver = QZ_CreateSubdriver(width, height, bpp, _fullscreen, true); if (_cocoa_subdriver == NULL) { Stop(); return "Could not create subdriver"; } - QZ_GameSizeChanged(); + this->GameSizeChanged(); QZ_UpdateVideoModes(); return NULL; @@ -281,7 +265,7 @@ bool VideoDriver_Cocoa::ChangeResolution(int w, int h) bool ret = _cocoa_subdriver->ChangeResolution(w, h, BlitterFactory::GetCurrentBlitter()->GetScreenDepth()); - QZ_GameSizeChanged(); + this->GameSizeChanged(); QZ_UpdateVideoModes(); return ret; @@ -320,6 +304,29 @@ void VideoDriver_Cocoa::EditBoxLostFocus() HandleTextInput(NULL, true); } +/** + * Handle a change of the display area. + */ +void VideoDriver_Cocoa::GameSizeChanged() +{ + if (_cocoa_subdriver == nullptr) return; + + /* Tell the game that the resolution has changed */ + _screen.width = _cocoa_subdriver->GetWidth(); + _screen.height = _cocoa_subdriver->GetHeight(); + _screen.pitch = _cocoa_subdriver->GetWidth(); + _screen.dst_ptr = _cocoa_subdriver->GetPixelBuffer(); + + /* Store old window size if we entered fullscreen mode. */ + bool fullscreen = _cocoa_subdriver->IsFullscreen(); + if (fullscreen && !_fullscreen) this->orig_res = _cur_resolution; + _fullscreen = fullscreen; + + BlitterFactory::GetCurrentBlitter()->PostResize(); + + ::GameSizeChanged(); +} + class WindowQuartzSubdriver; /* Subclass of OTTD_CocoaView to fix Quartz rendering */ @@ -825,7 +832,7 @@ bool WindowQuartzSubdriver::WindowResized() } } - QZ_GameSizeChanged(); + static_cast(VideoDriver::GetInstance())->GameSizeChanged(); /* Redraw screen */ this->num_dirty_rects = MAX_DIRTY_RECTS; diff --git a/src/video/cocoa/cocoa_wnd.mm b/src/video/cocoa/cocoa_wnd.mm index a2854adaf..8c16dd1ef 100644 --- a/src/video/cocoa/cocoa_wnd.mm +++ b/src/video/cocoa/cocoa_wnd.mm @@ -73,7 +73,7 @@ static OTTDMain *_ottd_main; [ _cocoa_subdriver->cocoaview resetCursorRects ]; /* Hand off to main application code. */ - QZ_GameLoop(); + static_cast(VideoDriver::GetInstance())->GameLoop(); /* We are done, thank you for playing. */ [ self performSelectorOnMainThread:@selector(stopEngine) withObject:nil waitUntilDone:FALSE ]; diff --git a/src/video/cocoa/event.mm b/src/video/cocoa/event.mm index cb3c753ac..642149858 100644 --- a/src/video/cocoa/event.mm +++ b/src/video/cocoa/event.mm @@ -617,7 +617,7 @@ static bool QZ_PollEvent() } -void QZ_GameLoop() +void VideoDriver_Cocoa::GameLoop() { uint32 cur_ticks = GetTick(); uint32 last_cur_ticks = cur_ticks; @@ -633,7 +633,7 @@ void QZ_GameLoop() _cocoa_subdriver->Draw(true); CSleep(1); - for (int i = 0; i < 2; i++) GameLoop(); + for (int i = 0; i < 2; i++) ::GameLoop(); UpdateWindows(); QZ_CheckPaletteAnim(); @@ -652,7 +652,17 @@ void QZ_GameLoop() while (QZ_PollEvent()) {} - if (_exit_game) break; + /* If we do that right after window creation, a grey bar will be left at the top. */ + if (this->fullscreen_on_mainloop) { + this->fullscreen_on_mainloop = false; + _cocoa_subdriver->ToggleFullscreen(true); + } + + if (_exit_game) { + /* Restore saved resolution if in fullscreen mode. */ + if (_cocoa_subdriver->IsFullscreen()) _cur_resolution = this->orig_res; + break; + } #if defined(_DEBUG) if (_current_mods & NSShiftKeyMask) @@ -678,7 +688,7 @@ void QZ_GameLoop() if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged(); - GameLoop(); + ::GameLoop(); UpdateWindows(); QZ_CheckPaletteAnim(); -- cgit v1.2.3-54-g00ecf