yuzu-emu
/
yuzu
Archived
1
0
Fork 0

Linux: handle dark system themes nicely

yuzu's default theme doesn't specify everything, which is fine for
windows, but in linux anything unspecified is set to the users theme.

Symptoms of this are that a linux user with a dark theme won't think
to change the theme to a dark theme when first using yuzu

Idea here is to try and support arbitrary themes on linux.

preliminary work on a "default_dark" theme, used only as overlay
for any themes that are measured to be dark mode.

Other work done:

FreeDesktop standard icon names:
plus -> list-add
delete refresh, we use view-refresh

remove duplicated icons for qdarkstyle_midnight_blue
referencing icon aliases in the qrc files is the way to go

Note:
Dynamic style changing doesn't appear to work with AppImage
This commit is contained in:
Kyle K 2022-07-28 07:50:20 -07:00
parent 1f7e62e86e
commit b51db12567
32 changed files with 819 additions and 35 deletions

View File

@ -41,20 +41,18 @@ Files: dist/qt_themes/*/icons/16x16/connected.png
dist/qt_themes/*/icons/48x48/sd_card.png dist/qt_themes/*/icons/48x48/sd_card.png
dist/qt_themes/*/icons/48x48/star.png dist/qt_themes/*/icons/48x48/star.png
dist/qt_themes/*/icons/256x256/plus_folder.png dist/qt_themes/*/icons/256x256/plus_folder.png
dist/qt_themes/colorful/icons/48x48/plus.png dist/qt_themes/colorful/icons/48x48/list-add.png
dist/qt_themes/default/icons/16x16/checked.png dist/qt_themes/default/icons/16x16/checked.png
dist/qt_themes/default/icons/16x16/failed.png dist/qt_themes/default/icons/16x16/failed.png
Copyright: https://icons8.com Copyright: https://icons8.com
License: CC-BY-ND-3.0 License: CC-BY-ND-3.0
Files: dist/qt_themes/*/icons/16x16/refresh.png Files: dist/qt_themes/*/icons/16x16/view-refresh.png
dist/qt_themes/*/icons/16x16/view-refresh.png
Copyright: Google, Inc. Copyright: Google, Inc.
License: Apache-2.0 License: Apache-2.0
Files: dist/qt_themes/default/icons/48x48/plus.png Files: dist/qt_themes/default/icons/48x48/list-add.png
dist/qt_themes/qdarkstyle/icons/48x48/plus.png dist/qt_themes/qdarkstyle/icons/48x48/list-add.png
dist/qt_themes/qdarkstyle_midnight_blue/icons/48x48/plus.png
Copyright: BreadFish64 Copyright: BreadFish64
License: CC0-1.0 License: CC0-1.0

View File

Before

Width:  |  Height:  |  Size: 496 B

After

Width:  |  Height:  |  Size: 496 B

View File

@ -13,7 +13,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
<file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file> <file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file>
<file alias="48x48/chip.png">icons/48x48/chip.png</file> <file alias="48x48/chip.png">icons/48x48/chip.png</file>
<file alias="48x48/folder.png">icons/48x48/folder.png</file> <file alias="48x48/folder.png">icons/48x48/folder.png</file>
<file alias="48x48/plus.png">icons/48x48/plus.png</file> <file alias="48x48/list-add.png">icons/48x48/list-add.png</file>
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file> <file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
<file alias="48x48/star.png">icons/48x48/star.png</file> <file alias="48x48/star.png">icons/48x48/star.png</file>
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file> <file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 362 B

View File

@ -3,6 +3,6 @@ Name=colorful_dark
Comment=Colorful theme (Dark style) Comment=Colorful theme (Dark style)
Inherits=colorful Inherits=colorful
Directories=16x16 Directories=16x16
[16x16] [16x16]
Size=16 Size=16

View File

@ -15,7 +15,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
<file alias="48x48/chip.png">../colorful/icons/48x48/chip.png</file> <file alias="48x48/chip.png">../colorful/icons/48x48/chip.png</file>
<file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file> <file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file>
<file alias="48x48/no_avatar.png">../qdarkstyle/icons/48x48/no_avatar.png</file> <file alias="48x48/no_avatar.png">../qdarkstyle/icons/48x48/no_avatar.png</file>
<file alias="48x48/plus.png">../colorful/icons/48x48/plus.png</file> <file alias="48x48/list-add.png">../colorful/icons/48x48/list-add.png</file>
<file alias="48x48/sd_card.png">../colorful/icons/48x48/sd_card.png</file> <file alias="48x48/sd_card.png">../colorful/icons/48x48/sd_card.png</file>
<file alias="256x256/plus_folder.png">../colorful/icons/256x256/plus_folder.png</file> <file alias="256x256/plus_folder.png">../colorful/icons/256x256/plus_folder.png</file>
</qresource> </qresource>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 362 B

View File

