Dark mode theme only for Windows

This commit is contained in:
Cacodemon345
2024-01-16 01:39:32 +06:00
parent 2cbfc8e047
commit bf99a1aaad
6 changed files with 2511 additions and 1 deletions

View File

@@ -181,6 +181,7 @@ add_library(ui STATIC
qt_mediahistorymanager.hpp qt_mediahistorymanager.hpp
../qt_resources.qrc ../qt_resources.qrc
./qdarkstyle/dark/darkstyle.qrc
) )
if(RTMIDI) if(RTMIDI)
@@ -198,7 +199,7 @@ if(WIN32)
target_sources(plat PRIVATE win_joystick_rawinput.c) target_sources(plat PRIVATE win_joystick_rawinput.c)
endif() endif()
target_sources(ui PRIVATE qt_d3d9renderer.hpp qt_d3d9renderer.cpp) target_sources(ui PRIVATE qt_d3d9renderer.hpp qt_d3d9renderer.cpp)
target_link_libraries(86Box hid d3d9) target_link_libraries(86Box hid d3d9 dwmapi)
# CMake 3.22 messed this up for clang/clang++ # CMake 3.22 messed this up for clang/clang++
# See https://gitlab.kitware.com/cmake/cmake/-/issues/22611 # See https://gitlab.kitware.com/cmake/cmake/-/issues/22611

View File

