Handle emoji myself in custom macOS title.

This commit is contained in:
John Preston 2023-04-26 22:11:33 +04:00
parent 37531086ec
commit bfdd116000
12 changed files with 74 additions and 28 deletions

View file

@ -28,6 +28,8 @@ public:
void setGeometry(QRect rect) override;
void close() override;
const style::TextStyle &titleTextStyle() const override;
private:
class Private;
friend class Private;

View file

@ -422,6 +422,10 @@ void WindowHelper::close() {
_private->close();
}
const style::TextStyle &WindowHelper::titleTextStyle() const {
return _title->textStyle();
}
void WindowHelper::init() {
updateCustomTitleVisibility(true);

View file

@ -6,6 +6,7 @@
//
#pragma once
#include "ui/text/text.h"
#include "ui/rp_widget.h"
#include "base/object_ptr.h"
@ -14,6 +15,7 @@
namespace style {
struct WindowTitle;
struct TextStyle;
} // namespace style
namespace Ui {
@ -25,12 +27,14 @@ namespace Platform {
class TitleWidget : public RpWidget {
public:
TitleWidget(not_null<RpWidget*> parent, int height);
~TitleWidget();
void setText(const QString &text);
void setStyle(const style::WindowTitle &st);
void setControlsRect(const QRect &rect);
[[nodiscard]] QString text() const;
[[nodiscard]] bool shouldBeHidden() const;
[[nodiscard]] const style::TextStyle &textStyle() const;
protected:
void paintEvent(QPaintEvent *e) override;
@ -43,11 +47,11 @@ private:
void init(int height);
not_null<const style::WindowTitle*> _st;
std::unique_ptr<style::TextStyle> _textStyle;
object_ptr<Ui::PlainShadow> _shadow;
QString _text;
int _textWidth = 0;
Ui::Text::String _string;
int _controlsRight = 0;
QFont _font;
};

View file

@ -8,6 +8,7 @@
#include "ui/widgets/buttons.h"
#include "ui/widgets/shadow.h"
#include "ui/painter.h"
#include "ui/ui_utility.h"
#include "base/debug_log.h"
#include "styles/style_widgets.h"
@ -27,10 +28,12 @@ TitleWidget::TitleWidget(not_null<RpWidget*> parent, int height)
init(height);
}
TitleWidget::~TitleWidget() = default;
void TitleWidget::setText(const QString &text) {
if (_text != text) {
_text = text;
_textWidth = QFontMetrics(_font).horizontalAdvance(_text);
_string.setText(textStyle(), text);
update();
}
}
@ -48,6 +51,10 @@ bool TitleWidget::shouldBeHidden() const {
return !_st->height;
}
const style::TextStyle &TitleWidget::textStyle() const {
return *_textStyle;
}
QString TitleWidget::text() const {
return _text;
}
@ -64,51 +71,55 @@ void TitleWidget::init(int height) {
setGeometry(0, 0, width, height);
}, lifetime());
const auto setFromFont = [&](const style::font &font) {
_textStyle = std::make_unique<style::TextStyle>(style::TextStyle{
.font = font,
.linkFont = font,
.linkFontOver = font,
});
};
const auto families = QStringList{
u".AppleSystemUIFont"_q,
u".SF NS Text"_q,
u"Helvetica Neue"_q,
};
for (auto family : families) {
_font.setFamily(family);
if (QFontInfo(_font).family() == _font.family()) {
auto font = QFont();
font.setFamily(family);
if (QFontInfo(font).family() == font.family()) {
static const auto logged = [&] {
LOG(("Title Font: %1").arg(family));
return true;
}();
const auto apple = (family == u".AppleSystemUIFont"_q);
setFromFont(style::font(
apple ? 13 : (height * 15) / 24,
apple ? style::internal::FontBold : 0,
family));
break;
}
}
if (QFontInfo(_font).family() != _font.family()) {
_font = st::semiboldFont;
_font.setPixelSize(13);
} else if (_font.family() == u".AppleSystemUIFont"_q) {
_font.setBold(true);
_font.setPixelSize(13);
} else {
_font.setPixelSize((height * 15) / 24);
if (!_textStyle) {
setFromFont(style::font(13, style::internal::FontSemibold, 0));
}
}
void TitleWidget::paintEvent(QPaintEvent *e) {
QPainter p(this);
Painter p(this);
const auto active = isActiveWindow();
p.fillRect(rect(), active ? _st->bgActive : _st->bg);
p.setFont(_font);
p.setPen(active ? _st->fgActive : _st->fg);
if ((width() - _controlsRight * 2) < _textWidth) {
const auto elided = QFontMetrics(_font).elidedText(
_text,
Qt::ElideRight,
width() - _controlsRight);
const auto padding = QMargins(_controlsRight, 0, 0, 0);
p.drawText(rect() - padding, elided, style::al_left);
const auto top = (height() - _textStyle->font->height) / 2;
if ((width() - _controlsRight * 2) < _string.maxWidth()) {
const auto left = _controlsRight;
_string.drawElided(p, left, top, width() - left);
} else {
p.drawText(rect(), _text, style::al_center);
const auto left = (width() - _string.maxWidth()) / 2;
_string.draw(p, left, top, width() - left);
}
}

View file

@ -205,6 +205,10 @@ void BasicWindowHelper::setBodyTitleArea(
_bodyTitleAreaTestMethod = std::move(testMethod);
}
const style::TextStyle &BasicWindowHelper::titleTextStyle() const {
return st::defaultWindowTitle.style;
}
QMargins BasicWindowHelper::nativeFrameMargins() const {
const auto inner = window()->geometry();
const auto outer = window()->frameGeometry();

View file

@ -12,6 +12,7 @@
namespace style {
struct WindowTitle;
struct TextStyle;
} // namespace style
namespace Ui {
@ -62,6 +63,8 @@ public:
virtual int manualRoundingRadius() const;
void setBodyTitleArea(Fn<WindowTitleHitTestFlags(QPoint)> testMethod);
[[nodiscard]] virtual const style::TextStyle &titleTextStyle() const;
protected:
[[nodiscard]] WindowTitleHitTestFlags bodyTitleAreaHit(
QPoint point) const {

View file

@ -26,7 +26,7 @@ void SetCustomFonts(const CustomFont &regular, const CustomFont &bold) {
BoldFont = bold;
}
QFont ResolveFont(uint32 flags, int size) {
QFont ResolveFont(const QString &familyOverride, uint32 flags, int size) {
static auto Database = QFontDatabase();
const auto bold = ((flags & FontBold) || (flags & FontSemibold));
@ -35,7 +35,12 @@ QFont ResolveFont(uint32 flags, int size) {
const auto useCustom = !custom.family.isEmpty();
auto result = QFont(QGuiApplication::font().family());
if (flags & FontMonospace) {
if (!familyOverride.isEmpty()) {
result.setFamily(familyOverride);
if (bold) {
result.setBold(true);
}
} else if (flags & FontMonospace) {
result.setFamily(MonospaceFont());
} else if (useCustom) {
const auto sizes = Database.smoothSizes(custom.family, custom.style);

View file

@ -40,6 +40,6 @@ inline bool operator>=(const CustomFont &a, const CustomFont &b) {
void SetCustomFonts(const CustomFont &regular, const CustomFont &bold);
[[nodiscard]] QFont ResolveFont(uint32 flags, int size);
[[nodiscard]] QFont ResolveFont(const QString &familyOverride, uint32 flags, int size);
} // namespace style

View file

@ -300,7 +300,7 @@ int CeilTextWidth(const QFont &font, const QString &text) {
}
FontData::FontData(int size, uint32 flags, int family, Font *other)
: f(ResolveFont(flags, size))
: f(ResolveFont(family ? fontFamilies[family] : QString(), flags, size))
, _m(f)
, _size(size)
, _flags(flags)

View file

@ -103,4 +103,8 @@ int RpWindow::manualRoundingRadius() const {
return _helper->manualRoundingRadius();
}
const style::TextStyle &RpWindow::titleTextStyle() const {
return _helper->titleTextStyle();
}
} // namespace Ui

View file

@ -11,6 +11,7 @@
namespace style {
struct WindowTitle;
struct TextStyle;
} // namespace style
namespace Ui {
@ -68,6 +69,8 @@ public:
[[nodiscard]] int manualRoundingRadius() const;
void setBodyTitleArea(Fn<WindowTitleHitTestFlags(QPoint)> testMethod);
[[nodiscard]] const style::TextStyle &titleTextStyle() const;
private:
const std::unique_ptr<Platform::BasicWindowHelper> _helper;

View file

@ -555,6 +555,7 @@ WindowTitle {
bgActive: color;
fg: color;
fgActive: color;
style: TextStyle;
minimize: IconButton;
minimizeIconActive: icon;
minimizeIconActiveOver: icon;
@ -1420,6 +1421,11 @@ defaultWindowTitle: WindowTitle {
bgActive: titleBgActive;
fg: titleFg;
fgActive: titleFgActive;
style: TextStyle(defaultTextStyle) {
font: font(semibold 12px);
linkFont: font(semibold 12px);
linkFontOver: font(semibold 12px underline);
}
minimize: IconButton(windowTitleButton) {
icon: icon {
{ windowTitleButtonSize, titleButtonBg },