@ -11,7 +11,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
<file alias="48x48/bad_folder.png">../colorful/icons/48x48/bad_folder.png</file> <file alias="48x48/bad_folder.png">../colorful/icons/48x48/bad_folder.png</file>
<file alias="48x48/chip.png">../colorful/icons/48x48/chip.png</file> <file alias="48x48/chip.png">../colorful/icons/48x48/chip.png</file>
<file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file> <file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file>
<file alias="48x48/plus.png">../colorful/icons/48x48/plus.png</file> <file alias="48x48/list-add.png">../colorful/icons/48x48/list-add.png</file>
<file alias="48x48/sd_card.png">../colorful/icons/48x48/sd_card.png</file> <file alias="48x48/sd_card.png">../colorful/icons/48x48/sd_card.png</file>
<file alias="256x256/plus_folder.png">../colorful/icons/256x256/plus_folder.png</file> <file alias="256x256/plus_folder.png">../colorful/icons/256x256/plus_folder.png</file>
</qresource> </qresource>

View File

@ -17,7 +17,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
<file alias="48x48/chip.png">icons/48x48/chip.png</file> <file alias="48x48/chip.png">icons/48x48/chip.png</file>
<file alias="48x48/folder.png">icons/48x48/folder.png</file> <file alias="48x48/folder.png">icons/48x48/folder.png</file>
<file alias="48x48/no_avatar.png">icons/48x48/no_avatar.png</file> <file alias="48x48/no_avatar.png">icons/48x48/no_avatar.png</file>
<file alias="48x48/plus.png">icons/48x48/plus.png</file> <file alias="48x48/list-add.png">icons/48x48/list-add.png</file>
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file> <file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
<file alias="48x48/star.png">icons/48x48/star.png</file> <file alias="48x48/star.png">icons/48x48/star.png</file>
<file alias="256x256/yuzu.png">icons/256x256/yuzu.png</file> <file alias="256x256/yuzu.png">icons/256x256/yuzu.png</file>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 349 B

View File

Before

Width:  |  Height:  |  Size: 316 B

After

Width:  |  Height:  |  Size: 316 B

View File

@ -0,0 +1,8 @@
[Icon Theme]
Name=default_dark
Comment=Colorful theme (Dark style)
Inherits=colorful
Directories=16x16
[16x16]
Size=16

25
dist/qt_themes/default_dark/style.qrc vendored Normal file
View File

@ -0,0 +1,25 @@
<!--
SPDX-FileCopyrightText: 2022 yuzu Emulator Project
SPDX-License-Identifier: GPL-2.0-or-later
-->
<RCC>
<qresource prefix="icons/default_dark">
<file alias="16x16/connected.png">../colorful/icons/16x16/connected.png</file>
<file alias="16x16/connected_notification.png">../colorful/icons/16x16/connected_notification.png</file>
<file alias="16x16/disconnected.png">../colorful/icons/16x16/disconnected.png</file>
<file alias="index.theme">icons/index.theme</file>
<file alias="16x16/lock.png">../colorful_dark/icons/16x16/lock.png</file>
<file alias="16x16/view-refresh.png">../colorful_dark/icons/16x16/view-refresh.png</file>
<file alias="48x48/bad_folder.png">../colorful/icons/48x48/bad_folder.png</file>
<file alias="48x48/chip.png">../colorful/icons/48x48/chip.png</file>
<file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file>
<file alias="48x48/no_avatar.png">../qdarkstyle/icons/48x48/no_avatar.png</file>
<file alias="48x48/list-add.png">../colorful/icons/48x48/list-add.png</file>
<file alias="48x48/sd_card.png">../colorful/icons/48x48/sd_card.png</file>
<file alias="256x256/plus_folder.png">../colorful/icons/256x256/plus_folder.png</file>
</qresource>
<qresource prefix="default_dark">
<file>style.qss</file>
</qresource>
</RCC>

689
dist/qt_themes/default_dark/style.qss vendored Normal file
View File

