fix: 150% and 200% zoom levels prevent the user from logging in
- TLDR: we were scaling twice, resulting in ginourmous pixel values The long story: - since Qt treats the various scale factors in a multiplicative way (see https://www.qt.io/blog/2016/01/26/high-dpi-support-in-qt-5-6 for explanation) and there's no way to get the screen's baseline scale factor programatically, we also have to export `QT_SCREEN_SCALE_FACTORS` to something that's not equal to `0` or `1` to force the monitor scale factor to `100%` and then compensate for it when exporting our own scale value using `QT_SCALE_FACTOR` - make the UI slider values go in `25%` steps, allowing for more fine grained control; with `100%` we fallback to the Qt's native handling of highdpi - raised the maximum to `300%` since on highres displays, one wouldn't be able to go over the implicit maximum of `200%` (due to the internal scaling being 2x) - scale our main window's minimum width/height so that we don't overflow the monitor's available space - modernize the `ConfirmAppRestartModal` to use `StatusDialog` - use the new `Utils.restartApplication()` when changing the UI language as well - remove some dead code In the (very) long term, we should take a different approach of scaling our app independently of Qt, just taking the monitor `Screen.devicePixelRatio` into account, similar to what other apps like Telegram do Fixes #13484
This commit is contained in:
parent
0497ecd82e
commit
630da7caaa
|
@ -1,44 +1,26 @@
|
||||||
import QtQuick 2.13
|
import QtQuick 2.15
|
||||||
import QtQuick.Controls 2.13
|
import QtQml.Models 2.15
|
||||||
import QtQuick.Layouts 1.13
|
|
||||||
|
|
||||||
import utils 1.0
|
|
||||||
|
|
||||||
import StatusQ.Controls 0.1
|
import StatusQ.Controls 0.1
|
||||||
|
import StatusQ.Core 0.1
|
||||||
|
import StatusQ.Popups.Dialog 0.1
|
||||||
|
|
||||||
import shared 1.0
|
StatusDialog {
|
||||||
import shared.panels 1.0
|
id: root
|
||||||
import shared.popups 1.0
|
|
||||||
|
|
||||||
// TODO: replace with StatusModal
|
|
||||||
ModalPopup {
|
|
||||||
height: 237
|
|
||||||
width: 400
|
|
||||||
|
|
||||||
property Popup parentPopup
|
|
||||||
|
|
||||||
title: qsTr("Application Restart")
|
title: qsTr("Application Restart")
|
||||||
|
|
||||||
StyledText {
|
contentItem: StatusBaseText {
|
||||||
text: qsTr("Please restart the application to apply the changes.")
|
text: qsTr("Please restart the application to apply the changes.")
|
||||||
font.pixelSize: 15
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
}
|
}
|
||||||
|
|
||||||
footer: Item {
|
footer: StatusDialogFooter {
|
||||||
id: footerContainer
|
rightButtons: ObjectModel {
|
||||||
width: parent.width
|
StatusButton {
|
||||||
height: children[0].height
|
type: StatusBaseButton.Type.Danger
|
||||||
|
text: qsTr("Restart")
|
||||||
StatusButton {
|
onClicked: root.accepted()
|
||||||
anchors.right: parent.right
|
}
|
||||||
anchors.rightMargin: Style.current.smallPadding
|
|
||||||
type: StatusBaseButton.Type.Danger
|
|
||||||
text: qsTr("Restart")
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
onClicked: Utils.restartApplication();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import QtQuick 2.13
|
import QtQuick 2.15
|
||||||
import QtQuick.Controls 2.13
|
import QtQuick.Controls 2.15
|
||||||
import QtQuick.Layouts 1.13
|
import QtQuick.Layouts 1.15
|
||||||
import QtQuick.Controls.Universal 2.12
|
import QtQuick.Window 2.15
|
||||||
|
import QtQuick.Controls.Universal 2.15
|
||||||
|
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
import shared 1.0
|
import shared 1.0
|
||||||
|
@ -37,20 +38,29 @@ SettingsContentBase {
|
||||||
appearanceView.updateFontSize(localAccountSensitiveSettings.fontSize)
|
appearanceView.updateFontSize(localAccountSensitiveSettings.fontSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
readonly property var priv: QtObject {
|
||||||
|
id: priv
|
||||||
|
|
||||||
|
readonly property real savedDpr: {
|
||||||
|
const scaleFactorStr = appearanceView.appearanceStore.readTextFile(uiScaleFilePath)
|
||||||
|
if (scaleFactorStr === "") {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
const scaleFactor = parseFloat(scaleFactorStr)
|
||||||
|
if (isNaN(scaleFactor)) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return scaleFactor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: appearanceContainer
|
id: appearanceContainer
|
||||||
anchors.left: !!parent ? parent.left : undefined
|
anchors.left: !!parent ? parent.left : undefined
|
||||||
|
anchors.leftMargin: Style.current.padding
|
||||||
width: appearanceView.contentWidth - 2 * Style.current.padding
|
width: appearanceView.contentWidth - 2 * Style.current.padding
|
||||||
height: childrenRect.height
|
height: childrenRect.height
|
||||||
|
|
||||||
ButtonGroup {
|
|
||||||
id: chatModeSetting
|
|
||||||
}
|
|
||||||
|
|
||||||
ButtonGroup {
|
|
||||||
id: appearanceSetting
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: preview
|
id: preview
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
|
@ -128,41 +138,34 @@ SettingsContentBase {
|
||||||
|
|
||||||
StatusQ.StatusLabeledSlider {
|
StatusQ.StatusLabeledSlider {
|
||||||
id: zoomSlider
|
id: zoomSlider
|
||||||
readonly property int initialValue: {
|
|
||||||
let scaleFactorStr = appearanceView.appearanceStore.readTextFile(uiScaleFilePath)
|
readonly property int initialValue: priv.savedDpr * 100
|
||||||
if (scaleFactorStr === "") {
|
readonly property bool dirty: value !== initialValue
|
||||||
return 100
|
|
||||||
}
|
|
||||||
let scaleFactor = parseFloat(scaleFactorStr)
|
|
||||||
if (isNaN(scaleFactor)) {
|
|
||||||
return 100
|
|
||||||
}
|
|
||||||
return scaleFactor * 100
|
|
||||||
}
|
|
||||||
anchors.top: labelZoom.bottom
|
anchors.top: labelZoom.bottom
|
||||||
anchors.topMargin: Style.current.padding
|
anchors.topMargin: Style.current.padding
|
||||||
width: parent.width
|
width: parent.width
|
||||||
from: 50
|
from: 50
|
||||||
to: 200
|
to: 300
|
||||||
stepSize: 50
|
stepSize: 25
|
||||||
model: [ qsTr("50%"), qsTr("100%"), qsTr("150%"), qsTr("200%") ]
|
model: [ qsTr("50%"), qsTr("75%"), qsTr("100%"), qsTr("125%"), qsTr("150%"), qsTr("175%"), qsTr("200%"),
|
||||||
|
qsTr("225%"), qsTr("250%"), qsTr("275%"), qsTr("300%")]
|
||||||
value: initialValue
|
value: initialValue
|
||||||
onValueChanged: {
|
onMoved: {
|
||||||
if (value !== initialValue) {
|
const uiScale = zoomSlider.value === 100 ? "" // reset to native highdpi
|
||||||
appearanceView.appearanceStore.writeTextFile(uiScaleFilePath, value / 100.0)
|
: zoomSlider.value / 100.0
|
||||||
}
|
appearanceView.appearanceStore.writeTextFile(uiScaleFilePath, uiScale)
|
||||||
}
|
}
|
||||||
onPressedChanged: {
|
onPressedChanged: {
|
||||||
if (!pressed && value !== initialValue) {
|
if (!pressed && dirty) {
|
||||||
confirmAppRestartModal.open()
|
confirmAppRestartModal.open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfirmAppRestartModal {
|
ConfirmAppRestartModal {
|
||||||
id: confirmAppRestartModal
|
id: confirmAppRestartModal
|
||||||
onClosed: {
|
onAccepted: Utils.restartApplication();
|
||||||
zoomSlider.value = zoomSlider.initialValue
|
onClosed: zoomSlider.value = zoomSlider.initialValue
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -189,13 +189,12 @@ SettingsContentBase {
|
||||||
sourceComponent: ConfirmationDialog {
|
sourceComponent: ConfirmationDialog {
|
||||||
headerSettings.title: qsTr("Change language")
|
headerSettings.title: qsTr("Change language")
|
||||||
confirmationText: qsTr("Display language has been changed. You must restart the application for changes to take effect.")
|
confirmationText: qsTr("Display language has been changed. You must restart the application for changes to take effect.")
|
||||||
confirmButtonLabel: qsTr("Close the app now")
|
confirmButtonLabel: qsTr("Restart")
|
||||||
onConfirmButtonClicked: {
|
onConfirmButtonClicked: {
|
||||||
languageConfirmationDialog.active = false
|
languageConfirmationDialog.active = false
|
||||||
Qt.quit()
|
Utils.restartApplication()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
18
ui/main.qml
18
ui/main.qml
|
@ -1,11 +1,11 @@
|
||||||
import QtQuick 2.13
|
import QtQuick 2.15
|
||||||
import QtQuick.Controls 2.13
|
import QtQuick.Controls 2.15
|
||||||
import QtQuick.Layouts 1.13
|
import QtQuick.Layouts 1.15
|
||||||
import Qt.labs.platform 1.1
|
import Qt.labs.platform 1.1
|
||||||
import Qt.labs.settings 1.0
|
import Qt.labs.settings 1.1
|
||||||
import QtQuick.Window 2.12
|
import QtQuick.Window 2.15
|
||||||
import QtQml 2.13
|
import QtQml 2.15
|
||||||
import QtQuick.Controls.Universal 2.12
|
import QtQuick.Controls.Universal 2.15
|
||||||
|
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
import shared 1.0
|
import shared 1.0
|
||||||
|
@ -25,8 +25,8 @@ StatusWindow {
|
||||||
|
|
||||||
id: applicationWindow
|
id: applicationWindow
|
||||||
objectName: "mainWindow"
|
objectName: "mainWindow"
|
||||||
minimumWidth: 1200
|
minimumWidth: 1200 / Screen.devicePixelRatio
|
||||||
minimumHeight: 680
|
minimumHeight: 680 / Screen.devicePixelRatio
|
||||||
color: Style.current.background
|
color: Style.current.background
|
||||||
title: {
|
title: {
|
||||||
// Set application settings
|
// Set application settings
|
||||||
|
|
|
@ -166,8 +166,18 @@ void dos_qguiapplication_enable_hdpi(const char *uiScaleFilePath)
|
||||||
|
|
||||||
QFile scaleFile(QString::fromUtf8(uiScaleFilePath));
|
QFile scaleFile(QString::fromUtf8(uiScaleFilePath));
|
||||||
if (scaleFile.open(QIODevice::ReadOnly)) {
|
if (scaleFile.open(QIODevice::ReadOnly)) {
|
||||||
const auto scale = scaleFile.readAll();
|
const auto scaleStr = scaleFile.readAll();
|
||||||
qputenv("QT_SCALE_FACTOR", scale);
|
bool ok = false;
|
||||||
|
const auto scale = scaleStr.toDouble(&ok);
|
||||||
|
if (ok) {
|
||||||
|
// we want to scale the app on our own
|
||||||
|
qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "0");
|
||||||
|
// workaround for bug/feature when Qt would bail out if the scale is "1" and revert to DPI based scaling
|
||||||
|
constexpr auto unaryScale = 1.1;
|
||||||
|
qputenv("QT_SCREEN_SCALE_FACTORS", QByteArray::number(unaryScale));
|
||||||
|
// compensate for the workaround above so that we get the desired scale factor
|
||||||
|
qputenv("QT_SCALE_FACTOR", QByteArray::number(scale/unaryScale, 'f', 2));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,7 +383,7 @@ void dos_qguiapplication_quit()
|
||||||
|
|
||||||
void dos_qguiapplication_restart()
|
void dos_qguiapplication_restart()
|
||||||
{
|
{
|
||||||
QProcess::startDetached(QCoreApplication::applicationFilePath());
|
QProcess::startDetached(QCoreApplication::applicationFilePath(), {});
|
||||||
dos_qguiapplication_quit();
|
dos_qguiapplication_quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue