mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/telegramdesktop/tdesktop
synced 2026-09-20 08:03:45 +08:00
Fix the scale of the external webapp shell.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -49,6 +49,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include <QtCore/QJsonObject>
|
||||
#include <QtCore/QJsonArray>
|
||||
#include <QtCore/QUrl>
|
||||
#include <QtCore/QtMath>
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtGui/QClipboard>
|
||||
#include <QtGui/QWindow>
|
||||
@@ -779,28 +780,12 @@ void FillNativeSharedPanelMenu(
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] QImage RasterizeStyleIcon(const style::icon &icon) {
|
||||
const auto size = icon.size();
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
auto image = QImage(size * ratio, QImage::Format_ARGB32_Premultiplied);
|
||||
image.setDevicePixelRatio(ratio);
|
||||
image.fill(Qt::transparent);
|
||||
auto painter = Painter(&image);
|
||||
icon.paintInCenter(painter, QRect(QPoint(), size));
|
||||
return image;
|
||||
}
|
||||
|
||||
[[nodiscard]] QImage RasterizeVerifiedBadge() {
|
||||
const auto size = st::infoVerifiedStar.size() + QSize(0, st::lineWidth);
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
auto image = QImage(size * ratio, QImage::Format_ARGB32_Premultiplied);
|
||||
image.setDevicePixelRatio(ratio);
|
||||
image.fill(Qt::transparent);
|
||||
auto painter = Painter(&image);
|
||||
const auto width = size.width();
|
||||
st::infoVerifiedStar.paint(painter, st::lineWidth, 0, width);
|
||||
st::infoPeerBadge.verifiedCheck.paint(painter, st::lineWidth, 0, width);
|
||||
return image;
|
||||
// WebKit maps CSS pixels to the screen by itself, so rasterize above any
|
||||
// screen density (Qt floors it on X11) and let it downscale.
|
||||
[[nodiscard]] int ExternalShellAssetRatio() {
|
||||
return std::min(
|
||||
style::DevicePixelRatio() + 1,
|
||||
style::kScaleMax / 100);
|
||||
}
|
||||
|
||||
[[nodiscard]] QString PngDataUrl(const QImage &image) {
|
||||
@@ -826,15 +811,41 @@ void FillNativeSharedPanelMenu(
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] QJsonObject SerializeStyleIconAsset(const style::icon &icon) {
|
||||
return SerializeRasterAsset(RasterizeStyleIcon(icon), icon.size());
|
||||
[[nodiscard]] QJsonObject SerializeStyleIconAsset(
|
||||
const style::icon &icon,
|
||||
const style::color &color) {
|
||||
const auto ratio = ExternalShellAssetRatio();
|
||||
const auto image = icon.instance(
|
||||
color->c,
|
||||
ratio * 100,
|
||||
true);
|
||||
return SerializeRasterAsset(image, image.size() / ratio);
|
||||
}
|
||||
|
||||
[[nodiscard]] QJsonObject SerializeVerifiedBadgeAsset() {
|
||||
const auto size = st::infoVerifiedStar.size() + QSize(0, st::lineWidth);
|
||||
const auto ratio = ExternalShellAssetRatio();
|
||||
const auto scale = ratio * 100;
|
||||
const auto star = st::infoVerifiedStar.instance(
|
||||
st::profileVerifiedCheckBg->c,
|
||||
scale,
|
||||
true);
|
||||
const auto check = st::infoPeerBadge.verifiedCheck.instance(
|
||||
st::profileVerifiedCheckFg->c,
|
||||
scale,
|
||||
true);
|
||||
const auto line = LinuxShell::Unscaled(st::lineWidth) * ratio;
|
||||
auto image = QImage(
|
||||
star.size() + QSize(0, line),
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
image.fill(Qt::transparent);
|
||||
{
|
||||
auto p = QPainter(&image);
|
||||
p.drawImage(line, 0, star);
|
||||
p.drawImage(line, 0, check);
|
||||
}
|
||||
return SerializeRasterAsset(
|
||||
RasterizeVerifiedBadge(),
|
||||
size,
|
||||
image,
|
||||
image.size() / ratio,
|
||||
tr::lng_sr_verified_badge(tr::now));
|
||||
}
|
||||
|
||||
@@ -845,7 +856,9 @@ void CollectSharedPanelMenuIcons(
|
||||
if (!item.iconKey.isEmpty()
|
||||
&& item.icon
|
||||
&& !result.contains(item.iconKey)) {
|
||||
result.insert(item.iconKey, SerializeStyleIconAsset(*item.icon));
|
||||
result.insert(
|
||||
item.iconKey,
|
||||
SerializeStyleIconAsset(*item.icon, st::menuIconColor));
|
||||
}
|
||||
if (!item.children.empty()) {
|
||||
CollectSharedPanelMenuIcons(item.children, result);
|
||||
@@ -1889,7 +1902,10 @@ void Panel::requestExternalShellButtonEmoji(const QString &name) {
|
||||
_delegate->botResolveButtonEmoji({
|
||||
.customEmojiId = state->args.iconCustomEmojiId,
|
||||
.textColor = state->textColor,
|
||||
.size = kExternalShellButtonIconSize,
|
||||
// Custom emoji take a logical size, rasterize them as other assets.
|
||||
.size = qCeil(kExternalShellButtonIconSize
|
||||
* ExternalShellAssetRatio()
|
||||
/ double(style::DevicePixelRatio())),
|
||||
.callback = std::move(send),
|
||||
});
|
||||
}
|
||||
@@ -1918,7 +1934,9 @@ void Panel::sendExternalShellAssets() {
|
||||
sendExternalShellMethod("setAssets", {
|
||||
{ u"icons"_q, icons },
|
||||
{ u"titleMenuIcon"_q,
|
||||
SerializeStyleIconAsset(st::separatePanelMenu.icon) },
|
||||
SerializeStyleIconAsset(
|
||||
st::separatePanelMenu.icon,
|
||||
st::boxTitleCloseFg) },
|
||||
{ u"verifiedBadge"_q, SerializeVerifiedBadgeAsset() },
|
||||
{ u"menuPalette"_q, LinuxShell::MenuPalette() },
|
||||
});
|
||||
@@ -2162,7 +2180,7 @@ bool Panel::createWebview(const Webview::ThemeParams ¶ms) {
|
||||
? Webview::WindowStyle::Frameless
|
||||
: Webview::WindowStyle::Default,
|
||||
.windowMargins = _externalShell
|
||||
? st::botWebViewShellShadowPadding
|
||||
? LinuxShell::Unscaled(st::botWebViewShellShadowPadding)
|
||||
: QMargins(),
|
||||
.initialSize = _externalShell
|
||||
? LinuxShell::WindowSize(st::botWebViewPanelSize)
|
||||
@@ -2596,7 +2614,9 @@ void Panel::sendContentSafeArea() {
|
||||
: 0;
|
||||
const auto scaled = top * style::DevicePixelRatio();
|
||||
auto report = 0;
|
||||
if (const auto screen = QGuiApplication::primaryScreen()) {
|
||||
if (_externalShell) {
|
||||
report = LinuxShell::Unscaled(top);
|
||||
} else if (const auto screen = QGuiApplication::primaryScreen()) {
|
||||
const auto dpi = screen->logicalDotsPerInch();
|
||||
const auto ratio = screen->devicePixelRatio();
|
||||
const auto basePair = screen->handle()->logicalBaseDpi();
|
||||
|
||||
@@ -158,17 +158,17 @@ QByteArray EventScript(
|
||||
}
|
||||
|
||||
QJsonObject Metrics() {
|
||||
const auto &shellPadding = st::botWebViewShellPadding;
|
||||
const auto &shadowPadding = st::botWebViewShellShadowPadding;
|
||||
const auto &titlePadding = st::botWebViewShellTitlePadding;
|
||||
const auto &menuButtonSize = st::botWebViewShellMenuButtonSize;
|
||||
const auto fullscreenButtonSize = QSize(
|
||||
const auto shellPadding = Unscaled(st::botWebViewShellPadding);
|
||||
const auto shadowPadding = Unscaled(st::botWebViewShellShadowPadding);
|
||||
const auto titlePadding = Unscaled(st::botWebViewShellTitlePadding);
|
||||
const auto menuButtonSize = Unscaled(st::botWebViewShellMenuButtonSize);
|
||||
const auto fullscreenButtonSize = Unscaled(QSize(
|
||||
st::fullScreenPanelClose.width,
|
||||
st::fullScreenPanelClose.height);
|
||||
st::fullScreenPanelClose.height));
|
||||
const auto fullscreenControlShift
|
||||
= st::separatePanelClose.rippleAreaPosition;
|
||||
= Unscaled(st::separatePanelClose.rippleAreaPosition);
|
||||
return {
|
||||
{ u"shellRadius"_q, st::botWebViewShellRadius },
|
||||
{ u"shellRadius"_q, Unscaled(st::botWebViewShellRadius) },
|
||||
{ u"shellPaddingTop"_q, shellPadding.top() },
|
||||
{ u"shellPaddingRight"_q, shellPadding.right() },
|
||||
{ u"shellPaddingBottom"_q, shellPadding.bottom() },
|
||||
@@ -177,20 +177,23 @@ QJsonObject Metrics() {
|
||||
{ u"shadowPaddingRight"_q, shadowPadding.right() },
|
||||
{ u"shadowPaddingBottom"_q, shadowPadding.bottom() },
|
||||
{ u"shadowPaddingLeft"_q, shadowPadding.left() },
|
||||
{ u"headerHeight"_q, st::botWebViewShellHeaderHeight },
|
||||
{ u"headerHeight"_q, Unscaled(st::botWebViewShellHeaderHeight) },
|
||||
{ u"titlePaddingTop"_q, titlePadding.top() },
|
||||
{ u"titlePaddingRight"_q, titlePadding.right() },
|
||||
{ u"titlePaddingBottom"_q, titlePadding.bottom() },
|
||||
{ u"titlePaddingLeft"_q, titlePadding.left() },
|
||||
{ u"badgeSkip"_q, st::botWebViewShellBadgeSkip },
|
||||
{ u"frameRadius"_q, st::botWebViewShellFrameRadius },
|
||||
{ u"badgeSkip"_q, Unscaled(st::botWebViewShellBadgeSkip) },
|
||||
{ u"frameRadius"_q, Unscaled(st::botWebViewShellFrameRadius) },
|
||||
{ u"controlWidth"_q, menuButtonSize.width() },
|
||||
{ u"controlHeight"_q, menuButtonSize.height() },
|
||||
{ u"buttonHeight"_q, st::botWebViewBottomButton.height },
|
||||
{ u"buttonGapX"_q, st::botWebViewBottomSkip.x() },
|
||||
{ u"buttonGapY"_q, st::botWebViewBottomSkip.y() },
|
||||
{ u"disclosureSkip"_q, st::botWebViewShellDisclosureSkip },
|
||||
{ u"footerButtonSkip"_q, st::botWebViewShellFooterButtonSkip },
|
||||
{ u"buttonHeight"_q, Unscaled(st::botWebViewBottomButton.height) },
|
||||
{ u"buttonGapX"_q, Unscaled(st::botWebViewBottomSkip.x()) },
|
||||
{ u"buttonGapY"_q, Unscaled(st::botWebViewBottomSkip.y()) },
|
||||
{ u"disclosureSkip"_q, Unscaled(st::botWebViewShellDisclosureSkip) },
|
||||
{
|
||||
u"footerButtonSkip"_q,
|
||||
Unscaled(st::botWebViewShellFooterButtonSkip),
|
||||
},
|
||||
{ u"fullscreenControlWidth"_q, fullscreenButtonSize.width() },
|
||||
{ u"fullscreenControlHeight"_q, fullscreenButtonSize.height() },
|
||||
{ u"fullscreenControlTop"_q, fullscreenControlShift.y() },
|
||||
@@ -200,11 +203,11 @@ QJsonObject Metrics() {
|
||||
}
|
||||
|
||||
QSize WindowSize(QSize contentSize) {
|
||||
const auto &shadowPadding = st::botWebViewShellShadowPadding;
|
||||
return contentSize + QSize(
|
||||
const auto shadowPadding = Unscaled(st::botWebViewShellShadowPadding);
|
||||
return Unscaled(contentSize) + QSize(
|
||||
shadowPadding.left() + shadowPadding.right(),
|
||||
shadowPadding.top()
|
||||
+ st::botWebViewShellHeaderHeight
|
||||
+ Unscaled(st::botWebViewShellHeaderHeight)
|
||||
+ shadowPadding.bottom());
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "ui/style/style_core_scale.h"
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QJsonObject>
|
||||
#include <QtCore/QSize>
|
||||
@@ -21,6 +23,18 @@ struct ResolvedColors {
|
||||
QColor bottomBg;
|
||||
};
|
||||
|
||||
// WebKit applies the system scale to CSS pixels by itself,
|
||||
// so the shell gets style values without the application scale.
|
||||
template <typename T>
|
||||
[[nodiscard]] T Unscaled(T value) {
|
||||
const auto factor = 100. / style::Scale();
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
return T(base::SafeRound(value * factor));
|
||||
} else {
|
||||
return value * factor;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined Q_OS_WIN && !defined Q_OS_MAC
|
||||
|
||||
[[nodiscard]] QByteArray InstallScript(const QString &shellToken);
|
||||
|
||||
Reference in New Issue
Block a user