@ -0,0 +1,689 @@
/*
* SPDX-FileCopyrightText: 2018 yuzu Emulator Project
* SPDX-License-Identifier: GPL-2.0-or-later
*/
QAbstractSpinBox {
min-height: 19px;
}
QPushButton#TogglableStatusBarButton {
color: #959595;
border: 1px solid transparent;
background-color: transparent;
padding: 0px 3px 0px 3px;
text-align: center;
}
/*
QPushButton#TogglableStatusBarButton:checked {
color: #000000;
}
*/
QPushButton#TogglableStatusBarButton:hover {
border: 1px solid #76797C;
}
QPushButton#RendererStatusBarButton {
color: #656565;
border: 1px solid transparent;
background-color: transparent;
padding: 0px 3px 0px 3px;
text-align: center;
}
QPushButton#RendererStatusBarButton:hover {
border: 1px solid #76797C;
}
QPushButton#RendererStatusBarButton:checked {
color: #e85c00;
}
QPushButton#RendererStatusBarButton:!checked {
color: #0066ff;
}
QPushButton#GPUStatusBarButton {
color: #656565;
border: 1px solid transparent;
background-color: transparent;
padding: 0px 3px 0px 3px;
text-align: center;
}
QPushButton#GPUStatusBarButton:hover {
border: 1px solid #76797C;
}
QPushButton#GPUStatusBarButton:checked {
color: #b06020;
}
QPushButton#GPUStatusBarButton:!checked {
color: #109010;
}
QPushButton#DockingStatusBarButton {
min-width: 0px;
/*color: #000000;*/
border: 1px solid transparent;
background-color: transparent;
padding: 0px 3px 0px 3px;
text-align: center;
}
QPushButton#DockingStatusBarButton:hover {
border: 1px solid #76797C;
}
QPushButton#buttonRefreshDevices {
min-width: 21px;
min-height: 21px;
max-width: 21px;
max-height: 21px;
}
QWidget#bottomPerGameInput,
QWidget#topControllerApplet,
QWidget#bottomControllerApplet,
QGroupBox#groupPlayer1Connected:checked,
QGroupBox#groupPlayer2Connected:checked,
QGroupBox#groupPlayer3Connected:checked,
QGroupBox#groupPlayer4Connected:checked,
QGroupBox#groupPlayer5Connected:checked,
QGroupBox#groupPlayer6Connected:checked,
QGroupBox#groupPlayer7Connected:checked,
QGroupBox#groupPlayer8Connected:checked {
background-color: #f5f5f5;
}
QWidget#topControllerApplet {
border-bottom: 1px solid #828790
}
QWidget#bottomPerGameInput,
QWidget#bottomControllerApplet {
border-top: 1px solid #828790
}
QWidget#topPerGameInput,
QWidget#middleControllerApplet {
background-color: #fff;
}
QWidget#topPerGameInput QComboBox,
QWidget#middleControllerApplet QComboBox {
width: 120px;
}
QWidget#connectedControllers {
background: transparent;
}
QWidget#playersSupported,
QWidget#controllersSupported,
QWidget#controllerSupported1,
QWidget#controllerSupported2,
QWidget#controllerSupported3,
QWidget#controllerSupported4,
QWidget#controllerSupported5,
QWidget#controllerSupported6 {
border: none;
background: transparent;
}
QGroupBox#groupPlayer1Connected,
QGroupBox#groupPlayer2Connected,
QGroupBox#groupPlayer3Connected,
QGroupBox#groupPlayer4Connected,
QGroupBox#groupPlayer5Connected,
QGroupBox#groupPlayer6Connected,
QGroupBox#groupPlayer7Connected,
QGroupBox#groupPlayer8Connected {
border: 1px solid #828790;
border-radius: 3px;
padding: 0px;
min-height: 98px;
max-height: 98px;
}
QGroupBox#groupPlayer1Connected:unchecked,
QGroupBox#groupPlayer2Connected:unchecked,
QGroupBox#groupPlayer3Connected:unchecked,
QGroupBox#groupPlayer4Connected:unchecked,
QGroupBox#groupPlayer5Connected:unchecked,
QGroupBox#groupPlayer6Connected:unchecked,
QGroupBox#groupPlayer7Connected:unchecked,
QGroupBox#groupPlayer8Connected:unchecked {
border: 1px solid #d9d9d9;
}
QGroupBox#groupPlayer1Connected::title,
QGroupBox#groupPlayer2Connected::title,
QGroupBox#groupPlayer3Connected::title,
QGroupBox#groupPlayer4Connected::title,
QGroupBox#groupPlayer5Connected::title,
QGroupBox#groupPlayer6Connected::title,
QGroupBox#groupPlayer7Connected::title,
QGroupBox#groupPlayer8Connected::title {
subcontrol-origin: margin;
subcontrol-position: top left;
padding-left: 0px;
padding-right: 0px;
padding-top: 1px;
margin-left: 0px;
margin-right: -4px;
margin-bottom: 4px;
}
QCheckBox#checkboxPlayer1Connected,
QCheckBox#checkboxPlayer2Connected,
QCheckBox#checkboxPlayer3Connected,
QCheckBox#checkboxPlayer4Connected,
QCheckBox#checkboxPlayer5Connected,
QCheckBox#checkboxPlayer6Connected,
QCheckBox#checkboxPlayer7Connected,
QCheckBox#checkboxPlayer8Connected {
spacing: 0px;
}
QWidget#Player1LEDs QCheckBox,
QWidget#Player2LEDs QCheckBox,
QWidget#Player3LEDs QCheckBox,
QWidget#Player4LEDs QCheckBox,
QWidget#Player5LEDs QCheckBox,
QWidget#Player6LEDs QCheckBox,
QWidget#Player7LEDs QCheckBox,
QWidget#Player8LEDs QCheckBox {
spacing: 0px;
}
QWidget#Player1LEDs QCheckBox::indicator,
QWidget#Player2LEDs QCheckBox::indicator,
QWidget#Player3LEDs QCheckBox::indicator,
QWidget#Player4LEDs QCheckBox::indicator,
QWidget#Player5LEDs QCheckBox::indicator,
QWidget#Player6LEDs QCheckBox::indicator,
QWidget#Player7LEDs QCheckBox::indicator,
QWidget#Player8LEDs QCheckBox::indicator {
width: 6px;
height: 6px;
margin-left: 0px;
}
QWidget#bottomPerGameInput QCheckBox#checkboxPlayer1Connected::indicator,
QWidget#bottomPerGameInput QCheckBox#checkboxPlayer2Connected::indicator,
QWidget#bottomPerGameInput QCheckBox#checkboxPlayer3Connected::indicator,
QWidget#bottomPerGameInput QCheckBox#checkboxPlayer4Connected::indicator,
QWidget#bottomPerGameInput QCheckBox#checkboxPlayer5Connected::indicator,
QWidget#bottomPerGameInput QCheckBox#checkboxPlayer6Connected::indicator,
QWidget#bottomPerGameInput QCheckBox#checkboxPlayer7Connected::indicator,
QWidget#bottomPerGameInput QCheckBox#checkboxPlayer8Connected::indicator {
width: 12px;
height: 12px;
}
QCheckBox#checkboxPlayer1Connected::indicator,
QCheckBox#checkboxPlayer2Connected::indicator,
QCheckBox#checkboxPlayer3Connected::indicator,
QCheckBox#checkboxPlayer4Connected::indicator,
QCheckBox#checkboxPlayer5Connected::indicator,
QCheckBox#checkboxPlayer6Connected::indicator,
QCheckBox#checkboxPlayer7Connected::indicator,
QCheckBox#checkboxPlayer8Connected::indicator {
width: 14px;
height: 14px;
}
QGroupBox#groupPlayer1Connected::indicator,
QGroupBox#groupPlayer2Connected::indicator,
QGroupBox#groupPlayer3Connected::indicator,
QGroupBox#groupPlayer4Connected::indicator,
QGroupBox#groupPlayer5Connected::indicator,
QGroupBox#groupPlayer6Connected::indicator,
QGroupBox#groupPlayer7Connected::indicator,
QGroupBox#groupPlayer8Connected::indicator {
width: 16px;
height: 16px;
}
QWidget#Player1LEDs QCheckBox::indicator:checked,
QWidget#Player2LEDs QCheckBox::indicator:checked,
QWidget#Player3LEDs QCheckBox::indicator:checked,
QWidget#Player4LEDs QCheckBox::indicator:checked,
QWidget#Player5LEDs QCheckBox::indicator:checked,
QWidget#Player6LEDs QCheckBox::indicator:checked,
QWidget#Player7LEDs QCheckBox::indicator:checked,
QWidget#Player8LEDs QCheckBox::indicator:checked,
QGroupBox#groupPlayer1Connected::indicator:checked,
QGroupBox#groupPlayer2Connected::indicator:checked,
QGroupBox#groupPlayer3Connected::indicator:checked,
QGroupBox#groupPlayer4Connected::indicator:checked,
QGroupBox#groupPlayer5Connected::indicator:checked,
QGroupBox#groupPlayer6Connected::indicator:checked,
QGroupBox#groupPlayer7Connected::indicator:checked,
QGroupBox#groupPlayer8Connected::indicator:checked,
QCheckBox#checkboxPlayer1Connected::indicator:checked,
QCheckBox#checkboxPlayer2Connected::indicator:checked,
QCheckBox#checkboxPlayer3Connected::indicator:checked,
QCheckBox#checkboxPlayer4Connected::indicator:checked,
QCheckBox#checkboxPlayer5Connected::indicator:checked,
QCheckBox#checkboxPlayer6Connected::indicator:checked,
QCheckBox#checkboxPlayer7Connected::indicator:checked,
QCheckBox#checkboxPlayer8Connected::indicator:checked,
QGroupBox#groupConnectedController::indicator:checked {
border-radius: 2px;
border: 1px solid #929192;
background: #39ff14;
image: none;
}
QWidget#Player1LEDs QCheckBox::indicator:unchecked,
QWidget#Player2LEDs QCheckBox::indicator:unchecked,
QWidget#Player3LEDs QCheckBox::indicator:unchecked,
QWidget#Player4LEDs QCheckBox::indicator:unchecked,
QWidget#Player5LEDs QCheckBox::indicator:unchecked,
QWidget#Player6LEDs QCheckBox::indicator:unchecked,
QWidget#Player7LEDs QCheckBox::indicator:unchecked,
QWidget#Player8LEDs QCheckBox::indicator:unchecked,
QGroupBox#groupPlayer1Connected::indicator:unchecked,
QGroupBox#groupPlayer2Connected::indicator:unchecked,
QGroupBox#groupPlayer3Connected::indicator:unchecked,
QGroupBox#groupPlayer4Connected::indicator:unchecked,
QGroupBox#groupPlayer5Connected::indicator:unchecked,
QGroupBox#groupPlayer6Connected::indicator:unchecked,
QGroupBox#groupPlayer7Connected::indicator:unchecked,
QGroupBox#groupPlayer8Connected::indicator:unchecked,
QCheckBox#checkboxPlayer1Connected::indicator:unchecked,
QCheckBox#checkboxPlayer2Connected::indicator:unchecked,
QCheckBox#checkboxPlayer3Connected::indicator:unchecked,
QCheckBox#checkboxPlayer4Connected::indicator:unchecked,
QCheckBox#checkboxPlayer5Connected::indicator:unchecked,
QCheckBox#checkboxPlayer6Connected::indicator:unchecked,
QCheckBox#checkboxPlayer7Connected::indicator:unchecked,
QCheckBox#checkboxPlayer8Connected::indicator:unchecked,
QGroupBox#groupConnectedController::indicator:unchecked {
border-radius: 2px;
border: 1px solid #929192;
background: transparent;
image: none;
}
QWidget#controllerPlayer1,
QWidget#controllerPlayer2,
QWidget#controllerPlayer3,
QWidget#controllerPlayer4,
QWidget#controllerPlayer5,
QWidget#controllerPlayer6,
QWidget#controllerPlayer7,
QWidget#controllerPlayer8 {
background: transparent;
}
QDialog#QtSoftwareKeyboardDialog,
QStackedWidget#topOSK {
background: rgba(51, 51, 51, .9);
}
QDialog#OverlayDialog,
QStackedWidget#stackedDialog {
background: rgba(51, 51, 51, .7);
}
QWidget#boxOSK,
QWidget#lineOSK,
QWidget#richDialog,
QWidget#lineDialog {
background: transparent;
}
QStackedWidget#bottomOSK,
QWidget#contentDialog,
QWidget#contentRichDialog {
background: rgba(240, 240, 240, 1);
}
QWidget#contentDialog,
QWidget#contentRichDialog {
margin: 5px;
border-radius: 6px;
}
QWidget#buttonsDialog,
QWidget#buttonsRichDialog {
margin: 5px;
border-top: 2px solid rgba(44, 44, 44, 1);
}
QWidget#legendOSKnum {
border-top: 1px solid rgba(44, 44, 44, 1);
}
QStackedWidget#stackedDialog QTextBrowser QScrollBar::vertical {
background: #cdcdcd;
width: 15px;
margin: 15px 3px 15px 3px;
border: 1px transparent;
border-radius: 4px;
}
QStackedWidget#stackedDialog QTextBrowser QScrollBar::horizoncal {
background: #cdcdcd;
height: 15px;
margin: 3px 15px 3px 15px;
border: 1px transparent;
border-radius: 4px;
}
QStackedWidget#stackedDialog QTextBrowser QScrollBar::handle {
background: #fff;
border-radius: 4px;
min-height: 5px;
min-width: 5px;
}
QStackedWidget#stackedDialog QTextBrowser QScrollBar::add-line,
QStackedWidget#stackedDialog QTextBrowser QScrollBar::sub-line,
QStackedWidget#stackedDialog QTextBrowser QScrollBar::add-page,
QStackedWidget#stackedDialog QTextBrowser QScrollBar::sub-page {
background: none;
}
QWidget#inputOSK {
border-bottom: 3px solid rgba(255, 255, 255, .9);
}
QWidget#inputOSK QLineEdit {
background: transparent;
border: none;
color: #ccc;
}
QWidget#inputBoxOSK {
border: 2px solid rgba(255, 255, 255, .9);
}
QWidget#inputBoxOSK QTextEdit {
background: transparent;
border: none;
color: #ccc;
}
QWidget#richDialog QTextBrowser {
background: transparent;
border: none;
padding: 35px 65px;
}
QWidget#lineOSK QLabel#label_header {
color: #f0f0f0;
}
QWidget#lineOSK QLabel#label_sub,
QWidget#lineOSK QLabel#label_characters,
QWidget#boxOSK QLabel#label_characters_box {
color: #ccc;
}
QWidget#contentDialog QLabel#label_title,
QWidget#contentRichDialog QLabel#label_title_rich {
color: #888;
}
QWidget#contentDialog QLabel#label_dialog {
padding: 20px 65px;
}
QWidget#contentDialog QLabel#label_title,
QWidget#contentRichDialog QLabel#label_title_rich {
padding: 0px 65px;
}
QDialog#OverlayDialog QPushButton {
color: rgba(49, 79, 239, 1);
background: transparent;
border: none;
padding: 0px;
min-width: 0px;
}
QDialog#OverlayDialog QPushButton:focus,
QDialog#OverlayDialog QPushButton:hover {
color: rgba(49, 79, 239, 1);
background: rgba(255, 255, 255, 1);
border: 5px solid rgba(148, 250, 202, 1);
border-radius: 6px;
outline: none;
}
QDialog#OverlayDialog QPushButton:pressed {
color: rgba(240, 240, 240, 1);
background: rgba(150, 150, 150, 1);
border: 5px solid rgba(148, 250, 202, 1);
border-radius: 6px;
outline: none;
}
QDialog#QtSoftwareKeyboardDialog QPushButton {
background: rgba(232, 232, 232, 1);
border: 2px solid rgba(240, 240, 240, 1);
}
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift {
background: rgba(218, 218, 218, 1);
border: 2px solid rgba(240, 240, 240, 1);
}
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num {
color: rgba(240, 240, 240, 1);
background: rgba(44, 44, 44, 1);
border: 2px solid rgba(240, 240, 240, 1);
}
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num {
color: rgba(240, 240, 240, 1);
background: rgba(49, 79, 239, 1);
border: 2px solid rgba(240, 240, 240, 1);
}
QDialog#QtSoftwareKeyboardDialog QPushButton:focus,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:focus,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:focus,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:focus,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:focus,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:focus,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:focus,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:focus,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:focus,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:focus,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:focus,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:focus,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:focus,
QDialog#QtSoftwareKeyboardDialog QPushButton:hover,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:hover,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:hover,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:hover,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:hover,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:hover,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:hover,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:hover,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:hover,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:hover,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:hover,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:hover,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:hover {
color: rgba(0, 0, 0, 1);
background: rgba(255, 255, 255, 1);
border: 5px solid rgba(148, 250, 202, 1);
border-radius: 6px;
outline: none;
}
QDialog#QtSoftwareKeyboardDialog QPushButton:pressed,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:pressed,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift:pressed,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:pressed,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:pressed,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:pressed,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:pressed,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift:pressed,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:pressed,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:pressed,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:pressed,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:pressed,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:pressed {
color: rgba(240, 240, 240, 1);
background: rgba(150, 150, 150, 1);
border: 5px solid rgba(148, 250, 202, 1);
border-radius: 6px;
}
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num {
image: url(:/overlay/osk_button_B.png);
image-position: right;
qproperty-icon: url(:/overlay/osk_button_backspace.png);
qproperty-iconSize: 36px;
}
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift {
image: url(:/overlay/osk_button_Y.png);
image-position: right;
}
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num {
image: url(:/overlay/osk_button_plus.png);
image-position: right;
}
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift {
image: url(:/overlay/osk_button_shift_lock_off.png);
image-position: left;
qproperty-icon: url(:/overlay/osk_button_shift.png);
qproperty-iconSize: 36px;
}
QDialog#QtSoftwareKeyboardDialog QPushButton#button_shift_shift {
image: url(:/overlay/osk_button_shift_lock_off.png);
image-position: left;
qproperty-icon: url(:/overlay/osk_button_shift_on.png);
qproperty-iconSize: 36px;
}
QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_bracket,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_bracket,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_left_parenthesis,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_right_parenthesis {
padding-bottom: 7px;
}
QDialog#QtSoftwareKeyboardDialog QWidget#titleOSK QLabel {
background: transparent;
color: #ccc;
}
QDialog#QtSoftwareKeyboardDialog QWidget#button_L,
QDialog#QtSoftwareKeyboardDialog QWidget#button_L_shift,
QDialog#QtSoftwareKeyboardDialog QWidget#button_L_num {
image: url(:/overlay/button_L.png);
}
QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left,
QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_shift,
QDialog#QtSoftwareKeyboardDialog QWidget#arrow_left_num {
image: url(:/overlay/arrow_left.png);
}
QDialog#QtSoftwareKeyboardDialog QWidget#button_R,
QDialog#QtSoftwareKeyboardDialog QWidget#button_R_shift,
QDialog#QtSoftwareKeyboardDialog QWidget#button_R_num {
image: url(:/overlay/button_R.png);
}
QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right,
QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_shift,
QDialog#QtSoftwareKeyboardDialog QWidget#arrow_right_num {
image: url(:/overlay/arrow_right.png);
}
QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick,
QDialog#QtSoftwareKeyboardDialog QWidget#button_press_stick_shift {
image: url(:/overlay/button_press_stick.png);
}
QDialog#QtSoftwareKeyboardDialog QWidget#button_X,
QDialog#QtSoftwareKeyboardDialog QWidget#button_X_shift,
QDialog#QtSoftwareKeyboardDialog QWidget#button_X_num {
image: url(:/overlay/button_X.png);
}
QDialog#QtSoftwareKeyboardDialog QWidget#button_A,
QDialog#QtSoftwareKeyboardDialog QWidget#button_A_shift,
QDialog#QtSoftwareKeyboardDialog QWidget#button_A_num {
image: url(:/overlay/button_A.png);
}
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return_shift:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled {
color: rgba(164, 164, 164, 1);
background-color: rgba(218, 218, 218, 1);
}
QDialog#QtSoftwareKeyboardDialog QPushButton#button_at:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_slash:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_percent:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_1:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_2:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_3:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_4:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_5:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_6:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_7:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_8:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_9:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_0:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_return:disabled {
color: rgba(164, 164, 164, 1);
}
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_shift:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_ok_num:disabled {
image: url(:/overlay/osk_button_plus_disabled.png);
}
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_shift:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_backspace_num:disabled {
image: url(:/overlay/osk_button_B_disabled.png);
}
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space:disabled,
QDialog#QtSoftwareKeyboardDialog QPushButton#button_space_shift:disabled {
image: url(:/overlay/osk_button_Y_disabled.png);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 362 B