@@ -0,0 +1,216 @@
<RCC warning="WARNING! File created programmatically. All changes made in this file will be lost!">
<qresource prefix="qss_icons/dark">
<file>rc/arrow_down.png</file>
<file>rc/arrow_down@2x.png</file>
<file>rc/arrow_down_disabled.png</file>
<file>rc/arrow_down_disabled@2x.png</file>
<file>rc/arrow_down_focus.png</file>
<file>rc/arrow_down_focus@2x.png</file>
<file>rc/arrow_down_pressed.png</file>
<file>rc/arrow_down_pressed@2x.png</file>
<file>rc/arrow_left.png</file>
<file>rc/arrow_left@2x.png</file>
<file>rc/arrow_left_disabled.png</file>
<file>rc/arrow_left_disabled@2x.png</file>
<file>rc/arrow_left_focus.png</file>
<file>rc/arrow_left_focus@2x.png</file>
<file>rc/arrow_left_pressed.png</file>
<file>rc/arrow_left_pressed@2x.png</file>
<file>rc/arrow_right.png</file>
<file>rc/arrow_right@2x.png</file>
<file>rc/arrow_right_disabled.png</file>
<file>rc/arrow_right_disabled@2x.png</file>
<file>rc/arrow_right_focus.png</file>
<file>rc/arrow_right_focus@2x.png</file>
<file>rc/arrow_right_pressed.png</file>
<file>rc/arrow_right_pressed@2x.png</file>
<file>rc/arrow_up.png</file>
<file>rc/arrow_up@2x.png</file>
<file>rc/arrow_up_disabled.png</file>
<file>rc/arrow_up_disabled@2x.png</file>
<file>rc/arrow_up_focus.png</file>
<file>rc/arrow_up_focus@2x.png</file>
<file>rc/arrow_up_pressed.png</file>
<file>rc/arrow_up_pressed@2x.png</file>
<file>rc/base_icon.png</file>
<file>rc/base_icon@2x.png</file>
<file>rc/base_icon_disabled.png</file>
<file>rc/base_icon_disabled@2x.png</file>
<file>rc/base_icon_focus.png</file>
<file>rc/base_icon_focus@2x.png</file>
<file>rc/base_icon_pressed.png</file>
<file>rc/base_icon_pressed@2x.png</file>
<file>rc/branch_closed.png</file>
<file>rc/branch_closed@2x.png</file>
<file>rc/branch_closed_disabled.png</file>
<file>rc/branch_closed_disabled@2x.png</file>
<file>rc/branch_closed_focus.png</file>
<file>rc/branch_closed_focus@2x.png</file>
<file>rc/branch_closed_pressed.png</file>
<file>rc/branch_closed_pressed@2x.png</file>
<file>rc/branch_end.png</file>
<file>rc/branch_end@2x.png</file>
<file>rc/branch_end_disabled.png</file>
<file>rc/branch_end_disabled@2x.png</file>
<file>rc/branch_end_focus.png</file>
<file>rc/branch_end_focus@2x.png</file>
<file>rc/branch_end_pressed.png</file>
<file>rc/branch_end_pressed@2x.png</file>
<file>rc/branch_line.png</file>
<file>rc/branch_line@2x.png</file>
<file>rc/branch_line_disabled.png</file>
<file>rc/branch_line_disabled@2x.png</file>
<file>rc/branch_line_focus.png</file>
<file>rc/branch_line_focus@2x.png</file>
<file>rc/branch_line_pressed.png</file>
<file>rc/branch_line_pressed@2x.png</file>
<file>rc/branch_more.png</file>
<file>rc/branch_more@2x.png</file>
<file>rc/branch_more_disabled.png</file>
<file>rc/branch_more_disabled@2x.png</file>
<file>rc/branch_more_focus.png</file>
<file>rc/branch_more_focus@2x.png</file>
<file>rc/branch_more_pressed.png</file>
<file>rc/branch_more_pressed@2x.png</file>
<file>rc/branch_open.png</file>
<file>rc/branch_open@2x.png</file>
<file>rc/branch_open_disabled.png</file>
<file>rc/branch_open_disabled@2x.png</file>
<file>rc/branch_open_focus.png</file>
<file>rc/branch_open_focus@2x.png</file>
<file>rc/branch_open_pressed.png</file>
<file>rc/branch_open_pressed@2x.png</file>
<file>rc/checkbox_checked.png</file>
<file>rc/checkbox_checked@2x.png</file>
<file>rc/checkbox_checked_disabled.png</file>
<file>rc/checkbox_checked_disabled@2x.png</file>
<file>rc/checkbox_checked_focus.png</file>
<file>rc/checkbox_checked_focus@2x.png</file>
<file>rc/checkbox_checked_pressed.png</file>
<file>rc/checkbox_checked_pressed@2x.png</file>
<file>rc/checkbox_indeterminate.png</file>
<file>rc/checkbox_indeterminate@2x.png</file>
<file>rc/checkbox_indeterminate_disabled.png</file>
<file>rc/checkbox_indeterminate_disabled@2x.png</file>
<file>rc/checkbox_indeterminate_focus.png</file>
<file>rc/checkbox_indeterminate_focus@2x.png</file>
<file>rc/checkbox_indeterminate_pressed.png</file>
<file>rc/checkbox_indeterminate_pressed@2x.png</file>
<file>rc/checkbox_unchecked.png</file>
<file>rc/checkbox_unchecked@2x.png</file>
<file>rc/checkbox_unchecked_disabled.png</file>
<file>rc/checkbox_unchecked_disabled@2x.png</file>
<file>rc/checkbox_unchecked_focus.png</file>
<file>rc/checkbox_unchecked_focus@2x.png</file>
<file>rc/checkbox_unchecked_pressed.png</file>
<file>rc/checkbox_unchecked_pressed@2x.png</file>
<file>rc/line_horizontal.png</file>
<file>rc/line_horizontal@2x.png</file>
<file>rc/line_horizontal_disabled.png</file>
<file>rc/line_horizontal_disabled@2x.png</file>
<file>rc/line_horizontal_focus.png</file>
<file>rc/line_horizontal_focus@2x.png</file>
<file>rc/line_horizontal_pressed.png</file>
<file>rc/line_horizontal_pressed@2x.png</file>
<file>rc/line_vertical.png</file>
<file>rc/line_vertical@2x.png</file>
<file>rc/line_vertical_disabled.png</file>
<file>rc/line_vertical_disabled@2x.png</file>
<file>rc/line_vertical_focus.png</file>
<file>rc/line_vertical_focus@2x.png</file>
<file>rc/line_vertical_pressed.png</file>
<file>rc/line_vertical_pressed@2x.png</file>
<file>rc/radio_checked.png</file>
<file>rc/radio_checked@2x.png</file>
<file>rc/radio_checked_disabled.png</file>
<file>rc/radio_checked_disabled@2x.png</file>
<file>rc/radio_checked_focus.png</file>
<file>rc/radio_checked_focus@2x.png</file>
<file>rc/radio_checked_pressed.png</file>
<file>rc/radio_checked_pressed@2x.png</file>
<file>rc/radio_unchecked.png</file>
<file>rc/radio_unchecked@2x.png</file>
<file>rc/radio_unchecked_disabled.png</file>
<file>rc/radio_unchecked_disabled@2x.png</file>
<file>rc/radio_unchecked_focus.png</file>
<file>rc/radio_unchecked_focus@2x.png</file>
<file>rc/radio_unchecked_pressed.png</file>
<file>rc/radio_unchecked_pressed@2x.png</file>
<file>rc/toolbar_move_horizontal.png</file>
<file>rc/toolbar_move_horizontal@2x.png</file>
<file>rc/toolbar_move_horizontal_disabled.png</file>
<file>rc/toolbar_move_horizontal_disabled@2x.png</file>
<file>rc/toolbar_move_horizontal_focus.png</file>
<file>rc/toolbar_move_horizontal_focus@2x.png</file>
<file>rc/toolbar_move_horizontal_pressed.png</file>
<file>rc/toolbar_move_horizontal_pressed@2x.png</file>
<file>rc/toolbar_move_vertical.png</file>
<file>rc/toolbar_move_vertical@2x.png</file>
<file>rc/toolbar_move_vertical_disabled.png</file>
<file>rc/toolbar_move_vertical_disabled@2x.png</file>
<file>rc/toolbar_move_vertical_focus.png</file>
<file>rc/toolbar_move_vertical_focus@2x.png</file>
<file>rc/toolbar_move_vertical_pressed.png</file>
<file>rc/toolbar_move_vertical_pressed@2x.png</file>
<file>rc/toolbar_separator_horizontal.png</file>
<file>rc/toolbar_separator_horizontal@2x.png</file>
<file>rc/toolbar_separator_horizontal_disabled.png</file>
<file>rc/toolbar_separator_horizontal_disabled@2x.png</file>
<file>rc/toolbar_separator_horizontal_focus.png</file>
<file>rc/toolbar_separator_horizontal_focus@2x.png</file>
<file>rc/toolbar_separator_horizontal_pressed.png</file>
<file>rc/toolbar_separator_horizontal_pressed@2x.png</file>
<file>rc/toolbar_separator_vertical.png</file>
<file>rc/toolbar_separator_vertical@2x.png</file>
<file>rc/toolbar_separator_vertical_disabled.png</file>
<file>rc/toolbar_separator_vertical_disabled@2x.png</file>
<file>rc/toolbar_separator_vertical_focus.png</file>
<file>rc/toolbar_separator_vertical_focus@2x.png</file>
<file>rc/toolbar_separator_vertical_pressed.png</file>
<file>rc/toolbar_separator_vertical_pressed@2x.png</file>
<file>rc/transparent.png</file>
<file>rc/transparent@2x.png</file>
<file>rc/transparent_disabled.png</file>
<file>rc/transparent_disabled@2x.png</file>
<file>rc/transparent_focus.png</file>
<file>rc/transparent_focus@2x.png</file>
<file>rc/transparent_pressed.png</file>
<file>rc/transparent_pressed@2x.png</file>
<file>rc/window_close.png</file>
<file>rc/window_close@2x.png</file>
<file>rc/window_close_disabled.png</file>
<file>rc/window_close_disabled@2x.png</file>
<file>rc/window_close_focus.png</file>
<file>rc/window_close_focus@2x.png</file>
<file>rc/window_close_pressed.png</file>
<file>rc/window_close_pressed@2x.png</file>
<file>rc/window_grip.png</file>
<file>rc/window_grip@2x.png</file>
<file>rc/window_grip_disabled.png</file>
<file>rc/window_grip_disabled@2x.png</file>
<file>rc/window_grip_focus.png</file>
<file>rc/window_grip_focus@2x.png</file>
<file>rc/window_grip_pressed.png</file>
<file>rc/window_grip_pressed@2x.png</file>
<file>rc/window_minimize.png</file>
<file>rc/window_minimize@2x.png</file>
<file>rc/window_minimize_disabled.png</file>
<file>rc/window_minimize_disabled@2x.png</file>
<file>rc/window_minimize_focus.png</file>
<file>rc/window_minimize_focus@2x.png</file>
<file>rc/window_minimize_pressed.png</file>
<file>rc/window_minimize_pressed@2x.png</file>
<file>rc/window_undock.png</file>
<file>rc/window_undock@2x.png</file>
<file>rc/window_undock_disabled.png</file>
<file>rc/window_undock_disabled@2x.png</file>
<file>rc/window_undock_focus.png</file>
<file>rc/window_undock_focus@2x.png</file>
<file>rc/window_undock_pressed.png</file>
<file>rc/window_undock_pressed@2x.png</file>
</qresource>
<qresource prefix="qdarkstyle/dark">
<file>darkstyle.qss</file>
</qresource>
</RCC>

