Skip to content

Commit

Permalink
Fix: [OSX] Quitting in fullscreen mode would loose the original windo…
Browse files Browse the repository at this point in the history
…w size.

This replicates the behaviour on e.g. Windows, which saves the original window size.
  • Loading branch information
michicc committed Jan 3, 2021
1 parent 6f352c2 commit b8fe942
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 32 deletions.
20 changes: 16 additions & 4 deletions src/video/cocoa/cocoa_v.h
Expand Up @@ -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 &param) override;

Expand Down Expand Up @@ -59,6 +65,16 @@ class VideoDriver_Cocoa : public VideoDriver {
* @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 {
Expand Down Expand Up @@ -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 */
53 changes: 30 additions & 23 deletions src/video/cocoa/cocoa_v.mm
Expand Up @@ -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.
*
Expand All @@ -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;
Expand Down Expand Up @@ -219,6 +199,7 @@ void QZ_GameSizeChanged()
/* 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();
Expand All @@ -228,13 +209,16 @@ void QZ_GameSizeChanged()
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;
Expand Down Expand Up @@ -281,7 +265,7 @@ void QZ_GameSizeChanged()

bool ret = _cocoa_subdriver->ChangeResolution(w, h, BlitterFactory::GetCurrentBlitter()->GetScreenDepth());

QZ_GameSizeChanged();
this->GameSizeChanged();
QZ_UpdateVideoModes();

return ret;
Expand Down Expand Up @@ -320,6 +304,29 @@ void QZ_GameSizeChanged()
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 */
Expand Down Expand Up @@ -834,7 +841,7 @@ static void ClearWindowBuffer(uint32 *buffer, uint32 pitch, uint32 height)
}
}

QZ_GameSizeChanged();
static_cast<VideoDriver_Cocoa *>(VideoDriver::GetInstance())->GameSizeChanged();

/* Redraw screen */
this->num_dirty_rects = MAX_DIRTY_RECTS;
Expand Down
2 changes: 1 addition & 1 deletion src/video/cocoa/cocoa_wnd.mm
Expand Up @@ -73,7 +73,7 @@ - (void)launchGameEngine: (NSNotification*) note
[ _cocoa_subdriver->cocoaview resetCursorRects ];

/* Hand off to main application code. */
QZ_GameLoop();
static_cast<VideoDriver_Cocoa *>(VideoDriver::GetInstance())->GameLoop();

/* We are done, thank you for playing. */
[ self performSelectorOnMainThread:@selector(stopEngine) withObject:nil waitUntilDone:FALSE ];
Expand Down
18 changes: 14 additions & 4 deletions src/video/cocoa/event.mm
Expand Up @@ -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;
Expand All @@ -628,12 +628,18 @@ void QZ_GameLoop()
uint32 st = 0;
#endif

/* 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);
}

DisplaySplashImage();
QZ_CheckPaletteAnim();
_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();
Expand All @@ -652,7 +658,11 @@ void QZ_GameLoop()

while (QZ_PollEvent()) {}

if (_exit_game) break;
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)
Expand All @@ -678,7 +688,7 @@ void QZ_GameLoop()

if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged();

GameLoop();
::GameLoop();

UpdateWindows();
QZ_CheckPaletteAnim();
Expand Down

0 comments on commit b8fe942

Please sign in to comment.