diff --git a/fonts/fc-custom.conf b/fonts/fc-custom.conf deleted file mode 100644 index ab5c183..0000000 --- a/fonts/fc-custom.conf +++ /dev/null @@ -1,57 +0,0 @@ - - - - /usr/share/fonts - /usr/local/share/fonts - ~/.fonts - ~/.local/share/fonts - /usr/X11R6/lib/X11/fonts - fonts - - - mono - - - monospace - - - - - sans serif - - - sans-serif - - - - - sans - - - sans-serif - - - /var/cache/fontconfig_11 - fontconfig_11 - ~/.fontconfig_11 - - - true - - - false - - - true - - - hintslight - - - lcddefault - - - rgb - - - diff --git a/fonts/fonts.qrc b/fonts/fonts.qrc index 64c7085..22a4a29 100644 --- a/fonts/fonts.qrc +++ b/fonts/fonts.qrc @@ -10,7 +10,4 @@ DAVazirMediumAsBold.ttf DAVazirMedium.ttf - - fc-custom.conf - diff --git a/ui/basic_click_handlers.cpp b/ui/basic_click_handlers.cpp index ca59447..c1e9d54 100644 --- a/ui/basic_click_handlers.cpp +++ b/ui/basic_click_handlers.cpp @@ -41,13 +41,16 @@ QString UrlClickHandler::copyToClipboardContextItemText() const { : Ui::Integration::Instance().phraseContextCopyLink(); } -QString UrlClickHandler::url() const { - if (isEmail()) { - return _originalUrl; +QString UrlClickHandler::EncodeForOpening(const QString &originalUrl) { + if (IsEmail(originalUrl)) { + return originalUrl; } - QUrl u(_originalUrl), good(u.isValid() ? u.toEncoded() : QString()); - QString result(good.isValid() ? QString::fromUtf8(good.toEncoded()) : _originalUrl); + const auto u = QUrl(originalUrl); + const auto good = QUrl(u.isValid() ? u.toEncoded() : QString()); + const auto result = good.isValid() + ? QString::fromUtf8(good.toEncoded()) + : originalUrl; if (!result.isEmpty() && !QRegularExpression( diff --git a/ui/basic_click_handlers.h b/ui/basic_click_handlers.h index 53969c6..ac8c7e3 100644 --- a/ui/basic_click_handlers.h +++ b/ui/basic_click_handlers.h @@ -59,11 +59,17 @@ public: const auto at = url.indexOf('@'), slash = url.indexOf('/'); return ((at > 0) && (slash < 0 || slash > at)); } + [[nodiscard]] static QString EncodeForOpening(const QString &originalUrl); [[nodiscard]] static bool IsSuspicious(const QString &url); [[nodiscard]] static QString ShowEncoded(const QString &url); protected: - QString url() const override; + [[nodiscard]] QString originalUrl() const { + return _originalUrl; + } + QString url() const override { + return EncodeForOpening(_originalUrl); + } QString readable() const override { return _readable; } diff --git a/ui/image/image_prepare.cpp b/ui/image/image_prepare.cpp index d372b22..3e48444 100644 --- a/ui/image/image_prepare.cpp +++ b/ui/image/image_prepare.cpp @@ -97,6 +97,20 @@ std::array PrepareCorners( return result; } +std::array CornersMask(int radius) { + return PrepareCornersMask(radius); +} + +std::array PrepareCorners( + int radius, + const style::color &color) { + auto result = CornersMask(radius); + for (auto &image : result) { + style::colorizeImage(image, color->c, &image); + } + return result; +} + QImage prepareBlur(QImage img) { if (img.isNull()) { return img; diff --git a/ui/image/image_prepare.h b/ui/image/image_prepare.h index ddfe40a..60261b7 100644 --- a/ui/image/image_prepare.h +++ b/ui/image/image_prepare.h @@ -27,12 +27,18 @@ namespace Images { [[nodiscard]] QPixmap PixmapFast(QImage &&image); [[nodiscard]] QImage BlurLargeImage(QImage image, int radius); + [[nodiscard]] const std::array &CornersMask( ImageRoundRadius radius); [[nodiscard]] std::array PrepareCorners( ImageRoundRadius radius, const style::color &color); +[[nodiscard]] std::array CornersMask(int radius); +[[nodiscard]] std::array PrepareCorners( + int radius, + const style::color &color); + QImage prepareBlur(QImage image); void prepareRound( QImage &image, diff --git a/ui/platform/win/ui_utility_win.cpp b/ui/platform/win/ui_utility_win.cpp index 392a65d..6af98ea 100644 --- a/ui/platform/win/ui_utility_win.cpp +++ b/ui/platform/win/ui_utility_win.cpp @@ -37,7 +37,7 @@ void IgnoreAllActivation(not_null widget) { ShowWindow(handle, SW_HIDE); const auto style = GetWindowLongPtr(handle, GWL_EXSTYLE); - SetWindowLong( + SetWindowLongPtr( handle, GWL_EXSTYLE, style | WS_EX_NOACTIVATE | WS_EX_APPWINDOW); diff --git a/ui/platform/win/ui_window_shadow_win.cpp b/ui/platform/win/ui_window_shadow_win.cpp index 644749b..2463aa9 100644 --- a/ui/platform/win/ui_window_shadow_win.cpp +++ b/ui/platform/win/ui_window_shadow_win.cpp @@ -213,7 +213,7 @@ void WindowShadow::init(QColor color) { return; } ShadowByHandle.emplace(_handles[i], this); - SetWindowLongPtr(_handles[i], GWLP_HWNDPARENT, (LONG)_handle); + SetWindowLongPtr(_handles[i], GWLP_HWNDPARENT, (LONG_PTR)_handle); _contexts[i] = CreateCompatibleDC(_screenContext); if (!_contexts[i]) { diff --git a/ui/round_rect.cpp b/ui/round_rect.cpp index 0af480b..eb42a51 100644 --- a/ui/round_rect.cpp +++ b/ui/round_rect.cpp @@ -74,6 +74,17 @@ RoundRect::RoundRect( }, _lifetime); } +RoundRect::RoundRect( + int radius, + const style::color &color) +: _color(color) +, _corners(Images::PrepareCorners(radius, color)) { + style::PaletteChanged( + ) | rpl::start_with_next([=] { + _corners = Images::PrepareCorners(radius, _color); + }, _lifetime); +} + const style::color &RoundRect::color() const { return _color; } diff --git a/ui/round_rect.h b/ui/round_rect.h index 4d65f4a..920c3dd 100644 --- a/ui/round_rect.h +++ b/ui/round_rect.h @@ -24,6 +24,7 @@ void DrawRoundedRect( class RoundRect final { public: RoundRect(ImageRoundRadius radius, const style::color &color); + RoundRect(int radius, const style::color &color); [[nodiscard]] const style::color &color() const; void paint( diff --git a/ui/text/text.cpp b/ui/text/text.cpp index 3f224c3..59a1108 100644 --- a/ui/text/text.cpp +++ b/ui/text/text.cpp @@ -535,6 +535,20 @@ bool Parser::checkEntities() { const auto entityLength = _waitingEntity->length(); const auto entityBegin = _start + _waitingEntity->offset(); const auto entityEnd = entityBegin + entityLength; + const auto pushSimpleUrl = [&](EntityType type) { + link.type = type; + link.data = QString(entityBegin, entityLength); + if (type == EntityType::Url) { + computeLinkText(link.data, &link.text, &link.shown); + } else { + link.text = link.data; + } + }; + const auto pushComplexUrl = [&] { + link.type = entityType; + link.data = _waitingEntity->data(); + link.text = QString(entityBegin, entityLength); + }; if (entityType == EntityType::Bold) { flags = TextBlockFBold; } else if (entityType == EntityType::Semibold) { @@ -559,18 +573,17 @@ bool Parser::checkEntities() { || entityType == EntityType::Hashtag || entityType == EntityType::Cashtag || entityType == EntityType::BotCommand) { - link.type = entityType; - link.data = QString(entityBegin, entityLength); - if (link.type == EntityType::Url) { - computeLinkText(link.data, &link.text, &link.shown); + pushSimpleUrl(entityType); + } else if (entityType == EntityType::CustomUrl) { + const auto url = _waitingEntity->data(); + const auto text = QString(entityBegin, entityLength); + if (url == text) { + pushSimpleUrl(EntityType::Url); } else { - link.text = link.data; + pushComplexUrl(); } - } else if (entityType == EntityType::CustomUrl - || entityType == EntityType::MentionName) { - link.type = entityType; - link.data = _waitingEntity->data(); - link.text = QString(_start + _waitingEntity->offset(), _waitingEntity->length()); + } else if (entityType == EntityType::MentionName) { + pushComplexUrl(); } if (link.type != EntityType::Invalid) { @@ -3271,16 +3284,20 @@ TextForMimeData String::toText( if (!composeExpanded && !composeEntities) { return; } - const auto skipLink = (entity.type == EntityType::CustomUrl) - && (entity.data.startsWith(qstr("internal:"))); + const auto customTextLink = (entity.type == EntityType::CustomUrl); + const auto internalLink = customTextLink + && entity.data.startsWith(qstr("internal:")); if (composeExpanded) { result.expanded.append(full); - if (entity.type == EntityType::CustomUrl && !skipLink) { + const auto sameAsTextLink = customTextLink + && (entity.data + == UrlClickHandler::EncodeForOpening(full.toString())); + if (customTextLink && !internalLink && !sameAsTextLink) { const auto &url = entity.data; result.expanded.append(qstr(" (")).append(url).append(')'); } } - if (composeEntities && !skipLink) { + if (composeEntities && !internalLink) { insertEntity({ entity.type, linkStart, diff --git a/ui/text/text_entity.cpp b/ui/text/text_entity.cpp index 087fa77..4d6de85 100644 --- a/ui/text/text_entity.cpp +++ b/ui/text/text_entity.cpp @@ -1587,7 +1587,8 @@ void ParseEntities(TextWithEntities &result, int32 flags, bool rich) { int32 len = result.text.size(), commandOffset = rich ? 0 : len; bool inLink = false, commandIsLink = false; - const QChar *start = result.text.constData(), *end = start + result.text.size(); + const auto start = result.text.constData(); + const auto end = start + result.text.size(); for (int32 offset = 0, matchOffset = offset, mentionSkip = 0; offset < len;) { if (commandOffset <= offset) { for (commandOffset = offset; commandOffset < len; ++commandOffset) { @@ -1642,6 +1643,10 @@ void ParseEntities(TextWithEntities &result, int32 flags, bool rich) { } if (!(start + mentionStart + 1)->isLetter() || !(start + mentionEnd - 1)->isLetterOrNumber()) { mentionSkip = mentionEnd; + if (mentionSkip < len + && (start + mentionSkip)->isLowSurrogate()) { + ++mentionSkip; + } mMention = RegExpMention().match(result.text, qMax(mentionSkip, matchOffset)); if (mMention.hasMatch()) { mentionStart = mMention.capturedStart(); diff --git a/ui/ui_utility.h b/ui/ui_utility.h index 4a1ce5e..a174909 100644 --- a/ui/ui_utility.h +++ b/ui/ui_utility.h @@ -24,23 +24,11 @@ class object_ptr; namespace Ui { namespace details { -struct ForwardTag { -}; - -struct InPlaceTag { -}; - template class AttachmentOwner : public QObject { public: - template - AttachmentOwner(QObject *parent, const ForwardTag&, OtherValue &&value) - : QObject(parent) - , _value(std::forward(value)) { - } - template - AttachmentOwner(QObject *parent, const InPlaceTag&, Args &&...args) + AttachmentOwner(QObject *parent, Args &&...args) : QObject(parent) , _value(std::forward(args)...) { } @@ -74,11 +62,19 @@ inline Value *CreateChild( } else { return CreateChild>( parent, - details::InPlaceTag{}, std::forward(args)...)->value(); } } +template +inline not_null>*> WrapAsQObject( + not_null parent, + Value &&value) { + return CreateChild>>( + parent.get(), + std::forward(value)); +} + inline void DestroyChild(QWidget *child) { delete child; } @@ -92,10 +88,7 @@ template inline not_null*> AttachAsChild( not_null parent, Value &&value) { - return CreateChild>>( - parent.get(), - details::ForwardTag{}, - std::forward(value))->value(); + return WrapAsQObject(parent, std::forward(value))->value(); } [[nodiscard]] bool AppInFocus();