From 0b26475300071ca96eda000acc4e07910780b1ef Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 26 Apr 2019 13:43:57 +0400 Subject: [PATCH] Fix render glitches in passcodebox. --- .../SourceFiles/chat_helpers/tabbed_panel.cpp | 7 +++- .../SourceFiles/dialogs/dialogs_widget.cpp | 5 ++- Telegram/SourceFiles/ui/twidget.cpp | 42 ++++++++++++++----- Telegram/SourceFiles/ui/twidget.h | 9 ++++ .../SourceFiles/ui/widgets/inner_dropdown.cpp | 6 +-- .../SourceFiles/ui/widgets/popup_menu.cpp | 6 +-- Telegram/SourceFiles/ui/widgets/shadow.cpp | 2 +- 7 files changed, 56 insertions(+), 21 deletions(-) diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_panel.cpp b/Telegram/SourceFiles/chat_helpers/tabbed_panel.cpp index 1d7b59ab96..a8c56da20b 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_panel.cpp +++ b/Telegram/SourceFiles/chat_helpers/tabbed_panel.cpp @@ -304,11 +304,14 @@ QImage TabbedPanel::grabForAnimation() { showChildren(); Ui::SendPendingMoveResizeEvents(this); - auto result = QImage(size() * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied); + auto result = QImage( + size() * cIntRetinaFactor(), + QImage::Format_ARGB32_Premultiplied); result.setDevicePixelRatio(cRetinaFactor()); result.fill(Qt::transparent); if (_selector) { - _selector->render(&result, _selector->geometry().topLeft()); + QPainter p(&result); + Ui::RenderWidget(p, _selector, _selector->pos()); } _a_show = base::take(showAnimation); diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index 28544b7cdc..b56dbed24c 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -563,7 +563,10 @@ void Widget::startWidthAnimation() { QImage::Format_ARGB32_Premultiplied); image.setDevicePixelRatio(cRetinaFactor()); image.fill(Qt::transparent); - _scroll->render(&image, QPoint(0, 0), QRect(QPoint(0, 0), grabGeometry.size()), QWidget::DrawChildren | QWidget::IgnoreMask); + { + QPainter p(&image); + Ui::RenderWidget(p, _scroll); + } _widthAnimationCache = App::pixmapFromImageInPlace(std::move(image)); _scroll->setGeometry(scrollGeometry); _scroll->hide(); diff --git a/Telegram/SourceFiles/ui/twidget.cpp b/Telegram/SourceFiles/ui/twidget.cpp index 9ebe6cb229..d40813859b 100644 --- a/Telegram/SourceFiles/ui/twidget.cpp +++ b/Telegram/SourceFiles/ui/twidget.cpp @@ -187,6 +187,15 @@ void SendPendingMoveResizeEvents(not_null target) { SendPendingEventsRecursive(target, !target->isVisible()); } +void MarkDirtyOpaqueChildrenRecursive(not_null target) { + target->resize(target->size()); // Calls setDirtyOpaqueRegion(). + for (const auto child : target->children()) { + if (const auto widget = qobject_cast(child)) { + MarkDirtyOpaqueChildrenRecursive(widget); + } + } +} + QPixmap GrabWidget(not_null target, QRect rect, QColor bg) { SendPendingMoveResizeEvents(target); if (rect.isNull()) { @@ -198,16 +207,15 @@ QPixmap GrabWidget(not_null target, QRect rect, QColor bg) { if (!target->testAttribute(Qt::WA_OpaquePaintEvent)) { result.fill(bg); } - target->render( - &result, - QPoint(0, 0), - rect, - QWidget::DrawChildren | QWidget::IgnoreMask); + { + QPainter p(&result); + RenderWidget(p, target, QPoint(), rect); + } return result; } QImage GrabWidgetToImage(not_null target, QRect rect, QColor bg) { - Ui::SendPendingMoveResizeEvents(target); + SendPendingMoveResizeEvents(target); if (rect.isNull()) { rect = target->rect(); } @@ -219,14 +227,26 @@ QImage GrabWidgetToImage(not_null target, QRect rect, QColor bg) { if (!target->testAttribute(Qt::WA_OpaquePaintEvent)) { result.fill(bg); } - target->render( - &result, - QPoint(0, 0), - rect, - QWidget::DrawChildren | QWidget::IgnoreMask); + { + QPainter p(&result); + RenderWidget(p, target, QPoint(), rect); + } return result; } +void RenderWidget( + QPainter &painter, + not_null source, + const QPoint &targetOffset, + const QRegion &sourceRegion, + QWidget::RenderFlags renderFlags) { + const auto visible = source->isVisible(); + source->render(&painter, targetOffset, sourceRegion, renderFlags); + if (!visible) { + MarkDirtyOpaqueChildrenRecursive(source); + } +} + void ForceFullRepaint(not_null widget) { const auto refresher = std::make_unique(widget); refresher->setGeometry(widget->rect()); diff --git a/Telegram/SourceFiles/ui/twidget.h b/Telegram/SourceFiles/ui/twidget.h index ef79a5fd88..6202dc7cc1 100644 --- a/Telegram/SourceFiles/ui/twidget.h +++ b/Telegram/SourceFiles/ui/twidget.h @@ -57,6 +57,15 @@ QImage GrabWidgetToImage( QRect rect = QRect(), QColor bg = QColor(255, 255, 255, 0)); +void RenderWidget( + QPainter &painter, + not_null source, + const QPoint &targetOffset = QPoint(), + const QRegion &sourceRegion = QRegion(), + QWidget::RenderFlags renderFlags + = QWidget::DrawChildren | QWidget::IgnoreMask); + + void ForceFullRepaint(not_null widget); void PostponeCall(FnMut &&callable); diff --git a/Telegram/SourceFiles/ui/widgets/inner_dropdown.cpp b/Telegram/SourceFiles/ui/widgets/inner_dropdown.cpp index 43e03d180b..652e4243cb 100644 --- a/Telegram/SourceFiles/ui/widgets/inner_dropdown.cpp +++ b/Telegram/SourceFiles/ui/widgets/inner_dropdown.cpp @@ -304,9 +304,9 @@ QImage InnerDropdown::grabForPanelAnimation() { { Painter p(&result); App::roundRect(p, rect().marginsRemoved(_st.padding), _st.bg, ImageRoundRadius::Small); - for (auto child : children()) { - if (auto widget = qobject_cast(child)) { - widget->render(&p, widget->pos(), widget->rect(), QWidget::DrawChildren | QWidget::IgnoreMask); + for (const auto child : children()) { + if (const auto widget = qobject_cast(child)) { + RenderWidget(p, widget, widget->pos()); } } } diff --git a/Telegram/SourceFiles/ui/widgets/popup_menu.cpp b/Telegram/SourceFiles/ui/widgets/popup_menu.cpp index ab9b724688..207653f72f 100644 --- a/Telegram/SourceFiles/ui/widgets/popup_menu.cpp +++ b/Telegram/SourceFiles/ui/widgets/popup_menu.cpp @@ -412,9 +412,9 @@ QImage PopupMenu::grabForPanelAnimation() { } else { p.fillRect(_inner, _st.menu.itemBg); } - for (auto child : children()) { - if (auto widget = qobject_cast(child)) { - widget->render(&p, widget->pos(), widget->rect(), QWidget::DrawChildren | QWidget::IgnoreMask); + for (const auto child : children()) { + if (const auto widget = qobject_cast(child)) { + RenderWidget(p, widget, widget->pos()); } } } diff --git a/Telegram/SourceFiles/ui/widgets/shadow.cpp b/Telegram/SourceFiles/ui/widgets/shadow.cpp index f8f1d8f993..b9d908dd0b 100644 --- a/Telegram/SourceFiles/ui/widgets/shadow.cpp +++ b/Telegram/SourceFiles/ui/widgets/shadow.cpp @@ -95,7 +95,7 @@ QPixmap Shadow::grab( { Painter p(&result); Ui::Shadow::paint(p, full.marginsRemoved(extend), full.width(), shadow); - target->render(&p, QPoint(extend.left(), extend.top()), rect, QWidget::DrawChildren | QWidget::IgnoreMask); + RenderWidget(p, target, QPoint(extend.left(), extend.top())); } return result; }