Handle emoji myself in custom macOS title.
This commit is contained in:
parent
37531086ec
commit
bfdd116000
12 changed files with 74 additions and 28 deletions
|
|
@ -28,6 +28,8 @@ public:
|
||||||
void setGeometry(QRect rect) override;
|
void setGeometry(QRect rect) override;
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
|
const style::TextStyle &titleTextStyle() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Private;
|
class Private;
|
||||||
friend class Private;
|
friend class Private;
|
||||||
|
|
|
||||||
|
|
@ -422,6 +422,10 @@ void WindowHelper::close() {
|
||||||
_private->close();
|
_private->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const style::TextStyle &WindowHelper::titleTextStyle() const {
|
||||||
|
return _title->textStyle();
|
||||||
|
}
|
||||||
|
|
||||||
void WindowHelper::init() {
|
void WindowHelper::init() {
|
||||||
updateCustomTitleVisibility(true);
|
updateCustomTitleVisibility(true);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
//
|
//
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "ui/text/text.h"
|
||||||
#include "ui/rp_widget.h"
|
#include "ui/rp_widget.h"
|
||||||
#include "base/object_ptr.h"
|
#include "base/object_ptr.h"
|
||||||
|
|
||||||
|
|
@ -14,6 +15,7 @@
|
||||||
|
|
||||||
namespace style {
|
namespace style {
|
||||||
struct WindowTitle;
|
struct WindowTitle;
|
||||||
|
struct TextStyle;
|
||||||
} // namespace style
|
} // namespace style
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
|
@ -25,12 +27,14 @@ namespace Platform {
|
||||||
class TitleWidget : public RpWidget {
|
class TitleWidget : public RpWidget {
|
||||||
public:
|
public:
|
||||||
TitleWidget(not_null<RpWidget*> parent, int height);
|
TitleWidget(not_null<RpWidget*> parent, int height);
|
||||||
|
~TitleWidget();
|
||||||
|
|
||||||
void setText(const QString &text);
|
void setText(const QString &text);
|
||||||
void setStyle(const style::WindowTitle &st);
|
void setStyle(const style::WindowTitle &st);
|
||||||
void setControlsRect(const QRect &rect);
|
void setControlsRect(const QRect &rect);
|
||||||
[[nodiscard]] QString text() const;
|
[[nodiscard]] QString text() const;
|
||||||
[[nodiscard]] bool shouldBeHidden() const;
|
[[nodiscard]] bool shouldBeHidden() const;
|
||||||
|
[[nodiscard]] const style::TextStyle &textStyle() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
|
@ -43,11 +47,11 @@ private:
|
||||||
void init(int height);
|
void init(int height);
|
||||||
|
|
||||||
not_null<const style::WindowTitle*> _st;
|
not_null<const style::WindowTitle*> _st;
|
||||||
|
std::unique_ptr<style::TextStyle> _textStyle;
|
||||||
object_ptr<Ui::PlainShadow> _shadow;
|
object_ptr<Ui::PlainShadow> _shadow;
|
||||||
QString _text;
|
QString _text;
|
||||||
int _textWidth = 0;
|
Ui::Text::String _string;
|
||||||
int _controlsRight = 0;
|
int _controlsRight = 0;
|
||||||
QFont _font;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/widgets/shadow.h"
|
#include "ui/widgets/shadow.h"
|
||||||
|
#include "ui/painter.h"
|
||||||
#include "ui/ui_utility.h"
|
#include "ui/ui_utility.h"
|
||||||
#include "base/debug_log.h"
|
#include "base/debug_log.h"
|
||||||
#include "styles/style_widgets.h"
|
#include "styles/style_widgets.h"
|
||||||
|
|
@ -27,10 +28,12 @@ TitleWidget::TitleWidget(not_null<RpWidget*> parent, int height)
|
||||||
init(height);
|
init(height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TitleWidget::~TitleWidget() = default;
|
||||||
|
|
||||||
void TitleWidget::setText(const QString &text) {
|
void TitleWidget::setText(const QString &text) {
|
||||||
if (_text != text) {
|
if (_text != text) {
|
||||||
_text = text;
|
_text = text;
|
||||||
_textWidth = QFontMetrics(_font).horizontalAdvance(_text);
|
_string.setText(textStyle(), text);
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -48,6 +51,10 @@ bool TitleWidget::shouldBeHidden() const {
|
||||||
return !_st->height;
|
return !_st->height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const style::TextStyle &TitleWidget::textStyle() const {
|
||||||
|
return *_textStyle;
|
||||||
|
}
|
||||||
|
|
||||||
QString TitleWidget::text() const {
|
QString TitleWidget::text() const {
|
||||||
return _text;
|
return _text;
|
||||||
}
|
}
|
||||||
|
|
@ -64,51 +71,55 @@ void TitleWidget::init(int height) {
|
||||||
setGeometry(0, 0, width, height);
|
setGeometry(0, 0, width, height);
|
||||||
}, lifetime());
|
}, 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{
|
const auto families = QStringList{
|
||||||
u".AppleSystemUIFont"_q,
|
u".AppleSystemUIFont"_q,
|
||||||
u".SF NS Text"_q,
|
u".SF NS Text"_q,
|
||||||
u"Helvetica Neue"_q,
|
u"Helvetica Neue"_q,
|
||||||
};
|
};
|
||||||
for (auto family : families) {
|
for (auto family : families) {
|
||||||
_font.setFamily(family);
|
auto font = QFont();
|
||||||
if (QFontInfo(_font).family() == _font.family()) {
|
font.setFamily(family);
|
||||||
|
if (QFontInfo(font).family() == font.family()) {
|
||||||
static const auto logged = [&] {
|
static const auto logged = [&] {
|
||||||
LOG(("Title Font: %1").arg(family));
|
LOG(("Title Font: %1").arg(family));
|
||||||
return true;
|
return true;
|
||||||
}();
|
}();
|
||||||
|
const auto apple = (family == u".AppleSystemUIFont"_q);
|
||||||
|
setFromFont(style::font(
|
||||||
|
apple ? 13 : (height * 15) / 24,
|
||||||
|
apple ? style::internal::FontBold : 0,
|
||||||
|
family));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!_textStyle) {
|
||||||
if (QFontInfo(_font).family() != _font.family()) {
|
setFromFont(style::font(13, style::internal::FontSemibold, 0));
|
||||||
_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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TitleWidget::paintEvent(QPaintEvent *e) {
|
void TitleWidget::paintEvent(QPaintEvent *e) {
|
||||||
QPainter p(this);
|
Painter p(this);
|
||||||
|
|
||||||
const auto active = isActiveWindow();
|
const auto active = isActiveWindow();
|
||||||
p.fillRect(rect(), active ? _st->bgActive : _st->bg);
|
p.fillRect(rect(), active ? _st->bgActive : _st->bg);
|
||||||
|
|
||||||
p.setFont(_font);
|
|
||||||
p.setPen(active ? _st->fgActive : _st->fg);
|
p.setPen(active ? _st->fgActive : _st->fg);
|
||||||
|
|
||||||
if ((width() - _controlsRight * 2) < _textWidth) {
|
const auto top = (height() - _textStyle->font->height) / 2;
|
||||||
const auto elided = QFontMetrics(_font).elidedText(
|
if ((width() - _controlsRight * 2) < _string.maxWidth()) {
|
||||||
_text,
|
const auto left = _controlsRight;
|
||||||
Qt::ElideRight,
|
_string.drawElided(p, left, top, width() - left);
|
||||||
width() - _controlsRight);
|
|
||||||
const auto padding = QMargins(_controlsRight, 0, 0, 0);
|
|
||||||
p.drawText(rect() - padding, elided, style::al_left);
|
|
||||||
} else {
|
} else {
|
||||||
p.drawText(rect(), _text, style::al_center);
|
const auto left = (width() - _string.maxWidth()) / 2;
|
||||||
|
_string.draw(p, left, top, width() - left);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -205,6 +205,10 @@ void BasicWindowHelper::setBodyTitleArea(
|
||||||
_bodyTitleAreaTestMethod = std::move(testMethod);
|
_bodyTitleAreaTestMethod = std::move(testMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const style::TextStyle &BasicWindowHelper::titleTextStyle() const {
|
||||||
|
return st::defaultWindowTitle.style;
|
||||||
|
}
|
||||||
|
|
||||||
QMargins BasicWindowHelper::nativeFrameMargins() const {
|
QMargins BasicWindowHelper::nativeFrameMargins() const {
|
||||||
const auto inner = window()->geometry();
|
const auto inner = window()->geometry();
|
||||||
const auto outer = window()->frameGeometry();
|
const auto outer = window()->frameGeometry();
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
namespace style {
|
namespace style {
|
||||||
struct WindowTitle;
|
struct WindowTitle;
|
||||||
|
struct TextStyle;
|
||||||
} // namespace style
|
} // namespace style
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
|
@ -62,6 +63,8 @@ public:
|
||||||
virtual int manualRoundingRadius() const;
|
virtual int manualRoundingRadius() const;
|
||||||
void setBodyTitleArea(Fn<WindowTitleHitTestFlags(QPoint)> testMethod);
|
void setBodyTitleArea(Fn<WindowTitleHitTestFlags(QPoint)> testMethod);
|
||||||
|
|
||||||
|
[[nodiscard]] virtual const style::TextStyle &titleTextStyle() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
[[nodiscard]] WindowTitleHitTestFlags bodyTitleAreaHit(
|
[[nodiscard]] WindowTitleHitTestFlags bodyTitleAreaHit(
|
||||||
QPoint point) const {
|
QPoint point) const {
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ void SetCustomFonts(const CustomFont ®ular, const CustomFont &bold) {
|
||||||
BoldFont = bold;
|
BoldFont = bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
QFont ResolveFont(uint32 flags, int size) {
|
QFont ResolveFont(const QString &familyOverride, uint32 flags, int size) {
|
||||||
static auto Database = QFontDatabase();
|
static auto Database = QFontDatabase();
|
||||||
|
|
||||||
const auto bold = ((flags & FontBold) || (flags & FontSemibold));
|
const auto bold = ((flags & FontBold) || (flags & FontSemibold));
|
||||||
|
|
@ -35,7 +35,12 @@ QFont ResolveFont(uint32 flags, int size) {
|
||||||
const auto useCustom = !custom.family.isEmpty();
|
const auto useCustom = !custom.family.isEmpty();
|
||||||
|
|
||||||
auto result = QFont(QGuiApplication::font().family());
|
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());
|
result.setFamily(MonospaceFont());
|
||||||
} else if (useCustom) {
|
} else if (useCustom) {
|
||||||
const auto sizes = Database.smoothSizes(custom.family, custom.style);
|
const auto sizes = Database.smoothSizes(custom.family, custom.style);
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,6 @@ inline bool operator>=(const CustomFont &a, const CustomFont &b) {
|
||||||
|
|
||||||
void SetCustomFonts(const CustomFont ®ular, const CustomFont &bold);
|
void SetCustomFonts(const CustomFont ®ular, const CustomFont &bold);
|
||||||
|
|
||||||
[[nodiscard]] QFont ResolveFont(uint32 flags, int size);
|
[[nodiscard]] QFont ResolveFont(const QString &familyOverride, uint32 flags, int size);
|
||||||
|
|
||||||
} // namespace style
|
} // namespace style
|
||||||
|
|
|
||||||
|
|
@ -300,7 +300,7 @@ int CeilTextWidth(const QFont &font, const QString &text) {
|
||||||
}
|
}
|
||||||
|
|
||||||
FontData::FontData(int size, uint32 flags, int family, Font *other)
|
FontData::FontData(int size, uint32 flags, int family, Font *other)
|
||||||
: f(ResolveFont(flags, size))
|
: f(ResolveFont(family ? fontFamilies[family] : QString(), flags, size))
|
||||||
, _m(f)
|
, _m(f)
|
||||||
, _size(size)
|
, _size(size)
|
||||||
, _flags(flags)
|
, _flags(flags)
|
||||||
|
|
|
||||||
|
|
@ -103,4 +103,8 @@ int RpWindow::manualRoundingRadius() const {
|
||||||
return _helper->manualRoundingRadius();
|
return _helper->manualRoundingRadius();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const style::TextStyle &RpWindow::titleTextStyle() const {
|
||||||
|
return _helper->titleTextStyle();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
namespace style {
|
namespace style {
|
||||||
struct WindowTitle;
|
struct WindowTitle;
|
||||||
|
struct TextStyle;
|
||||||
} // namespace style
|
} // namespace style
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
|
@ -68,6 +69,8 @@ public:
|
||||||
[[nodiscard]] int manualRoundingRadius() const;
|
[[nodiscard]] int manualRoundingRadius() const;
|
||||||
void setBodyTitleArea(Fn<WindowTitleHitTestFlags(QPoint)> testMethod);
|
void setBodyTitleArea(Fn<WindowTitleHitTestFlags(QPoint)> testMethod);
|
||||||
|
|
||||||
|
[[nodiscard]] const style::TextStyle &titleTextStyle() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::unique_ptr<Platform::BasicWindowHelper> _helper;
|
const std::unique_ptr<Platform::BasicWindowHelper> _helper;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -555,6 +555,7 @@ WindowTitle {
|
||||||
bgActive: color;
|
bgActive: color;
|
||||||
fg: color;
|
fg: color;
|
||||||
fgActive: color;
|
fgActive: color;
|
||||||
|
style: TextStyle;
|
||||||
minimize: IconButton;
|
minimize: IconButton;
|
||||||
minimizeIconActive: icon;
|
minimizeIconActive: icon;
|
||||||
minimizeIconActiveOver: icon;
|
minimizeIconActiveOver: icon;
|
||||||
|
|
@ -1420,6 +1421,11 @@ defaultWindowTitle: WindowTitle {
|
||||||
bgActive: titleBgActive;
|
bgActive: titleBgActive;
|
||||||
fg: titleFg;
|
fg: titleFg;
|
||||||
fgActive: titleFgActive;
|
fgActive: titleFgActive;
|
||||||
|
style: TextStyle(defaultTextStyle) {
|
||||||
|
font: font(semibold 12px);
|
||||||
|
linkFont: font(semibold 12px);
|
||||||
|
linkFontOver: font(semibold 12px underline);
|
||||||
|
}
|
||||||
minimize: IconButton(windowTitleButton) {
|
minimize: IconButton(windowTitleButton) {
|
||||||
icon: icon {
|
icon: icon {
|
||||||
{ windowTitleButtonSize, titleButtonBg },
|
{ windowTitleButtonSize, titleButtonBg },
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue