dark/light mode & accent color

This commit is contained in:
Hane 2024-11-26 17:11:01 +01:00
commit 60890cecad
9 changed files with 178 additions and 44 deletions

View file

@ -653,7 +653,7 @@ Overseer::Overseer() : epsc(this){
}
void Overseer::populateSystemValues() {
updateDarkMode();
updateColors();
}
void Overseer::openControlPanel() {
@ -688,7 +688,7 @@ ProcessedNativeEvent Overseer::processTopLevelWindowMessage(void* msg) {
switch(message->message) {
case WM_SETTINGCHANGE:
if(!wcscmp(((wchar_t*)message->lParam), L"ImmersiveColorSet"))
return updateDarkMode();
return updateColors();
break;
default:
return ProcessedNativeEvent::NONE;
@ -699,23 +699,36 @@ ProcessedNativeEvent Overseer::processTopLevelWindowMessage(void* msg) {
#endif
}
ProcessedNativeEvent Overseer::updateDarkMode(){
ProcessedNativeEvent Overseer::updateColors() {
// DwmGetColorizationColor( WM_DWMCOLORIZATIONCOLORCHANGED
DWORD value = 0;
DWORD size = sizeof(DWORD);
LSTATUS result;
//Theme bg color
result = RegGetValueW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", L"AppsUseLightTheme", RRF_RT_REG_DWORD, nullptr, &value, &size);
this->lightMode = (bool)value;
return ProcessedNativeEvent::LIGHT_MODE;
//Accent color
result = RegGetValueW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\DWM", L"ColorizationColor", RRF_RT_REG_DWORD, nullptr, &value, &size);
if (result == ERROR_SUCCESS) {
this->accentColor = value;
} else this->accentColor = 0xffffffff;
return ProcessedNativeEvent::COLORS;
}
bool Overseer::isLightMode() {
return this->lightMode;
}
uint32_t Overseer::getAccentColor() {
return this->accentColor;
}
NGuid Overseer::getGuid() {
return guid;
}

View file

@ -113,8 +113,9 @@ class Overseer {
void populateSystemValues();
void openControlPanel();
ProcessedNativeEvent processTopLevelWindowMessage(void* msg);
ProcessedNativeEvent updateDarkMode();
ProcessedNativeEvent updateColors();
bool isLightMode();
uint32_t getAccentColor();
std::vector<Endpoint*> getPlaybackEndpoints();
std::vector<Endpoint*> getCaptureEndpoints();
@ -138,6 +139,7 @@ class Overseer {
NGuid guid;
bool lightMode;
uint32_t accentColor;
IMMDeviceEnumerator *deviceEnumerator;
EndpointSituationCallback epsc;

View file

@ -221,6 +221,10 @@ bool OverseerHandler::isLightMode() {
return this->os->isLightMode();
}
uint32_t OverseerHandler::getAccentColor() {
return this->os->getAccentColor();
}
std::vector<Endpoint*> OverseerHandler::getPlaybackEndpoints() {
return this->os->getPlaybackEndpoints();
}

View file

@ -101,6 +101,7 @@ public:
void openControlPanel();
ProcessedNativeEvent processTopLevelWindowMessage(void* msg);
bool isLightMode();
uint32_t getAccentColor();
//void setChangeFrontDefaultsFunction(std::function<void(Roles, std::wstring)> changeFrontDefaults);
//void changeFrontDefaultsCallback(Roles role, std::wstring endpointId);

View file

@ -37,8 +37,8 @@
//INIT BACK
enum ProcessedNativeEvent {
NONE = 0,
LIGHT_MODE = (1 << 0),
NONE = 0,
COLORS = (1 << 0),
};
enum AudioChannel {

View file

@ -7,19 +7,27 @@ bool DarkModeEventFilter::nativeEventFilter(const QByteArray &eventType, void *m
if (eventType == "windows_generic_MSG") {
ProcessedNativeEvent event = osh->processTopLevelWindowMessage(message);
switch(event) {
case LIGHT_MODE:
case COLORS:
StylingHelper::setBackgroundColor(osh->isLightMode());
//Update accent color across entire app
{
uint32_t color = osh->getAccentColor();
uint8_t r, g, b, a;
if (StylingHelper::argbToDiscreteValues(osh->getAccentColor(), &r, &g, &b, &a)) {
const QWidgetList topLevelWidgets = QApplication::topLevelWidgets();
for (QWidget *widget : topLevelWidgets) {
if(qobject_cast<MainWindow*>(widget)) {
((MainWindow*)widget)->updateColor(r, g, b, a);
}
}
}
}
return true;
break;
default:
break;
}
/*
* if ([event type] == NSKeyDown) {
* // Handle key event
* qDebug() << QString::fromNSString([event characters]);
* }
*/
}
return false;
}
@ -124,8 +132,8 @@ void MeterSlider::paintEvent(QPaintEvent *event) {
sliderComplex2.subControls |= QStyle::SC_SliderTickmarks;
QPainter painter(this);
QStyle* stle = QApplication::style();
stle->drawComplexControl((QStyle::ComplexControl)CC_MeterSlider, &sliderComplex2, &painter, this);
QStyle* style = QApplication::style();
style->drawComplexControl((QStyle::ComplexControl)CC_MeterSlider, &sliderComplex2, &painter, this);
//Q_D(QSlider);
@ -252,6 +260,13 @@ QRect MainWindow::setSizePosition(QScreen* screen, int width, int height) {
}
}
void MainWindow::updateColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
QColor color(r, g, b, a);
QPalette pal = QPalette(color);
pal.setColor(QPalette::Highlight, color);
scrollArea->verticalScrollBar()->setPalette(pal);
}
void MainWindow::compose() {
//todo: invalidate layout when adding sessions with window open
//We need dynamically added child widgets to expand so that we know their height
@ -1022,6 +1037,10 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scrollArea->setContentsMargins(QMargins(0, 0, 0, 0));
//ScrollBarFocusFilter focusFilter = new ScrollBarFocusFilter(this);
scrollArea->verticalScrollBar()->installEventFilter(this);
scrollArea->horizontalScrollBar()->installEventFilter(this);
//scrollArea->verticalScrollBar()->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
//scrollArea->verticalScrollBar()->setSingleStep(1);
@ -1071,6 +1090,13 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
}
});
/*
* Set accent color
*/
uint8_t a, r, g, b;
if (StylingHelper::argbToDiscreteValues(osh->getAccentColor(), &r, &g, &b, &a))
this->updateColor(r, g, b, a);
/*
* Set of function callback definitons for EndpointSituationCallback
*/
@ -1090,6 +1116,50 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
}
bool MainWindow::eventFilter(QObject *object, QEvent *event) {
//QScrollBar* widgetCast = qobject_cast<QScrollBar*>(object);
if (object == scrollArea->verticalScrollBar()) {
[[maybe_unused]] QEvent::Type tipo = event->type();
if (event->type() == QHoverEvent::HoverEnter) {
log_debugcpp("Hover event: ");
log_debugcpp("\tGlobal pos: "
+ std::to_string(((QHoverEvent*)event)->globalPosition().x())
+ ", "
+ std::to_string(((QHoverEvent*)event)->globalPosition().y()));
log_debugcpp("\tNewWid pos: "
+ std::to_string(((QHoverEvent*)event)->position().x())
+ ", "
+ std::to_string(((QHoverEvent*)event)->position().y()));
log_debugcpp("\tOldWid pos: "
+ std::to_string(((QHoverEvent*)event)->oldPos().x())
+ ", "
+ std::to_string(((QHoverEvent*)event)->oldPos().y()));
}
if (event->type() == QScrollEvent::ScrollFinished) {
QHoverEvent* hoverEvent = new QHoverEvent(QEvent::HoverEnter,
scrollArea->verticalScrollBar()->mapFromGlobal(QCursor::pos()),
QCursor::pos(),
scrollArea->verticalScrollBar()->mapFromGlobal(QCursor::pos()));
log_debugcpp("ScrollFinished event: ");
log_debugcpp("\tGlobal pos: "
+ std::to_string(QCursor::pos().x())
+ ", "
+ std::to_string(QCursor::pos().y()));
log_debugcpp("\tWidget pos: "
+ std::to_string(scrollArea->verticalScrollBar()->mapFromGlobal(QCursor::pos()).x())
+ ", "
+ std::to_string(scrollArea->verticalScrollBar()->mapFromGlobal(QCursor::pos()).y()));
QCoreApplication::instance()->postEvent(scrollArea->verticalScrollBar(), hoverEvent);
/*
* QCoreApplication::instance()->postEvent(this, new CustomWidgetEvent<SessionHandler*>((QEvent::Type)CustomQEvent::SessionWidgetObsolete, sessionHandler));
*/
//scrollArea->setFocus(Qt::MouseFocusReason);
return false;
}}
return false;
}
void MainWindow::flushRoleChanges() {
//TODO: bucket list deque
std::pair<Roles, std::wstring> change = roleBucketList.front();

View file

@ -182,6 +182,7 @@ public:
MainWindow(QWidget *parent = nullptr);
void reloadEndpointWidgets();
void compose();
void updateColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
protected:
void closeEvent(QCloseEvent *event) override;
@ -200,6 +201,7 @@ private slots:
private:
//std::vector<EndpointHandler*> *ephs;
bool eventFilter(QObject *object, QEvent *event);
void flushRoleChanges();
void changeFrontDefaults(Roles role, EndpointWidget* newDef, EndpointWidget* oldDef);

View file

@ -78,6 +78,29 @@ namespace StylingHelper {
QGuiApplication::setPalette(pal);
}
static inline void setAccentColor(bool lightMode) {
//QApplication* app = (QApplication*)QApplication::instance();
QPalette pal = QGuiApplication::palette();
if(lightMode) {
pal.setColor(QPalette::Window, Qt::white);
pal.setColor(QPalette::WindowText, Qt::black);
} else {
pal.setColor(QPalette::Window, Qt::black);
pal.setColor(QPalette::WindowText, Qt::white);
}
QGuiApplication::setPalette(pal);
}
static inline bool argbToDiscreteValues(uint32_t color, uint8_t *r, uint8_t *g, uint8_t *b, uint8_t *a) {
if(!r || !g || !b || !a) return false;
*a = (color >> 24) & 0xFF;
*r = (color >> 16) & 0xFF;
*g = (color >> 8) & 0xFF;
*b = color & 0xFF;
return true;
}
static inline QLatin1String operator""_L1(const char* ch, uint64_t) {
return QLatin1String(ch);
}

View file

@ -6,6 +6,7 @@
using namespace StylingHelper;
class MixerStyle : public QProxyStyle {
public:
using QProxyStyle::QProxyStyle;
@ -448,8 +449,8 @@ public:
//QColor arrowColor = QColor(188,143,143,100);
arrowColor.setAlpha(160);
const QColor bgColor = backgroundColor(option->palette, widget);
const bool isDarkBg = bgColor.red() < 128 && bgColor.green() < 128 && bgColor.blue() < 128;
const QColor appBgColor = QGuiApplication::palette().window().color();
const bool isDarkBg = appBgColor.red() < 128 && appBgColor.green() < 128 && appBgColor.blue() < 128;
if (transient) {
if (horizontal) {
@ -482,10 +483,10 @@ public:
gradient.setColorAt(0.9, buttonColor.darker(105));
gradient.setColorAt(1, buttonColor.darker(107));
} else {
gradient.setColorAt(0, bgColor.lighter(157));
gradient.setColorAt(0.1, bgColor.lighter(155));
gradient.setColorAt(0.9, bgColor.lighter(155));
gradient.setColorAt(1, bgColor.lighter(157));
gradient.setColorAt(0, appBgColor.lighter(157));
gradient.setColorAt(0.1, appBgColor.lighter(155));
gradient.setColorAt(0.9, appBgColor.lighter(155));
gradient.setColorAt(1, appBgColor.lighter(157));
}
painter->save();
@ -505,23 +506,27 @@ public:
}
QRect pixmapRect = scrollBarSlider;
QLinearGradient gradient(pixmapRect.center().x(), pixmapRect.top(),
pixmapRect.center().x(), pixmapRect.bottom());
if (!horizontal)
gradient = QLinearGradient(pixmapRect.left(), pixmapRect.center().y(),
pixmapRect.right(), pixmapRect.center().y());
QColor highlightColor = option->palette.highlight().color();
/*
* QLinearGradient gradient(pixmapRect.center().x(), pixmapRect.top(),
* pixmapRect.center().x(), pixmapRect.bottom());
* if (!horizontal)
* gradient = QLinearGradient(pixmapRect.left(), pixmapRect.center().y(),
* pixmapRect.right(), pixmapRect.center().y());
*/
QLinearGradient highlightedGradient = gradient;
//QLinearGradient highlightedGradient = gradient;
QColor midColor2 = mergedColors(gradientStartColor, gradientStopColor, 40);
gradient.setColorAt(0, calculateButtonColor(option->palette).lighter(108));
gradient.setColorAt(1, calculateButtonColor(option->palette));
QColor heldColor = 0xc4e3d7e0;//Qt::gray;//osh->isLightMode() ? Qt::white : Qt::black;
//gradient.setColorAt(0, option->palette.highlight().color());
//gradient.setColorAt(1, option->palette.highlight().color());
highlightedGradient.setColorAt(0, gradientStartColor.darker(102));
highlightedGradient.setColorAt(1, gradientStopColor.lighter(102));
//highlightedGradient.setColorAt(0, gradientStartColor.darker(102));
//highlightedGradient.setColorAt(1, gradientStopColor.lighter(102));
// Paint slider
if (scrollBar->subControls & SC_ScrollBarSlider) {
log_debugcpp("Final scrollbar paint if");
if (transient) {
QRect rect = scrollBarSlider.adjusted(horizontal ? 1 : 2, horizontal ? 2 : 1, -1, -1);
painter->setPen(Qt::NoPen);
@ -535,14 +540,20 @@ public:
} else {
QRect pixmapRect = scrollBarSlider;
painter->setPen(QPen(alphaOutline));
if (option->state & State_Sunken && scrollBar->activeSubControls & SC_ScrollBarSlider)
painter->setBrush(midColor2);
else if (option->state & State_MouseOver && scrollBar->activeSubControls & SC_ScrollBarSlider)
painter->setBrush(highlightedGradient);
else if (!isDarkBg)
painter->setBrush(gradient);
else
painter->setBrush(midColor2);
if (option->state & State_Sunken
&& scrollBar->activeSubControls & SC_ScrollBarSlider)
painter->setBrush(heldColor);
else if (option->state & State_MouseOver
&& scrollBar->activeSubControls & SC_ScrollBarSlider) {
painter->setBrush(highlightColor);
}
else //if (!isDarkBg)
if(!isDarkBg)
painter->setBrush(Qt::black);
else painter->setBrush(Qt::white);
//else
// painter->setBrush(heldColor);
painter->drawRoundedRect(pixmapRect.adjusted(horizontal ? -1 : 0, horizontal ? 0 : -1, horizontal ? 0 : -1, horizontal ? -1 : 0), 5, 5);
@ -675,6 +686,13 @@ private:
return gradient;
}
QColor highlightedOutline(const QPalette &pal) const {
QColor highlightedOutline = highlight(pal);//.darker(25);//QColor(Qt::green);
if (highlightedOutline.value() > 160)
highlightedOutline.setHsl(highlightedOutline.hue(), highlightedOutline.saturation(), 160);
return highlightedOutline;
}
QColor calculateButtonColor(const QPalette &pal) const {
QColor buttonColor = pal.button().color();
int val = qGray(buttonColor.rgb());
@ -835,3 +853,4 @@ private:
*/
//void MixerStyle::