view src/gui/theme.cc @ 266:1a6a5d3a94cd

dep/animone: make bsd.cc and x11.cc actually work apparently I broke these, and even now the x11 code *still* doesn't want to work correctly (at least on FreeBSD). half of the PID response codes are just 0 or the PID for the X server itself... wtf? maybe dwm just doesn't support the XRes extension, or I'm just stupid. i don't know.
author Paper <paper@paper.us.eu.org>
date Thu, 11 Apr 2024 22:05:41 -0400
parents 862d0d8619f6
children 657fda1b9cac
line wrap: on
line source

#include "core/config.h"
#include "core/session.h"
#include <QApplication>
#include <QDebug>
#include <QFile>
#include <QStyleFactory>
#include <QTextStream>
#ifdef MACOSX
#	include "sys/osx/dark_theme.h"
#elif WIN32
#	include "sys/win32/dark_theme.h"
#else
#	ifdef GLIB
#		include "sys/glib/dark_theme.h"
#	endif
#endif

/* Weird quirks of this implementation:
 *   1. Dark mode stuff in Qt changes a lot and Qt 5 and Qt 6 are massively different
 *   2. Some widgets, i.e. QTabWidget, QTabBar, etc., just completely IGNORE the QPalette setting
 *      on different platforms and the only way to fix it is by using Fusion
 *   3. Windows dark mode support in Qt 6.5 (with Fusion) is completely unavoidable
 */

namespace Theme {

Theme::Theme(Themes theme) {
	this->theme = theme;
}

Themes Theme::GetTheme() const {
	return theme;
}

bool Theme::IsInDarkTheme() const {
	if (theme != Themes::OS)
		return (theme == Themes::DARK);
#ifdef MACOSX
	if (osx::DarkThemeAvailable())
		return osx::IsInDarkTheme();
#elif defined(WIN32)
	if (win32::DarkThemeAvailable())
		return win32::IsInDarkTheme();
#else
#	ifdef GLIB
	return glib::IsInDarkTheme();
#	endif
#endif
	return (theme == Themes::DARK);
}

void Theme::SetToDarkTheme() {
	/* macOS >= 10.14 has its own global dark theme,
	   use it :) */
#ifdef MACOSX
	if (osx::DarkThemeAvailable())
		osx::SetToDarkTheme();
	else
#elif defined(WIN32)
	if (win32::DarkThemeAvailable())
		win32::SetTitleBarsToBlack(true);
#endif
		SetStyleSheet(Themes::DARK);
}

void Theme::SetToLightTheme() {
#ifdef MACOSX
	if (osx::DarkThemeAvailable())
		osx::SetToLightTheme();
	else
#elif defined(WIN32)
	if (win32::DarkThemeAvailable())
		win32::SetTitleBarsToBlack(false);
#endif
		SetStyleSheet(Themes::LIGHT);
}

Themes Theme::GetCurrentOSTheme() const {
	return IsInDarkTheme() ? Themes::DARK : Themes::LIGHT;

	/* Currently OS detection only supports Windows and macOS.
	   Please don't be shy if you're willing to port it to other OSes
	   (or desktop environments, or window managers) */
	return Themes::LIGHT;
}

/* this function is private, and should stay that way */
void Theme::SetStyleSheet(Themes theme) {
	switch (theme) {
		case Themes::DARK: {
			const QColor darkGray(53, 53, 53);
			const QColor gray(128, 128, 128);
			const QColor black(25, 25, 25);
			const QColor blue(42, 130, 218);

			QPalette pal(QApplication::style()->standardPalette());
			pal.setColor(QPalette::Window, darkGray);
			pal.setColor(QPalette::WindowText, Qt::white);
			pal.setColor(QPalette::Base, black);
			pal.setColor(QPalette::AlternateBase, darkGray);
			pal.setColor(QPalette::ToolTipBase, blue);
			pal.setColor(QPalette::ToolTipText, Qt::white);
			pal.setColor(QPalette::Text, Qt::white);
			pal.setColor(QPalette::Button, darkGray);
			pal.setColor(QPalette::ButtonText, Qt::white);
			pal.setColor(QPalette::Link, blue);
			pal.setColor(QPalette::Highlight, blue);
			pal.setColor(QPalette::HighlightedText, Qt::black);

			pal.setColor(QPalette::Active, QPalette::Button, gray.darker());
			pal.setColor(QPalette::Disabled, QPalette::ButtonText, gray);
			pal.setColor(QPalette::Disabled, QPalette::WindowText, gray);
			pal.setColor(QPalette::Disabled, QPalette::Text, gray);
			pal.setColor(QPalette::Disabled, QPalette::Light, darkGray);
			qApp->setPalette(pal);

#ifdef WIN32
			qApp->setStyleSheet([] {
				QFile f(":/dark.qss");
				if (!f.exists())
					return QStringLiteral("");
				f.open(QFile::ReadOnly | QFile::Text);
				QTextStream ts(&f);
				return ts.readAll();
			}());
#endif
			break;
		}
		default:
			/* this sucks, it relies on the standard palette which
			 * may or may not be a dark style itself. */
			QPalette pal(QApplication::style()->standardPalette());
#ifdef WIN32 /* fuck you Qt 6 */
			pal.setColor(QPalette::Window, QColor(0xF0, 0xF0, 0xF0));
#endif
			qApp->setPalette(pal);

			qApp->setStyleSheet("");
			break;
	}
}

void Theme::SetTheme(Themes theme) {
	switch (theme) {
		case Themes::LIGHT: SetToLightTheme(); break;
		case Themes::DARK: SetToDarkTheme(); break;
		case Themes::OS:
			if (GetCurrentOSTheme() == Themes::LIGHT)
				SetToLightTheme();
			else
				SetToDarkTheme();
			break;
	}
	this->theme = theme;
}

void Theme::RepaintCurrentTheme() {
	Theme::SetTheme(theme);
}

} // namespace Theme