Support new rounding in bot inline keyboards.

This commit is contained in:
John Preston 2022-10-03 15:11:05 +04:00
parent 9cab06e17d
commit e5f2d83548
58 changed files with 498 additions and 305 deletions

View file

@ -373,8 +373,8 @@ void Rows::ensureRippleBySelection(not_null<Row*> row, Selection selected) {
const auto menu = v::is<MenuSelection>(selected); const auto menu = v::is<MenuSelection>(selected);
const auto menuArea = menuToggleArea(row); const auto menuArea = menuToggleArea(row);
auto mask = menu auto mask = menu
? Ui::RippleAnimation::ellipseMask(menuArea.size()) ? Ui::RippleAnimation::EllipseMask(menuArea.size())
: Ui::RippleAnimation::rectMask({ width(), row->height }); : Ui::RippleAnimation::RectMask({ width(), row->height });
ripple = std::make_unique<Ui::RippleAnimation>( ripple = std::make_unique<Ui::RippleAnimation>(
st::defaultRippleAnimation, st::defaultRippleAnimation,
std::move(mask), std::move(mask),

View file

@ -1410,7 +1410,7 @@ void PeerListContent::mousePressEvent(QMouseEvent *e) {
row->addRipple(_st.item, _controller->customRowRippleMaskGenerator(), point, std::move(updateCallback)); row->addRipple(_st.item, _controller->customRowRippleMaskGenerator(), point, std::move(updateCallback));
} else { } else {
const auto maskGenerator = [&] { const auto maskGenerator = [&] {
return Ui::RippleAnimation::rectMask( return Ui::RippleAnimation::RectMask(
QSize(width(), _rowHeight)); QSize(width(), _rowHeight));
}; };
row->addRipple(_st.item, maskGenerator, point, std::move(updateCallback)); row->addRipple(_st.item, maskGenerator, point, std::move(updateCallback));

View file

@ -60,7 +60,7 @@ constexpr auto kSortByOnlineThrottle = 3 * crl::time(1000);
//} //}
// //
//QImage MembersAddButton::prepareRippleMask() const { //QImage MembersAddButton::prepareRippleMask() const {
// return Ui::RippleAnimation::ellipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize)); // return Ui::RippleAnimation::EllipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize));
//} //}
// //
//QPoint MembersAddButton::prepareRippleStartPosition() const { //QPoint MembersAddButton::prepareRippleStartPosition() const {

View file

@ -138,7 +138,7 @@ void Row::elementAddRipple(
} }
auto &ripple = *pointer; auto &ripple = *pointer;
if (!ripple) { if (!ripple) {
auto mask = Ui::RippleAnimation::roundRectMask( auto mask = Ui::RippleAnimation::RoundRectMask(
(element == kAcceptButton (element == kAcceptButton
? _delegate->rowAcceptButtonSize() ? _delegate->rowAcceptButtonSize()
: _delegate->rowRejectButtonSize()), : _delegate->rowRejectButtonSize()),

View file

@ -256,7 +256,9 @@ private:
const Section _section; const Section _section;
const bool _isInstalled; const bool _isInstalled;
int32 _rowHeight; Ui::RoundRect _buttonBgOver, _buttonBg;
int32 _rowHeight = 0;
std::vector<std::unique_ptr<Row>> _rows; std::vector<std::unique_ptr<Row>> _rows;
std::vector<std::unique_ptr<Row>> _oldRows; std::vector<std::unique_ptr<Row>> _oldRows;
@ -1126,6 +1128,16 @@ StickersBox::Inner::Inner(
, _api(&_controller->session().mtp()) , _api(&_controller->session().mtp())
, _section(section) , _section(section)
, _isInstalled(_section == Section::Installed || _section == Section::Masks) , _isInstalled(_section == Section::Installed || _section == Section::Masks)
, _buttonBgOver(
ImageRoundRadius::Small,
(_isInstalled
? st::stickersUndoRemove
: st::stickersTrendingAdd).textBgOver)
, _buttonBg(
ImageRoundRadius::Small,
(_isInstalled
? st::stickersUndoRemove
: st::stickersTrendingAdd).textBg)
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) , _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
, _shiftingAnimation([=](crl::time now) { , _shiftingAnimation([=](crl::time now) {
return shiftingAnimationCallback(now); return shiftingAnimationCallback(now);
@ -1147,6 +1159,16 @@ StickersBox::Inner::Inner(
, _api(&_controller->session().mtp()) , _api(&_controller->session().mtp())
, _section(StickersBox::Section::Installed) , _section(StickersBox::Section::Installed)
, _isInstalled(_section == Section::Installed || _section == Section::Masks) , _isInstalled(_section == Section::Installed || _section == Section::Masks)
, _buttonBgOver(
ImageRoundRadius::Small,
(_isInstalled
? st::stickersUndoRemove
: st::stickersTrendingAdd).textBgOver)
, _buttonBg(
ImageRoundRadius::Small,
(_isInstalled
? st::stickersUndoRemove
: st::stickersTrendingAdd).textBg)
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) , _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
, _shiftingAnimation([=](crl::time now) { , _shiftingAnimation([=](crl::time now) {
return shiftingAnimationCallback(now); return shiftingAnimationCallback(now);
@ -1566,8 +1588,7 @@ void StickersBox::Inner::paintFakeButton(Painter &p, not_null<Row*> row, int ind
: st::stickersTrendingAdd; : st::stickersTrendingAdd;
const auto textWidth = _isInstalled ? _undoWidth : _addWidth; const auto textWidth = _isInstalled ? _undoWidth : _addWidth;
const auto &text = _isInstalled ? _undoText : _addText; const auto &text = _isInstalled ? _undoText : _addText;
const auto &textBg = selected ? st.textBgOver : st.textBg; (selected ? _buttonBgOver : _buttonBg).paint(p, myrtlrect(rect));
Ui::FillRoundRect(p, myrtlrect(rect), textBg, ImageRoundRadius::Small);
if (row->ripple) { if (row->ripple) {
row->ripple->paint(p, rect.x(), rect.y(), width()); row->ripple->paint(p, rect.x(), rect.y(), width());
if (row->ripple->empty()) { if (row->ripple->empty()) {
@ -1618,16 +1639,16 @@ void StickersBox::Inner::setActionDown(int newActionDown) {
if (_isInstalled) { if (_isInstalled) {
if (row->removed) { if (row->removed) {
auto rippleSize = QSize(_undoWidth - st::stickersUndoRemove.width, st::stickersUndoRemove.height); auto rippleSize = QSize(_undoWidth - st::stickersUndoRemove.width, st::stickersUndoRemove.height);
auto rippleMask = Ui::RippleAnimation::roundRectMask(rippleSize, st::roundRadiusSmall); auto rippleMask = Ui::RippleAnimation::RoundRectMask(rippleSize, st::roundRadiusSmall);
ensureRipple(st::stickersUndoRemove.ripple, std::move(rippleMask), removeButton); ensureRipple(st::stickersUndoRemove.ripple, std::move(rippleMask), removeButton);
} else { } else {
auto rippleSize = st::stickersRemove.rippleAreaSize; auto rippleSize = st::stickersRemove.rippleAreaSize;
auto rippleMask = Ui::RippleAnimation::ellipseMask(QSize(rippleSize, rippleSize)); auto rippleMask = Ui::RippleAnimation::EllipseMask(QSize(rippleSize, rippleSize));
ensureRipple(st::stickersRemove.ripple, std::move(rippleMask), removeButton); ensureRipple(st::stickersRemove.ripple, std::move(rippleMask), removeButton);
} }
} else if (!row->isInstalled() || row->isArchived() || row->removed) { } else if (!row->isInstalled() || row->isArchived() || row->removed) {
auto rippleSize = QSize(_addWidth - st::stickersTrendingAdd.width, st::stickersTrendingAdd.height); auto rippleSize = QSize(_addWidth - st::stickersTrendingAdd.width, st::stickersTrendingAdd.height);
auto rippleMask = Ui::RippleAnimation::roundRectMask(rippleSize, st::roundRadiusSmall); auto rippleMask = Ui::RippleAnimation::RoundRectMask(rippleSize, st::roundRadiusSmall);
ensureRipple(st::stickersTrendingAdd.ripple, std::move(rippleMask), removeButton); ensureRipple(st::stickersTrendingAdd.ripple, std::move(rippleMask), removeButton);
} }
} }
@ -1683,7 +1704,7 @@ void StickersBox::Inner::setPressed(SelectedRow pressed) {
if (_megagroupSet && pressedIndex >= 0 && pressedIndex < _rows.size()) { if (_megagroupSet && pressedIndex >= 0 && pressedIndex < _rows.size()) {
update(0, _itemsTop + pressedIndex * _rowHeight, width(), _rowHeight); update(0, _itemsTop + pressedIndex * _rowHeight, width(), _rowHeight);
auto &set = _rows[pressedIndex]; auto &set = _rows[pressedIndex];
auto rippleMask = Ui::RippleAnimation::rectMask(QSize(width(), _rowHeight)); auto rippleMask = Ui::RippleAnimation::RectMask(QSize(width(), _rowHeight));
if (!set->ripple) { if (!set->ripple) {
set->ripple = std::make_unique<Ui::RippleAnimation>(st::defaultRippleAnimation, std::move(rippleMask), [this, pressedIndex] { set->ripple = std::make_unique<Ui::RippleAnimation>(st::defaultRippleAnimation, std::move(rippleMask), [this, pressedIndex] {
update(0, _itemsTop + pressedIndex * _rowHeight, width(), _rowHeight); update(0, _itemsTop + pressedIndex * _rowHeight, width(), _rowHeight);

View file

@ -258,7 +258,7 @@ BoxController::Row::CallType BoxController::Row::ComputeCallType(
void BoxController::Row::rightActionAddRipple(QPoint point, Fn<void()> updateCallback) { void BoxController::Row::rightActionAddRipple(QPoint point, Fn<void()> updateCallback) {
if (!_actionRipple) { if (!_actionRipple) {
auto mask = Ui::RippleAnimation::ellipseMask( auto mask = Ui::RippleAnimation::EllipseMask(
QSize(_st->rippleAreaSize, _st->rippleAreaSize)); QSize(_st->rippleAreaSize, _st->rippleAreaSize));
_actionRipple = std::make_unique<Ui::RippleAnimation>( _actionRipple = std::make_unique<Ui::RippleAnimation>(
_st->ripple, _st->ripple,

View file

@ -747,7 +747,7 @@ void MembersRow::rightActionAddRipple(
QPoint point, QPoint point,
Fn<void()> updateCallback) { Fn<void()> updateCallback) {
if (!_actionRipple) { if (!_actionRipple) {
auto mask = Ui::RippleAnimation::ellipseMask(QSize( auto mask = Ui::RippleAnimation::EllipseMask(QSize(
st::groupCallActiveButton.rippleAreaSize, st::groupCallActiveButton.rippleAreaSize,
st::groupCallActiveButton.rippleAreaSize)); st::groupCallActiveButton.rippleAreaSize));
_actionRipple = std::make_unique<Ui::RippleAnimation>( _actionRipple = std::make_unique<Ui::RippleAnimation>(

View file

@ -217,7 +217,7 @@ QPoint JoinAsAction::prepareRippleStartPosition() const {
} }
QImage JoinAsAction::prepareRippleMask() const { QImage JoinAsAction::prepareRippleMask() const {
return Ui::RippleAnimation::rectMask(size()); return Ui::RippleAnimation::RectMask(size());
} }
int JoinAsAction::contentHeight() const { int JoinAsAction::contentHeight() const {
@ -365,7 +365,7 @@ QPoint RecordingAction::prepareRippleStartPosition() const {
} }
QImage RecordingAction::prepareRippleMask() const { QImage RecordingAction::prepareRippleMask() const {
return Ui::RippleAnimation::rectMask(size()); return Ui::RippleAnimation::RectMask(size());
} }
int RecordingAction::contentHeight() const { int RecordingAction::contentHeight() const {

View file

@ -50,7 +50,7 @@ private:
}; };
QImage SourceButton::prepareRippleMask() const { QImage SourceButton::prepareRippleMask() const {
return RippleAnimation::roundRectMask(size(), st::roundRadiusLarge); return RippleAnimation::RoundRectMask(size(), st::roundRadiusLarge);
} }
class Source final { class Source final {

View file

@ -28,7 +28,9 @@ public:
not_null<BotKeyboard*> parent, not_null<BotKeyboard*> parent,
const style::BotKeyboardButton &st); const style::BotKeyboardButton &st);
int buttonRadius() const override; Images::CornersMaskRef buttonRounding(
Ui::BubbleRounding outer,
RectParts sides) const override;
void startPaint(QPainter &p, const Ui::ChatStyle *st) const override; void startPaint(QPainter &p, const Ui::ChatStyle *st) const override;
const style::TextStyle &textStyle() const override; const style::TextStyle &textStyle() const override;
@ -39,6 +41,7 @@ protected:
QPainter &p, QPainter &p,
const Ui::ChatStyle *st, const Ui::ChatStyle *st,
const QRect &rect, const QRect &rect,
Ui::BubbleRounding rounding,
float64 howMuchOver) const override; float64 howMuchOver) const override;
void paintButtonIcon( void paintButtonIcon(
QPainter &p, QPainter &p,
@ -76,14 +79,18 @@ void Style::repaint(not_null<const HistoryItem*> item) const {
_parent->update(); _parent->update();
} }
int Style::buttonRadius() const { Images::CornersMaskRef Style::buttonRounding(
return st::roundRadiusSmall; Ui::BubbleRounding outer,
RectParts sides) const {
using namespace Images;
return CornersMaskRef(CornersMask(ImageRoundRadius::Small));
} }
void Style::paintButtonBg( void Style::paintButtonBg(
QPainter &p, QPainter &p,
const Ui::ChatStyle *st, const Ui::ChatStyle *st,
const QRect &rect, const QRect &rect,
Ui::BubbleRounding rounding,
float64 howMuchOver) const { float64 howMuchOver) const {
Ui::FillRoundRect(p, rect, st::botKbBg, Ui::BotKeyboardCorners); Ui::FillRoundRect(p, rect, st::botKbBg, Ui::BotKeyboardCorners);
} }
@ -131,7 +138,12 @@ void BotKeyboard::paintEvent(QPaintEvent *e) {
if (_impl) { if (_impl) {
int x = rtl() ? st::botKbScroll.width : _st->margin; int x = rtl() ? st::botKbScroll.width : _st->margin;
p.translate(x, st::botKbScroll.deltat); p.translate(x, st::botKbScroll.deltat);
_impl->paint(p, nullptr, width(), clip.translated(-x, -st::botKbScroll.deltat)); _impl->paint(
p,
nullptr,
{},
width(),
clip.translated(-x, -st::botKbScroll.deltat));
} }
} }
@ -237,7 +249,7 @@ void BotKeyboard::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool activ
void BotKeyboard::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) { void BotKeyboard::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) {
if (!_impl) return; if (!_impl) return;
_impl->clickHandlerPressedChanged(p, pressed); _impl->clickHandlerPressedChanged(p, pressed, {});
} }
bool BotKeyboard::updateMarkup(HistoryItem *to, bool force) { bool BotKeyboard::updateMarkup(HistoryItem *to, bool force) {

View file

@ -1966,7 +1966,7 @@ std::unique_ptr<Ui::RippleAnimation> EmojiListWidget::createButtonRipple(
? st::stickerPanRemoveSet.ripple ? st::stickerPanRemoveSet.ripple
: st::emojiPanButton.ripple; : st::emojiPanButton.ripple;
auto mask = remove auto mask = remove
? Ui::RippleAnimation::ellipseMask(QSize( ? Ui::RippleAnimation::EllipseMask(QSize(
st::stickerPanRemoveSet.rippleAreaSize, st::stickerPanRemoveSet.rippleAreaSize,
st::stickerPanRemoveSet.rippleAreaSize)) st::stickerPanRemoveSet.rippleAreaSize))
: rightButton(section).rippleMask; : rightButton(section).rippleMask;

View file

@ -177,6 +177,16 @@ StickersListWidget::StickersListWidget(
, _isMasks(masks) , _isMasks(masks)
, _updateItemsTimer([=] { updateItems(); }) , _updateItemsTimer([=] { updateItems(); })
, _updateSetsTimer([=] { updateSets(); }) , _updateSetsTimer([=] { updateSets(); })
, _trendingAddBgOver(
ImageRoundRadius::Small,
st::stickersTrendingAdd.textBgOver)
, _trendingAddBg(ImageRoundRadius::Small, st::stickersTrendingAdd.textBg)
, _groupCategoryAddBgOver(
ImageRoundRadius::Small,
st::stickerGroupCategoryAdd.textBgOver)
, _groupCategoryAddBg(
ImageRoundRadius::Small,
st::stickerGroupCategoryAdd.textBg)
, _pathGradient(std::make_unique<Ui::PathShiftGradient>( , _pathGradient(std::make_unique<Ui::PathShiftGradient>(
st::windowBgRipple, st::windowBgRipple,
st::windowBgOver, st::windowBgOver,
@ -840,9 +850,7 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) {
if (featuredHasAddButton(info.section)) { if (featuredHasAddButton(info.section)) {
auto add = featuredAddRect(info); auto add = featuredAddRect(info);
auto selected = selectedButton ? (selectedButton->section == info.section) : false; auto selected = selectedButton ? (selectedButton->section == info.section) : false;
auto &textBg = selected ? st::stickersTrendingAdd.textBgOver : st::stickersTrendingAdd.textBg; (selected ? _trendingAddBgOver : _trendingAddBg).paint(p, myrtlrect(add));
Ui::FillRoundRect(p, myrtlrect(add), textBg, ImageRoundRadius::Small);
if (set.ripple) { if (set.ripple) {
set.ripple->paint(p, add.x(), add.y(), width()); set.ripple->paint(p, add.x(), add.y(), width());
if (set.ripple->empty()) { if (set.ripple->empty()) {
@ -1068,12 +1076,10 @@ void StickersListWidget::paintMegagroupEmptySet(Painter &p, int y, bool buttonSe
auto infoLeft = megagroupSetInfoLeft(); auto infoLeft = megagroupSetInfoLeft();
_megagroupSetAbout.drawLeft(p, infoLeft, y, width() - infoLeft, width()); _megagroupSetAbout.drawLeft(p, infoLeft, y, width() - infoLeft, width());
auto &textBg = buttonSelected
? st::stickerGroupCategoryAdd.textBgOver
: st::stickerGroupCategoryAdd.textBg;
auto button = _megagroupSetButtonRect.translated(0, y); auto button = _megagroupSetButtonRect.translated(0, y);
Ui::FillRoundRect(p, myrtlrect(button), textBg, ImageRoundRadius::Small); (buttonSelected ? _groupCategoryAddBgOver : _groupCategoryAddBg).paint(
p,
myrtlrect(button));
if (_megagroupSetButtonRipple) { if (_megagroupSetButtonRipple) {
_megagroupSetButtonRipple->paint(p, button.x(), button.y(), width()); _megagroupSetButtonRipple->paint(p, button.x(), button.y(), width());
if (_megagroupSetButtonRipple->empty()) { if (_megagroupSetButtonRipple->empty()) {
@ -1486,7 +1492,7 @@ void StickersListWidget::setPressed(OverState newPressed) {
} else if (std::get_if<OverGroupAdd>(&_pressed)) { } else if (std::get_if<OverGroupAdd>(&_pressed)) {
if (!_megagroupSetButtonRipple) { if (!_megagroupSetButtonRipple) {
auto maskSize = _megagroupSetButtonRect.size(); auto maskSize = _megagroupSetButtonRect.size();
auto mask = Ui::RippleAnimation::roundRectMask(maskSize, st::roundRadiusSmall); auto mask = Ui::RippleAnimation::RoundRectMask(maskSize, st::roundRadiusSmall);
_megagroupSetButtonRipple = std::make_unique<Ui::RippleAnimation>(st::stickerGroupCategoryAdd.ripple, std::move(mask), [this] { _megagroupSetButtonRipple = std::make_unique<Ui::RippleAnimation>(st::stickerGroupCategoryAdd.ripple, std::move(mask), [this] {
rtlupdate(megagroupSetButtonRectFinal()); rtlupdate(megagroupSetButtonRectFinal());
}); });
@ -1514,14 +1520,14 @@ std::unique_ptr<Ui::RippleAnimation> StickersListWidget::createButtonRipple(int
if (shownSets()[section].externalLayout) { if (shownSets()[section].externalLayout) {
auto maskSize = QSize(_addWidth - st::stickersTrendingAdd.width, st::stickersTrendingAdd.height); auto maskSize = QSize(_addWidth - st::stickersTrendingAdd.width, st::stickersTrendingAdd.height);
auto mask = Ui::RippleAnimation::roundRectMask(maskSize, st::roundRadiusSmall); auto mask = Ui::RippleAnimation::RoundRectMask(maskSize, st::roundRadiusSmall);
return std::make_unique<Ui::RippleAnimation>( return std::make_unique<Ui::RippleAnimation>(
st::stickersTrendingAdd.ripple, st::stickersTrendingAdd.ripple,
std::move(mask), std::move(mask),
[this, section] { rtlupdate(featuredAddRect(section)); }); [this, section] { rtlupdate(featuredAddRect(section)); });
} }
auto maskSize = QSize(st::stickerPanRemoveSet.rippleAreaSize, st::stickerPanRemoveSet.rippleAreaSize); auto maskSize = QSize(st::stickerPanRemoveSet.rippleAreaSize, st::stickerPanRemoveSet.rippleAreaSize);
auto mask = Ui::RippleAnimation::ellipseMask(maskSize); auto mask = Ui::RippleAnimation::EllipseMask(maskSize);
return std::make_unique<Ui::RippleAnimation>( return std::make_unique<Ui::RippleAnimation>(
st::stickerPanRemoveSet.ripple, st::stickerPanRemoveSet.ripple,
std::move(mask), std::move(mask),

View file

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "chat_helpers/tabbed_selector.h" #include "chat_helpers/tabbed_selector.h"
#include "data/stickers/data_stickers.h" #include "data/stickers/data_stickers.h"
#include "ui/round_rect.h"
#include "base/variant.h" #include "base/variant.h"
#include "base/timer.h" #include "base/timer.h"
@ -365,6 +366,9 @@ private:
OverState _pressed; OverState _pressed;
QPoint _lastMousePosition; QPoint _lastMousePosition;
Ui::RoundRect _trendingAddBgOver, _trendingAddBg;
Ui::RoundRect _groupCategoryAddBgOver, _groupCategoryAddBg;
const std::unique_ptr<Ui::PathShiftGradient> _pathGradient; const std::unique_ptr<Ui::PathShiftGradient> _pathGradient;
Ui::Text::String _megagroupSetAbout; Ui::Text::String _megagroupSetAbout;

View file

@ -298,6 +298,12 @@ TabbedSelector::TabbedSelector(
, _controller(controller) , _controller(controller)
, _level(level) , _level(level)
, _mode(mode) , _mode(mode)
, _panelRounding(Ui::PrepareCornerPixmaps(
ImageRoundRadius::Small,
st::emojiPanBg))
, _categoriesRounding(Ui::PrepareCornerPixmaps(
ImageRoundRadius::Small,
st::emojiPanCategories))
, _topShadow(full() ? object_ptr<Ui::PlainShadow>(this) : nullptr) , _topShadow(full() ? object_ptr<Ui::PlainShadow>(this) : nullptr)
, _bottomShadow(this) , _bottomShadow(this)
, _scroll(this, st::emojiScroll) , _scroll(this, st::emojiScroll)
@ -410,6 +416,16 @@ TabbedSelector::TabbedSelector(
}, lifetime()); }, lifetime());
} }
style::PaletteChanged(
) | rpl::start_with_next([=] {
_panelRounding = Ui::PrepareCornerPixmaps(
ImageRoundRadius::Small,
st::emojiPanBg);
_categoriesRounding = Ui::PrepareCornerPixmaps(
ImageRoundRadius::Small,
st::emojiPanCategories);
}, lifetime());
if (hasEmojiTab()) { if (hasEmojiTab()) {
session().data().stickers().emojiSetInstalled( session().data().stickers().emojiSetInstalled(
) | rpl::start_with_next([=](uint64 setId) { ) | rpl::start_with_next([=](uint64 setId) {
@ -646,26 +662,19 @@ void TabbedSelector::paintSlideFrame(QPainter &p) {
} }
void TabbedSelector::paintBgRoundedPart(QPainter &p) { void TabbedSelector::paintBgRoundedPart(QPainter &p) {
const auto threeRadius = 3 * _roundRadius; const auto fill = _dropDown
const auto topOrBottomPart = _dropDown ? QRect(0, height() - _roundRadius, width(), _roundRadius)
? QRect(0, height() - threeRadius, width(), threeRadius) : _tabsSlider
: QRect( ? QRect(0, 0, width(), _tabsSlider->height())
0, : QRect(0, 0, width(), _roundRadius);
0, Ui::FillRoundRect(p, fill, st::emojiPanBg, {
width(), .p = {
(_tabsSlider _dropDown ? QPixmap() : _panelRounding.p[0],
? _tabsSlider->height() + _roundRadius _dropDown ? QPixmap() : _panelRounding.p[1],
: threeRadius)); _dropDown ? _panelRounding.p[2] : QPixmap(),
Ui::FillRoundRect( _dropDown ? _panelRounding.p[3] : QPixmap(),
p, },
topOrBottomPart, });
st::emojiPanBg,
ImageRoundRadius::Small,
(_dropDown
? RectPart::FullBottom
: tabbed()
? (RectPart::FullTop | RectPart::NoTopBottom)
: RectPart::FullTop));
} }
void TabbedSelector::paintContent(QPainter &p) { void TabbedSelector::paintContent(QPainter &p) {
@ -675,18 +684,22 @@ void TabbedSelector::paintContent(QPainter &p) {
if (_roundRadius > 0) { if (_roundRadius > 0) {
paintBgRoundedPart(p); paintBgRoundedPart(p);
const auto &pixmaps = hasSectionIcons()
? _categoriesRounding
: _panelRounding;
const auto footerPart = QRect( const auto footerPart = QRect(
0, 0,
_footerTop - (_dropDown ? 0 : _roundRadius), _footerTop,
width(), width(),
_st.footer + _roundRadius); _st.footer);
Ui::FillRoundRect( Ui::FillRoundRect(p, footerPart, footerBg, {
p, .p = {
footerPart, _dropDown ? pixmaps.p[0] : QPixmap(),
footerBg, _dropDown ? pixmaps.p[1] : QPixmap(),
ImageRoundRadius::Small, _dropDown ? QPixmap() : pixmaps.p[2],
(RectPart::NoTopBottom _dropDown ? QPixmap() : pixmaps.p[3],
| (_dropDown ? RectPart::FullTop : RectPart::FullBottom))); },
});
} else { } else {
if (_tabsSlider) { if (_tabsSlider) {
p.fillRect(0, 0, width(), _tabsSlider->height(), st::emojiPanBg); p.fillRect(0, 0, width(), _tabsSlider->height(), st::emojiPanBg);

View file

@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/effects/animations.h" #include "ui/effects/animations.h"
#include "ui/effects/message_sending_animation_common.h" #include "ui/effects/message_sending_animation_common.h"
#include "ui/effects/panel_animation.h" #include "ui/effects/panel_animation.h"
#include "ui/cached_round_corners.h"
#include "mtproto/sender.h" #include "mtproto/sender.h"
#include "base/object_ptr.h" #include "base/object_ptr.h"
@ -252,6 +253,8 @@ private:
Mode _mode = Mode::Full; Mode _mode = Mode::Full;
int _roundRadius = 0; int _roundRadius = 0;
int _footerTop = 0; int _footerTop = 0;
Ui::CornersPixmaps _panelRounding;
Ui::CornersPixmaps _categoriesRounding;
PeerData *_currentPeer = nullptr; PeerData *_currentPeer = nullptr;
class SlideAnimation; class SlideAnimation;

View file

@ -93,7 +93,7 @@ void BasicRow::addRipple(
QSize size, QSize size,
Fn<void()> updateCallback) { Fn<void()> updateCallback) {
if (!_ripple) { if (!_ripple) {
auto mask = Ui::RippleAnimation::rectMask(size); auto mask = Ui::RippleAnimation::RectMask(size);
_ripple = std::make_unique<Ui::RippleAnimation>( _ripple = std::make_unique<Ui::RippleAnimation>(
st::dialogsRipple, st::dialogsRipple,
std::move(mask), std::move(mask),

View file

@ -922,7 +922,23 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
const auto stm = &st->messageStyle(false, false); const auto stm = &st->messageStyle(false, false);
if (clip.y() < _botAbout->rect.y() + _botAbout->rect.height() && clip.y() + clip.height() > _botAbout->rect.y()) { if (clip.y() < _botAbout->rect.y() + _botAbout->rect.height() && clip.y() + clip.height() > _botAbout->rect.y()) {
p.setTextPalette(stm->textPalette); p.setTextPalette(stm->textPalette);
Ui::FillRoundRect(p, _botAbout->rect, stm->msgBg, stm->msgBgCornersLarge, &stm->msgShadow); using Corner = Ui::BubbleCornerRounding;
const auto rounding = Ui::BubbleRounding{
Corner::Large,
Corner::Large,
Corner::Large,
Corner::Large,
};
Ui::PaintBubble(p, Ui::SimpleBubble{
.st = st,
.geometry = _botAbout->rect,
.pattern = context.bubblesPattern,
.patternViewport = context.viewport,
.outerWidth = width(),
.selected = false,
.outbg = false,
.rounding = rounding,
});
auto top = _botAbout->rect.top() + st::msgPadding.top(); auto top = _botAbout->rect.top() + st::msgPadding.top();
if (!_history->peer->isRepliesChat()) { if (!_history->peer->isRepliesChat()) {

View file

@ -724,14 +724,16 @@ int ReplyKeyboard::naturalHeight() const {
void ReplyKeyboard::paint( void ReplyKeyboard::paint(
Painter &p, Painter &p,
const Ui::ChatStyle *st, const Ui::ChatStyle *st,
Ui::BubbleRounding rounding,
int outerWidth, int outerWidth,
const QRect &clip) const { const QRect &clip) const {
Assert(_st != nullptr); Assert(_st != nullptr);
Assert(_width > 0); Assert(_width > 0);
_st->startPaint(p, st); _st->startPaint(p, st);
for (const auto &row : _rows) { for (auto y = 0, rowsCount = int(_rows.size()); y != rowsCount; ++y) {
for (const auto &button : row) { for (auto x = 0, count = int(_rows[y].size()); x != count; ++x) {
const auto &button = _rows[y][x];
const auto rect = button.rect; const auto rect = button.rect;
if (rect.y() >= clip.y() + clip.height()) return; if (rect.y() >= clip.y() + clip.height()) return;
if (rect.y() + rect.height() < clip.y()) continue; if (rect.y() + rect.height() < clip.y()) continue;
@ -739,7 +741,20 @@ void ReplyKeyboard::paint(
// just ignore the buttons that didn't layout well // just ignore the buttons that didn't layout well
if (rect.x() + rect.width() > _width) break; if (rect.x() + rect.width() > _width) break;
_st->paintButton(p, st, outerWidth, button); auto buttonRounding = Ui::BubbleRounding();
using Corner = Ui::BubbleCornerRounding;
buttonRounding.topLeft = buttonRounding.topRight = Corner::Small;
buttonRounding.bottomLeft = ((y + 1 == rowsCount)
&& !x
&& (rounding.bottomLeft == Corner::Large))
? Corner::Large
: Corner::Small;
buttonRounding.bottomRight = ((y + 1 == rowsCount)
&& (x + 1 == count)
&& (rounding.bottomRight == Corner::Large))
? Corner::Large
: Corner::Small;
_st->paintButton(p, st, outerWidth, button, buttonRounding);
} }
} }
} }
@ -787,7 +802,8 @@ ReplyKeyboard::ButtonCoords ReplyKeyboard::findButtonCoordsByClickHandler(const
void ReplyKeyboard::clickHandlerPressedChanged( void ReplyKeyboard::clickHandlerPressedChanged(
const ClickHandlerPtr &handler, const ClickHandlerPtr &handler,
bool pressed) { bool pressed,
Ui::BubbleRounding rounding) {
if (!handler) return; if (!handler) return;
_savedPressed = pressed ? handler : ClickHandlerPtr(); _savedPressed = pressed ? handler : ClickHandlerPtr();
@ -796,13 +812,22 @@ void ReplyKeyboard::clickHandlerPressedChanged(
auto &button = _rows[coords.i][coords.j]; auto &button = _rows[coords.i][coords.j];
if (pressed) { if (pressed) {
if (!button.ripple) { if (!button.ripple) {
auto mask = Ui::RippleAnimation::roundRectMask( const auto sides = RectPart()
| (!coords.i ? RectPart::Top : RectPart())
| (!coords.j ? RectPart::Left : RectPart())
| ((coords.i + 1 == _rows.size())
? RectPart::Bottom
: RectPart())
| ((coords.j + 1 == _rows[coords.i].size())
? RectPart::Right
: RectPart());
auto mask = Ui::RippleAnimation::RoundRectMask(
button.rect.size(), button.rect.size(),
_st->buttonRadius()); _st->buttonRounding(rounding, sides));
button.ripple = std::make_unique<Ui::RippleAnimation>( button.ripple = std::make_unique<Ui::RippleAnimation>(
_st->_st->ripple, _st->_st->ripple,
std::move(mask), std::move(mask),
[this] { _st->repaint(_item); }); [=] { _st->repaint(_item); });
} }
button.ripple->add(_savedCoords - button.rect.topLeft()); button.ripple->add(_savedCoords - button.rect.topLeft());
} else { } else {
@ -877,9 +902,10 @@ void ReplyKeyboard::Style::paintButton(
Painter &p, Painter &p,
const Ui::ChatStyle *st, const Ui::ChatStyle *st,
int outerWidth, int outerWidth,
const ReplyKeyboard::Button &button) const { const ReplyKeyboard::Button &button,
Ui::BubbleRounding rounding) const {
const QRect &rect = button.rect; const QRect &rect = button.rect;
paintButtonBg(p, st, rect, button.howMuchOver); paintButtonBg(p, st, rect, rounding, button.howMuchOver);
if (button.ripple) { if (button.ripple) {
const auto color = st ? &st->msgBotKbRippleBg()->c : nullptr; const auto color = st ? &st->msgBotKbRippleBg()->c : nullptr;
button.ripple->paint(p, rect.x(), rect.y(), outerWidth, color); button.ripple->paint(p, rect.x(), rect.y(), outerWidth, color);

View file

@ -25,6 +25,10 @@ namespace Data {
class Session; class Session;
} // namespace Data } // namespace Data
namespace Images {
struct CornersMaskRef;
} // namespace Images
namespace HistoryView { namespace HistoryView {
class Element; class Element;
class Document; class Document;
@ -323,7 +327,9 @@ public:
int buttonSkip() const; int buttonSkip() const;
int buttonPadding() const; int buttonPadding() const;
int buttonHeight() const; int buttonHeight() const;
virtual int buttonRadius() const = 0; [[nodiscard]] virtual Images::CornersMaskRef buttonRounding(
Ui::BubbleRounding outer,
RectParts sides) const = 0;
virtual void repaint(not_null<const HistoryItem*> item) const = 0; virtual void repaint(not_null<const HistoryItem*> item) const = 0;
virtual ~Style() { virtual ~Style() {
@ -334,6 +340,7 @@ public:
QPainter &p, QPainter &p,
const Ui::ChatStyle *st, const Ui::ChatStyle *st,
const QRect &rect, const QRect &rect,
Ui::BubbleRounding rounding,
float64 howMuchOver) const = 0; float64 howMuchOver) const = 0;
virtual void paintButtonIcon( virtual void paintButtonIcon(
QPainter &p, QPainter &p,
@ -355,7 +362,8 @@ public:
Painter &p, Painter &p,
const Ui::ChatStyle *st, const Ui::ChatStyle *st,
int outerWidth, int outerWidth,
const ReplyKeyboard::Button &button) const; const ReplyKeyboard::Button &button,
Ui::BubbleRounding rounding) const;
friend class ReplyKeyboard; friend class ReplyKeyboard;
}; };
@ -377,12 +385,18 @@ public:
void paint( void paint(
Painter &p, Painter &p,
const Ui::ChatStyle *st, const Ui::ChatStyle *st,
Ui::BubbleRounding rounding,
int outerWidth, int outerWidth,
const QRect &clip) const; const QRect &clip) const;
ClickHandlerPtr getLink(QPoint point) const; ClickHandlerPtr getLink(QPoint point) const;
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active); void clickHandlerActiveChanged(
void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed); const ClickHandlerPtr &p,
bool active);
void clickHandlerPressedChanged(
const ClickHandlerPtr &p,
bool pressed,
Ui::BubbleRounding rounding);
void clearSelection(); void clearSelection();
void updateMessageId(); void updateMessageId();

View file

@ -912,7 +912,7 @@ rpl::producer<> RecordLock::locks() const {
} }
QImage RecordLock::prepareRippleMask() const { QImage RecordLock::prepareRippleMask() const {
return Ui::RippleAnimation::ellipseMask(_rippleRect.size()); return Ui::RippleAnimation::EllipseMask(_rippleRect.size());
} }
QPoint RecordLock::prepareRippleStartPosition() const { QPoint RecordLock::prepareRippleStartPosition() const {
@ -976,7 +976,7 @@ void CancelButton::init() {
} }
QImage CancelButton::prepareRippleMask() const { QImage CancelButton::prepareRippleMask() const {
return Ui::RippleAnimation::ellipseMask(_rippleRect.size()); return Ui::RippleAnimation::EllipseMask(_rippleRect.size());
} }
QPoint CancelButton::prepareRippleStartPosition() const { QPoint CancelButton::prepareRippleStartPosition() const {

View file

@ -1216,11 +1216,6 @@ void Element::clickHandlerActiveChanged(
void Element::clickHandlerPressedChanged( void Element::clickHandlerPressedChanged(
const ClickHandlerPtr &handler, const ClickHandlerPtr &handler,
bool pressed) { bool pressed) {
if (const auto markup = _data->Get<HistoryMessageReplyMarkup>()) {
if (const auto keyboard = markup->inlineKeyboard.get()) {
keyboard->clickHandlerPressedChanged(handler, pressed);
}
}
PressedLink(pressed ? this : nullptr); PressedLink(pressed ? this : nullptr);
repaint(); repaint();
if (const auto media = this->media()) { if (const auto media = this->media()) {

View file

@ -63,7 +63,9 @@ class KeyboardStyle : public ReplyKeyboard::Style {
public: public:
using ReplyKeyboard::Style::Style; using ReplyKeyboard::Style::Style;
int buttonRadius() const override; Images::CornersMaskRef buttonRounding(
Ui::BubbleRounding outer,
RectParts sides) const override;
void startPaint( void startPaint(
QPainter &p, QPainter &p,
@ -76,6 +78,7 @@ protected:
QPainter &p, QPainter &p,
const Ui::ChatStyle *st, const Ui::ChatStyle *st,
const QRect &rect, const QRect &rect,
Ui::BubbleRounding rounding,
float64 howMuchOver) const override; float64 howMuchOver) const override;
void paintButtonIcon( void paintButtonIcon(
QPainter &p, QPainter &p,
@ -107,23 +110,54 @@ void KeyboardStyle::repaint(not_null<const HistoryItem*> item) const {
item->history()->owner().requestItemRepaint(item); item->history()->owner().requestItemRepaint(item);
} }
int KeyboardStyle::buttonRadius() const { Images::CornersMaskRef KeyboardStyle::buttonRounding(
return st::dateRadius; Ui::BubbleRounding outer,
RectParts sides) const {
using namespace Images;
using namespace Ui;
using Radius = CachedCornerRadius;
using Corner = BubbleCornerRounding;
auto result = CornersMaskRef(CachedCornersMasks(Radius::BubbleSmall));
if (sides & RectPart::Bottom) {
const auto &large = CachedCornersMasks(Radius::BubbleLarge);
auto round = [&](RectPart side, int index) {
if ((sides & side) && (outer[index] == Corner::Large)) {
result.p[index] = &large[index];
}
};
round(RectPart::Left, kBottomLeft);
round(RectPart::Right, kBottomRight);
}
return result;
} }
void KeyboardStyle::paintButtonBg( void KeyboardStyle::paintButtonBg(
QPainter &p, QPainter &p,
const Ui::ChatStyle *st, const Ui::ChatStyle *st,
const QRect &rect, const QRect &rect,
Ui::BubbleRounding rounding,
float64 howMuchOver) const { float64 howMuchOver) const {
Expects(st != nullptr); Expects(st != nullptr);
const auto sti = &st->imageStyle(false); const auto sti = &st->imageStyle(false);
Ui::FillRoundRect(p, rect, sti->msgServiceBg, sti->msgServiceBgCorners); const auto &small = sti->msgServiceBgCornersSmall;
const auto &large = sti->msgServiceBgCornersLarge;
auto corners = Ui::CornersPixmaps();
using Corner = Ui::BubbleCornerRounding;
for (auto i = 0; i != 4; ++i) {
corners.p[i] = (rounding[i] == Corner::Large ? large : small).p[i];
}
Ui::FillRoundRect(p, rect, sti->msgServiceBg, corners);
if (howMuchOver > 0) { if (howMuchOver > 0) {
auto o = p.opacity(); auto o = p.opacity();
p.setOpacity(o * howMuchOver); p.setOpacity(o * howMuchOver);
Ui::FillRoundRect(p, rect, st->msgBotKbOverBgAdd(), st->msgBotKbOverBgAddCorners()); const auto &small = st->msgBotKbOverBgAddCornersSmall();
const auto &large = st->msgBotKbOverBgAddCornersLarge();
auto over = Ui::CornersPixmaps();
for (auto i = 0; i != 4; ++i) {
over.p[i] = (rounding[i] == Corner::Large ? large : small).p[i];
}
Ui::FillRoundRect(p, rect, st->msgBotKbOverBgAdd(), over);
p.setOpacity(o); p.setOpacity(o);
} }
} }
@ -354,7 +388,7 @@ void Message::animateReaction(Reactions::AnimationArgs &&args) {
const auto bubble = drawBubble(); const auto bubble = drawBubble();
const auto reactionsInBubble = _reactions && embedReactionsInBubble(); const auto reactionsInBubble = _reactions && embedReactionsInBubble();
const auto mediaDisplayed = media && media->isDisplayed(); const auto mediaDisplayed = media && media->isDisplayed();
auto keyboard = item->inlineReplyKeyboard(); const auto keyboard = item->inlineReplyKeyboard();
auto keyboardHeight = 0; auto keyboardHeight = 0;
if (keyboard) { if (keyboard) {
keyboardHeight = keyboard->naturalHeight(); keyboardHeight = keyboard->naturalHeight();
@ -729,13 +763,19 @@ void Message::draw(Painter &p, const PaintContext &context) const {
p.setTextPalette(stm->textPalette); p.setTextPalette(stm->textPalette);
auto keyboard = item->inlineReplyKeyboard(); const auto keyboard = item->inlineReplyKeyboard();
const auto messageRounding = countMessageRounding();
if (keyboard) { if (keyboard) {
const auto keyboardHeight = st::msgBotKbButton.margin + keyboard->naturalHeight(); const auto keyboardHeight = st::msgBotKbButton.margin + keyboard->naturalHeight();
g.setHeight(g.height() - keyboardHeight); g.setHeight(g.height() - keyboardHeight);
const auto keyboardPosition = QPoint(g.left(), g.top() + g.height() + st::msgBotKbButton.margin); const auto keyboardPosition = QPoint(g.left(), g.top() + g.height() + st::msgBotKbButton.margin);
p.translate(keyboardPosition); p.translate(keyboardPosition);
keyboard->paint(p, context.st, g.width(), context.clip.translated(-keyboardPosition)); keyboard->paint(
p,
context.st,
messageRounding,
g.width(),
context.clip.translated(-keyboardPosition));
p.translate(-keyboardPosition); p.translate(-keyboardPosition);
} }
@ -772,7 +812,7 @@ void Message::draw(Painter &p, const PaintContext &context) const {
.outerWidth = width(), .outerWidth = width(),
.selected = context.selected(), .selected = context.selected(),
.outbg = context.outbg, .outbg = context.outbg,
.rounding = countBubbleRounding(), .rounding = countBubbleRounding(messageRounding),
}, },
.selection = mediaSelectionIntervals, .selection = mediaSelectionIntervals,
}); });
@ -1375,8 +1415,15 @@ bool Message::displayFromPhoto() const {
void Message::clickHandlerPressedChanged( void Message::clickHandlerPressedChanged(
const ClickHandlerPtr &handler, const ClickHandlerPtr &handler,
bool pressed) { bool pressed) {
if (const auto markup = data()->Get<HistoryMessageReplyMarkup>()) {
if (const auto keyboard = markup->inlineKeyboard.get()) {
keyboard->clickHandlerPressedChanged(
handler,
pressed,
countMessageRounding());
}
}
Element::clickHandlerPressedChanged(handler, pressed); Element::clickHandlerPressedChanged(handler, pressed);
if (!handler) { if (!handler) {
return; return;
} else if (_comments && (handler == _comments->link)) { } else if (_comments && (handler == _comments->link)) {
@ -1408,7 +1455,7 @@ void Message::toggleCommentsButtonRipple(bool pressed) {
radius); radius);
p.fillRect(0, 0, linkWidth, radius * 2, Qt::white); p.fillRect(0, 0, linkWidth, radius * 2, Qt::white);
}; };
auto mask = Ui::RippleAnimation::maskByDrawer( auto mask = Ui::RippleAnimation::MaskByDrawer(
QSize(linkWidth, linkHeight), QSize(linkWidth, linkHeight),
false, false,
drawMask); drawMask);
@ -2161,7 +2208,7 @@ void Message::drawInfo(
} else if (type == InfoDisplayType::Background) { } else if (type == InfoDisplayType::Background) {
const auto dateW = size.width() + 2 * st::msgDateImgPadding.x(); const auto dateW = size.width() + 2 * st::msgDateImgPadding.x();
const auto dateH = size.height() + 2 * st::msgDateImgPadding.y(); const auto dateH = size.height() + 2 * st::msgDateImgPadding.y();
Ui::FillRoundRect(p, dateX - st::msgDateImgPadding.x(), dateY - st::msgDateImgPadding.y(), dateW, dateH, sti->msgServiceBg, sti->msgServiceBgCorners); Ui::FillRoundRect(p, dateX - st::msgDateImgPadding.x(), dateY - st::msgDateImgPadding.y(), dateW, dateH, sti->msgServiceBg, sti->msgServiceBgCornersSmall);
} }
_bottomInfo.paint( _bottomInfo.paint(
p, p,
@ -2988,7 +3035,7 @@ QRect Message::countGeometry() const {
height() - contentTop - marginBottom()); height() - contentTop - marginBottom());
} }
Ui::BubbleRounding Message::countBubbleRounding() const { Ui::BubbleRounding Message::countMessageRounding() const {
const auto smallTop = isAttachedToPrevious(); const auto smallTop = isAttachedToPrevious();
const auto smallBottom = isAttachedToNext(); const auto smallBottom = isAttachedToNext();
const auto media = smallBottom ? nullptr : this->media(); const auto media = smallBottom ? nullptr : this->media();
@ -3015,6 +3062,20 @@ Ui::BubbleRounding Message::countBubbleRounding() const {
}; };
} }
Ui::BubbleRounding Message::countBubbleRounding(
Ui::BubbleRounding messageRounding) const {
if (const auto keyboard = data()->inlineReplyKeyboard()) {
messageRounding.bottomLeft
= messageRounding.bottomRight
= Ui::BubbleCornerRounding::Small;
}
return messageRounding;
}
Ui::BubbleRounding Message::countBubbleRounding() const {
return countBubbleRounding(countMessageRounding());
}
int Message::resizeContentGetHeight(int newWidth) { int Message::resizeContentGetHeight(int newWidth) {
if (isHidden()) { if (isHidden()) {
return marginTop() + marginBottom(); return marginTop() + marginBottom();

View file

@ -225,6 +225,9 @@ private:
void updateMediaInBubbleState(); void updateMediaInBubbleState();
QRect countGeometry() const; QRect countGeometry() const;
[[nodiscard]] Ui::BubbleRounding countMessageRounding() const;
[[nodiscard]] Ui::BubbleRounding countBubbleRounding(
Ui::BubbleRounding messageRounding) const;
[[nodiscard]] Ui::BubbleRounding countBubbleRounding() const; [[nodiscard]] Ui::BubbleRounding countBubbleRounding() const;
int resizeContentGetHeight(int newWidth); int resizeContentGetHeight(int newWidth);

View file

@ -169,7 +169,7 @@ ViewButton::Inner::Inner(
void ViewButton::Inner::updateMask(int height) { void ViewButton::Inner::updateMask(int height) {
ripple = std::make_unique<Ui::RippleAnimation>( ripple = std::make_unique<Ui::RippleAnimation>(
st::defaultRippleAnimation, st::defaultRippleAnimation,
Ui::RippleAnimation::roundRectMask( Ui::RippleAnimation::RoundRectMask(
QSize(lastWidth, height - margins.top() - margins.bottom()), QSize(lastWidth, height - margins.top() - margins.bottom()),
st::roundRadiusLarge), st::roundRadiusLarge),
updateCallback); updateCallback);

View file

@ -564,7 +564,7 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
if (mediaUnread) { if (mediaUnread) {
statusW += st::mediaUnreadSkip + st::mediaUnreadSize; statusW += st::mediaUnreadSkip + st::mediaUnreadSize;
} }
Ui::FillRoundRect(p, style::rtlrect(statusX - st::msgDateImgPadding.x(), statusY - st::msgDateImgPadding.y(), statusW, statusH, width()), sti->msgServiceBg, sti->msgServiceBgCorners); Ui::FillRoundRect(p, style::rtlrect(statusX - st::msgDateImgPadding.x(), statusY - st::msgDateImgPadding.y(), statusW, statusH, width()), sti->msgServiceBg, sti->msgServiceBgCornersSmall);
p.setFont(st::normalFont); p.setFont(st::normalFont);
p.setPen(st->msgServiceFg()); p.setPen(st->msgServiceFg());
p.drawTextLeft(statusX, statusY, width(), _statusText, statusW - 2 * st::msgDateImgPadding.x()); p.drawTextLeft(statusX, statusY, width(), _statusText, statusW - 2 * st::msgDateImgPadding.x());
@ -596,7 +596,7 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
int recty = painty; int recty = painty;
if (rtl()) rectx = width() - rectx - rectw; if (rtl()) rectx = width() - rectx - rectw;
Ui::FillRoundRect(p, rectx, recty, rectw, recth, sti->msgServiceBg, sti->msgServiceBgCorners); Ui::FillRoundRect(p, rectx, recty, rectw, recth, sti->msgServiceBg, sti->msgServiceBgCornersSmall);
p.setPen(st->msgServiceFg()); p.setPen(st->msgServiceFg());
rectx += st::msgReplyPadding.left(); rectx += st::msgReplyPadding.left();
rectw = innerw; rectw = innerw;

View file

@ -227,7 +227,7 @@ void UnwrappedMedia::drawSurrounding(
int recty = 0; int recty = 0;
if (rtl()) rectx = width() - rectx - rectw; if (rtl()) rectx = width() - rectx - rectw;
Ui::FillRoundRect(p, rectx, recty, rectw, recth, sti->msgServiceBg, sti->msgServiceBgCorners); Ui::FillRoundRect(p, rectx, recty, rectw, recth, sti->msgServiceBg, sti->msgServiceBgCornersSmall);
p.setPen(st->msgServiceFg()); p.setPen(st->msgServiceFg());
rectx += st::msgReplyPadding.left(); rectx += st::msgReplyPadding.left();
rectw -= st::msgReplyPadding.left() + st::msgReplyPadding.right(); rectw -= st::msgReplyPadding.left() + st::msgReplyPadding.right();

View file

@ -1519,7 +1519,7 @@ void Poll::toggleRipple(Answer &answer, bool pressed) {
- st::msgPadding.left() - st::msgPadding.left()
- st::msgPadding.right(); - st::msgPadding.right();
if (!answer.ripple) { if (!answer.ripple) {
auto mask = Ui::RippleAnimation::rectMask(QSize( auto mask = Ui::RippleAnimation::RectMask(QSize(
outerWidth, outerWidth,
countAnswerHeight(answer, innerWidth))); countAnswerHeight(answer, innerWidth)));
answer.ripple = std::make_unique<Ui::RippleAnimation>( answer.ripple = std::make_unique<Ui::RippleAnimation>(
@ -1581,11 +1581,11 @@ void Poll::toggleLinkRipple(bool pressed) {
p.fillRect(0, 0, linkWidth, radius * 2, Qt::white); p.fillRect(0, 0, linkWidth, radius * 2, Qt::white);
}; };
auto mask = isRoundedInBubbleBottom() auto mask = isRoundedInBubbleBottom()
? Ui::RippleAnimation::maskByDrawer( ? Ui::RippleAnimation::MaskByDrawer(
QSize(linkWidth, linkHeight), QSize(linkWidth, linkHeight),
false, false,
drawMask) drawMask)
: Ui::RippleAnimation::rectMask({ linkWidth, linkHeight }); : Ui::RippleAnimation::RectMask({ linkWidth, linkHeight });
_linkRipple = std::make_unique<Ui::RippleAnimation>( _linkRipple = std::make_unique<Ui::RippleAnimation>(
st::defaultRippleAnimation, st::defaultRippleAnimation,
std::move(mask), std::move(mask),

View file

@ -259,7 +259,7 @@ void MediaGift::Button::toggleRipple(bool pressed) {
const auto linkHeight = size.height(); const auto linkHeight = size.height();
if (!ripple) { if (!ripple) {
const auto drawMask = [&](QPainter &p) { drawBg(p); }; const auto drawMask = [&](QPainter &p) { drawBg(p); };
auto mask = Ui::RippleAnimation::maskByDrawer( auto mask = Ui::RippleAnimation::MaskByDrawer(
QSize(linkWidth, linkHeight), QSize(linkWidth, linkHeight),
false, false,
drawMask); drawMask);

View file

@ -326,14 +326,16 @@ void LayerWidget::paintEvent(QPaintEvent *e) {
const auto clip = e->rect(); const auto clip = e->rect();
const auto radius = st::boxRadius; const auto radius = st::boxRadius;
auto parts = RectPart::None | 0; const auto &corners = Ui::CachedCornerPixmaps(Ui::BoxCorners);
if (!_tillBottom) { if (!_tillBottom) {
const auto bottom = QRect{ 0, height() - radius, width(), radius }; const auto bottom = QRect{ 0, height() - radius, width(), radius };
if (clip.intersects(bottom)) { if (clip.intersects(bottom)) {
if (const auto rounding = _content->bottomSkipRounding()) { if (const auto rounding = _content->bottomSkipRounding()) {
rounding->paint(p, rect(), RectPart::FullBottom); rounding->paint(p, rect(), RectPart::FullBottom);
} else { } else {
parts |= RectPart::FullBottom; Ui::FillRoundRect(p, bottom, st::boxBg, {
.p = { QPixmap(), QPixmap(), corners.p[2], corners.p[3] }
});
} }
} }
} else if (!_contentTillBottom) { } else if (!_contentTillBottom) {
@ -342,19 +344,13 @@ void LayerWidget::paintEvent(QPaintEvent *e) {
p.fillRect(0, height() - radius, width(), radius, color); p.fillRect(0, height() - radius, width(), radius, color);
} }
if (_content->animatingShow()) { if (_content->animatingShow()) {
if (clip.intersects({ 0, 0, width(), radius })) { const auto top = QRect{ 0, 0, width(), radius };
parts |= RectPart::FullTop; if (clip.intersects(top)) {
Ui::FillRoundRect(p, top, st::boxBg, {
.p = { corners.p[0], corners.p[1], QPixmap(), QPixmap() }
});
} }
parts |= RectPart::Left | RectPart::Center | RectPart::Right; p.fillRect(0, radius, width(), height() - 2 * radius, st::boxBg);
}
if (parts) {
Ui::FillRoundRect(
p,
rect(),
st::boxBg,
Ui::BoxCorners,
nullptr,
parts);
} }
} }

View file

@ -18,7 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "settings/settings_chat.h" #include "settings/settings_chat.h"
#include "settings/settings_main.h" #include "settings/settings_main.h"
#include "settings/settings_premium.h" #include "settings/settings_premium.h"
#include "ui/effects/ripple_animation.h" // maskByDrawer. #include "ui/effects/ripple_animation.h" // MaskByDrawer.
#include "ui/widgets/discrete_sliders.h" #include "ui/widgets/discrete_sliders.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/shadow.h" #include "ui/widgets/shadow.h"
@ -986,7 +986,7 @@ void WrapWidget::showNewContent(
const auto s = QSize( const auto s = QSize(
newContent->width(), newContent->width(),
animationParams.topSkip); animationParams.topSkip);
auto image = Ui::RippleAnimation::maskByDrawer(s, false, [&]( auto image = Ui::RippleAnimation::MaskByDrawer(s, false, [&](
QPainter &p) { QPainter &p) {
const auto r = QRect(0, 0, s.width(), s.height() * 2); const auto r = QRect(0, 0, s.width(), s.height() * 2);
p.drawRoundedRect(r, st::boxRadius, st::boxRadius); p.drawRoundedRect(r, st::boxRadius, st::boxRadius);

View file

@ -777,8 +777,7 @@ void ListWidget::paintEvent(QPaintEvent *e) {
if (_dateBadge->corners.p[0].isNull()) { if (_dateBadge->corners.p[0].isNull()) {
_dateBadge->corners = Ui::PrepareCornerPixmaps( _dateBadge->corners = Ui::PrepareCornerPixmaps(
Ui::HistoryServiceMsgRadius(), Ui::HistoryServiceMsgRadius(),
st::roundedBg, st::roundedBg);
nullptr);
} }
HistoryView::ServiceMessagePainter::PaintDate( HistoryView::ServiceMessagePainter::PaintDate(
p, p,

View file

@ -336,7 +336,7 @@ QPoint BotAction::prepareRippleStartPosition() const {
} }
QImage BotAction::prepareRippleMask() const { QImage BotAction::prepareRippleMask() const {
return Ui::RippleAnimation::rectMask(size()); return Ui::RippleAnimation::RectMask(size());
} }
int BotAction::contentHeight() const { int BotAction::contentHeight() const {

View file

@ -36,6 +36,9 @@ Widget::Widget(
, _contentMaxHeight(st::emojiPanMaxHeight) , _contentMaxHeight(st::emojiPanMaxHeight)
, _contentHeight(_contentMaxHeight) , _contentHeight(_contentMaxHeight)
, _scroll(this, st::inlineBotsScroll) , _scroll(this, st::inlineBotsScroll)
, _innerRounding(Ui::PrepareCornerPixmaps(
ImageRoundRadius::Small,
st::emojiPanBg))
, _inlineRequestTimer([=] { onInlineRequest(); }) { , _inlineRequestTimer([=] { onInlineRequest(); }) {
resize(QRect(0, 0, st::emojiPanWidth, _contentHeight).marginsAdded(innerPadding()).size()); resize(QRect(0, 0, st::emojiPanWidth, _contentHeight).marginsAdded(innerPadding()).size());
_width = width(); _width = width();
@ -59,6 +62,13 @@ Widget::Widget(
_inner->clearInlineRowsPanel(); _inner->clearInlineRowsPanel();
}, lifetime()); }, lifetime());
style::PaletteChanged(
) | rpl::start_with_next([=] {
_innerRounding = Ui::PrepareCornerPixmaps(
ImageRoundRadius::Small,
st::emojiPanBg);
}, lifetime());
macWindowDeactivateEvents( macWindowDeactivateEvents(
) | rpl::filter([=] { ) | rpl::filter([=] {
return !isHidden(); return !isHidden();
@ -150,7 +160,17 @@ void Widget::paintEvent(QPaintEvent *e) {
void Widget::paintContent(QPainter &p) { void Widget::paintContent(QPainter &p) {
auto inner = innerRect(); auto inner = innerRect();
Ui::FillRoundRect(p, inner, st::emojiPanBg, ImageRoundRadius::Small, RectPart::FullTop | RectPart::FullBottom); const auto radius = st::roundRadiusSmall;
const auto top = Ui::CornersPixmaps{
.p = { _innerRounding.p[0], _innerRounding.p[1], QPixmap(), QPixmap() },
};
Ui::FillRoundRect(p, inner.x(), inner.y(), inner.width(), radius, st::emojiPanBg, top);
const auto bottom = Ui::CornersPixmaps{
.p = { QPixmap(), QPixmap(), _innerRounding.p[2], _innerRounding.p[3] },
};
Ui::FillRoundRect(p, inner.x(), inner.y() + inner.height() - radius, inner.width(), radius, st::emojiPanBg, bottom);
auto horizontal = horizontalRect(); auto horizontal = horizontalRect();
auto sidesTop = horizontal.y(); auto sidesTop = horizontal.y();

View file

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/rp_widget.h" #include "ui/rp_widget.h"
#include "ui/abstract_button.h" #include "ui/abstract_button.h"
#include "ui/cached_round_corners.h"
#include "ui/widgets/tooltip.h" #include "ui/widgets/tooltip.h"
#include "ui/effects/animations.h" #include "ui/effects/animations.h"
#include "ui/effects/panel_animation.h" #include "ui/effects/panel_animation.h"
@ -144,6 +145,7 @@ private:
object_ptr<Ui::ScrollArea> _scroll; object_ptr<Ui::ScrollArea> _scroll;
QPointer<Inner> _inner; QPointer<Inner> _inner;
Ui::CornersPixmaps _innerRounding;
std::map<QString, std::unique_ptr<CacheEntry>> _inlineCache; std::map<QString, std::unique_ptr<CacheEntry>> _inlineCache;
base::Timer _inlineRequestTimer; base::Timer _inlineRequestTimer;

View file

@ -71,8 +71,18 @@ void Dropdown::paintEvent(QPaintEvent *e) {
auto shadowedRect = rect().marginsRemoved(getMargin()); auto shadowedRect = rect().marginsRemoved(getMargin());
auto shadowedSides = RectPart::Left | RectPart::Right | RectPart::Bottom; auto shadowedSides = RectPart::Left | RectPart::Right | RectPart::Bottom;
Ui::Shadow::paint(p, shadowedRect, width(), st::defaultRoundShadow, shadowedSides); Ui::Shadow::paint(p, shadowedRect, width(), st::defaultRoundShadow, shadowedSides);
auto parts = RectPart::NoTopBottom | RectPart::FullBottom; const auto &corners = Ui::CachedCornerPixmaps(Ui::MenuCorners);
Ui::FillRoundRect(p, QRect(shadowedRect.x(), -st::roundRadiusSmall, shadowedRect.width(), shadowedRect.y() + shadowedRect.height() + st::roundRadiusSmall), st::menuBg, Ui::MenuCorners, nullptr, parts); const auto fill = Ui::CornersPixmaps{
.p = { QPixmap(), QPixmap(), corners.p[2], corners.p[3] },
};
Ui::FillRoundRect(
p,
shadowedRect.x(),
0,
shadowedRect.width(),
shadowedRect.y() + shadowedRect.height(),
st::menuBg,
fill);
} }
void Dropdown::enterEventHook(QEnterEvent *e) { void Dropdown::enterEventHook(QEnterEvent *e) {

View file

@ -160,8 +160,7 @@ void Panel::paintEvent(QPaintEvent *e) {
| (rtl() ? RectPart::Left : RectPart::Right) | (rtl() ? RectPart::Left : RectPart::Right)
| RectPart::Top; | RectPart::Top;
Ui::Shadow::paint(p, shadowedRect, width(), st::defaultRoundShadow, shadowedSides); Ui::Shadow::paint(p, shadowedRect, width(), st::defaultRoundShadow, shadowedSides);
auto parts = RectPart::Full; Ui::FillRoundRect(p, shadowedRect, st::menuBg, Ui::MenuCorners);
Ui::FillRoundRect(p, shadowedRect, st::menuBg, Ui::MenuCorners, nullptr, parts);
} }
void Panel::enterEventHook(QEnterEvent *e) { void Panel::enterEventHook(QEnterEvent *e) {

View file

@ -149,7 +149,7 @@ void PeerListWidget::mousePressEvent(QMouseEvent *e) {
const auto item = _items[_pressed]; const auto item = _items[_pressed];
if (!item->ripple) { if (!item->ripple) {
auto memberRowWidth = rowWidth(); auto memberRowWidth = rowWidth();
auto mask = Ui::RippleAnimation::rectMask(QSize(memberRowWidth, _st.height)); auto mask = Ui::RippleAnimation::RectMask(QSize(memberRowWidth, _st.height));
item->ripple = std::make_unique<Ui::RippleAnimation>(_st.button.ripple, std::move(mask), [this, index = _pressed] { item->ripple = std::make_unique<Ui::RippleAnimation>(_st.button.ripple, std::move(mask), [this, index = _pressed] {
repaintRow(index); repaintRow(index);
}); });

View file

@ -515,20 +515,16 @@ void LayerWidget::paintEvent(QPaintEvent *e) {
auto clip = e->rect(); auto clip = e->rect();
auto r = st::boxRadius; auto r = st::boxRadius;
auto parts = RectPart::None | 0; auto parts = RectPart::None | 0;
const auto &pixmaps = Ui::CachedCornerPixmaps(Ui::BoxCorners);
if (!_tillTop && clip.intersects({ 0, 0, width(), r })) { if (!_tillTop && clip.intersects({ 0, 0, width(), r })) {
parts |= RectPart::FullTop; Ui::FillRoundRect(p, 0, 0, width(), r, st::boxBg, {
.p = { pixmaps.p[0], pixmaps.p[1], QPixmap(), QPixmap() },
});
} }
if (!_tillBottom && clip.intersects({ 0, height() - r, width(), r })) { if (!_tillBottom && clip.intersects({ 0, height() - r, width(), r })) {
parts |= RectPart::FullBottom; Ui::FillRoundRect(p, 0, height() - r, width(), r, st::boxBg, {
} .p = { QPixmap(), QPixmap(), pixmaps.p[2], pixmaps.p[3] },
if (parts) { });
Ui::FillRoundRect(
p,
rect(),
st::boxBg,
Ui::BoxCorners,
nullptr,
parts);
} }
if (_tillTop) { if (_tillTop) {
p.fillRect(0, 0, width(), r, st::boxBg); p.fillRect(0, 0, width(), r, st::boxBg);

View file

@ -277,14 +277,13 @@ struct ForwardedTooltip {
{ line, line, line, line + arrowSize }); { line, line, line, line + arrowSize });
const auto origin = full.topLeft(); const auto origin = full.topLeft();
const auto rounded = std::make_shared<Ui::RoundRect>(
ImageRoundRadius::Large,
st::toastBg);
const auto paint = [=](QPainter &p) { const auto paint = [=](QPainter &p) {
p.translate(-origin); p.translate(-origin);
Ui::FillRoundRect( rounded->paint(p, geometry);
p,
geometry,
st::toastBg,
ImageRoundRadius::Large);
p.setFont(font); p.setFont(font);
p.setPen(st::toastFg); p.setPen(st::toastFg);

View file

@ -416,8 +416,7 @@ CalendarBox::FloatingDate::FloatingDate(
, _corners( , _corners(
PrepareCornerPixmaps( PrepareCornerPixmaps(
HistoryServiceMsgRadius(), HistoryServiceMsgRadius(),
st::roundedBg, st::roundedBg)) {
nullptr)) {
_context->monthValue( _context->monthValue(
) | rpl::start_with_next([=](QDate month) { ) | rpl::start_with_next([=](QDate month) {
_text = langMonthOfYearFull(month.month(), month.year()); _text = langMonthOfYearFull(month.month(), month.year());
@ -670,7 +669,7 @@ void CalendarBox::Inner::mousePressEvent(QMouseEvent *e) {
auto cell = QRect(rowsLeft() + col * _st.cellSize.width(), rowsTop() + row * _st.cellSize.height(), _st.cellSize.width(), _st.cellSize.height()); auto cell = QRect(rowsLeft() + col * _st.cellSize.width(), rowsTop() + row * _st.cellSize.height(), _st.cellSize.width(), _st.cellSize.height());
auto it = _ripples.find(_selected); auto it = _ripples.find(_selected);
if (it == _ripples.cend()) { if (it == _ripples.cend()) {
auto mask = RippleAnimation::ellipseMask(QSize(_st.cellInner, _st.cellInner)); auto mask = RippleAnimation::EllipseMask(QSize(_st.cellInner, _st.cellInner));
auto update = [this, cell] { rtlupdate(cell); }; auto update = [this, cell] { rtlupdate(cell); };
it = _ripples.emplace(_selected, std::make_unique<RippleAnimation>(st::defaultRippleAnimation, std::move(mask), std::move(update))).first; it = _ripples.emplace(_selected, std::make_unique<RippleAnimation>(st::defaultRippleAnimation, std::move(mask), std::move(update))).first;
} }

View file

@ -347,7 +347,7 @@ void CountrySelectBox::Inner::mousePressEvent(QMouseEvent *e) {
} }
} }
if (!_ripples[_pressed]) { if (!_ripples[_pressed]) {
auto mask = RippleAnimation::rectMask(QSize(width(), _rowHeight)); auto mask = RippleAnimation::RectMask(QSize(width(), _rowHeight));
_ripples[_pressed] = std::make_unique<RippleAnimation>(st::countryRipple, std::move(mask), [this, index = _pressed] { _ripples[_pressed] = std::make_unique<RippleAnimation>(st::countryRipple, std::move(mask), [this, index = _pressed] {
updateRow(index); updateRow(index);
}); });

View file

@ -22,7 +22,6 @@ namespace {
constexpr auto kCachedCornerRadiusCount = int(CachedCornerRadius::kCount); constexpr auto kCachedCornerRadiusCount = int(CachedCornerRadius::kCount);
std::vector<CornersPixmaps> Corners; std::vector<CornersPixmaps> Corners;
base::flat_map<uint32, CornersPixmaps> CornersMap;
QImage CornersMaskLarge[4], CornersMaskSmall[4]; QImage CornersMaskLarge[4], CornersMaskSmall[4];
rpl::lifetime PaletteChangedLifetime; rpl::lifetime PaletteChangedLifetime;
@ -109,56 +108,84 @@ void StartCachedCorners() {
void FinishCachedCorners() { void FinishCachedCorners() {
Corners.clear(); Corners.clear();
CornersMap.clear();
PaletteChangedLifetime.destroy(); PaletteChangedLifetime.destroy();
} }
void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, const CornersPixmaps &corner, const style::color *shadow, RectParts parts) { void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, const CornersPixmaps &corners) {
auto cornerWidth = corner.p[0].width() / style::DevicePixelRatio(); using namespace Images;
auto cornerHeight = corner.p[0].height() / style::DevicePixelRatio();
if (w < 2 * cornerWidth || h < 2 * cornerHeight) return; const auto fillBg = [&](QRect rect) {
if (w > 2 * cornerWidth) { p.fillRect(rect, bg);
if (parts & RectPart::Top) { };
p.fillRect(x + cornerWidth, y, w - 2 * cornerWidth, cornerHeight, bg); const auto fillCorner = [&](int x, int y, int index) {
if (const auto &pix = corners.p[index]; !pix.isNull()) {
p.drawPixmap(x, y, pix);
} }
if (parts & RectPart::Bottom) { };
p.fillRect(x + cornerWidth, y + h - cornerHeight, w - 2 * cornerWidth, cornerHeight, bg);
if (shadow) { if (corners.p[kTopLeft].isNull()
p.fillRect(x + cornerWidth, y + h, w - 2 * cornerWidth, st::msgShadow, *shadow); && corners.p[kTopRight].isNull()
&& corners.p[kBottomLeft].isNull()
&& corners.p[kBottomRight].isNull()) {
p.fillRect(x, y, w, h, bg);
return;
}
const auto ratio = style::DevicePixelRatio();
const auto cornerSize = [&](int index) {
return corners.p[index].isNull()
? 0
: (corners.p[index].width() / ratio);
};
const auto verticalSkip = [&](int left, int right) {
return std::max(cornerSize(left), cornerSize(right));
};
const auto top = verticalSkip(kTopLeft, kTopRight);
const auto bottom = verticalSkip(kBottomLeft, kBottomRight);
if (top) {
const auto left = cornerSize(kTopLeft);
const auto right = cornerSize(kTopRight);
if (left) {
fillCorner(x, y, kTopLeft);
if (const auto add = top - left) {
fillBg({ x, y + left, left, add });
}
}
if (const auto fill = w - left - right; fill > 0) {
fillBg({ x + left, y, fill, top });
}
if (right) {
fillCorner(x + w - right, y, kTopRight);
if (const auto add = top - right) {
fillBg({ x + w - right, y + right, right, add });
} }
} }
} }
if (h > 2 * cornerHeight) { if (const auto fill = h - top - bottom; fill > 0) {
if ((parts & RectPart::NoTopBottom) == RectPart::NoTopBottom) { fillBg({ x, y + top, w, fill });
p.fillRect(x, y + cornerHeight, w, h - 2 * cornerHeight, bg); }
} else { if (bottom) {
if (parts & RectPart::Left) { const auto left = cornerSize(kBottomLeft);
p.fillRect(x, y + cornerHeight, cornerWidth, h - 2 * cornerHeight, bg); const auto right = cornerSize(kBottomRight);
} if (left) {
if ((parts & RectPart::Center) && w > 2 * cornerWidth) { fillCorner(x, y + h - left, kBottomLeft);
p.fillRect(x + cornerWidth, y + cornerHeight, w - 2 * cornerWidth, h - 2 * cornerHeight, bg); if (const auto add = bottom - left) {
} fillBg({ x, y + h - bottom, left, add });
if (parts & RectPart::Right) { }
p.fillRect(x + w - cornerWidth, y + cornerHeight, cornerWidth, h - 2 * cornerHeight, bg); }
if (const auto fill = w - left - right; fill > 0) {
fillBg({ x + left, y + h - bottom, fill, bottom });
}
if (right) {
fillCorner(x + w - right, y + h - right, kBottomRight);
if (const auto add = bottom - right) {
fillBg({ x + w - right, y + h - bottom, right, add });
} }
} }
}
if (parts & RectPart::TopLeft) {
p.drawPixmap(x, y, corner.p[0]);
}
if (parts & RectPart::TopRight) {
p.drawPixmap(x + w - cornerWidth, y, corner.p[1]);
}
if (parts & RectPart::BottomLeft) {
p.drawPixmap(x, y + h - cornerHeight, corner.p[2]);
}
if (parts & RectPart::BottomRight) {
p.drawPixmap(x + w - cornerWidth, y + h - cornerHeight, corner.p[3]);
} }
} }
void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, CachedRoundCorners index, const style::color *shadow, RectParts parts) { void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, CachedRoundCorners index) {
FillRoundRect(p, x, y, w, h, bg, Corners[index], shadow, parts); FillRoundRect(p, x, y, w, h, bg, CachedCornerPixmaps(index));
} }
void FillRoundShadow(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, const CornersPixmaps &corners) { void FillRoundShadow(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, const CornersPixmaps &corners) {
@ -188,6 +215,12 @@ void FillRoundShadow(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::col
fillCorner(x + w - right, y + h + st::msgShadow, kRight); fillCorner(x + w - right, y + h + st::msgShadow, kRight);
} }
const CornersPixmaps &CachedCornerPixmaps(CachedRoundCorners index) {
Expects(index >= 0 && index < RoundCornersCount);
return Corners[index];
}
CornersPixmaps PrepareCornerPixmaps(int32 radius, style::color bg, const style::color *sh) { CornersPixmaps PrepareCornerPixmaps(int32 radius, style::color bg, const style::color *sh) {
auto images = PrepareCorners(radius, bg, sh); auto images = PrepareCorners(radius, bg, sh);
auto result = CornersPixmaps(); auto result = CornersPixmaps();
@ -208,24 +241,6 @@ CornersPixmaps PrepareCornerPixmaps(ImageRoundRadius radius, style::color bg, co
Unexpected("Image round radius in PrepareCornerPixmaps."); Unexpected("Image round radius in PrepareCornerPixmaps.");
} }
void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, ImageRoundRadius radius, RectParts parts) {
if (radius == ImageRoundRadius::None) {
p.fillRect(x, y, w, h, bg);
return;
}
const auto colorKey = ((uint32(bg->c.alpha()) & 0xFF) << 24)
| ((uint32(bg->c.red()) & 0xFF) << 16)
| ((uint32(bg->c.green()) & 0xFF) << 8)
| ((uint32(bg->c.blue()) & 0xFF));
auto i = CornersMap.find(colorKey);
if (i == end(CornersMap)) {
i = CornersMap.emplace(
colorKey,
PrepareCornerPixmaps(radius, bg, nullptr)).first;
}
FillRoundRect(p, x, y, w, h, bg, i->second, nullptr, parts);
}
[[nodiscard]] int CachedCornerRadiusValue(CachedCornerRadius tag) { [[nodiscard]] int CachedCornerRadiusValue(CachedCornerRadius tag) {
using Radius = CachedCornerRadius; using Radius = CachedCornerRadius;
switch (tag) { switch (tag) {

View file

@ -36,26 +36,23 @@ enum CachedRoundCorners : int {
RoundCornersCount RoundCornersCount
}; };
void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, CachedRoundCorners index, const style::color *shadow = nullptr, RectParts parts = RectPart::Full); void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, CachedRoundCorners index);
inline void FillRoundRect(QPainter &p, const QRect &rect, style::color bg, CachedRoundCorners index, const style::color *shadow = nullptr, RectParts parts = RectPart::Full) { inline void FillRoundRect(QPainter &p, const QRect &rect, style::color bg, CachedRoundCorners index) {
FillRoundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, index, shadow, parts); FillRoundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, index);
}
void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, ImageRoundRadius radius, RectParts parts = RectPart::Full);
inline void FillRoundRect(QPainter &p, const QRect &rect, style::color bg, ImageRoundRadius radius, RectParts parts = RectPart::Full) {
FillRoundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, radius, parts);
} }
[[nodiscard]] const CornersPixmaps &CachedCornerPixmaps(CachedRoundCorners index);
[[nodiscard]] CornersPixmaps PrepareCornerPixmaps( [[nodiscard]] CornersPixmaps PrepareCornerPixmaps(
int32 radius, int32 radius,
style::color bg, style::color bg,
const style::color *sh); const style::color *sh = nullptr);
[[nodiscard]] CornersPixmaps PrepareCornerPixmaps( [[nodiscard]] CornersPixmaps PrepareCornerPixmaps(
ImageRoundRadius radius, ImageRoundRadius radius,
style::color bg, style::color bg,
const style::color *sh); const style::color *sh = nullptr);
void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, const CornersPixmaps &corner, const style::color *shadow = nullptr, RectParts parts = RectPart::Full); void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, const CornersPixmaps &corners);
inline void FillRoundRect(QPainter &p, const QRect &rect, style::color bg, const CornersPixmaps &corner, const style::color *shadow = nullptr, RectParts parts = RectPart::Full) { inline void FillRoundRect(QPainter &p, const QRect &rect, style::color bg, const CornersPixmaps &corners) {
return FillRoundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, corner, shadow, parts); return FillRoundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, corners);
} }
void FillRoundShadow(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, const CornersPixmaps &corners); void FillRoundShadow(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, const CornersPixmaps &corners);
inline void FillRoundShadow(QPainter &p, const QRect &rect, style::color shadow, const CornersPixmaps &corners) { inline void FillRoundShadow(QPainter &p, const QRect &rect, style::color shadow, const CornersPixmaps &corners) {

View file

@ -307,13 +307,12 @@ void Panel::Button::paintEvent(QPaintEvent *e) {
} }
QImage Panel::Button::prepareRippleMask() const { QImage Panel::Button::prepareRippleMask() const {
const auto drawMask = [&](QPainter &p) { return RippleAnimation::MaskByDrawer(size(), false, [&](QPainter &p) {
p.drawRoundedRect( p.drawRoundedRect(
rect().marginsAdded({ 0, st::callRadius * 2, 0, 0 }), rect().marginsAdded({ 0, st::callRadius * 2, 0, 0 }),
st::callRadius, st::callRadius,
st::callRadius); st::callRadius);
}; });
return RippleAnimation::maskByDrawer(size(), false, drawMask);
} }
QPoint Panel::Button::prepareRippleStartPosition() const { QPoint Panel::Button::prepareRippleStartPosition() const {

View file

@ -657,7 +657,7 @@ msgBotKbSwitchPmIcon: icon {{ "inline_button_switch", msgBotKbIconFg }};
msgBotKbPaymentIcon: icon {{ "inline_button_card", msgBotKbIconFg }}; msgBotKbPaymentIcon: icon {{ "inline_button_card", msgBotKbIconFg }};
msgBotKbWebviewIcon: icon {{ "inline_button_web", msgBotKbIconFg }}; msgBotKbWebviewIcon: icon {{ "inline_button_web", msgBotKbIconFg }};
msgBotKbButton: BotKeyboardButton { msgBotKbButton: BotKeyboardButton {
margin: 5px; margin: 2px;
padding: 10px; padding: 10px;
height: 36px; height: 36px;
textTop: 8px; textTop: 8px;

View file

@ -28,49 +28,6 @@ void EnsureCorners(
} }
} }
void RectWithCorners(
QPainter &p,
QRect rect,
const style::color &bg,
const CornersPixmaps &corners,
RectParts roundCorners) {
const auto parts = RectPart::Top
| RectPart::NoTopBottom
| RectPart::Bottom
| roundCorners;
FillRoundRect(p, rect, bg, corners, nullptr, parts);
if ((roundCorners & RectPart::AllCorners) != RectPart::AllCorners) {
const auto size = corners.p[0].width() / style::DevicePixelRatio();
if (!(roundCorners & RectPart::TopLeft)) {
p.fillRect(rect.x(), rect.y(), size, size, bg);
}
if (!(roundCorners & RectPart::TopRight)) {
p.fillRect(
rect.x() + rect.width() - size,
rect.y(),
size,
size,
bg);
}
if (!(roundCorners & RectPart::BottomLeft)) {
p.fillRect(
rect.x(),
rect.y() + rect.height() - size,
size,
size,
bg);
}
if (!(roundCorners & RectPart::BottomRight)) {
p.fillRect(
rect.x() + rect.width() - size,
rect.y() + rect.height() - size,
size,
size,
bg);
}
}
}
} // namespace } // namespace
not_null<const MessageStyle*> ChatPaintContext::messageStyle() const { not_null<const MessageStyle*> ChatPaintContext::messageStyle() const {
@ -485,13 +442,15 @@ void ChatStyle::assignPalette(not_null<const style::palette*> palette) {
} }
for (auto &style : _imageStyles) { for (auto &style : _imageStyles) {
style.msgDateImgBgCorners = {}; style.msgDateImgBgCorners = {};
style.msgServiceBgCorners = {}; style.msgServiceBgCornersSmall = {};
style.msgServiceBgCornersLarge = {};
style.msgShadowCornersSmall = {}; style.msgShadowCornersSmall = {};
style.msgShadowCornersLarge = {}; style.msgShadowCornersLarge = {};
} }
_serviceBgCornersNormal = {}; _serviceBgCornersNormal = {};
_serviceBgCornersInverted = {}; _serviceBgCornersInverted = {};
_msgBotKbOverBgAddCorners = {}; _msgBotKbOverBgAddCornersSmall = {};
_msgBotKbOverBgAddCornersLarge = {};
for (auto &corners : _msgSelectOverlayCorners) { for (auto &corners : _msgSelectOverlayCorners) {
corners = {}; corners = {};
} }
@ -555,8 +514,12 @@ const MessageImageStyle &ChatStyle::imageStyle(bool selected) const {
(st::msgDateImgPadding.y() * 2 + st::normalFont->height) / 2, (st::msgDateImgPadding.y() * 2 + st::normalFont->height) / 2,
result.msgDateImgBg); result.msgDateImgBg);
EnsureCorners( EnsureCorners(
result.msgServiceBgCorners, result.msgServiceBgCornersSmall,
st::dateRadius, st::bubbleRadiusSmall,
result.msgServiceBg);
EnsureCorners(
result.msgServiceBgCornersLarge,
st::bubbleRadiusLarge,
result.msgServiceBg); result.msgServiceBg);
EnsureCorners( EnsureCorners(
result.msgShadowCornersSmall, result.msgShadowCornersSmall,
@ -569,12 +532,20 @@ const MessageImageStyle &ChatStyle::imageStyle(bool selected) const {
return result; return result;
} }
const CornersPixmaps &ChatStyle::msgBotKbOverBgAddCorners() const { const CornersPixmaps &ChatStyle::msgBotKbOverBgAddCornersSmall() const {
EnsureCorners( EnsureCorners(
_msgBotKbOverBgAddCorners, _msgBotKbOverBgAddCornersSmall,
st::dateRadius, st::bubbleRadiusSmall,
msgBotKbOverBgAdd()); msgBotKbOverBgAdd());
return _msgBotKbOverBgAddCorners; return _msgBotKbOverBgAddCornersSmall;
}
const CornersPixmaps &ChatStyle::msgBotKbOverBgAddCornersLarge() const {
EnsureCorners(
_msgBotKbOverBgAddCornersLarge,
st::bubbleRadiusLarge,
msgBotKbOverBgAdd());
return _msgBotKbOverBgAddCornersLarge;
} }
const CornersPixmaps &ChatStyle::msgSelectOverlayCorners( const CornersPixmaps &ChatStyle::msgSelectOverlayCorners(

View file

@ -80,7 +80,8 @@ struct MessageStyle {
struct MessageImageStyle { struct MessageImageStyle {
CornersPixmaps msgDateImgBgCorners; CornersPixmaps msgDateImgBgCorners;
CornersPixmaps msgServiceBgCorners; CornersPixmaps msgServiceBgCornersSmall;
CornersPixmaps msgServiceBgCornersLarge;
CornersPixmaps msgShadowCornersSmall; CornersPixmaps msgShadowCornersSmall;
CornersPixmaps msgShadowCornersLarge; CornersPixmaps msgShadowCornersLarge;
style::color msgServiceBg; style::color msgServiceBg;
@ -191,7 +192,8 @@ public:
bool selected) const; bool selected) const;
[[nodiscard]] const MessageImageStyle &imageStyle(bool selected) const; [[nodiscard]] const MessageImageStyle &imageStyle(bool selected) const;
[[nodiscard]] const CornersPixmaps &msgBotKbOverBgAddCorners() const; [[nodiscard]] const CornersPixmaps &msgBotKbOverBgAddCornersSmall() const;
[[nodiscard]] const CornersPixmaps &msgBotKbOverBgAddCornersLarge() const;
[[nodiscard]] const CornersPixmaps &msgSelectOverlayCorners( [[nodiscard]] const CornersPixmaps &msgSelectOverlayCorners(
CachedCornerRadius radius) const; CachedCornerRadius radius) const;
@ -318,7 +320,8 @@ private:
mutable std::array<MessageStyle, 4> _messageStyles; mutable std::array<MessageStyle, 4> _messageStyles;
mutable std::array<MessageImageStyle, 2> _imageStyles; mutable std::array<MessageImageStyle, 2> _imageStyles;
mutable CornersPixmaps _msgBotKbOverBgAddCorners; mutable CornersPixmaps _msgBotKbOverBgAddCornersSmall;
mutable CornersPixmaps _msgBotKbOverBgAddCornersLarge;
mutable CornersPixmaps _msgSelectOverlayCorners[ mutable CornersPixmaps _msgSelectOverlayCorners[
int(CachedCornerRadius::kCount)]; int(CachedCornerRadius::kCount)];

View file

@ -28,6 +28,8 @@ void PaintBubbleGeneric(
FillSh &&fillSh, FillSh &&fillSh,
FillCorner &&fillCorner, FillCorner &&fillCorner,
PaintTail &&paintTail) { PaintTail &&paintTail) {
using namespace Images;
const auto topLeft = args.rounding.topLeft; const auto topLeft = args.rounding.topLeft;
const auto topRight = args.rounding.topRight; const auto topRight = args.rounding.topRight;
const auto bottomWithTailLeft = args.rounding.bottomLeft; const auto bottomWithTailLeft = args.rounding.bottomLeft;
@ -64,7 +66,7 @@ void PaintBubbleGeneric(
const auto left = cornerSize(topLeft); const auto left = cornerSize(topLeft);
const auto right = cornerSize(topRight); const auto right = cornerSize(topRight);
if (left) { if (left) {
fillCorner(rect.left(), rect.top(), 0, topLeft); fillCorner(rect.left(), rect.top(), kTopLeft, topLeft);
if (const auto add = top - left) { if (const auto add = top - left) {
fillBg({ rect.left(), rect.top() + left, left, add }); fillBg({ rect.left(), rect.top() + left, left, add });
} }
@ -76,7 +78,7 @@ void PaintBubbleGeneric(
fillCorner( fillCorner(
rect.left() + rect.width() - right, rect.left() + rect.width() - right,
rect.top(), rect.top(),
1, kTopRight,
topRight); topRight);
if (const auto add = top - right) { if (const auto add = top - right) {
fillBg({ fillBg({
@ -88,8 +90,8 @@ void PaintBubbleGeneric(
} }
} }
} }
if (const auto h = rect.height() - top - bottom; h > 0) { if (const auto fill = rect.height() - top - bottom; fill > 0) {
fillBg({ rect.left(), rect.top() + top, rect.width(), h }); fillBg({ rect.left(), rect.top() + top, rect.width(), fill });
} }
if (bottom) { if (bottom) {
const auto left = cornerSize(bottomLeft); const auto left = cornerSize(bottomLeft);
@ -98,7 +100,7 @@ void PaintBubbleGeneric(
fillCorner( fillCorner(
rect.left(), rect.left(),
rect.top() + rect.height() - left, rect.top() + rect.height() - left,
2, kBottomLeft,
bottomLeft); bottomLeft);
if (const auto add = bottom - left) { if (const auto add = bottom - left) {
fillBg({ fillBg({
@ -121,7 +123,7 @@ void PaintBubbleGeneric(
fillCorner( fillCorner(
rect.left() + rect.width() - right, rect.left() + rect.width() - right,
rect.top() + rect.height() - right, rect.top() + rect.height() - right,
3, kBottomRight,
bottomRight); bottomRight);
if (const auto add = bottom - right) { if (const auto add = bottom - right) {
fillBg({ fillBg({

View file

@ -213,7 +213,7 @@ QPoint ActionWithTimer::prepareRippleStartPosition() const {
} }
QImage ActionWithTimer::prepareRippleMask() const { QImage ActionWithTimer::prepareRippleMask() const {
return Ui::RippleAnimation::rectMask(size()); return Ui::RippleAnimation::RectMask(size());
} }
int ActionWithTimer::contentHeight() const { int ActionWithTimer::contentHeight() const {

View file

@ -122,7 +122,7 @@ QPoint EmojiButton::prepareRippleStartPosition() const {
} }
QImage EmojiButton::prepareRippleMask() const { QImage EmojiButton::prepareRippleMask() const {
return RippleAnimation::ellipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize)); return RippleAnimation::EllipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize));
} }
} // namespace Ui } // namespace Ui

View file

@ -202,7 +202,7 @@ QImage SendButton::prepareRippleMask() const {
auto size = (_type == Type::Record) auto size = (_type == Type::Record)
? st::historyAttachEmoji.rippleAreaSize ? st::historyAttachEmoji.rippleAreaSize
: st::historyReplyCancel.rippleAreaSize; : st::historyReplyCancel.rippleAreaSize;
return RippleAnimation::ellipseMask(QSize(size, size)); return RippleAnimation::EllipseMask(QSize(size, size));
} }
QPoint SendButton::prepareRippleStartPosition() const { QPoint SendButton::prepareRippleStartPosition() const {

View file

@ -444,7 +444,7 @@ QPoint Action::prepareRippleStartPosition() const {
} }
QImage Action::prepareRippleMask() const { QImage Action::prepareRippleMask() const {
return Ui::RippleAnimation::rectMask(size()); return Ui::RippleAnimation::RectMask(size());
} }
int Action::contentHeight() const { int Action::contentHeight() const {

View file

@ -70,7 +70,8 @@ constexpr auto kIcons = std::array{
FilterIconPanel::FilterIconPanel(QWidget *parent) FilterIconPanel::FilterIconPanel(QWidget *parent)
: RpWidget(parent) : RpWidget(parent)
, _inner(Ui::CreateChild<Ui::RpWidget>(this)) { , _inner(Ui::CreateChild<Ui::RpWidget>(this))
, _innerBg(ImageRoundRadius::Small, st::dialogsBg) {
setup(); setup();
} }
@ -117,11 +118,7 @@ void FilterIconPanel::setupInner() {
_inner->paintRequest( _inner->paintRequest(
) | rpl::start_with_next([=](QRect clip) { ) | rpl::start_with_next([=](QRect clip) {
auto p = Painter(_inner); auto p = Painter(_inner);
Ui::FillRoundRect( _innerBg.paint(p, _inner->rect());
p,
_inner->rect(),
st::dialogsBg,
ImageRoundRadius::Small);
p.setFont(st::emojiPanHeaderFont); p.setFont(st::emojiPanHeaderFont);
p.setPen(st::emojiPanHeaderFg); p.setPen(st::emojiPanHeaderFg);
p.drawTextLeft( p.drawTextLeft(

View file

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/timer.h" #include "base/timer.h"
#include "ui/rp_widget.h" #include "ui/rp_widget.h"
#include "ui/effects/animations.h" #include "ui/effects/animations.h"
#include "ui/round_rect.h"
namespace Ui { namespace Ui {
@ -69,6 +70,7 @@ private:
const not_null<Ui::RpWidget*> _inner; const not_null<Ui::RpWidget*> _inner;
rpl::event_stream<FilterIcon> _chosen; rpl::event_stream<FilterIcon> _chosen;
Ui::RoundRect _innerBg;
int _selected = -1; int _selected = -1;
int _pressed = -1; int _pressed = -1;

View file

@ -127,7 +127,7 @@ HistoryDownButton::HistoryDownButton(QWidget *parent, const style::TwoIconButton
} }
QImage HistoryDownButton::prepareRippleMask() const { QImage HistoryDownButton::prepareRippleMask() const {
return Ui::RippleAnimation::ellipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize)); return Ui::RippleAnimation::EllipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize));
} }
QPoint HistoryDownButton::prepareRippleStartPosition() const { QPoint HistoryDownButton::prepareRippleStartPosition() const {
@ -502,7 +502,7 @@ QPoint UserpicButton::countPhotoPosition() const {
} }
QImage UserpicButton::prepareRippleMask() const { QImage UserpicButton::prepareRippleMask() const {
return Ui::RippleAnimation::ellipseMask(QSize( return Ui::RippleAnimation::EllipseMask(QSize(
_st.photoSize, _st.photoSize,
_st.photoSize)); _st.photoSize));
} }
@ -896,7 +896,7 @@ QPoint SilentToggle::prepareRippleStartPosition() const {
} }
QImage SilentToggle::prepareRippleMask() const { QImage SilentToggle::prepareRippleMask() const {
return RippleAnimation::ellipseMask( return RippleAnimation::EllipseMask(
QSize(_st.rippleAreaSize, _st.rippleAreaSize)); QSize(_st.rippleAreaSize, _st.rippleAreaSize));
} }

View file

@ -265,19 +265,32 @@ void SettingsSlider::startRipple(int sectionIndex) {
}); });
} }
QImage SettingsSlider::prepareRippleMask(int sectionIndex, const Section &section) { QImage SettingsSlider::prepareRippleMask(
int sectionIndex,
const Section &section) {
auto size = QSize(section.width, height() - _st.rippleBottomSkip); auto size = QSize(section.width, height() - _st.rippleBottomSkip);
if (!_rippleTopRoundRadius || (sectionIndex > 0 && sectionIndex + 1 < getSectionsCount())) { if (!_rippleTopRoundRadius
return RippleAnimation::rectMask(size); || (sectionIndex > 0 && sectionIndex + 1 < getSectionsCount())) {
return RippleAnimation::RectMask(size);
} }
return RippleAnimation::maskByDrawer(size, false, [this, sectionIndex, width = section.width](QPainter &p) { return RippleAnimation::MaskByDrawer(size, false, [&](QPainter &p) {
auto plusRadius = _rippleTopRoundRadius + 1; auto plusRadius = _rippleTopRoundRadius + 1;
p.drawRoundedRect(0, 0, width, height() + plusRadius, _rippleTopRoundRadius, _rippleTopRoundRadius); p.drawRoundedRect(
0,
0,
section.width,
height() + plusRadius,
_rippleTopRoundRadius,
_rippleTopRoundRadius);
if (sectionIndex > 0) { if (sectionIndex > 0) {
p.fillRect(0, 0, plusRadius, plusRadius, p.brush()); p.fillRect(0, 0, plusRadius, plusRadius, p.brush());
} }
if (sectionIndex + 1 < getSectionsCount()) { if (sectionIndex + 1 < getSectionsCount()) {
p.fillRect(width - plusRadius, 0, plusRadius, plusRadius, p.brush()); p.fillRect(
section.width - plusRadius,
0,
plusRadius,
plusRadius, p.brush());
} }
}); });
} }

View file

@ -745,7 +745,7 @@ void EditorBlock::addRowRipple(int index) {
auto &row = rowAtIndex(index); auto &row = rowAtIndex(index);
auto ripple = row.ripple(); auto ripple = row.ripple();
if (!ripple) { if (!ripple) {
auto mask = Ui::RippleAnimation::rectMask(QSize(width(), row.height())); auto mask = Ui::RippleAnimation::RectMask(QSize(width(), row.height()));
ripple = row.setRipple(std::make_unique<Ui::RippleAnimation>(st::defaultRippleAnimation, std::move(mask), [this, index = findRowIndex(&row)] { ripple = row.setRipple(std::make_unique<Ui::RippleAnimation>(st::defaultRippleAnimation, std::move(mask), [this, index = findRowIndex(&row)] {
updateRow(_data[index]); updateRow(_data[index]);
})); }));

@ -1 +1 @@
Subproject commit 2c2a7887e644dff7130d764c5a7b04aaa0463056 Subproject commit 89ae115a878feb9e07fe7423fcf123397eba5966