Add support for loading profiles on suspend/resume

This commit is contained in:
Zach Deibert 2024-11-12 22:42:32 -06:00 committed by Adam Honse
parent 7d96b27f28
commit bd3cc94212
17 changed files with 612 additions and 91 deletions

View file

@ -122,7 +122,8 @@ INCLUDEPATH +=
AutoStart/ \ AutoStart/ \
KeyboardLayoutManager/ \ KeyboardLayoutManager/ \
RGBController/ \ RGBController/ \
qt/ qt/ \
SuspendResume/
HEADERS += \ HEADERS += \
$$GUI_H \ $$GUI_H \
@ -156,6 +157,7 @@ HEADERS +=
serial_port/serial_port.h \ serial_port/serial_port.h \
StringUtils.h \ StringUtils.h \
super_io/super_io.h \ super_io/super_io.h \
SuspendResume/SuspendResume.h \
AutoStart/AutoStart.h \ AutoStart/AutoStart.h \
KeyboardLayoutManager/KeyboardLayoutManager.h \ KeyboardLayoutManager/KeyboardLayoutManager.h \
RGBController/RGBController.h \ RGBController/RGBController.h \
@ -388,6 +390,7 @@ win32:SOURCES +=
i2c_smbus/i2c_smbus_piix4.cpp \ i2c_smbus/i2c_smbus_piix4.cpp \
scsiapi/scsiapi_windows.c \ scsiapi/scsiapi_windows.c \
serial_port/find_usb_serial_port_win.cpp \ serial_port/find_usb_serial_port_win.cpp \
SuspendResume/SuspendResume_Windows.cpp \
wmi/wmi.cpp \ wmi/wmi.cpp \
AutoStart/AutoStart-Windows.cpp \ AutoStart/AutoStart-Windows.cpp \
@ -405,6 +408,7 @@ win32:HEADERS +=
i2c_smbus/i2c_smbus_piix4.h \ i2c_smbus/i2c_smbus_piix4.h \
wmi/wmi.h \ wmi/wmi.h \
AutoStart/AutoStart-Windows.h \ AutoStart/AutoStart-Windows.h \
SuspendResume/SuspendResume_Windows.h \
win32:contains(QMAKE_TARGET.arch, x86_64) { win32:contains(QMAKE_TARGET.arch, x86_64) {
LIBS += \ LIBS += \
@ -499,6 +503,7 @@ contains(QMAKE_PLATFORM, linux) {
dependencies/NVFC/nvapi.h \ dependencies/NVFC/nvapi.h \
i2c_smbus/i2c_smbus_linux.h \ i2c_smbus/i2c_smbus_linux.h \
AutoStart/AutoStart-Linux.h \ AutoStart/AutoStart-Linux.h \
SuspendResume/SuspendResume_Linux_FreeBSD.h \
INCLUDEPATH += \ INCLUDEPATH += \
dependencies/NVFC \ dependencies/NVFC \
@ -516,6 +521,8 @@ contains(QMAKE_PLATFORM, linux) {
LIBS += -lstdc++fs LIBS += -lstdc++fs
} }
QT += dbus
QMAKE_CXXFLAGS += -Wno-implicit-fallthrough -Wno-psabi QMAKE_CXXFLAGS += -Wno-implicit-fallthrough -Wno-psabi
#-------------------------------------------------------------------------------------------# #-------------------------------------------------------------------------------------------#
@ -550,6 +557,7 @@ contains(QMAKE_PLATFORM, linux) {
scsiapi/scsiapi_linux.c \ scsiapi/scsiapi_linux.c \
serial_port/find_usb_serial_port_linux.cpp \ serial_port/find_usb_serial_port_linux.cpp \
AutoStart/AutoStart-Linux.cpp \ AutoStart/AutoStart-Linux.cpp \
SuspendResume/SuspendResume_Linux_FreeBSD.cpp \
#-------------------------------------------------------------------------------------------# #-------------------------------------------------------------------------------------------#
# Set up install paths # # Set up install paths #
@ -622,6 +630,7 @@ contains(QMAKE_PLATFORM, freebsd) {
HEADERS += \ HEADERS += \
AutoStart/AutoStart-FreeBSD.h \ AutoStart/AutoStart-FreeBSD.h \
SuspendResume/SuspendResume_Linux_FreeBSD.h \
HEADERS -= \ HEADERS -= \
Controllers/SeagateController/RGBController_Seagate.h \ Controllers/SeagateController/RGBController_Seagate.h \
@ -639,6 +648,8 @@ contains(QMAKE_PLATFORM, freebsd) {
LIBS += -lstdc++fs LIBS += -lstdc++fs
} }
QT += dbus
#-------------------------------------------------------------------------------------------# #-------------------------------------------------------------------------------------------#
# Determine which hidapi to use based on availability # # Determine which hidapi to use based on availability #
# Prefer hidraw backend, then libusb # # Prefer hidraw backend, then libusb #
@ -667,6 +678,7 @@ contains(QMAKE_PLATFORM, freebsd) {
dependencies/hueplusplus-1.1.0/src/LinHttpHandler.cpp \ dependencies/hueplusplus-1.1.0/src/LinHttpHandler.cpp \
serial_port/find_usb_serial_port_linux.cpp \ serial_port/find_usb_serial_port_linux.cpp \
AutoStart/AutoStart-FreeBSD.cpp \ AutoStart/AutoStart-FreeBSD.cpp \
SuspendResume/SuspendResume_Linux_FreeBSD.cpp \
SOURCES -= \ SOURCES -= \
Controllers/SeagateController/RGBController_Seagate.cpp \ Controllers/SeagateController/RGBController_Seagate.cpp \
@ -726,6 +738,7 @@ macx {
HEADERS += \ HEADERS += \
AutoStart/AutoStart-MacOS.h \ AutoStart/AutoStart-MacOS.h \
qt/macutils.h \ qt/macutils.h \
SuspendResume/SuspendResume_MacOS.h \
HEADERS += $$CONTROLLER_H_MACOS HEADERS += $$CONTROLLER_H_MACOS
@ -734,6 +747,7 @@ macx {
serial_port/find_usb_serial_port_macos.cpp \ serial_port/find_usb_serial_port_macos.cpp \
AutoStart/AutoStart-MacOS.cpp \ AutoStart/AutoStart-MacOS.cpp \
qt/macutils.mm \ qt/macutils.mm \
SuspendResume/SuspendResume_MacOS.cpp \
SOURCES += $$CONTROLLER_CPP_MACOS SOURCES += $$CONTROLLER_CPP_MACOS

View file

@ -232,7 +232,7 @@ void PluginManager::AddPlugin(const filesystem::path& path, bool is_system)
if(entry.enabled) if(entry.enabled)
{ {
LoadPlugin(path); LoadPlugin(&ActivePlugins.back());
} }
} }
else else
@ -319,7 +319,7 @@ void PluginManager::RemovePlugin(const filesystem::path& path)
if(ActivePlugins[plugin_idx].loader->isLoaded()) if(ActivePlugins[plugin_idx].loader->isLoaded())
{ {
LOG_TRACE("[PluginManager] Plugin %s is active, unloading", path.c_str()); 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); ActivePlugins.erase(ActivePlugins.begin() + plugin_idx);
} }
void PluginManager::LoadPlugin(const filesystem::path& path) void PluginManager::EnablePlugin(const filesystem::path& path)
{ {
unsigned int plugin_idx; unsigned int plugin_idx;
@ -351,10 +351,16 @@ void PluginManager::LoadPlugin(const filesystem::path& path)
return; 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 the plugin is in the list but is incompatible, return |
\*---------------------------------------------------------------------*/ \*---------------------------------------------------------------------*/
if(ActivePlugins[plugin_idx].incompatible) if(plugin_entry->incompatible)
{ {
return; 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 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(); bool dark_theme = OpenRGBThemeManager::IsDarkTheme();
@ -378,7 +384,7 @@ void PluginManager::LoadPlugin(const filesystem::path& path)
{ {
if(plugin->GetPluginAPIVersion() == OPENRGB_PLUGIN_API_VERSION) if(plugin->GetPluginAPIVersion() == OPENRGB_PLUGIN_API_VERSION)
{ {
ActivePlugins[plugin_idx].plugin = plugin; plugin_entry->plugin = plugin;
plugin->Load(dark_theme, ResourceManager::get()); plugin->Load(dark_theme, ResourceManager::get());
@ -387,7 +393,7 @@ void PluginManager::LoadPlugin(const filesystem::path& path)
\*-------------------------------------------------*/ \*-------------------------------------------------*/
if(AddPluginCallbackArg != nullptr) 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; unsigned int plugin_idx;
@ -418,48 +424,62 @@ void PluginManager::UnloadPlugin(const filesystem::path& path)
return; 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 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 | | Call plugin's Unload function before GUI removal |
\*-------------------------------------------------*/ \*-------------------------------------------------*/
ActivePlugins[plugin_idx].plugin->Unload(); plugin_entry->plugin->Unload();
/*-------------------------------------------------*\ /*-------------------------------------------------*\
| Call the Remove Plugin callback | | Call the Remove Plugin callback |
\*-------------------------------------------------*/ \*-------------------------------------------------*/
if(RemovePluginCallbackVal != nullptr) 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) 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 else
{ {
LOG_TRACE("[PluginManager] Plugin %s successfully unloaded", path.c_str()); LOG_TRACE("[PluginManager] Plugin %s successfully unloaded", plugin_entry->path.c_str());
} }
} }
else 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() void PluginManager::UnloadPlugins()
{ {
for(const OpenRGBPluginEntry& plugin_entry: ActivePlugins) for(OpenRGBPluginEntry& plugin_entry: ActivePlugins)
{ {
if(plugin_entry.loader->isLoaded()) UnloadPlugin(&plugin_entry);
{
plugin_entry.plugin->Unload();
}
} }
} }

View file

@ -47,14 +47,18 @@ public:
void AddPlugin(const filesystem::path& path, bool is_system); void AddPlugin(const filesystem::path& path, bool is_system);
void RemovePlugin(const filesystem::path& path); void RemovePlugin(const filesystem::path& path);
void LoadPlugin(const filesystem::path& path); void EnablePlugin(const filesystem::path& path);
void UnloadPlugin(const filesystem::path& path); void DisablePlugin(const filesystem::path& path);
void LoadPlugins();
void UnloadPlugins(); void UnloadPlugins();
std::vector<OpenRGBPluginEntry> ActivePlugins; std::vector<OpenRGBPluginEntry> ActivePlugins;
private: private:
void LoadPlugin(OpenRGBPluginEntry* plugin_entry);
void UnloadPlugin(OpenRGBPluginEntry* plugin_entry);
void ScanAndLoadPluginsFrom(const filesystem::path & plugins_dir, bool is_system); void ScanAndLoadPluginsFrom(const filesystem::path & plugins_dir, bool is_system);
AddPluginCallback AddPluginCallbackVal; AddPluginCallback AddPluginCallbackVal;

View file

@ -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

View file

@ -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 <QDBusConnection>
#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)
{
}

View file

@ -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 <QDBusConnection>
#include <QObject>
#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;
};

View file

@ -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 <stdint.h>
#include "SuspendResume.h"
#include "IOKit/pwr_mgt/IOPMLib.h"
#include "IOKit/IOMessage.h"
SuspendResumeListener::SuspendResumeListener()
{
root_port = IORegisterForSystemPower(this, &port_ref, &SuspendResumeListener::SystemPowerCallback, &notifier);
CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(port_ref), kCFRunLoopCommonModes);
}
SuspendResumeListener::~SuspendResumeListener()
{
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(port_ref), kCFRunLoopCommonModes);
IODeregisterForSystemPower(&notifier);
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;
}
}

View file

@ -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 <stdint.h>
#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;
};

View file

@ -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 <QByteArray>
#include <QCoreApplication>
#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;
}

View file

@ -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 <QAbstractNativeEventFilter>
#include <QByteArray>
#include "SuspendResume.h"
class SuspendResumeListener : public SuspendResumeListenerBase, private QAbstractNativeEventFilter
{
protected:
SuspendResumeListener();
virtual ~SuspendResumeListener();
private:
bool nativeEventFilter(const QByteArray &event_type, void *message, long *result);
};

View file

@ -236,6 +236,15 @@ int main(int argc, char* argv[])
if(ret_flags & RET_FLAG_START_MINIMIZED) 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__ #ifdef __APPLE__
MacUtils::ToggleApplicationDocklessState(false); MacUtils::ToggleApplicationDocklessState(false);
#endif #endif

View file

@ -7,6 +7,7 @@
| SPDX-License-Identifier: GPL-2.0-only | | SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/ \*---------------------------------------------------------*/
#include <string>
#include <functional> #include <functional>
#include "OpenRGBDialog2.h" #include "OpenRGBDialog2.h"
#include "LogManager.h" #include "LogManager.h"
@ -182,6 +183,7 @@ OpenRGBDialog2::OpenRGBDialog2(QWidget *parent) : QMainWindow(parent), ui(new Op
SettingsManager* settings_manager = ResourceManager::get()->GetSettingsManager(); SettingsManager* settings_manager = ResourceManager::get()->GetSettingsManager();
std::string ui_string = "UserInterface"; std::string ui_string = "UserInterface";
json ui_settings; json ui_settings;
bool new_settings_keys = false;
ui_settings = settings_manager->GetSettings(ui_string); ui_settings = settings_manager->GetSettings(ui_string);
@ -205,9 +207,7 @@ OpenRGBDialog2::OpenRGBDialog2(QWidget *parent) : QMainWindow(parent), ui(new Op
geometry_settings["height"] = 0; geometry_settings["height"] = 0;
ui_settings["geometry"] = geometry_settings; ui_settings["geometry"] = geometry_settings;
new_settings_keys = true;
settings_manager->SetSettings(ui_string, ui_settings);
settings_manager->SaveSettings();
} }
/*-----------------------------------------------------*\ /*-----------------------------------------------------*\
@ -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; autoload_profiles = ui_settings["autoload_profiles"];
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();
} }
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 | | 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")) if(!ui_settings.contains("minimize_on_close"))
{ {
ui_settings["minimize_on_close"] = false; ui_settings["minimize_on_close"] = false;
new_settings_keys = true;
settings_manager->SetSettings(ui_string, ui_settings);
settings_manager->SaveSettings();
} }
connect(trayIcon,SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(on_ReShow(QSystemTrayIcon::ActivationReason))); 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")) if(!ui_settings.contains("greyscale_tray_icon"))
{ {
ui_settings["greyscale_tray_icon"] = false; ui_settings["greyscale_tray_icon"] = false;
new_settings_keys = true;
settings_manager->SetSettings(ui_string, ui_settings);
settings_manager->SaveSettings();
} }
/*-----------------------------------------------------*\ /*-----------------------------------------------------*\
@ -390,6 +413,16 @@ OpenRGBDialog2::OpenRGBDialog2(QWidget *parent) : QMainWindow(parent), ui(new Op
SetTrayIcon(ui_settings["greyscale_tray_icon"].get<bool>()); SetTrayIcon(ui_settings["greyscale_tray_icon"].get<bool>());
} }
/*-----------------------------------------------------*\
| 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->setToolTip("OpenRGB");
trayIcon->setContextMenu(trayIconMenu); trayIcon->setContextMenu(trayIconMenu);
trayIcon->show(); trayIcon->show();
@ -616,48 +649,53 @@ void OpenRGBDialog2::closeEvent(QCloseEvent *event)
else else
{ {
plugin_manager->UnloadPlugins(); 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(); event->accept();
QApplication::exit(0); 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"; json ui_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("UserInterface");
const std::string set_on_exit = "set_on_exit";
const std::string profile_name = "profile_name";
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) json autoload_profiles = ui_settings["autoload_profiles"];
&& ui_settings[exit_profile].contains(profile_name) ) if(autoload_profiles.contains(name))
{ {
if(ui_settings[exit_profile][set_on_exit].get<bool>()) json profile = autoload_profiles[name];
if (profile.contains("enabled") && profile["enabled"].get<bool>() && profile.contains("name"))
{ {
/*-----------------------------------------------------*\ /*-----------------------------------------------------*\
| Set the profile name from settings and check the | | Set the profile name from settings and check the |
| profile combobox for a match | | profile combobox for a match |
\*-----------------------------------------------------*/ \*-----------------------------------------------------*/
std::string profile = ui_settings[exit_profile][profile_name].get<std::string>(); std::string profile_name = profile["name"].get<std::string>();
int profile_index = ui->ProfileBox->findText(QString::fromStdString(profile)); int profile_index = ui->ProfileBox->findText(QString::fromStdString(profile_name));
if(profile_index > -1) if(profile_index > -1)
{ {
ui->ProfileBox->setCurrentIndex(profile_index); ui->ProfileBox->setCurrentIndex(profile_index);
on_ButtonLoadProfile_clicked(); return true;
/*-----------------------------------------------------*\
| Pause briefly to ensure that all profiles are loaded. |
\*-----------------------------------------------------*/
std::this_thread::sleep_for(std::chrono::milliseconds(250));
} }
} }
} }
} }
return false;
} }
void OpenRGBDialog2::AddPluginsPage() void OpenRGBDialog2::AddPluginsPage()
@ -1381,6 +1419,24 @@ void OpenRGBDialog2::UpdateProfileList()
emit ProfileListChanged(); 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() void OpenRGBDialog2::on_Exit()
{ {
/*-----------------------------------------------*\ /*-----------------------------------------------*\
@ -1506,6 +1562,15 @@ void OpenRGBDialog2::on_ShowHide()
MacUtils::ToggleApplicationDocklessState(true); MacUtils::ToggleApplicationDocklessState(true);
#endif #endif
show(); show();
if(isMinimized())
{
bool maximize = isMaximized();
showNormal();
if(maximize)
{
showMaximized();
}
}
} }
else else
{ {
@ -1592,6 +1657,15 @@ void OpenRGBDialog2::on_ReShow(QSystemTrayIcon::ActivationReason reason)
if (isHidden()) if (isHidden())
{ {
show(); show();
if(isMinimized())
{
bool maximize = isMaximized();
showNormal();
if(maximize)
{
showMaximized();
}
}
} }
} }
} }

View file

@ -9,6 +9,7 @@
#pragma once #pragma once
#include <string>
#include <vector> #include <vector>
#include <QMainWindow> #include <QMainWindow>
#include <QTimer> #include <QTimer>
@ -37,6 +38,7 @@
#include "OpenRGBYeelightSettingsPage/OpenRGBYeelightSettingsPage.h" #include "OpenRGBYeelightSettingsPage/OpenRGBYeelightSettingsPage.h"
#include "OpenRGBNanoleafSettingsPage/OpenRGBNanoleafSettingsPage.h" #include "OpenRGBNanoleafSettingsPage/OpenRGBNanoleafSettingsPage.h"
#include "PluginManager.h" #include "PluginManager.h"
#include "SuspendResume.h"
#include "i2c_smbus.h" #include "i2c_smbus.h"
#include "LogManager.h" #include "LogManager.h"
@ -50,7 +52,7 @@ namespace Ui
class OpenRGBDialog2; class OpenRGBDialog2;
} }
class Ui::OpenRGBDialog2 : public QMainWindow class Ui::OpenRGBDialog2 : public QMainWindow, private SuspendResumeListener
{ {
Q_OBJECT Q_OBJECT
@ -144,7 +146,7 @@ private:
void UpdateDevicesList(); void UpdateDevicesList();
void UpdateProfileList(); void UpdateProfileList();
void closeEvent(QCloseEvent *event); void closeEvent(QCloseEvent *event);
void LoadExitProfile(); bool SelectConfigProfile(const std::string name);
void SetDetectionViewState(bool detection_showing); void SetDetectionViewState(bool detection_showing);
void SaveProfile(); void SaveProfile();
@ -162,6 +164,9 @@ private:
void ShowLEDView(); void ShowLEDView();
void HideLEDView(); void HideLEDView();
void OnSuspend();
void OnResume();
private slots: private slots:
void on_Exit(); void on_Exit();
void on_LightsOff(); void on_LightsOff();

View file

@ -335,11 +335,11 @@ void Ui::OpenRGBPluginsPage::on_EnableButton_clicked(OpenRGBPluginsEntry* entry)
if(enabled) if(enabled)
{ {
plugin_manager->LoadPlugin(entry_path); plugin_manager->EnablePlugin(entry_path);
} }
else else
{ {
plugin_manager->UnloadPlugin(entry_path); plugin_manager->DisablePlugin(entry_path);
} }
} }

View file

@ -288,9 +288,13 @@ void OpenRGBSettingsPage::UpdateProfiles()
if(profile_manager != NULL) if(profile_manager != NULL)
{ {
ui->ComboBoxAutoStartProfile->blockSignals(true); ui->ComboBoxAutoStartProfile->blockSignals(true);
ui->ComboBoxSuspendProfile->blockSignals(true);
ui->ComboBoxResumeProfile->blockSignals(true);
ui->ComboBoxExitProfile->blockSignals(true); ui->ComboBoxExitProfile->blockSignals(true);
ui->ComboBoxAutoStartProfile->clear(); ui->ComboBoxAutoStartProfile->clear();
ui->ComboBoxSuspendProfile->clear();
ui->ComboBoxResumeProfile->clear();
ui->ComboBoxExitProfile->clear(); ui->ComboBoxExitProfile->clear();
for(std::size_t profile_index = 0; profile_index < profile_manager->profile_list.size(); profile_index++) 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()); QString new_profile = QString(profile_manager->profile_list[profile_index].c_str());
ui->ComboBoxAutoStartProfile->addItem(new_profile); ui->ComboBoxAutoStartProfile->addItem(new_profile);
ui->ComboBoxSuspendProfile->addItem(new_profile);
ui->ComboBoxResumeProfile->addItem(new_profile);
ui->ComboBoxExitProfile->addItem(new_profile); ui->ComboBoxExitProfile->addItem(new_profile);
} }
ui->ComboBoxAutoStartProfile->blockSignals(false); ui->ComboBoxAutoStartProfile->blockSignals(false);
ui->ComboBoxSuspendProfile->blockSignals(false);
ui->ComboBoxResumeProfile->blockSignals(false);
ui->ComboBoxExitProfile->blockSignals(false); ui->ComboBoxExitProfile->blockSignals(false);
} }
@ -330,28 +338,88 @@ void OpenRGBSettingsPage::UpdateProfiles()
\*---------------------------------------------------------*/ \*---------------------------------------------------------*/
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")) json autoload_profiles = ui_settings["autoload_profiles"];
{
bool is_set_on_exit = ui_settings["exit_profile"]["set_on_exit"];
ui->CheckboxSetOnExit->setChecked(is_set_on_exit); if(autoload_profiles.contains("exit_profile"))
ui->ComboBoxExitProfile->setEnabled(is_set_on_exit); {
json profile = autoload_profiles["exit_profile"];
if(profile.contains("enabled"))
{
bool is_enabled = profile["enabled"].get<bool>();
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<std::string>();
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"))
{ {
/*-----------------------------------------------------*\ json profile = autoload_profiles["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<std::string>();
int profile_index = ui->ComboBoxExitProfile->findText(QString::fromStdString(profile_name));
if(profile_index > -1) if(profile.contains("enabled"))
{ {
ui->ComboBoxExitProfile->setCurrentIndex(profile_index); bool is_enabled = profile["enabled"].get<bool>();
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<std::string>();
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<bool>();
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<std::string>();
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) void Ui::OpenRGBSettingsPage::on_CheckboxSetOnExit_clicked(bool checked)
{ {
json ui_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("UserInterface"); json ui_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("UserInterface");
ui_settings["exit_profile"]["set_on_exit"] = checked; ui_settings["autoload_profiles"]["exit_profile"]["enabled"] = checked;
ui_settings["exit_profile"]["profile_name"] = ui->ComboBoxExitProfile->currentText().toStdString(); ui_settings["autoload_profiles"]["exit_profile"]["name"] = ui->ComboBoxExitProfile->currentText().toStdString();
ResourceManager::get()->GetSettingsManager()->SetSettings("UserInterface", ui_settings); ResourceManager::get()->GetSettingsManager()->SetSettings("UserInterface", ui_settings);
SaveSettings(); SaveSettings();
@ -474,8 +542,46 @@ void Ui::OpenRGBSettingsPage::on_CheckboxSetOnExit_clicked(bool checked)
void Ui::OpenRGBSettingsPage::on_ComboBoxExitProfile_currentTextChanged(const QString exit_profile_name) void Ui::OpenRGBSettingsPage::on_ComboBoxExitProfile_currentTextChanged(const QString exit_profile_name)
{ {
json ui_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("UserInterface"); json ui_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("UserInterface");
ui_settings["exit_profile"]["profile_name"] = exit_profile_name.toStdString(); 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); ResourceManager::get()->GetSettingsManager()->SetSettings("UserInterface", ui_settings);
SaveSettings(); SaveSettings();
} }

View file

@ -83,6 +83,10 @@ private slots:
void on_CheckboxSetOnExit_clicked(bool checked); void on_CheckboxSetOnExit_clicked(bool checked);
void on_ComboBoxExitProfile_currentTextChanged(const QString exit_profile_name); 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_CheckboxDisableKeyExpansion_clicked();
void on_CheckboxShowLEDView_clicked(); void on_CheckboxShowLEDView_clicked();
}; };

View file

@ -85,7 +85,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="30" column="0"> <item row="32" column="0">
<widget class="QCheckBox" name="CheckboxSetOnExit"> <widget class="QCheckBox" name="CheckboxSetOnExit">
<property name="text"> <property name="text">
<string>Set Profile on Exit</string> <string>Set Profile on Exit</string>
@ -119,7 +119,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="30" column="1"> <item row="32" column="1">
<widget class="QComboBox" name="ComboBoxExitProfile"/> <widget class="QComboBox" name="ComboBoxExitProfile"/>
</item> </item>
<item row="14" column="0"> <item row="14" column="0">
@ -146,14 +146,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="31" column="0"> <item row="33" column="0">
<widget class="QLabel" name="AutoStartStatusLabel"> <widget class="QLabel" name="AutoStartStatusLabel">
<property name="text"> <property name="text">
<string>Start at Login Status</string> <string>Start at Login Status</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="32" column="0"> <item row="34" column="0">
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
@ -278,6 +278,26 @@
<item row="12" column="1"> <item row="12" column="1">
<widget class="QComboBox" name="ComboBoxHexFormat"/> <widget class="QComboBox" name="ComboBoxHexFormat"/>
</item> </item>
<item row="30" column="0">
<widget class="QCheckBox" name="CheckboxSetOnSuspend">
<property name="text">
<string>Set Profile on Suspend</string>
</property>
</widget>
</item>
<item row="30" column="1">
<widget class="QComboBox" name="ComboBoxSuspendProfile"/>
</item>
<item row="31" column="0">
<widget class="QCheckBox" name="CheckboxSetOnResume">
<property name="text">
<string>Set Profile on Resume</string>
</property>
</widget>
</item>
<item row="31" column="1">
<widget class="QComboBox" name="ComboBoxResumeProfile"/>
</item>
</layout> </layout>
</widget> </widget>
</widget> </widget>