mirror of
https://git.citron-emu.org/citron/emulator
synced 2025-12-20 11:03:56 +00:00
frontend: Improve High DPI support and scaling
This patch enhances High DPI support across the Qt frontend with the following improvements: **Windows DPI Awareness:** - Add shellscalingapi.h include for Windows DPI functions - Implement Per Monitor DPI Awareness (Windows 8.1+) and Per Monitor v2 DPI Awareness (Windows 10+) - Use SetProcessDPIAware() and SetProcessDpiAwareness() for better multi-monitor scaling - Dynamically load shcore.dll to access modern DPI awareness APIs **Configuration Dialog Enhancements:** - Add comprehensive High DPI responsive CSS media queries for different DPI levels (192dpi, 240dpi) - Scale UI elements (buttons, comboboxes, line edits, checkboxes, radio buttons) based on screen DPI - Improve scroll area styling with proper scrollbar theming for high DPI displays - Set proper window attributes for scaling (WA_TranslucentBackground, WA_NoSystemBackground) - Calculate logical window size based on device pixel ratio for accurate scaling **UI Improvements:** - Enhanced scroll area styling with custom scrollbar appearance - Better visual feedback with hover effects on scrollbar handles - Improved spacing and sizing for high DPI displays - Set proper window modality and title for configuration dialog These changes provide better visual quality and usability on high DPI displays, particularly on Windows systems with multiple monitors or high-resolution screens. The scaling is now more accurate and consistent across different display configurations. Signed-off-by: Zephyron <zephyron@citron-emu.org>
This commit is contained in:
@@ -25,6 +25,14 @@
|
|||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
|
<!-- High DPI support: Enable automatic scaling and proper window modality -->
|
||||||
|
<property name="windowModality">
|
||||||
|
<enum>Qt::ApplicationModal</enum>
|
||||||
|
</property>
|
||||||
|
<!-- High DPI scaling attributes -->
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>citron Configuration</string>
|
||||||
|
</property>
|
||||||
<property name="styleSheet">
|
<property name="styleSheet">
|
||||||
<string>QDialog {
|
<string>QDialog {
|
||||||
background-color: #2b2b2b;
|
background-color: #2b2b2b;
|
||||||
@@ -441,6 +449,77 @@ QRadioButton::indicator:checked {
|
|||||||
QRadioButton::indicator:hover {
|
QRadioButton::indicator:hover {
|
||||||
border-color: #4a9eff;
|
border-color: #4a9eff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* High DPI specific styles */
|
||||||
|
@media (min-resolution: 192dpi) {
|
||||||
|
QPushButton.tabButton {
|
||||||
|
padding: 12px 16px;
|
||||||
|
min-width: 90px;
|
||||||
|
max-width: 170px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QComboBox {
|
||||||
|
min-width: 140px;
|
||||||
|
min-height: 32px;
|
||||||
|
padding: 10px 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLineEdit {
|
||||||
|
min-height: 24px;
|
||||||
|
padding: 10px 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton {
|
||||||
|
min-height: 24px;
|
||||||
|
padding: 12px 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QCheckBox::indicator {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRadioButton::indicator {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-resolution: 240dpi) {
|
||||||
|
QPushButton.tabButton {
|
||||||
|
padding: 14px 18px;
|
||||||
|
min-width: 95px;
|
||||||
|
max-width: 180px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QComboBox {
|
||||||
|
min-width: 160px;
|
||||||
|
min-height: 36px;
|
||||||
|
padding: 12px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLineEdit {
|
||||||
|
min-height: 28px;
|
||||||
|
padding: 12px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton {
|
||||||
|
min-height: 28px;
|
||||||
|
padding: 14px 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QCheckBox::indicator {
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRadioButton::indicator {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
</string>
|
</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
|||||||
@@ -43,7 +43,60 @@ QScrollArea* CreateScrollArea(QWidget* widget) {
|
|||||||
scroll_area->setFrameShape(QFrame::NoFrame);
|
scroll_area->setFrameShape(QFrame::NoFrame);
|
||||||
scroll_area->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
scroll_area->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||||
scroll_area->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
scroll_area->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||||
scroll_area->setStyleSheet(QLatin1String("QScrollArea { border: none; background-color: #2b2b2b; }"));
|
|
||||||
|
// High DPI support: Scroll area will inherit scaling from parent
|
||||||
|
|
||||||
|
// Set style with high DPI aware styling
|
||||||
|
scroll_area->setStyleSheet(QLatin1String(
|
||||||
|
"QScrollArea { "
|
||||||
|
"border: none; "
|
||||||
|
"background-color: #2b2b2b; "
|
||||||
|
"}"
|
||||||
|
"QScrollArea > QWidget > QWidget { "
|
||||||
|
"background-color: #2b2b2b; "
|
||||||
|
"}"
|
||||||
|
"QScrollBar:vertical { "
|
||||||
|
"background-color: #3d3d3d; "
|
||||||
|
"width: 14px; "
|
||||||
|
"border-radius: 7px; "
|
||||||
|
"margin: 2px; "
|
||||||
|
"}"
|
||||||
|
"QScrollBar::handle:vertical { "
|
||||||
|
"background-color: #5d5d5d; "
|
||||||
|
"border-radius: 6px; "
|
||||||
|
"min-height: 30px; "
|
||||||
|
"margin: 1px; "
|
||||||
|
"}"
|
||||||
|
"QScrollBar::handle:vertical:hover { "
|
||||||
|
"background-color: #4a9eff; "
|
||||||
|
"}"
|
||||||
|
"QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical { "
|
||||||
|
"border: none; "
|
||||||
|
"background: none; "
|
||||||
|
"height: 0px; "
|
||||||
|
"}"
|
||||||
|
"QScrollBar:horizontal { "
|
||||||
|
"background-color: #3d3d3d; "
|
||||||
|
"height: 14px; "
|
||||||
|
"border-radius: 7px; "
|
||||||
|
"margin: 2px; "
|
||||||
|
"}"
|
||||||
|
"QScrollBar::handle:horizontal { "
|
||||||
|
"background-color: #5d5d5d; "
|
||||||
|
"border-radius: 6px; "
|
||||||
|
"min-width: 30px; "
|
||||||
|
"margin: 1px; "
|
||||||
|
"}"
|
||||||
|
"QScrollBar::handle:horizontal:hover { "
|
||||||
|
"background-color: #4a9eff; "
|
||||||
|
"}"
|
||||||
|
"QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal { "
|
||||||
|
"border: none; "
|
||||||
|
"background: none; "
|
||||||
|
"width: 0px; "
|
||||||
|
"}"
|
||||||
|
));
|
||||||
|
|
||||||
return scroll_area;
|
return scroll_area;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,16 +134,28 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_,
|
|||||||
setWindowFlags(Qt::Dialog | Qt::WindowTitleHint | Qt::WindowSystemMenuHint |
|
setWindowFlags(Qt::Dialog | Qt::WindowTitleHint | Qt::WindowSystemMenuHint |
|
||||||
Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint);
|
Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint);
|
||||||
|
|
||||||
|
// High DPI support: Set proper attributes for scaling
|
||||||
|
setAttribute(Qt::WA_TranslucentBackground, false);
|
||||||
|
setAttribute(Qt::WA_NoSystemBackground, false);
|
||||||
|
setAttribute(Qt::WA_DontShowOnScreen, false);
|
||||||
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
// Set size policy and enable resizing
|
// Set size policy and enable resizing
|
||||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||||
|
|
||||||
// Get screen geometry and set to fullscreen
|
// Get screen geometry and set to fullscreen with high DPI awareness
|
||||||
QScreen* screen = QApplication::primaryScreen();
|
QScreen* screen = QApplication::primaryScreen();
|
||||||
if (screen) {
|
if (screen) {
|
||||||
QRect screenGeometry = screen->availableGeometry();
|
QRect screenGeometry = screen->availableGeometry();
|
||||||
setGeometry(screenGeometry);
|
|
||||||
|
// Calculate logical size based on device pixel ratio for high DPI support
|
||||||
|
qreal devicePixelRatio = screen->devicePixelRatio();
|
||||||
|
int logicalWidth = static_cast<int>(screenGeometry.width() / devicePixelRatio);
|
||||||
|
int logicalHeight = static_cast<int>(screenGeometry.height() / devicePixelRatio);
|
||||||
|
|
||||||
|
// Set geometry using logical units
|
||||||
|
setGeometry(0, 0, logicalWidth, logicalHeight);
|
||||||
showMaximized(); // Start maximized/fullscreen
|
showMaximized(); // Start maximized/fullscreen
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -183,6 +183,7 @@ Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <shellscalingapi.h>
|
||||||
extern "C" {
|
extern "C" {
|
||||||
// tells Nvidia and AMD drivers to use the dedicated GPU by default on laptops with switchable
|
// tells Nvidia and AMD drivers to use the dedicated GPU by default on laptops with switchable
|
||||||
// graphics
|
// graphics
|
||||||
@@ -5252,8 +5253,29 @@ static void SetHighDPIAttributes() {
|
|||||||
Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Enable high DPI scaling and pixmaps
|
||||||
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||||
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||||
|
|
||||||
|
// Set the DPI awareness for better scaling on Windows
|
||||||
|
#ifdef _WIN32
|
||||||
|
// Enable Per Monitor DPI Awareness for Windows 8.1+
|
||||||
|
SetProcessDPIAware();
|
||||||
|
|
||||||
|
// For Windows 10+, use Per Monitor v2 DPI Awareness
|
||||||
|
// This provides better scaling for multi-monitor setups
|
||||||
|
HMODULE shcore = LoadLibrary(L"shcore.dll");
|
||||||
|
if (shcore) {
|
||||||
|
typedef HRESULT(WINAPI* SetProcessDpiAwarenessFunc)(int);
|
||||||
|
SetProcessDpiAwarenessFunc setProcessDpiAwareness =
|
||||||
|
(SetProcessDpiAwarenessFunc)GetProcAddress(shcore, "SetProcessDpiAwareness");
|
||||||
|
if (setProcessDpiAwareness) {
|
||||||
|
// PROCESS_PER_MONITOR_DPI_AWARE_V2 = 2
|
||||||
|
setProcessDpiAwareness(2);
|
||||||
|
}
|
||||||
|
FreeLibrary(shcore);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
|
|||||||
Reference in New Issue
Block a user