View File

Before

Width:  |  Height:  |  Size: 339 B

After

Width:  |  Height:  |  Size: 339 B

View File

@ -10,7 +10,7 @@
<file alias="48x48/chip.png">icons/48x48/chip.png</file> <file alias="48x48/chip.png">icons/48x48/chip.png</file>
<file alias="48x48/folder.png">icons/48x48/folder.png</file> <file alias="48x48/folder.png">icons/48x48/folder.png</file>
<file alias="48x48/no_avatar.png">icons/48x48/no_avatar.png</file> <file alias="48x48/no_avatar.png">icons/48x48/no_avatar.png</file>
<file alias="48x48/plus.png">icons/48x48/plus.png</file> <file alias="48x48/list-add.png">icons/48x48/list-add.png</file>
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file> <file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
<file alias="48x48/star.png">icons/48x48/star.png</file> <file alias="48x48/star.png">icons/48x48/star.png</file>
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file> <file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 362 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 362 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 542 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 339 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 676 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 725 B

View File

@ -1,15 +1,16 @@
<RCC> <RCC>
<qresource prefix="icons/qdarkstyle_midnight_blue"> <qresource prefix="icons/qdarkstyle_midnight_blue">
<file alias="index.theme">icons/index.theme</file> <file alias="index.theme">icons/index.theme</file>
<file alias="16x16/lock.png">icons/16x16/lock.png</file> <file alias="16x16/lock.png">../qdarkstyle/icons/16x16/lock.png</file>
<file alias="16x16/view-refresh.png">icons/16x16/view-refresh.png</file> <file alias="16x16/view-refresh.png">../qdarkstyle/icons/16x16/view-refresh.png</file>
<file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file> <file alias="48x48/bad_folder.png">../qdarkstyle/icons/48x48/bad_folder.png</file>
<file alias="48x48/chip.png">icons/48x48/chip.png</file> <file alias="48x48/chip.png">../qdarkstyle/icons/48x48/chip.png</file>
<file alias="48x48/folder.png">icons/48x48/folder.png</file> <file alias="48x48/folder.png">../qdarkstyle/icons/48x48/folder.png</file>
<file alias="48x48/plus.png">icons/48x48/plus.png</file> <file alias="48x48/no_avatar.png">../qdarkstyle/icons/48x48/no_avatar.png</file>
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file> <file alias="48x48/list-add.png">../qdarkstyle/icons/48x48/list-add.png</file>
<file alias="48x48/star.png">icons/48x48/star.png</file> <file alias="48x48/sd_card.png">../qdarkstyle/icons/48x48/sd_card.png</file>
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file> <file alias="48x48/star.png">../qdarkstyle/icons/48x48/star.png</file>
<file alias="256x256/plus_folder.png">../qdarkstyle/icons/256x256/plus_folder.png</file>
</qresource> </qresource>
<qresource prefix="qss_icons"> <qresource prefix="qss_icons">
<file>rc/arrow_down.png</file> <file>rc/arrow_down.png</file>

