diff --git a/OpenRGB.pro b/OpenRGB.pro index 3aa398cd..e2004c87 100644 --- a/OpenRGB.pro +++ b/OpenRGB.pro @@ -122,7 +122,8 @@ INCLUDEPATH += AutoStart/ \ KeyboardLayoutManager/ \ RGBController/ \ - qt/ + qt/ \ + SuspendResume/ HEADERS += \ $$GUI_H \ @@ -156,6 +157,7 @@ HEADERS += serial_port/serial_port.h \ StringUtils.h \ super_io/super_io.h \ + SuspendResume/SuspendResume.h \ AutoStart/AutoStart.h \ KeyboardLayoutManager/KeyboardLayoutManager.h \ RGBController/RGBController.h \ @@ -388,6 +390,7 @@ win32:SOURCES += i2c_smbus/i2c_smbus_piix4.cpp \ scsiapi/scsiapi_windows.c \ serial_port/find_usb_serial_port_win.cpp \ + SuspendResume/SuspendResume_Windows.cpp \ wmi/wmi.cpp \ AutoStart/AutoStart-Windows.cpp \ @@ -405,6 +408,7 @@ win32:HEADERS += i2c_smbus/i2c_smbus_piix4.h \ wmi/wmi.h \ AutoStart/AutoStart-Windows.h \ + SuspendResume/SuspendResume_Windows.h \ win32:contains(QMAKE_TARGET.arch, x86_64) { LIBS += \ @@ -499,6 +503,7 @@ contains(QMAKE_PLATFORM, linux) { dependencies/NVFC/nvapi.h \ i2c_smbus/i2c_smbus_linux.h \ AutoStart/AutoStart-Linux.h \ + SuspendResume/SuspendResume_Linux_FreeBSD.h \ INCLUDEPATH += \ dependencies/NVFC \ @@ -516,6 +521,8 @@ contains(QMAKE_PLATFORM, linux) { LIBS += -lstdc++fs } + QT += dbus + QMAKE_CXXFLAGS += -Wno-implicit-fallthrough -Wno-psabi #-------------------------------------------------------------------------------------------# @@ -550,6 +557,7 @@ contains(QMAKE_PLATFORM, linux) { scsiapi/scsiapi_linux.c \ serial_port/find_usb_serial_port_linux.cpp \ AutoStart/AutoStart-Linux.cpp \ + SuspendResume/SuspendResume_Linux_FreeBSD.cpp \ #-------------------------------------------------------------------------------------------# # Set up install paths # @@ -622,6 +630,7 @@ contains(QMAKE_PLATFORM, freebsd) { HEADERS += \ AutoStart/AutoStart-FreeBSD.h \ + SuspendResume/SuspendResume_Linux_FreeBSD.h \ HEADERS -= \ Controllers/SeagateController/RGBController_Seagate.h \ @@ -639,6 +648,8 @@ contains(QMAKE_PLATFORM, freebsd) { LIBS += -lstdc++fs } + QT += dbus + #-------------------------------------------------------------------------------------------# # Determine which hidapi to use based on availability # # Prefer hidraw backend, then libusb # @@ -667,6 +678,7 @@ contains(QMAKE_PLATFORM, freebsd) { dependencies/hueplusplus-1.1.0/src/LinHttpHandler.cpp \ serial_port/find_usb_serial_port_linux.cpp \ AutoStart/AutoStart-FreeBSD.cpp \ + SuspendResume/SuspendResume_Linux_FreeBSD.cpp \ SOURCES -= \ Controllers/SeagateController/RGBController_Seagate.cpp \ @@ -726,6 +738,7 @@ macx { HEADERS += \ AutoStart/AutoStart-MacOS.h \ qt/macutils.h \ + SuspendResume/SuspendResume_MacOS.h \ HEADERS += $$CONTROLLER_H_MACOS @@ -734,6 +747,7 @@ macx { serial_port/find_usb_serial_port_macos.cpp \ AutoStart/AutoStart-MacOS.cpp \ qt/macutils.mm \ + SuspendResume/SuspendResume_MacOS.cpp \ SOURCES += $$CONTROLLER_CPP_MACOS diff --git a/PluginManager.cpp b/PluginManager.cpp index ba865867..dd4881f3 100644 --- a/PluginManager.cpp +++ b/PluginManager.cpp @@ -232,7 +232,7 @@ void PluginManager::AddPlugin(const filesystem::path& path, bool is_system) if(entry.enabled) { - LoadPlugin(path); + LoadPlugin(&ActivePlugins.back()); } } else @@ -319,7 +319,7 @@ void PluginManager::RemovePlugin(const filesystem::path& path) if(ActivePlugins[plugin_idx].loader->isLoaded()) { LOG_TRACE("[PluginManager] Plugin %s is active, unloading", path.c_str()); - UnloadPlugin(path); + UnloadPlugin(&ActivePlugins[plugin_idx]); } /*---------------------------------------------------------------------*\ @@ -328,7 +328,7 @@ void PluginManager::RemovePlugin(const filesystem::path& path) ActivePlugins.erase(ActivePlugins.begin() + plugin_idx); } -void PluginManager::LoadPlugin(const filesystem::path& path) +void PluginManager::EnablePlugin(const filesystem::path& path) { unsigned int plugin_idx; @@ -351,10 +351,16 @@ void PluginManager::LoadPlugin(const filesystem::path& path) return; } + ActivePlugins[plugin_idx].enabled = true; + LoadPlugin(&ActivePlugins[plugin_idx]); +} + +void PluginManager::LoadPlugin(OpenRGBPluginEntry* plugin_entry) +{ /*---------------------------------------------------------------------*\ | If the plugin is in the list but is incompatible, return | \*---------------------------------------------------------------------*/ - if(ActivePlugins[plugin_idx].incompatible) + if(plugin_entry->incompatible) { return; } @@ -362,11 +368,11 @@ void PluginManager::LoadPlugin(const filesystem::path& path) /*---------------------------------------------------------------------*\ | If the selected plugin is in the list but not loaded, load it | \*---------------------------------------------------------------------*/ - if(!ActivePlugins[plugin_idx].loader->isLoaded()) + if(!plugin_entry->loader->isLoaded()) { - ActivePlugins[plugin_idx].loader->load(); + plugin_entry->loader->load(); - QObject* instance = ActivePlugins[plugin_idx].loader->instance(); + QObject* instance = plugin_entry->loader->instance(); bool dark_theme = OpenRGBThemeManager::IsDarkTheme(); @@ -378,7 +384,7 @@ void PluginManager::LoadPlugin(const filesystem::path& path) { if(plugin->GetPluginAPIVersion() == OPENRGB_PLUGIN_API_VERSION) { - ActivePlugins[plugin_idx].plugin = plugin; + plugin_entry->plugin = plugin; plugin->Load(dark_theme, ResourceManager::get()); @@ -387,7 +393,7 @@ void PluginManager::LoadPlugin(const filesystem::path& path) \*-------------------------------------------------*/ if(AddPluginCallbackArg != nullptr) { - AddPluginCallbackVal(AddPluginCallbackArg, &ActivePlugins[plugin_idx]); + AddPluginCallbackVal(AddPluginCallbackArg, plugin_entry); } } } @@ -395,7 +401,7 @@ void PluginManager::LoadPlugin(const filesystem::path& path) } } -void PluginManager::UnloadPlugin(const filesystem::path& path) +void PluginManager::DisablePlugin(const filesystem::path& path) { unsigned int plugin_idx; @@ -418,48 +424,62 @@ void PluginManager::UnloadPlugin(const filesystem::path& path) return; } + ActivePlugins[plugin_idx].enabled = false; + UnloadPlugin(&ActivePlugins[plugin_idx]); +} + +void PluginManager::UnloadPlugin(OpenRGBPluginEntry* plugin_entry) +{ /*---------------------------------------------------------------------*\ | If the selected plugin is in the list and loaded, unload it | \*---------------------------------------------------------------------*/ - if(ActivePlugins[plugin_idx].loader->isLoaded()) + if(plugin_entry->loader->isLoaded()) { /*-------------------------------------------------*\ | Call plugin's Unload function before GUI removal | \*-------------------------------------------------*/ - ActivePlugins[plugin_idx].plugin->Unload(); + plugin_entry->plugin->Unload(); /*-------------------------------------------------*\ | Call the Remove Plugin callback | \*-------------------------------------------------*/ if(RemovePluginCallbackVal != nullptr) { - RemovePluginCallbackVal(RemovePluginCallbackArg, &ActivePlugins[plugin_idx]); + RemovePluginCallbackVal(RemovePluginCallbackArg, plugin_entry); } - bool unloaded = ActivePlugins[plugin_idx].loader->unload(); + bool unloaded = plugin_entry->loader->unload(); if(!unloaded) { - LOG_WARNING("[PluginManager] Plugin %s cannot be unloaded", path.c_str()); + LOG_WARNING("[PluginManager] Plugin %s cannot be unloaded", plugin_entry->path.c_str()); } else { - LOG_TRACE("[PluginManager] Plugin %s successfully unloaded", path.c_str()); + LOG_TRACE("[PluginManager] Plugin %s successfully unloaded", plugin_entry->path.c_str()); } } else { - LOG_TRACE("[PluginManager] Plugin %s was already unloaded", path.c_str()); + LOG_TRACE("[PluginManager] Plugin %s was already unloaded", plugin_entry->path.c_str()); + } +} + +void PluginManager::LoadPlugins() +{ + for(OpenRGBPluginEntry& plugin_entry: ActivePlugins) + { + if(plugin_entry.enabled) + { + LoadPlugin(&plugin_entry); + } } } void PluginManager::UnloadPlugins() { - for(const OpenRGBPluginEntry& plugin_entry: ActivePlugins) + for(OpenRGBPluginEntry& plugin_entry: ActivePlugins) { - if(plugin_entry.loader->isLoaded()) - { - plugin_entry.plugin->Unload(); - } + UnloadPlugin(&plugin_entry); } } diff --git a/PluginManager.h b/PluginManager.h index b2a79c69..389e5fd1 100644 --- a/PluginManager.h +++ b/PluginManager.h @@ -47,14 +47,18 @@ public: void AddPlugin(const filesystem::path& path, bool is_system); void RemovePlugin(const filesystem::path& path); - void LoadPlugin(const filesystem::path& path); - void UnloadPlugin(const filesystem::path& path); + void EnablePlugin(const filesystem::path& path); + void DisablePlugin(const filesystem::path& path); + void LoadPlugins(); void UnloadPlugins(); std::vector ActivePlugins; private: + void LoadPlugin(OpenRGBPluginEntry* plugin_entry); + void UnloadPlugin(OpenRGBPluginEntry* plugin_entry); + void ScanAndLoadPluginsFrom(const filesystem::path & plugins_dir, bool is_system); AddPluginCallback AddPluginCallbackVal; diff --git a/SuspendResume/SuspendResume.h b/SuspendResume/SuspendResume.h new file mode 100644 index 00000000..48b614c2 --- /dev/null +++ b/SuspendResume/SuspendResume.h @@ -0,0 +1,31 @@ +/*---------------------------------------------------------*\ +| SuspendResume.h | +| | +| Suspend/resume common implementation | +| | +| Zach Deibert (zachdeibert) 12 Nov 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +class SuspendResumeListenerBase +{ +protected: + virtual void OnSuspend() = 0; + virtual void OnResume() = 0; +}; + +#ifdef _WIN32 +#include "SuspendResume_Windows.h" +#endif + +#ifdef __APPLE__ +#include "SuspendResume_MacOS.h" +#endif + +#if defined(__linux__) || defined(__FreeBSD__) +#include "SuspendResume_Linux_FreeBSD.h" +#endif diff --git a/SuspendResume/SuspendResume_Linux_FreeBSD.cpp b/SuspendResume/SuspendResume_Linux_FreeBSD.cpp new file mode 100644 index 00000000..594b887b --- /dev/null +++ b/SuspendResume/SuspendResume_Linux_FreeBSD.cpp @@ -0,0 +1,39 @@ +/*---------------------------------------------------------*\ +| SuspendResume_Linux_FreeBSD.cpp | +| | +| Suspend/resume Linux/FreeBSD implementation | +| | +| Zach Deibert (zachdeibert) 12 Nov 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "SuspendResume.h" + +SuspendResumeLoginManager::SuspendResumeLoginManager(SuspendResumeListener *srl) : srl(srl), bus(QDBusConnection::systemBus()) +{ + bus.connect("org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "PrepareForSleep", this, SLOT(PrepareForSleep())); +} + +SuspendResumeLoginManager::~SuspendResumeLoginManager() +{ + bus.disconnect("org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "PrepareForSleep", this, SLOT(PrepareForSleep())); +} + +void SuspendResumeLoginManager::PrepareForSleep(bool mode) +{ + if(mode) + { + srl->OnSuspend(); + } + else + { + srl->OnResume(); + } +} + +SuspendResumeListener::SuspendResumeListener() : login_manager(this) +{ +} diff --git a/SuspendResume/SuspendResume_Linux_FreeBSD.h b/SuspendResume/SuspendResume_Linux_FreeBSD.h new file mode 100644 index 00000000..f6248bdd --- /dev/null +++ b/SuspendResume/SuspendResume_Linux_FreeBSD.h @@ -0,0 +1,45 @@ +/*---------------------------------------------------------*\ +| SuspendResume_Linux_FreeBSD.h | +| | +| Suspend/resume Linux/FreeBSD implementation | +| | +| Zach Deibert (zachdeibert) 12 Nov 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "SuspendResume.h" + +class SuspendResumeListener; + +class SuspendResumeLoginManager : public QObject +{ + Q_OBJECT + +public: + SuspendResumeLoginManager(SuspendResumeListener *srl); + ~SuspendResumeLoginManager(); + +public slots: + void PrepareForSleep(bool mode); + +private: + SuspendResumeListener *srl; + QDBusConnection bus; +}; + +class SuspendResumeListener : public SuspendResumeListenerBase +{ + friend class SuspendResumeLoginManager; + +protected: + SuspendResumeListener(); + +private: + SuspendResumeLoginManager login_manager; +}; diff --git a/SuspendResume/SuspendResume_MacOS.cpp b/SuspendResume/SuspendResume_MacOS.cpp new file mode 100644 index 00000000..f38505e6 --- /dev/null +++ b/SuspendResume/SuspendResume_MacOS.cpp @@ -0,0 +1,45 @@ +/*---------------------------------------------------------*\ +| SuspendResume_MacOS.cpp | +| | +| Suspend/resume MacOS implementation | +| | +| Zach Deibert (zachdeibert) 12 Nov 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "SuspendResume.h" +#include "IOKit/pwr_mgt/IOPMLib.h" +#include "IOKit/IOMessage.h" + +SuspendResumeListener::SuspendResumeListener() +{ + root_port = IORegisterForSystemPower(this, &port_ref, &SuspendResumeListener::SystemPowerCallback, ¬ifier); + CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(port_ref), kCFRunLoopCommonModes); +} + +SuspendResumeListener::~SuspendResumeListener() +{ + CFRunLoopRemoveSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(port_ref), kCFRunLoopCommonModes); + IODeregisterForSystemPower(¬ifier); + IOServiceClose(root_port); + IONotificationPortDestroy(port_ref); +} + +void SuspendResumeListener::SystemPowerCallback(void *refcon, io_service_t service, uint32_t message_type, void *message_argument) +{ + (void)service; + SuspendResumeListener *spl = (SuspendResumeListener *)refcon; + switch(message_type) + { + case kIOMessageSystemWillSleep: + spl->OnSuspend(); + IOAllowPowerChange(spl->root_port, (intptr_t)message_argument); + break; + case kIOMessageSystemHasPoweredOn: + spl->OnResume(); + break; + } +} diff --git a/SuspendResume/SuspendResume_MacOS.h b/SuspendResume/SuspendResume_MacOS.h new file mode 100644 index 00000000..ef5638a1 --- /dev/null +++ b/SuspendResume/SuspendResume_MacOS.h @@ -0,0 +1,31 @@ +/*---------------------------------------------------------*\ +| SuspendResume_MacOS.h | +| | +| Suspend/resume MacOS implementation | +| | +| Zach Deibert (zachdeibert) 12 Nov 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "SuspendResume.h" +#include "IOKit/pwr_mgt/IOPMLib.h" +#include "IOKit/IOMessage.h" + +class SuspendResumeListener : public SuspendResumeListenerBase +{ +protected: + SuspendResumeListener(); + virtual ~SuspendResumeListener(); + +private: + static void SystemPowerCallback(void *refcon, io_service_t service, uint32_t message_type, void *message_argument); + + io_connect_t root_port; + IONotificationPortRef port_ref; + io_object_t notifier; +}; diff --git a/SuspendResume/SuspendResume_Windows.cpp b/SuspendResume/SuspendResume_Windows.cpp new file mode 100644 index 00000000..6c01ca06 --- /dev/null +++ b/SuspendResume/SuspendResume_Windows.cpp @@ -0,0 +1,48 @@ +/*---------------------------------------------------------*\ +| SuspendResume_Windows.cpp | +| | +| Suspend/resume Windows implementation | +| | +| Zach Deibert (zachdeibert) 12 Nov 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "SuspendResume.h" +#include "windows.h" + +SuspendResumeListener::SuspendResumeListener() +{ + QCoreApplication::instance()->installNativeEventFilter(this); +} + +SuspendResumeListener::~SuspendResumeListener() +{ + QCoreApplication::instance()->removeNativeEventFilter(this); +} + +bool SuspendResumeListener::nativeEventFilter(const QByteArray &event_type, void *message, long *result) +{ + (void)result; + if(event_type == "windows_generic_MSG") + { + switch(((MSG *)message)->message) + { + case WM_POWERBROADCAST: + switch(((MSG *)message)->wParam) + { + case PBT_APMSUSPEND: + OnSuspend(); + break; + case PBT_APMRESUMEAUTOMATIC: + OnResume(); + break; + } + break; + } + } + return false; +} diff --git a/SuspendResume/SuspendResume_Windows.h b/SuspendResume/SuspendResume_Windows.h new file mode 100644 index 00000000..2c88fb6c --- /dev/null +++ b/SuspendResume/SuspendResume_Windows.h @@ -0,0 +1,26 @@ +/*---------------------------------------------------------*\ +| SuspendResume_Windows.h | +| | +| Suspend/resume Windows implementation | +| | +| Zach Deibert (zachdeibert) 12 Nov 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "SuspendResume.h" + +class SuspendResumeListener : public SuspendResumeListenerBase, private QAbstractNativeEventFilter +{ +protected: + SuspendResumeListener(); + virtual ~SuspendResumeListener(); + +private: + bool nativeEventFilter(const QByteArray &event_type, void *message, long *result); +}; diff --git a/main.cpp b/main.cpp index 06d9931a..781e99ab 100644 --- a/main.cpp +++ b/main.cpp @@ -236,6 +236,15 @@ int main(int argc, char* argv[]) if(ret_flags & RET_FLAG_START_MINIMIZED) { +#ifdef _WIN32 + /*---------------------------------------------------------*\ + | Show the window always, even if it will immediately be | + | hidden. On Windows, events are not delivered to | + | nativeEventFilter (for SuspendResume) until the window | + | has been shown once. | + \*---------------------------------------------------------*/ + dlg.showMinimized(); +#endif #ifdef __APPLE__ MacUtils::ToggleApplicationDocklessState(false); #endif diff --git a/qt/OpenRGBDialog2/OpenRGBDialog2.cpp b/qt/OpenRGBDialog2/OpenRGBDialog2.cpp index c4fd2301..52fbd92e 100644 --- a/qt/OpenRGBDialog2/OpenRGBDialog2.cpp +++ b/qt/OpenRGBDialog2/OpenRGBDialog2.cpp @@ -7,6 +7,7 @@ | SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ +#include #include #include "OpenRGBDialog2.h" #include "LogManager.h" @@ -182,6 +183,7 @@ OpenRGBDialog2::OpenRGBDialog2(QWidget *parent) : QMainWindow(parent), ui(new Op SettingsManager* settings_manager = ResourceManager::get()->GetSettingsManager(); std::string ui_string = "UserInterface"; json ui_settings; + bool new_settings_keys = false; ui_settings = settings_manager->GetSettings(ui_string); @@ -205,9 +207,7 @@ OpenRGBDialog2::OpenRGBDialog2(QWidget *parent) : QMainWindow(parent), ui(new Op geometry_settings["height"] = 0; ui_settings["geometry"] = geometry_settings; - - settings_manager->SetSettings(ui_string, ui_settings); - settings_manager->SaveSettings(); + new_settings_keys = true; } /*-----------------------------------------------------*\ @@ -247,20 +247,47 @@ OpenRGBDialog2::OpenRGBDialog2(QWidget *parent) : QMainWindow(parent), ui(new Op } /*-----------------------------------------------------*\ - | If set_on_exit doesn't exist, write it to config | + | If autoload_profiles doesn't exist or has missing | + | profiles, write it to config | \*-----------------------------------------------------*/ - if(!ui_settings.contains("exit_profile")) + json autoload_profiles; + if(ui_settings.contains("autoload_profiles")) { - json on_exit_settings; - - on_exit_settings["set_on_exit"] = false; - on_exit_settings["profile_name"] = ""; - - ui_settings["exit_profile"] = on_exit_settings; - - settings_manager->SetSettings(ui_string, ui_settings); - settings_manager->SaveSettings(); + autoload_profiles = ui_settings["autoload_profiles"]; } + else + { + new_settings_keys = true; + } + + if(!autoload_profiles.contains("exit_profile")) + { + json profile; + profile["enabled"] = false; + profile["name"] = ""; + autoload_profiles["exit_profile"] = profile; + new_settings_keys = true; + } + + if(!autoload_profiles.contains("resume_profile")) + { + json profile; + profile["enabled"] = false; + profile["name"] = ""; + autoload_profiles["resume_profile"] = profile; + new_settings_keys = true; + } + + if(!autoload_profiles.contains("suspend_profile")) + { + json profile; + profile["enabled"] = false; + profile["name"] = ""; + autoload_profiles["suspend_profile"] = profile; + new_settings_keys = true; + } + + ui_settings["autoload_profiles"] = autoload_profiles; /*-----------------------------------------------------*\ | Register detection progress callback with resource | @@ -362,9 +389,7 @@ OpenRGBDialog2::OpenRGBDialog2(QWidget *parent) : QMainWindow(parent), ui(new Op if(!ui_settings.contains("minimize_on_close")) { ui_settings["minimize_on_close"] = false; - - settings_manager->SetSettings(ui_string, ui_settings); - settings_manager->SaveSettings(); + new_settings_keys = true; } connect(trayIcon,SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(on_ReShow(QSystemTrayIcon::ActivationReason))); @@ -376,9 +401,7 @@ OpenRGBDialog2::OpenRGBDialog2(QWidget *parent) : QMainWindow(parent), ui(new Op if(!ui_settings.contains("greyscale_tray_icon")) { ui_settings["greyscale_tray_icon"] = false; - - settings_manager->SetSettings(ui_string, ui_settings); - settings_manager->SaveSettings(); + new_settings_keys = true; } /*-----------------------------------------------------*\ @@ -390,6 +413,16 @@ OpenRGBDialog2::OpenRGBDialog2(QWidget *parent) : QMainWindow(parent), ui(new Op SetTrayIcon(ui_settings["greyscale_tray_icon"].get()); } + /*-----------------------------------------------------*\ + | Save the settings if new default values have been | + | inserted | + \*-----------------------------------------------------*/ + if(new_settings_keys) + { + settings_manager->SetSettings(ui_string, ui_settings); + settings_manager->SaveSettings(); + } + trayIcon->setToolTip("OpenRGB"); trayIcon->setContextMenu(trayIconMenu); trayIcon->show(); @@ -616,48 +649,53 @@ void OpenRGBDialog2::closeEvent(QCloseEvent *event) else { plugin_manager->UnloadPlugins(); - LoadExitProfile(); + + if(SelectConfigProfile("exit_profile")) + { + on_ButtonLoadProfile_clicked(); + + /*-----------------------------------------------------*\ + | Pause briefly to ensure that all profiles are loaded. | + \*-----------------------------------------------------*/ + std::this_thread::sleep_for(std::chrono::milliseconds(250)); + } + event->accept(); QApplication::exit(0); } } -void OpenRGBDialog2::LoadExitProfile() +bool OpenRGBDialog2::SelectConfigProfile(const std::string name) { /*-----------------------------------------------------*\ - | Set Exit Profile (if enabled and valid) | + | Set automatic profile (if enabled and valid) | \*-----------------------------------------------------*/ - const std::string exit_profile = "exit_profile"; - const std::string set_on_exit = "set_on_exit"; - const std::string profile_name = "profile_name"; - json ui_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("UserInterface"); + json ui_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("UserInterface"); - if(ui_settings.contains(exit_profile)) + if(ui_settings.contains("autoload_profiles")) { - if( ui_settings[exit_profile].contains(set_on_exit) - && ui_settings[exit_profile].contains(profile_name) ) + json autoload_profiles = ui_settings["autoload_profiles"]; + if(autoload_profiles.contains(name)) { - if(ui_settings[exit_profile][set_on_exit].get()) + json profile = autoload_profiles[name]; + if (profile.contains("enabled") && profile["enabled"].get() && profile.contains("name")) { /*-----------------------------------------------------*\ | Set the profile name from settings and check the | | profile combobox for a match | \*-----------------------------------------------------*/ - std::string profile = ui_settings[exit_profile][profile_name].get(); - int profile_index = ui->ProfileBox->findText(QString::fromStdString(profile)); + std::string profile_name = profile["name"].get(); + int profile_index = ui->ProfileBox->findText(QString::fromStdString(profile_name)); if(profile_index > -1) { ui->ProfileBox->setCurrentIndex(profile_index); - on_ButtonLoadProfile_clicked(); - /*-----------------------------------------------------*\ - | Pause briefly to ensure that all profiles are loaded. | - \*-----------------------------------------------------*/ - std::this_thread::sleep_for(std::chrono::milliseconds(250)); + return true; } } } } + return false; } void OpenRGBDialog2::AddPluginsPage() @@ -1381,6 +1419,24 @@ void OpenRGBDialog2::UpdateProfileList() emit ProfileListChanged(); } +void OpenRGBDialog2::OnSuspend() +{ + if(SelectConfigProfile("suspend_profile")) + { + plugin_manager->UnloadPlugins(); + on_ButtonLoadProfile_clicked(); + } +} + +void OpenRGBDialog2::OnResume() +{ + if(SelectConfigProfile("resume_profile")) + { + on_ButtonLoadProfile_clicked(); + } + plugin_manager->LoadPlugins(); +} + void OpenRGBDialog2::on_Exit() { /*-----------------------------------------------*\ @@ -1506,6 +1562,15 @@ void OpenRGBDialog2::on_ShowHide() MacUtils::ToggleApplicationDocklessState(true); #endif show(); + if(isMinimized()) + { + bool maximize = isMaximized(); + showNormal(); + if(maximize) + { + showMaximized(); + } + } } else { @@ -1592,6 +1657,15 @@ void OpenRGBDialog2::on_ReShow(QSystemTrayIcon::ActivationReason reason) if (isHidden()) { show(); + if(isMinimized()) + { + bool maximize = isMaximized(); + showNormal(); + if(maximize) + { + showMaximized(); + } + } } } } diff --git a/qt/OpenRGBDialog2/OpenRGBDialog2.h b/qt/OpenRGBDialog2/OpenRGBDialog2.h index fde6dc62..bfba91d3 100644 --- a/qt/OpenRGBDialog2/OpenRGBDialog2.h +++ b/qt/OpenRGBDialog2/OpenRGBDialog2.h @@ -9,6 +9,7 @@ #pragma once +#include #include #include #include @@ -37,6 +38,7 @@ #include "OpenRGBYeelightSettingsPage/OpenRGBYeelightSettingsPage.h" #include "OpenRGBNanoleafSettingsPage/OpenRGBNanoleafSettingsPage.h" #include "PluginManager.h" +#include "SuspendResume.h" #include "i2c_smbus.h" #include "LogManager.h" @@ -50,7 +52,7 @@ namespace Ui class OpenRGBDialog2; } -class Ui::OpenRGBDialog2 : public QMainWindow +class Ui::OpenRGBDialog2 : public QMainWindow, private SuspendResumeListener { Q_OBJECT @@ -144,7 +146,7 @@ private: void UpdateDevicesList(); void UpdateProfileList(); void closeEvent(QCloseEvent *event); - void LoadExitProfile(); + bool SelectConfigProfile(const std::string name); void SetDetectionViewState(bool detection_showing); void SaveProfile(); @@ -162,6 +164,9 @@ private: void ShowLEDView(); void HideLEDView(); + void OnSuspend(); + void OnResume(); + private slots: void on_Exit(); void on_LightsOff(); diff --git a/qt/OpenRGBPluginsPage/OpenRGBPluginsPage.cpp b/qt/OpenRGBPluginsPage/OpenRGBPluginsPage.cpp index cd49bd55..b550c762 100644 --- a/qt/OpenRGBPluginsPage/OpenRGBPluginsPage.cpp +++ b/qt/OpenRGBPluginsPage/OpenRGBPluginsPage.cpp @@ -335,11 +335,11 @@ void Ui::OpenRGBPluginsPage::on_EnableButton_clicked(OpenRGBPluginsEntry* entry) if(enabled) { - plugin_manager->LoadPlugin(entry_path); + plugin_manager->EnablePlugin(entry_path); } else { - plugin_manager->UnloadPlugin(entry_path); + plugin_manager->DisablePlugin(entry_path); } } diff --git a/qt/OpenRGBSettingsPage/OpenRGBSettingsPage.cpp b/qt/OpenRGBSettingsPage/OpenRGBSettingsPage.cpp index 0f832ccb..86af79f6 100644 --- a/qt/OpenRGBSettingsPage/OpenRGBSettingsPage.cpp +++ b/qt/OpenRGBSettingsPage/OpenRGBSettingsPage.cpp @@ -288,9 +288,13 @@ void OpenRGBSettingsPage::UpdateProfiles() if(profile_manager != NULL) { ui->ComboBoxAutoStartProfile->blockSignals(true); + ui->ComboBoxSuspendProfile->blockSignals(true); + ui->ComboBoxResumeProfile->blockSignals(true); ui->ComboBoxExitProfile->blockSignals(true); ui->ComboBoxAutoStartProfile->clear(); + ui->ComboBoxSuspendProfile->clear(); + ui->ComboBoxResumeProfile->clear(); ui->ComboBoxExitProfile->clear(); for(std::size_t profile_index = 0; profile_index < profile_manager->profile_list.size(); profile_index++) @@ -298,10 +302,14 @@ void OpenRGBSettingsPage::UpdateProfiles() QString new_profile = QString(profile_manager->profile_list[profile_index].c_str()); ui->ComboBoxAutoStartProfile->addItem(new_profile); + ui->ComboBoxSuspendProfile->addItem(new_profile); + ui->ComboBoxResumeProfile->addItem(new_profile); ui->ComboBoxExitProfile->addItem(new_profile); } ui->ComboBoxAutoStartProfile->blockSignals(false); + ui->ComboBoxSuspendProfile->blockSignals(false); + ui->ComboBoxResumeProfile->blockSignals(false); ui->ComboBoxExitProfile->blockSignals(false); } @@ -330,28 +338,88 @@ void OpenRGBSettingsPage::UpdateProfiles() \*---------------------------------------------------------*/ json ui_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("UserInterface"); - if(ui_settings.contains("exit_profile")) + if(ui_settings.contains("autoload_profiles")) { - if(ui_settings["exit_profile"].contains("set_on_exit")) - { - bool is_set_on_exit = ui_settings["exit_profile"]["set_on_exit"]; + json autoload_profiles = ui_settings["autoload_profiles"]; - ui->CheckboxSetOnExit->setChecked(is_set_on_exit); - ui->ComboBoxExitProfile->setEnabled(is_set_on_exit); + if(autoload_profiles.contains("exit_profile")) + { + json profile = autoload_profiles["exit_profile"]; + + if(profile.contains("enabled")) + { + bool is_enabled = profile["enabled"].get(); + ui->CheckboxSetOnExit->setChecked(is_enabled); + ui->ComboBoxExitProfile->setEnabled(is_enabled); + } + + if(profile.contains("name")) + { + /*-----------------------------------------------------*\ + | Set the profile name from settings and check the | + | profile combobox for a match | + \*-----------------------------------------------------*/ + std::string profile_name = profile["name"].get(); + int profile_index = ui->ComboBoxExitProfile->findText(QString::fromStdString(profile_name)); + + if(profile_index > -1) + { + ui->ComboBoxExitProfile->setCurrentIndex(profile_index); + } + } } - if(ui_settings["exit_profile"].contains("profile_name")) + if(autoload_profiles.contains("resume_profile")) { - /*-----------------------------------------------------*\ - | Set the profile name from settings and check the | - | profile combobox for a match | - \*-----------------------------------------------------*/ - std::string profile_name = ui_settings["exit_profile"]["profile_name"].get(); - int profile_index = ui->ComboBoxExitProfile->findText(QString::fromStdString(profile_name)); + json profile = autoload_profiles["resume_profile"]; - if(profile_index > -1) + if(profile.contains("enabled")) { - ui->ComboBoxExitProfile->setCurrentIndex(profile_index); + bool is_enabled = profile["enabled"].get(); + ui->CheckboxSetOnResume->setChecked(is_enabled); + ui->ComboBoxResumeProfile->setEnabled(is_enabled); + } + + if(profile.contains("name")) + { + /*-----------------------------------------------------*\ + | Set the profile name from settings and check the | + | profile combobox for a match | + \*-----------------------------------------------------*/ + std::string profile_name = profile["name"].get(); + int profile_index = ui->ComboBoxResumeProfile->findText(QString::fromStdString(profile_name)); + + if(profile_index > -1) + { + ui->ComboBoxResumeProfile->setCurrentIndex(profile_index); + } + } + } + + if(autoload_profiles.contains("suspend_profile")) + { + json profile = autoload_profiles["suspend_profile"]; + + if(profile.contains("enabled")) + { + bool is_enabled = profile["enabled"].get(); + ui->CheckboxSetOnSuspend->setChecked(is_enabled); + ui->ComboBoxSuspendProfile->setEnabled(is_enabled); + } + + if(profile.contains("name")) + { + /*-----------------------------------------------------*\ + | Set the profile name from settings and check the | + | profile combobox for a match | + \*-----------------------------------------------------*/ + std::string profile_name = profile["name"].get(); + int profile_index = ui->ComboBoxSuspendProfile->findText(QString::fromStdString(profile_name)); + + if(profile_index > -1) + { + ui->ComboBoxSuspendProfile->setCurrentIndex(profile_index); + } } } } @@ -463,9 +531,9 @@ void Ui::OpenRGBSettingsPage::on_CheckboxRunZoneChecks_clicked() void Ui::OpenRGBSettingsPage::on_CheckboxSetOnExit_clicked(bool checked) { - json ui_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("UserInterface"); - ui_settings["exit_profile"]["set_on_exit"] = checked; - ui_settings["exit_profile"]["profile_name"] = ui->ComboBoxExitProfile->currentText().toStdString(); + json ui_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("UserInterface"); + ui_settings["autoload_profiles"]["exit_profile"]["enabled"] = checked; + ui_settings["autoload_profiles"]["exit_profile"]["name"] = ui->ComboBoxExitProfile->currentText().toStdString(); ResourceManager::get()->GetSettingsManager()->SetSettings("UserInterface", ui_settings); SaveSettings(); @@ -474,8 +542,46 @@ void Ui::OpenRGBSettingsPage::on_CheckboxSetOnExit_clicked(bool checked) void Ui::OpenRGBSettingsPage::on_ComboBoxExitProfile_currentTextChanged(const QString exit_profile_name) { - json ui_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("UserInterface"); - ui_settings["exit_profile"]["profile_name"] = exit_profile_name.toStdString(); + json ui_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("UserInterface"); + ui_settings["autoload_profiles"]["exit_profile"]["name"] = exit_profile_name.toStdString(); + ResourceManager::get()->GetSettingsManager()->SetSettings("UserInterface", ui_settings); + SaveSettings(); +} + +void Ui::OpenRGBSettingsPage::on_CheckboxSetOnResume_clicked(bool checked) +{ + json ui_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("UserInterface"); + ui_settings["autoload_profiles"]["resume_profile"]["enabled"] = checked; + ui_settings["autoload_profiles"]["resume_profile"]["name"] = ui->ComboBoxResumeProfile->currentText().toStdString(); + ResourceManager::get()->GetSettingsManager()->SetSettings("UserInterface", ui_settings); + SaveSettings(); + + ui->ComboBoxResumeProfile->setEnabled(checked); +} + +void Ui::OpenRGBSettingsPage::on_ComboBoxResumeProfile_currentTextChanged(const QString resume_profile_name) +{ + json ui_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("UserInterface"); + ui_settings["autoload_profiles"]["resume_profile"]["name"] = resume_profile_name.toStdString(); + ResourceManager::get()->GetSettingsManager()->SetSettings("UserInterface", ui_settings); + SaveSettings(); +} + +void Ui::OpenRGBSettingsPage::on_CheckboxSetOnSuspend_clicked(bool checked) +{ + json ui_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("UserInterface"); + ui_settings["autoload_profiles"]["suspend_profile"]["enabled"] = checked; + ui_settings["autoload_profiles"]["suspend_profile"]["name"] = ui->ComboBoxSuspendProfile->currentText().toStdString(); + ResourceManager::get()->GetSettingsManager()->SetSettings("UserInterface", ui_settings); + SaveSettings(); + + ui->ComboBoxSuspendProfile->setEnabled(checked); +} + +void Ui::OpenRGBSettingsPage::on_ComboBoxSuspendProfile_currentTextChanged(const QString suspend_profile_name) +{ + json ui_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("UserInterface"); + ui_settings["autoload_profiles"]["suspend_profile"]["name"] = suspend_profile_name.toStdString(); ResourceManager::get()->GetSettingsManager()->SetSettings("UserInterface", ui_settings); SaveSettings(); } diff --git a/qt/OpenRGBSettingsPage/OpenRGBSettingsPage.h b/qt/OpenRGBSettingsPage/OpenRGBSettingsPage.h index 917a47fc..4e33aa83 100644 --- a/qt/OpenRGBSettingsPage/OpenRGBSettingsPage.h +++ b/qt/OpenRGBSettingsPage/OpenRGBSettingsPage.h @@ -83,6 +83,10 @@ private slots: void on_CheckboxSetOnExit_clicked(bool checked); void on_ComboBoxExitProfile_currentTextChanged(const QString exit_profile_name); + void on_CheckboxSetOnResume_clicked(bool checked); + void on_ComboBoxResumeProfile_currentTextChanged(const QString resume_profile_name); + void on_CheckboxSetOnSuspend_clicked(bool checked); + void on_ComboBoxSuspendProfile_currentTextChanged(const QString suspend_profile_name); void on_CheckboxDisableKeyExpansion_clicked(); void on_CheckboxShowLEDView_clicked(); }; diff --git a/qt/OpenRGBSettingsPage/OpenRGBSettingsPage.ui b/qt/OpenRGBSettingsPage/OpenRGBSettingsPage.ui index a0ce4362..638d1a15 100644 --- a/qt/OpenRGBSettingsPage/OpenRGBSettingsPage.ui +++ b/qt/OpenRGBSettingsPage/OpenRGBSettingsPage.ui @@ -85,7 +85,7 @@ - + Set Profile on Exit @@ -119,7 +119,7 @@ - + @@ -146,14 +146,14 @@ - + Start at Login Status - + Qt::Vertical @@ -278,6 +278,26 @@ + + + + Set Profile on Suspend + + + + + + + + + + Set Profile on Resume + + + + + +