File diff suppressed because it is too large Load Diff

View File

@@ -30,6 +30,8 @@
#include <QFont> #include <QFont>
#include <QDialog> #include <QDialog>
#include <QMessageBox> #include <QMessageBox>
#include <QFile>
#include <QTextStream>
#ifdef QT_STATIC #ifdef QT_STATIC
/* Static builds need plugin imports */ /* Static builds need plugin imports */
@@ -154,6 +156,10 @@ main_thread_fn()
static std::thread *main_thread; static std::thread *main_thread;
#ifdef Q_OS_WINDOWS
extern bool windows_is_light_theme();
#endif
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
@@ -168,6 +174,22 @@ main(int argc, char *argv[])
QApplication app(argc, argv); QApplication app(argc, argv);
QLocale::setDefault(QLocale::C); QLocale::setDefault(QLocale::C);
#ifdef Q_OS_WINDOWS
Q_INIT_RESOURCE(darkstyle);
if (!windows_is_light_theme()) {
QFile f(":qdarkstyle/dark/darkstyle.qss");
if (!f.exists()) {
printf("Unable to set stylesheet, file not found\n");
} else {
f.open(QFile::ReadOnly | QFile::Text);
QTextStream ts(&f);
qApp->setStyleSheet(ts.readAll());
}
}
#endif
qt_set_sequence_auto_mnemonic(false); qt_set_sequence_auto_mnemonic(false);
Q_INIT_RESOURCE(qt_resources); Q_INIT_RESOURCE(qt_resources);
Q_INIT_RESOURCE(qt_translations); Q_INIT_RESOURCE(qt_translations);

