diff --git a/src/macro-core/macro-dock.cpp b/src/macro-core/macro-dock.cpp index 5e3e2191..c887649b 100644 --- a/src/macro-core/macro-dock.cpp +++ b/src/macro-core/macro-dock.cpp @@ -44,6 +44,9 @@ MacroDock::MacroDock(Macro *m, QWidget *parent) wrapper->setFrameShadow(QFrame::Sunken); wrapper->setLayout(layout); setWidget(wrapper); + + setFloating(true); + hide(); } void MacroDock::SetName(const QString &name) diff --git a/src/macro-core/macro.cpp b/src/macro-core/macro.cpp index f5309f83..e7c382a9 100644 --- a/src/macro-core/macro.cpp +++ b/src/macro-core/macro.cpp @@ -267,6 +267,11 @@ void Macro::SetOnChangeHighlight() _onChangeTriggered = true; } +bool Macro::DockIsVisible() const +{ + return _dock && _dockAction && _dock->isVisible(); +} + void Macro::SetPaused(bool pause) { if (_paused && !pause) { @@ -341,13 +346,7 @@ bool Macro::Save(obs_data_t *obj) const return true; } - obs_data_set_bool(obj, "registerDock", _registerDock); - // The object name is used to restore the position of the dock - if (_registerDock) { - SetDockWidgetName(); - } - obs_data_set_bool(obj, "dockHasRunButton", _dockHasRunButton); - obs_data_set_bool(obj, "dockHasPauseButton", _dockHasPauseButton); + SaveDockSettings(obj); obs_data_set_bool(obj, "registerHotkeys", _registerHotkeys); obs_data_array_t *pauseHotkey = obs_hotkey_save(_pauseHotkey); @@ -438,9 +437,7 @@ bool Macro::Load(obs_data_t *obj) return true; } - _dockHasRunButton = obs_data_get_bool(obj, "dockHasRunButton"); - _dockHasPauseButton = obs_data_get_bool(obj, "dockHasPauseButton"); - EnableDock(obs_data_get_bool(obj, "registerDock")); + LoadDockSettings(obj); obs_data_set_default_bool(obj, "registerHotkeys", true); _registerHotkeys = obs_data_get_bool(obj, "registerHotkeys"); @@ -583,22 +580,103 @@ bool Macro::PauseHotkeysEnabled() return _registerHotkeys; } +void Macro::SaveDockSettings(obs_data_t *obj) const +{ + auto dockSettings = obs_data_create(); + obs_data_set_bool(dockSettings, "register", _registerDock); + // The object name is used to restore the position of the dock + if (_registerDock) { + SetDockWidgetName(); + } + obs_data_set_bool(dockSettings, "hasRunButton", _dockHasRunButton); + obs_data_set_bool(dockSettings, "hasPauseButton", _dockHasPauseButton); + if (_dock) { + auto window = static_cast( + obs_frontend_get_main_window()); + obs_data_set_bool(dockSettings, "isFloating", + _dock->isFloating()); + obs_data_set_bool(dockSettings, "isVisible", DockIsVisible()); + obs_data_set_int(dockSettings, "area", + window->dockWidgetArea(_dock)); + obs_data_set_string( + dockSettings, "geometry", + _dock->saveGeometry().toBase64().constData()); + } + obs_data_set_obj(obj, "dockSettings", dockSettings); + obs_data_release(dockSettings); +} + +void Macro::LoadDockSettings(obs_data_t *obj) +{ + auto dockSettings = obs_data_get_obj(obj, "dockSettings"); + if (!dockSettings) { + // TODO: Remove this fallback + _dockHasRunButton = obs_data_get_bool(obj, "dockHasRunButton"); + _dockHasPauseButton = + obs_data_get_bool(obj, "dockHasPauseButton"); + EnableDock(obs_data_get_bool(obj, "registerDock")); + return; + } + + const bool dockEnabled = obs_data_get_bool(dockSettings, "register"); + _dockIsVisible = obs_data_get_bool(dockSettings, "isVisible"); + if (dockEnabled) { + _dockHasRunButton = + obs_data_get_bool(dockSettings, "hasRunButton"); + _dockHasPauseButton = + obs_data_get_bool(dockSettings, "hasPauseButton"); + _dockIsFloating = obs_data_get_bool(dockSettings, "isFloating"); + _dockArea = static_cast( + obs_data_get_int(dockSettings, "area")); + auto geometryStr = + obs_data_get_string(dockSettings, "geometry"); + if (geometryStr && strlen(geometryStr)) { + _dockGeo = + QByteArray::fromBase64(QByteArray(geometryStr)); + } + } + EnableDock(dockEnabled); + obs_data_release(dockSettings); +} + void Macro::EnableDock(bool value) { if (_registerDock == value) { return; } + // Reset dock regardless RemoveDock(); - if (!_registerDock) { - _dock = new MacroDock(this, - static_cast( - obs_frontend_get_main_window())); - _dockAction = - static_cast(obs_frontend_add_dock(_dock)); - SetDockWidgetName(); + + // Unregister dock + if (_registerDock) { + _dockIsFloating = true; + _dockGeo = QByteArray(); + _registerDock = value; + return; } + // Create new dock widget + auto window = + static_cast(obs_frontend_get_main_window()); + _dock = new MacroDock(this, window); + SetDockWidgetName(); // Used by OBS to restore position + + // Register new dock + _dockAction = static_cast(obs_frontend_add_dock(_dock)); + + // Note that OBSBasic::OBSInit() has precedence over the visibility and + // geometry set here. + // The function calls here are only intended to attempt to restore the + // dock status when switching scene collections. + _dock->setVisible(_dockIsVisible); + if (window->dockWidgetArea(_dock) != _dockArea) { + window->addDockWidget(_dockArea, _dock); + } + if (_dock->isFloating() != _dockIsFloating) { + _dock->setFloating(_dockIsFloating); + } + _dock->restoreGeometry(_dockGeo); _registerDock = value; } diff --git a/src/macro-core/macro.hpp b/src/macro-core/macro.hpp index 5d5276b7..33ec88e5 100644 --- a/src/macro-core/macro.hpp +++ b/src/macro-core/macro.hpp @@ -4,6 +4,7 @@ #include "macro-ref.hpp" #include +#include #include #include #include @@ -96,7 +97,10 @@ private: void RunActions(bool &ret, bool ignorePause); void RunActions(bool ignorePause); void SetOnChangeHighlight(); + bool DockIsVisible() const; void SetDockWidgetName() const; + void SaveDockSettings(obs_data_t *obj) const; + void LoadDockSettings(obs_data_t *obj); void RemoveDock(); std::string _name = ""; @@ -125,6 +129,10 @@ private: bool _registerDock = false; bool _dockHasRunButton = true; bool _dockHasPauseButton = true; + bool _dockIsFloating = true; + bool _dockIsVisible = false; + Qt::DockWidgetArea _dockArea; + QByteArray _dockGeo; MacroDock *_dock = nullptr; QAction *_dockAction = nullptr; diff --git a/src/status-control.cpp b/src/status-control.cpp index d94ffdc2..ccb84f62 100644 --- a/src/status-control.cpp +++ b/src/status-control.cpp @@ -146,6 +146,9 @@ StatusDock::StatusDock(QWidget *parent) : OBSDock(parent) wrapper->setFrameShadow(QFrame::Sunken); wrapper->setLayout(layout); setWidget(wrapper); + + setFloating(true); + hide(); } void SetupDock()