View File

@ -286,7 +286,7 @@ void GameList::OnUpdateThemedIcons() {
} }
case GameListItemType::AddDir: case GameListItemType::AddDir:
child->setData( child->setData(
QIcon::fromTheme(QStringLiteral("plus")) QIcon::fromTheme(QStringLiteral("list-add"))
.pixmap(icon_size) .pixmap(icon_size)
.scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), .scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
Qt::DecorationRole); Qt::DecorationRole);

View File

@ -294,7 +294,7 @@ public:
const int icon_size = UISettings::values.folder_icon_size.GetValue(); const int icon_size = UISettings::values.folder_icon_size.GetValue();
setData(QIcon::fromTheme(QStringLiteral("plus")) setData(QIcon::fromTheme(QStringLiteral("list-add"))
.pixmap(icon_size) .pixmap(icon_size)
.scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), .scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
Qt::DecorationRole); Qt::DecorationRole);

View File

@ -257,6 +257,18 @@ static QString PrettyProductName() {
return QSysInfo::prettyProductName(); return QSysInfo::prettyProductName();
} }
bool GMainWindow::check_dark_mode() {
#ifdef __linux__
const QPalette test_palette(qApp->palette());
const QColor text_color = test_palette.color(QPalette::Active, QPalette::Text);
const QColor window_color = test_palette.color(QPalette::Active, QPalette::Window);
return (text_color.value() > window_color.value());
#else
// TODO: Windows
return false;
#endif // __linux__
}
GMainWindow::GMainWindow(bool has_broken_vulkan) GMainWindow::GMainWindow(bool has_broken_vulkan)
: ui{std::make_unique<Ui::MainWindow>()}, system{std::make_unique<Core::System>()}, : ui{std::make_unique<Ui::MainWindow>()}, system{std::make_unique<Core::System>()},
input_subsystem{std::make_shared<InputCommon::InputSubsystem>()}, input_subsystem{std::make_shared<InputCommon::InputSubsystem>()},
@ -274,6 +286,13 @@ GMainWindow::GMainWindow(bool has_broken_vulkan)
ui->setupUi(this); ui->setupUi(this);
statusBar()->hide(); statusBar()->hide();
// Check dark mode before a theme is loaded
os_dark_mode = check_dark_mode();
startup_icon_theme = QIcon::themeName();
// fallback can only be set once, colorful theme icons are okay on both light/dark
QIcon::setFallbackThemeName(QStringLiteral("colorful"));
QIcon::setFallbackSearchPaths(QStringList(QStringLiteral(":/icons")));
default_theme_paths = QIcon::themeSearchPaths(); default_theme_paths = QIcon::themeSearchPaths();
UpdateUITheme(); UpdateUITheme();
@ -3930,8 +3949,21 @@ void GMainWindow::filterBarSetChecked(bool state) {
emit(OnToggleFilterBar()); emit(OnToggleFilterBar());
} }
static void AdjustLinkColor() {
QPalette new_pal(qApp->palette());
if (UISettings::IsDarkTheme()) {
new_pal.setColor(QPalette::Link, QColor(0, 190, 255, 255));
} else {
new_pal.setColor(QPalette::Link, QColor(0, 140, 200, 255));
}
if (qApp->palette().color(QPalette::Link) != new_pal.color(QPalette::Link)) {
qApp->setPalette(new_pal);
}
}
void GMainWindow::UpdateUITheme() { void GMainWindow::UpdateUITheme() {
const QString default_theme = QStringLiteral("default"); const QString default_theme =
QString::fromUtf8(UISettings::themes[static_cast<size_t>(Config::default_theme)].second);
QString current_theme = UISettings::values.theme; QString current_theme = UISettings::values.theme;
QStringList theme_paths(default_theme_paths); QStringList theme_paths(default_theme_paths);
@ -3939,6 +3971,23 @@ void GMainWindow::UpdateUITheme() {
current_theme = default_theme; current_theme = default_theme;
} }
#ifdef _WIN32
QIcon::setThemeName(current_theme);
AdjustLinkColor();
#else
if (current_theme == QStringLiteral("default") || current_theme == QStringLiteral("colorful")) {
QIcon::setThemeName(current_theme == QStringLiteral("colorful") ? current_theme
: startup_icon_theme);
QIcon::setThemeSearchPaths(theme_paths);
if (check_dark_mode()) {
current_theme = QStringLiteral("default_dark");
}
} else {
QIcon::setThemeName(current_theme);
QIcon::setThemeSearchPaths(QStringList(QStringLiteral(":/icons")));
AdjustLinkColor();
}
#endif
if (current_theme != default_theme) { if (current_theme != default_theme) {
QString theme_uri{QStringLiteral(":%1/style.qss").arg(current_theme)}; QString theme_uri{QStringLiteral(":%1/style.qss").arg(current_theme)};
QFile f(theme_uri); QFile f(theme_uri);
@ -3961,17 +4010,6 @@ void GMainWindow::UpdateUITheme() {
qApp->setStyleSheet({}); qApp->setStyleSheet({});
setStyleSheet({}); setStyleSheet({});
} }
QPalette new_pal(qApp->palette());
if (UISettings::IsDarkTheme()) {
new_pal.setColor(QPalette::Link, QColor(0, 190, 255, 255));
} else {
new_pal.setColor(QPalette::Link, QColor(0, 140, 200, 255));
}
qApp->setPalette(new_pal);
QIcon::setThemeName(current_theme);
QIcon::setThemeSearchPaths(theme_paths);
} }
void GMainWindow::LoadTranslation() { void GMainWindow::LoadTranslation() {
@ -4022,6 +4060,26 @@ void GMainWindow::SetDiscordEnabled([[maybe_unused]] bool state) {
discord_rpc->Update(); discord_rpc->Update();
} }
void GMainWindow::changeEvent(QEvent* event) {
#ifdef __linux__
// PaletteChange event appears to only reach so far into the GUI, explicitly asking to
// UpdateUITheme is a decent work around
if (event->type() == QEvent::PaletteChange) {
const QPalette test_palette(qApp->palette());
const QString current_theme = UISettings::values.theme;
// Keeping eye on QPalette::Window to avoid looping. QPalette::Text might be useful too
static QColor last_window_color;
const QColor window_color = test_palette.color(QPalette::Active, QPalette::Window);
if (last_window_color != window_color && (current_theme == QStringLiteral("default") ||
current_theme == QStringLiteral("colorful"))) {
UpdateUITheme();
}
last_window_color = window_color;
}
#endif // __linux__
QWidget::changeEvent(event);
}
#ifdef main #ifdef main
#undef main #undef main
#endif #endif

View File

@ -251,6 +251,7 @@ private:
bool ConfirmForceLockedExit(); bool ConfirmForceLockedExit();
void RequestGameExit(); void RequestGameExit();
void RequestGameResume(); void RequestGameResume();
void changeEvent(QEvent* event) override;
void closeEvent(QCloseEvent* event) override; void closeEvent(QCloseEvent* event) override;
#ifdef __linux__ #ifdef __linux__
@ -392,6 +393,10 @@ private:
QTimer mouse_hide_timer; QTimer mouse_hide_timer;
QTimer mouse_center_timer; QTimer mouse_center_timer;
QString startup_icon_theme;
bool os_dark_mode = false;
bool check_dark_mode();
// FS // FS
std::shared_ptr<FileSys::VfsFilesystem> vfs; std::shared_ptr<FileSys::VfsFilesystem> vfs;
std::unique_ptr<FileSys::ManualContentProvider> provider; std::unique_ptr<FileSys::ManualContentProvider> provider;