From f2ebd09c07d96e5a6d00f3c9b2d7d8ff868362f5 Mon Sep 17 00:00:00 2001 From: black-sliver <59490463+black-sliver@users.noreply.github.com> Date: Sun, 5 May 2024 19:54:35 +0200 Subject: [PATCH] UI: restore window size when loading pack --- src/core/statemanager.cpp | 30 +++++++++++++ src/core/statemanager.h | 3 ++ src/poptracker.cpp | 90 +++++++++++++++++++++++++++++---------- 3 files changed, 101 insertions(+), 22 deletions(-) diff --git a/src/core/statemanager.cpp b/src/core/statemanager.cpp index a9310b82..1ce61af9 100644 --- a/src/core/statemanager.cpp +++ b/src/core/statemanager.cpp @@ -89,6 +89,7 @@ bool StateManager::saveState(Tracker* tracker, ScriptHost*, return true; } } + bool StateManager::loadState(Tracker* tracker, ScriptHost* scripthost, json& extra_out, bool fromfile, const std::string& name, bool external) { @@ -134,3 +135,32 @@ bool StateManager::loadState(Tracker* tracker, ScriptHost* scripthost, json& ext printf("%s\n", res ? "ok" : "error"); return res; } + +json StateManager::getStateExtra(Tracker* tracker, + bool fromfile, const std::string& name, bool external) +{ + if (!tracker) + return false; + auto pack = tracker->getPack(); + if (!pack) + return false; + + if (!fromfile) { + auto it = _states.find({ pack->getUID(), pack->getVersion(), pack->getVariant(), name }); + if (it != _states.end()) { + return it->second["extra"]; + } + } else { + std::string s; + std::string filename = external ? name : os_pathcat(_dir, + sanitize_dir(pack->getUID()), + sanitize_dir(pack->getVersion()), + sanitize_dir(pack->getVariant()), name+".json"); + if (readFile(filename, s)) { + auto j = parse_jsonc(s); + if (j.is_object()) + return j["extra"]; + } + } + return nullptr; +} diff --git a/src/core/statemanager.h b/src/core/statemanager.h index 6c20337a..bd5c508e 100644 --- a/src/core/statemanager.h +++ b/src/core/statemanager.h @@ -17,6 +17,9 @@ class StateManager { static bool loadState(Tracker* tracker, ScriptHost* scripthost, json& extra_out, bool file=false, const std::string& name="autosave", bool external=false); + static json getStateExtra(Tracker* tracker, + bool file=false, const std::string& name="autosave", + bool external=false); static void setDir(const std::string& dir); private: diff --git a/src/poptracker.cpp b/src/poptracker.cpp index 1a5e11ae..baad3ff7 100644 --- a/src/poptracker.cpp +++ b/src/poptracker.cpp @@ -112,6 +112,28 @@ void PopTracker::global_wrap(lua_State *L, PopTracker* self) lua_rawseti(L, LUA_REGISTRYINDEX, (lua_Integer)globalPopIndex); } +static json windowToJson(Ui::Window* win) +{ + auto pos = win->getPlacementPosition(); + auto size = win->getSize(); + auto disppos = win->getPositionOnDisplay(); + + // detect invalid positioning and size + if (pos.left <= -32768 || pos.left >= 32767 || + pos.top <= -32768 || pos.top >= 32767) + return nullptr; + if (size.width < 1 || size.height < 1) + return nullptr; + + return { + {"pos", {pos.left,pos.top}}, + {"size",{size.width,size.height}}, + {"display", win->getDisplay()}, + {"display_name", win->getDisplayName()}, + {"display_pos", {disppos.left,disppos.top}} + }; +} + PopTracker::PopTracker(int argc, char** argv, bool cli, const json& args) { _args = args; @@ -621,8 +643,15 @@ bool PopTracker::start() } std::string filename; - if (!Dlg::SaveFile("Save State", lastName.c_str(), {{"JSON Files",{"*.json"}}}, filename)) return; - json extra = { { "at_uri", _atUri }, {"at_slot", _atSlot } }; + if (!Dlg::SaveFile("Save State", lastName.c_str(), {{"JSON Files",{"*.json"}}}, filename)) + return; + auto jWindow = windowToJson(_win); + json extra = { + {"at_uri", _atUri}, + {"at_slot", _atSlot} + }; + if (!jWindow.is_null()) + extra["window"] = jWindow; if (StateManager::saveState(_tracker, _scriptHost, _win->getHints(), extra, true, filename, true)) { _exportFile = filename; // this is local encoding for fopen @@ -839,16 +868,7 @@ bool PopTracker::frame() if (!res) { // application is going to exit - auto pos = _win->getPlacementPosition(); - auto size = _win->getSize(); - auto disppos = _win->getPositionOnDisplay(); - - // detect invalid positioning and size - if (pos.left <= -32768 || pos.left >= 32767 || - pos.top <= -32768 || pos.top >= 32767) - pos = Ui::Position::UNDEFINED; - if (size.width < 1 || size.height < 1) - size = Ui::Size::UNDEFINED; + auto jWindow = windowToJson(_win); // save to config _config["format_version"] = 1; @@ -859,14 +879,8 @@ bool PopTracker::frame() {"uid",_pack->getUID()}, {"version",_pack->getVersion()} }; - if (pos != Ui::Position::UNDEFINED && size != Ui::Size::UNDEFINED) - _config["window"] = { - {"pos", {pos.left,pos.top}}, - {"size",{size.width,size.height}}, - {"display", _win->getDisplay()}, - {"display_name", _win->getDisplayName()}, - {"display_pos", {disppos.left,disppos.top}} - }; + if (!jWindow.is_null()) + _config["window"] = jWindow; else _config.erase("window"); _config["export_file"] = pathToUTF8(_exportFile); @@ -897,7 +911,13 @@ bool PopTracker::frame() if (res && _tracker && AUTOSAVE_INTERVAL>0 && std::chrono::duration_cast(now - _autosaveTimer).count() >= AUTOSAVE_INTERVAL) { - json extra = { { "at_uri", _atUri }, {"at_slot", _atSlot } }; + auto jWindow = windowToJson(_win); + json extra = { + {"at_uri", _atUri}, + {"at_slot", _atSlot} + }; + if (!jWindow.is_null()) + extra["window"] = jWindow; StateManager::saveState(_tracker, _scriptHost, _win->getHints(), extra, true); _autosaveTimer = std::chrono::steady_clock::now(); } @@ -998,7 +1018,13 @@ const std::string& PopTracker::getPackInstallDir() const void PopTracker::unloadTracker() { if (_tracker) { - json extra = { { "at_uri", _atUri }, {"at_slot", _atSlot } }; + auto jWindow = windowToJson(_win); + json extra = { + {"at_uri", _atUri}, + {"at_slot", _atSlot} + }; + if (!jWindow.is_null()) + extra["window"] = jWindow; StateManager::saveState(_tracker, _scriptHost, _win->getHints(), extra, true); } @@ -1198,6 +1224,26 @@ bool PopTracker::loadTracker(const std::string& pack, const std::string& variant json_to_lua(_L, _debugFlags); lua_setglobal(_L, "DEBUG"); + if (loadAutosave) { + // restore window size before loading any layout + json extra = StateManager::getStateExtra(_tracker, true); + if (extra.is_object()) { + auto& jWindow = extra["window"]; + if (jWindow.is_object()) { + auto& jSize = jWindow["size"]; + if (jSize.is_array() && jSize[0].is_number_integer() && jSize[1].is_number_integer()) { + printf("Restoring window size %dx%d\n", jSize[0].get(), jSize[1].get()); + Ui::Size size = {std::max(96, jSize[0].get()), + std::max(96, jSize[1].get())}; + _win->setMinSize(size); + _win->resize(size); + // when making the window bigger, make sure it doesn't display garbage + _ui->render(); + } + } + } + } + printf("Updating UI\n"); _win->setTracker(_tracker); if (auto at = _scriptHost->getAutoTracker()) {