View File

@@ -19,6 +19,13 @@
#include <QComboBox> #include <QComboBox>
#include <QAbstractItemView> #include <QAbstractItemView>
#ifdef Q_OS_WINDOWS
#include <dwmapi.h>
#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
#endif
#endif
int int
StyleOverride::styleHint( StyleOverride::styleHint(
StyleHint hint, StyleHint hint,
@@ -48,6 +55,10 @@ StyleOverride::polish(QWidget *widget)
widget->setWindowFlag(Qt::MSWindowsFixedSizeDialogHint, true); widget->setWindowFlag(Qt::MSWindowsFixedSizeDialogHint, true);
} }
widget->setWindowFlag(Qt::WindowContextHelpButtonHint, false); widget->setWindowFlag(Qt::WindowContextHelpButtonHint, false);
#ifdef Q_OS_WINDOWS
BOOL DarkMode = TRUE;
DwmSetWindowAttribute((HWND)widget->winId(), DWMWA_USE_IMMERSIVE_DARK_MODE, (LPCVOID)&DarkMode, sizeof(DarkMode));
#endif
} }
if (qobject_cast<QComboBox *>(widget)) { if (qobject_cast<QComboBox *>(widget)) {

View File

@@ -34,10 +34,17 @@
#include "qt_winrawinputfilter.hpp" #include "qt_winrawinputfilter.hpp"
#include <QMenuBar> #include <QMenuBar>
#include <QFile>
#include <QTextStream>
#include <QApplication>
#include <atomic> #include <atomic>
#include <windows.h> #include <windows.h>
#include <dwmapi.h>
#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
#endif
#include <86box/keyboard.h> #include <86box/keyboard.h>
#include <86box/mouse.h> #include <86box/mouse.h>
@@ -49,6 +56,34 @@
#include "qt_rendererstack.hpp" #include "qt_rendererstack.hpp"
bool windows_is_light_theme() {
// based on https://stackoverflow.com/questions/51334674/how-to-detect-windows-10-light-dark-mode-in-win32-application
// The value is expected to be a REG_DWORD, which is a signed 32-bit little-endian
auto buffer = std::vector<char>(4);
auto cbData = static_cast<DWORD>(buffer.size() * sizeof(char));
auto res = RegGetValueW(
HKEY_CURRENT_USER,
L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
L"AppsUseLightTheme",
RRF_RT_REG_DWORD, // expected value type
nullptr,
buffer.data(),
&cbData);
if (res != ERROR_SUCCESS) {
return 1;
}
// convert bytes written to our buffer to an int, assuming little-endian
auto i = int(buffer[3] << 24 |
buffer[2] << 16 |
buffer[1] << 8 |
buffer[0]);
return i == 1;
}
extern "C" void win_joystick_handle(PRAWINPUT); extern "C" void win_joystick_handle(PRAWINPUT);
std::unique_ptr<WindowsRawInputFilter> std::unique_ptr<WindowsRawInputFilter>
WindowsRawInputFilter::Register(MainWindow *window) WindowsRawInputFilter::Register(MainWindow *window)
@@ -124,6 +159,24 @@ WindowsRawInputFilter::nativeEventFilter(const QByteArray &eventType, void *mess
} }
return true; return true;
} else if (msg && msg->message == WM_SETTINGCHANGE && msg->lParam != NULL && wcscmp(L"ImmersiveColorSet", (wchar_t*)msg->lParam) == 0) {
if (!windows_is_light_theme()) {
QFile f(":qdarkstyle/dark/darkstyle.qss");
if (!f.exists()) {
printf("Unable to set stylesheet, file not found\n");
} else {
f.open(QFile::ReadOnly | QFile::Text);
QTextStream ts(&f);
qApp->setStyleSheet(ts.readAll());
}
// From Dolphin emulator code:
// TODO: When switching from light to dark, the window decorations remain light. Qt seems very
// convinced that it needs to change these in response to this message, so even if we set them
// to dark here, Qt sets them back to light afterwards.
} else {
qApp->setStyleSheet("");
}
} }
/* Stop processing of Alt-F4 */ /* Stop processing of Alt-F4 */