From d857eaa2b13a97ce31a8bf8b1383ec9c595c984e Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sat, 2 May 2020 16:46:37 +0200 Subject: [PATCH] Make windows positioning independent for launcher, emulator and debugger (resolves #615) --- docs/index.html | 30 ++++++++++++++ src/common/FrameBufferSDL2.cxx | 72 ++++++++++++++++------------------ src/common/FrameBufferSDL2.hxx | 22 ++++++++--- src/debugger/Debugger.cxx | 3 +- src/emucore/Console.cxx | 4 +- src/emucore/FrameBuffer.cxx | 58 ++++++++++++++++++++++++++- src/emucore/FrameBuffer.hxx | 42 ++++++++++++++++---- src/emucore/OSystem.cxx | 3 +- src/emucore/Settings.cxx | 14 +++++-- src/gui/Launcher.cxx | 3 +- 10 files changed, 190 insertions(+), 61 deletions(-) diff --git a/docs/index.html b/docs/index.html index c845b487f..dc6246702 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1999,6 +1999,16 @@ Centers game window (if possible). + +
-windowedpos <WxH>
+ Sets the window position in windowed emulator mode. + + + +
-display <number>
+ Sets the display for Stella's emulator. + +
-palette <standard|z26|user>
Set the palette to either normal Stella, the one used in the z26 @@ -2376,6 +2386,16 @@ launcher only happens when started with the launcher). + +
-launcherpos <WxH>
+ Sets the window position in windowed ROM launcher mode. + + + +
-launcherdisplay <number>
+ Sets the display for the ROM launcher. + +
-launcherres <WxH>
Set the size of the ROM launcher. @@ -2522,6 +2542,16 @@ Relocate calls out of address range in the disassembler. + +
-dbg.pos <WxH>
+ Sets the window position in windowed debugger mode. + + + +
-dbg.display <number>
+ Sets the display for the debugger. + +
-dbg.res <WxH>
Set the size of the debugger window. diff --git a/src/common/FrameBufferSDL2.cxx b/src/common/FrameBufferSDL2.cxx index bce5c2e7c..4d013a35d 100644 --- a/src/common/FrameBufferSDL2.cxx +++ b/src/common/FrameBufferSDL2.cxx @@ -48,8 +48,6 @@ FrameBufferSDL2::FrameBufferSDL2(OSystem& osystem) // since the structure may be needed before any FBSurface's have // been created myPixelFormat = SDL_AllocFormat(SDL_PIXELFORMAT_ARGB8888); - - myWindowedPos = myOSystem.settings().getPoint("windowedpos"); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -183,27 +181,34 @@ void FrameBufferSDL2::queryHardware(vector& fullscreenRes, } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Int32 FrameBufferSDL2::getCurrentDisplayIndex() +bool FrameBufferSDL2::isCurrentWindowPositioned() const +{ + ASSERT_MAIN_THREAD; + + return !myCenter + && myWindow && !(SDL_GetWindowFlags(myWindow) & SDL_WINDOW_FULLSCREEN_DESKTOP); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Common::Point FrameBufferSDL2::getCurrentWindowPos() const +{ + ASSERT_MAIN_THREAD; + + Common::Point pos; + + SDL_GetWindowPosition(myWindow, &pos.x, &pos.y); + + return pos; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Int32 FrameBufferSDL2::getCurrentDisplayIndex() const { ASSERT_MAIN_THREAD; return SDL_GetWindowDisplayIndex(myWindow); } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void FrameBufferSDL2::updateWindowedPos() -{ - ASSERT_MAIN_THREAD; - - // only save if the window is not centered and not in full screen mode - if (!myCenter && myWindow && !(SDL_GetWindowFlags(myWindow) & SDL_WINDOW_FULLSCREEN_DESKTOP)) - { - // save current windowed position - SDL_GetWindowPosition(myWindow, &myWindowedPos.x, &myWindowedPos.y); - myOSystem.settings().setValue("windowedpos", myWindowedPos); - } -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode) { @@ -213,24 +218,13 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode) if(SDL_WasInit(SDL_INIT_VIDEO) == 0) return false; - Int32 displayIndex = mode.fsIndex; - if (displayIndex == -1) - { - // windowed mode - if (myWindow) - { - // Show it on same screen as the previous window - displayIndex = SDL_GetWindowDisplayIndex(myWindow); - } - if (displayIndex < 0) - { - // fallback to the last used screen if still existing - displayIndex = std::min(myNumDisplays, myOSystem.settings().getInt("display")); - } - } + // TODO: On multiple displays, switching from centered mode, does not respect + // current window's display (which many not be centered anymore) - // save and get last windowed window's position - updateWindowedPos(); + // Get windowed window's last display + Int32 displayIndex = std::min(myNumDisplays, myOSystem.settings().getInt(getDisplayKey())); + // Get windowed window's last position + myWindowedPos = myOSystem.settings().getPoint(getPositionKey()); // Always recreate renderer (some systems need this) if(myRenderer) @@ -249,7 +243,7 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode) posX = myWindowedPos.x; posY = myWindowedPos.y; - // make sure the window is at least partially visibile + // Make sure the window is at least partially visibile int x0 = 0, y0 = 0, x1 = 0, y1 = 0; for (int display = SDL_GetNumVideoDisplays() - 1; display >= 0; display--) @@ -276,13 +270,15 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode) // toggling fullscreen windowed mode // So we have a special case for macOS #ifndef BSPF_MACOS - // Don't re-create the window if its size hasn't changed, as it's not - // necessary, and causes flashing in fullscreen mode + // Don't re-create the window if its display and size hasn't changed, + // as it's not necessary, and causes flashing in fullscreen mode if(myWindow) { + int d = SDL_GetWindowDisplayIndex(myWindow); int w, h; + SDL_GetWindowSize(myWindow, &w, &h); - if(uInt32(w) != mode.screen.w || uInt32(h) != mode.screen.h) + if(d != displayIndex || uInt32(w) != mode.screen.w || uInt32(h) != mode.screen.h) { SDL_DestroyWindow(myWindow); myWindow = nullptr; diff --git a/src/common/FrameBufferSDL2.hxx b/src/common/FrameBufferSDL2.hxx index 857891685..d2825037c 100644 --- a/src/common/FrameBufferSDL2.hxx +++ b/src/common/FrameBufferSDL2.hxx @@ -95,6 +95,21 @@ class FrameBufferSDL2 : public FrameBuffer */ void readPixels(uInt8* buffer, uInt32 pitch, const Common::Rect& rect) const override; + /** + This method is called to query if the current window is not centered + or fullscreen. + + @return True, if the current window is positioned + */ + bool isCurrentWindowPositioned() const override; + + /** + This method is called to query the video hardware for position of + the current window + + @return The position of the currently displayed window + */ + Common::Point getCurrentWindowPos() const override; /** This method is called to query the video hardware for the index of the display the current window is displayed on @@ -102,12 +117,7 @@ class FrameBufferSDL2 : public FrameBuffer @return the current display index or a negative value if no window is displayed */ - Int32 getCurrentDisplayIndex() override; - - /** - This method is called to preserve the last current windowed position. - */ - void updateWindowedPos() override; + Int32 getCurrentDisplayIndex() const override; /** Clear the frame buffer. diff --git a/src/debugger/Debugger.cxx b/src/debugger/Debugger.cxx index a96f208ec..6f5078228 100644 --- a/src/debugger/Debugger.cxx +++ b/src/debugger/Debugger.cxx @@ -115,7 +115,8 @@ void Debugger::initialize() FBInitStatus Debugger::initializeVideo() { string title = string("Stella ") + STELLA_VERSION + ": Debugger mode"; - return myOSystem.frameBuffer().createDisplay(title, myWidth, myHeight); + return myOSystem.frameBuffer().createDisplay(title, FrameBuffer::BufferType::Debugger, + myWidth, myHeight); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/Console.cxx b/src/emucore/Console.cxx index fc5c1e9be..3fe69b147 100644 --- a/src/emucore/Console.cxx +++ b/src/emucore/Console.cxx @@ -574,7 +574,7 @@ void Console::toggleTurbo() initializeAudio(); // update VSync - myOSystem.createFrameBuffer(); + initializeVideo(); ostringstream ss; ss << "Turbo mode " << (!enabled ? "enabled" : "disabled"); @@ -651,7 +651,7 @@ FBInitStatus Console::initializeVideo(bool full) bool devSettings = myOSystem.settings().getBool("dev.settings"); const string& title = string("Stella ") + STELLA_VERSION + ": \"" + myProperties.get(PropType::Cart_Name) + "\""; - fbstatus = myOSystem.frameBuffer().createDisplay(title, + fbstatus = myOSystem.frameBuffer().createDisplay(title, FrameBuffer::BufferType::Emulator, TIAConstants::viewableWidth, TIAConstants::viewableHeight, false); if(fbstatus != FBInitStatus::Success) return fbstatus; diff --git a/src/emucore/FrameBuffer.cxx b/src/emucore/FrameBuffer.cxx index eb35cfe5c..250a895cf 100644 --- a/src/emucore/FrameBuffer.cxx +++ b/src/emucore/FrameBuffer.cxx @@ -203,10 +203,14 @@ FontDesc FrameBuffer::getFontDesc(const string& name) const #endif // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -FBInitStatus FrameBuffer::createDisplay(const string& title, +FBInitStatus FrameBuffer::createDisplay(const string& title, BufferType type, uInt32 width, uInt32 height, bool honourHiDPI) { + // always save, maybe only the mode of the window has changed + saveCurrentWindowPosition(); + myBufferType = type; + ++myInitializedCount; myScreenTitle = title; @@ -789,6 +793,58 @@ void FrameBuffer::stateChanged(EventHandlerState state) update(true); // force full update } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string FrameBuffer::getDisplayKey() +{ + // save current window's display and position + switch(myBufferType) + { + case BufferType::Launcher: + return "launcherdisplay"; + + case BufferType::Emulator: + return "display"; + + #ifdef DEBUGGER_SUPPORT + case BufferType::Debugger: + return "dbg.display"; + #endif + + default: + return ""; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string FrameBuffer::getPositionKey() +{ + // save current window's display and position + switch(myBufferType) + { + case BufferType::Launcher: + return "launcherpos"; + + case BufferType::Emulator: + return "windowedpos"; + + #ifdef DEBUGGER_SUPPORT + case BufferType::Debugger: + return "dbg.pos"; + #endif + + default: + return ""; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FrameBuffer::saveCurrentWindowPosition() +{ + myOSystem.settings().setValue(getDisplayKey(), getCurrentDisplayIndex()); + if(isCurrentWindowPositioned()) + myOSystem.settings().setValue(getPositionKey(), getCurrentWindowPos()); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FrameBuffer::setFullscreen(bool enable) { diff --git a/src/emucore/FrameBuffer.hxx b/src/emucore/FrameBuffer.hxx index 35c656cf0..a73b01ffb 100644 --- a/src/emucore/FrameBuffer.hxx +++ b/src/emucore/FrameBuffer.hxx @@ -81,6 +81,13 @@ class FrameBuffer } }; + enum class BufferType { + None, + Launcher, + Emulator, + Debugger + }; + enum class ScalingInterpolation { none, sharp, @@ -115,7 +122,8 @@ class FrameBuffer @return Status of initialization (see FBInitStatus 'enum') */ - FBInitStatus createDisplay(const string& title, uInt32 width, uInt32 height, + FBInitStatus createDisplay(const string& title, BufferType type, + uInt32 width, uInt32 height, bool honourHiDPI = true); /** @@ -299,6 +307,13 @@ class FrameBuffer bool hidpiEnabled() const { return myHiDPIEnabled; } uInt32 hidpiScaleFactor() const { return myHiDPIEnabled ? 2 : 1; } + /** + These methods are used to load/save position and display of the current window. + */ + string getPositionKey(); + string getDisplayKey(); + void saveCurrentWindowPosition(); + #ifdef GUI_SUPPORT /** Get the font object(s) of the framebuffer @@ -371,6 +386,21 @@ class FrameBuffer */ virtual void readPixels(uInt8* buffer, uInt32 pitch, const Common::Rect& rect) const = 0; + /** + This method is called to query if the current window is not centered or fullscreen. + + @return True, if the current window is positioned + */ + virtual bool isCurrentWindowPositioned() const = 0; + + /** + This method is called to query the video hardware for position of + the current window + + @return The position of the currently displayed window + */ + virtual Common::Point getCurrentWindowPos() const = 0; + /** This method is called to query the video hardware for the index of the display the current window is displayed on @@ -378,12 +408,7 @@ class FrameBuffer @return the current display index or a negative value if no window is displayed */ - virtual Int32 getCurrentDisplayIndex() = 0; - - /** - This method is called to preserve the last current windowed position. - */ - virtual void updateWindowedPos() = 0; + virtual Int32 getCurrentDisplayIndex() const = 0; /** Clear the framebuffer. @@ -554,6 +579,9 @@ class FrameBuffer // Title of the main window/screen string myScreenTitle; + // Type of the frame buffer + BufferType myBufferType{BufferType::None}; + // Number of displays int myNumDisplays{1}; diff --git a/src/emucore/OSystem.cxx b/src/emucore/OSystem.cxx index bbaa72aa5..ccf6838cb 100644 --- a/src/emucore/OSystem.cxx +++ b/src/emucore/OSystem.cxx @@ -239,8 +239,7 @@ void OSystem::saveConfig() if(myFrameBuffer) { // Save the last windowed position and display on system shutdown - myFrameBuffer->updateWindowedPos(); - settings().setValue("display", myFrameBuffer->getCurrentDisplayIndex()); + myFrameBuffer->saveCurrentWindowPosition(); Logger::debug("Saving TV effects options ..."); myFrameBuffer->tiaSurface().ntsc().saveConfig(settings()); diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx index 599c8badf..b0e5cd7a6 100644 --- a/src/emucore/Settings.cxx +++ b/src/emucore/Settings.cxx @@ -126,6 +126,8 @@ Settings::Settings() // ROM browser options setPermanent("exitlauncher", "false"); setPermanent("followlauncher", "false"); + setPermanent("launcherpos", Common::Point(50, 50)); + setPermanent("launcherdisplay", 0); setPermanent("launcherres", Common::Size(900, 600)); setPermanent("launcherfont", "medium"); setPermanent("launcherroms", "true"); @@ -137,6 +139,8 @@ Settings::Settings() setPermanent("dbg.res", Common::Size(DebuggerDialog::kMediumFontMinW, DebuggerDialog::kMediumFontMinH)); + setPermanent("dbg.pos", Common::Point(50, 50)); + setPermanent("dbg.display", 0); #endif setPermanent("uipalette", "standard"); setPermanent("hidpi", "false"); @@ -396,8 +400,8 @@ void Settings::usage() const << " -vsync <1|0> Enable 'synchronize to vertical blank interrupt'\n" << " -fullscreen <1|0> Enable fullscreen mode\n" << " -center <1|0> Centers game window in windowed modes\n" - << " -windowedpos Sets the window position in windowed modes\n" - << " -display Sets the display for Stella\n" + << " -windowedpos Sets the window position in windowed emulator mode\n" + << " -display Sets the display for Stella's emulator\n" << " -palette \n" @@ -493,8 +497,10 @@ void Settings::usage() const << " -rominfo Display detailed information for the given ROM\n" << " -listrominfo Display contents of stella.pro, one line per ROM\n" << " entry\n" - << endl + << endl << " -exitlauncher <1|0> On exiting a ROM, go back to the ROM launcher\n" + << " -launcherpos Sets the window position in windowed EOM launcher mode\n" + << " -launcherdisplay Sets the display for the ROM launcher\n" << " -launcherres The resolution to use in ROM launcher mode\n" << " -launcherfont Relocate calls out of address range in\n" << " disassembler\n" << endl + << " -dbg.pos Sets the window position in windowed debugger mode\n" + << " -dbg.display Sets the display for the debugger\n" << " -dbg.res The resolution to use in debugger mode\n" << " -dbg.fontsize \n" diff --git a/src/gui/Launcher.cxx b/src/gui/Launcher.cxx index 379d9841e..315a14f41 100644 --- a/src/gui/Launcher.cxx +++ b/src/gui/Launcher.cxx @@ -59,7 +59,8 @@ Launcher::~Launcher() FBInitStatus Launcher::initializeVideo() { string title = string("Stella ") + STELLA_VERSION; - return myOSystem.frameBuffer().createDisplay(title, myWidth, myHeight); + return myOSystem.frameBuffer().createDisplay(title, FrameBuffer::BufferType::Launcher, + myWidth, myHeight); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -