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>
|
||||
</sizepolicy>
|
||||
</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">
|
||||
<string>QDialog {
|
||||
background-color: #2b2b2b;
|
||||
@@ -441,6 +449,77 @@ QRadioButton::indicator:checked {
|
||||
QRadioButton::indicator:hover {
|
||||
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>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
|
||||
@@ -43,7 +43,60 @@ QScrollArea* CreateScrollArea(QWidget* widget) {
|
||||
scroll_area->setFrameShape(QFrame::NoFrame);
|
||||
scroll_area->setHorizontalScrollBarPolicy(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;
|
||||
}
|
||||
|
||||
@@ -81,16 +134,28 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_,
|
||||
setWindowFlags(Qt::Dialog | Qt::WindowTitleHint | Qt::WindowSystemMenuHint |
|
||||
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);
|
||||
|
||||
// Set size policy and enable resizing
|
||||
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();
|
||||
if (screen) {
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -183,6 +183,7 @@ Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <shellscalingapi.h>
|
||||
extern "C" {
|
||||
// tells Nvidia and AMD drivers to use the dedicated GPU by default on laptops with switchable
|
||||
// graphics
|
||||
@@ -5252,8 +5253,29 @@ static void SetHighDPIAttributes() {
|
||||
Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||
#endif
|
||||
|
||||
// Enable high DPI scaling and pixmaps
|
||||
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
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[]) {
|
||||
|
||||
Reference in New Issue
Block a user