From 2bdce7dce643962cf4a4933731831f04a21d6bf6 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 5 Apr 2019 14:13:54 +0400 Subject: [PATCH] Fix window activations handling without event loop nesting. This was causing an assertion violation in Ui::PostponeCall. - Add a generic Core::QtSignalProducer to convert Qt signals to rpl::producer. - Track event loop nesting inside QtSignalProducer. - Use QtSignalProducer for QWindow::activeChanged tracking. --- .../SourceFiles/chat_helpers/tabbed_panel.cpp | 19 +++++----- .../SourceFiles/chat_helpers/tabbed_panel.h | 1 - .../SourceFiles/core/main_queue_processor.cpp | 6 ++-- .../SourceFiles/core/media_active_cache.h | 2 +- Telegram/SourceFiles/core/sandbox.h | 17 ++++++--- .../inline_bots/inline_results_widget.cpp | 20 +++++------ .../inline_bots/inline_results_widget.h | 6 ++-- Telegram/SourceFiles/mainwindow.cpp | 9 ++++- .../media/player/media_player_panel.cpp | 35 +++++-------------- .../media/player/media_player_panel.h | 1 - .../player/media_player_volume_controller.cpp | 25 +++++++------ .../player/media_player_volume_controller.h | 4 +-- Telegram/SourceFiles/ui/rp_widget.h | 20 +++++++++++ .../SourceFiles/ui/widgets/inner_dropdown.cpp | 33 ++++++++++------- .../SourceFiles/ui/widgets/inner_dropdown.h | 4 +-- Telegram/SourceFiles/ui/widgets/tooltip.cpp | 18 +++++----- Telegram/SourceFiles/ui/widgets/tooltip.h | 8 ++--- Telegram/SourceFiles/window/main_window.cpp | 14 ++++++-- .../SourceFiles/window/window_main_menu.cpp | 33 +++-------------- Telegram/gyp/telegram_sources.txt | 1 + 20 files changed, 136 insertions(+), 140 deletions(-) diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_panel.cpp b/Telegram/SourceFiles/chat_helpers/tabbed_panel.cpp index ac3ff8b2a7..1d7b59ab96 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_panel.cpp +++ b/Telegram/SourceFiles/chat_helpers/tabbed_panel.cpp @@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/window_controller.h" #include "mainwindow.h" #include "core/application.h" +#include "core/qt_signal_producer.h" #include "styles/style_chat_helpers.h" namespace ChatHelpers { @@ -90,11 +91,13 @@ TabbedPanel::TabbedPanel( }); }, lifetime()); - if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) { - connect(App::wnd()->windowHandle(), &QWindow::activeChanged, this, [=] { - windowActiveChanged(); - }); - } + macWindowDeactivateEvents( + ) | rpl::filter([=] { + return !isHidden() && !preventAutoHide(); + }) | rpl::start_with_next([=] { + hideAnimated(); + }, lifetime()); + setAttribute(Qt::WA_OpaquePaintEvent, false); hideChildren(); @@ -146,12 +149,6 @@ void TabbedPanel::updateContentHeight() { update(); } -void TabbedPanel::windowActiveChanged() { - if (!App::wnd()->windowHandle()->isActive() && !isHidden() && !preventAutoHide()) { - hideAnimated(); - } -} - void TabbedPanel::paintEvent(QPaintEvent *e) { Painter p(this); diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_panel.h b/Telegram/SourceFiles/chat_helpers/tabbed_panel.h index e63d94564a..6f144a3a13 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_panel.h +++ b/Telegram/SourceFiles/chat_helpers/tabbed_panel.h @@ -68,7 +68,6 @@ private: return !_selector; } void showFromSelector(); - void windowActiveChanged(); style::margins innerPadding() const; diff --git a/Telegram/SourceFiles/core/main_queue_processor.cpp b/Telegram/SourceFiles/core/main_queue_processor.cpp index 013733cf1a..73e43064ab 100644 --- a/Telegram/SourceFiles/core/main_queue_processor.cpp +++ b/Telegram/SourceFiles/core/main_queue_processor.cpp @@ -58,9 +58,9 @@ MainQueueProcessor::MainQueueProcessor() { } }); crl::wrap_main_queue([](void (*callable)(void*), void *argument) { - Sandbox::Instance().registerEnterFromEventLoop(); - const auto wrap = Sandbox::Instance().createEventNestingLevel(); - callable(argument); + Sandbox::Instance().customEnterFromEventLoop([&] { + callable(argument); + }); }); base::InitObservables(ProcessObservables); diff --git a/Telegram/SourceFiles/core/media_active_cache.h b/Telegram/SourceFiles/core/media_active_cache.h index cd825566d1..a395a88570 100644 --- a/Telegram/SourceFiles/core/media_active_cache.h +++ b/Telegram/SourceFiles/core/media_active_cache.h @@ -80,4 +80,4 @@ void MediaActiveCache::check(Unload &&unload) { } } -} // namespace Images +} // namespace Core diff --git a/Telegram/SourceFiles/core/sandbox.h b/Telegram/SourceFiles/core/sandbox.h index 1873c27117..5d8d8b208c 100644 --- a/Telegram/SourceFiles/core/sandbox.h +++ b/Telegram/SourceFiles/core/sandbox.h @@ -16,6 +16,12 @@ class Application; class Sandbox final : public QApplication , private QAbstractNativeEventFilter { +private: + auto createEventNestingLevel() { + incrementEventNestingLevel(); + return gsl::finally([=] { decrementEventNestingLevel(); }); + } + public: Sandbox(not_null launcher, int &argc, char **argv); @@ -29,10 +35,12 @@ public: void postponeCall(FnMut &&callable); bool notify(QObject *receiver, QEvent *e) override; - void registerEnterFromEventLoop(); - auto createEventNestingLevel() { - incrementEventNestingLevel(); - return gsl::finally([=] { decrementEventNestingLevel(); }); + + template + auto customEnterFromEventLoop(Callable &&callable) { + registerEnterFromEventLoop(); + const auto wrap = createEventNestingLevel(); + return callable(); } void activateWindowDelayed(not_null widget); @@ -65,6 +73,7 @@ private: void closeApplication(); // will be done in aboutToQuit() void checkForQuit(); // will be done in exec() + void registerEnterFromEventLoop(); void incrementEventNestingLevel(); void decrementEventNestingLevel(); bool nativeEventFilter( diff --git a/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp b/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp index 4f8308be3b..c00b3dc6b6 100644 --- a/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp @@ -718,7 +718,10 @@ void Inner::onSwitchPm() { } // namespace internal -Widget::Widget(QWidget *parent, not_null controller) : TWidget(parent) +Widget::Widget( + QWidget *parent, + not_null controller) +: RpWidget(parent) , _controller(controller) , _contentMaxHeight(st::emojiPanMaxHeight) , _contentHeight(_contentMaxHeight) @@ -742,9 +745,12 @@ Widget::Widget(QWidget *parent, not_null controller) : TWid _inlineRequestTimer.setSingleShot(true); connect(&_inlineRequestTimer, SIGNAL(timeout()), this, SLOT(onInlineRequest())); - if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) { - connect(App::wnd()->windowHandle(), SIGNAL(activeChanged()), this, SLOT(onWndActiveChanged())); - } + macWindowDeactivateEvents( + ) | rpl::filter([=] { + return !isHidden(); + }) | rpl::start_with_next([=] { + leaveEvent(nullptr); + }, lifetime()); // Inner widget has OpaquePaintEvent attribute so it doesn't repaint on scroll. // But we should force it to repaint so that GIFs will continue to animate without update() calls. @@ -795,12 +801,6 @@ void Widget::updateContentHeight() { update(); } -void Widget::onWndActiveChanged() { - if (!App::wnd()->windowHandle()->isActive() && !isHidden()) { - leaveEvent(0); - } -} - void Widget::paintEvent(QPaintEvent *e) { Painter p(this); diff --git a/Telegram/SourceFiles/inline_bots/inline_results_widget.h b/Telegram/SourceFiles/inline_bots/inline_results_widget.h index 6ce27573f6..d58d236367 100644 --- a/Telegram/SourceFiles/inline_bots/inline_results_widget.h +++ b/Telegram/SourceFiles/inline_bots/inline_results_widget.h @@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include "ui/twidget.h" +#include "ui/rp_widget.h" #include "ui/abstract_button.h" #include "ui/effects/animations.h" #include "ui/effects/panel_animation.h" @@ -161,7 +161,7 @@ private: } // namespace internal -class Widget : public TWidget, private MTP::Sender { +class Widget : public Ui::RpWidget, private MTP::Sender { Q_OBJECT public: @@ -192,8 +192,6 @@ protected: void paintEvent(QPaintEvent *e) override; private slots: - void onWndActiveChanged(); - void onScroll(); void onInlineRequest(); diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index 17ac35cb9c..a6daee23c1 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -106,7 +106,14 @@ void MainWindow::initHook() { Platform::MainWindow::initHook(); QCoreApplication::instance()->installEventFilter(this); - connect(windowHandle(), &QWindow::activeChanged, this, [this] { checkHistoryActivation(); }, Qt::QueuedConnection); + + // Non-queued activeChanged handlers must use QtSignalProducer. + connect( + windowHandle(), + &QWindow::activeChanged, + this, + [=] { checkHistoryActivation(); }, + Qt::QueuedConnection); } void MainWindow::firstShow() { diff --git a/Telegram/SourceFiles/media/player/media_player_panel.cpp b/Telegram/SourceFiles/media/player/media_player_panel.cpp index 545b40ae51..45b3f2cd86 100644 --- a/Telegram/SourceFiles/media/player/media_player_panel.cpp +++ b/Telegram/SourceFiles/media/player/media_player_panel.cpp @@ -54,12 +54,6 @@ bool Panel::overlaps(const QRect &globalRect) { return rect().marginsRemoved(QMargins(marginLeft, contentTop(), marginRight, contentBottom())).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size())); } -void Panel::windowActiveChanged() { - if (!App::wnd()->windowHandle()->isActive() && !isHidden()) { - leaveEvent(nullptr); - } -} - void Panel::resizeEvent(QResizeEvent *e) { updateControlsGeometry(); } @@ -173,7 +167,7 @@ void Panel::enterEventHook(QEvent *e) { } else { _showTimer.callOnce(0); } - return TWidget::enterEventHook(e); + return RpWidget::enterEventHook(e); } void Panel::leaveEventHook(QEvent *e) { @@ -186,7 +180,7 @@ void Panel::leaveEventHook(QEvent *e) { } else { _hideTimer.callOnce(300); } - return TWidget::leaveEventHook(e); + return RpWidget::leaveEventHook(e); } void Panel::showFromOther() { @@ -217,15 +211,12 @@ void Panel::ensureCreated() { }); refreshList(); - if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) { - if (const auto window = App::wnd()) { - connect( - window->windowHandle(), - &QWindow::activeChanged, - this, - &Panel::windowActiveChanged); - } - } + macWindowDeactivateEvents( + ) | rpl::filter([=] { + return !isHidden(); + }) | rpl::start_with_next([=] { + leaveEvent(nullptr); + }, _refreshListLifetime); _ignoringEnterEvents = false; } @@ -306,16 +297,6 @@ void Panel::performDestroy() { _scroll->takeWidget().destroy(); _listPeer = _listMigratedPeer = nullptr; _refreshListLifetime.destroy(); - - if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) { - if (const auto window = App::wnd()) { - disconnect( - window->windowHandle(), - &QWindow::activeChanged, - this, - &Panel::windowActiveChanged); - } - } } Info::Key Panel::key() const { diff --git a/Telegram/SourceFiles/media/player/media_player_panel.h b/Telegram/SourceFiles/media/player/media_player_panel.h index 060c9ac2fd..bf03b78b1a 100644 --- a/Telegram/SourceFiles/media/player/media_player_panel.h +++ b/Telegram/SourceFiles/media/player/media_player_panel.h @@ -60,7 +60,6 @@ private: void listHeightUpdated(int newHeight); int emptyInnerHeight() const; bool contentTooSmall() const; - void windowActiveChanged(); void ensureCreated(); void performDestroy(); diff --git a/Telegram/SourceFiles/media/player/media_player_volume_controller.cpp b/Telegram/SourceFiles/media/player/media_player_volume_controller.cpp index daeaf85f63..08bbb0649a 100644 --- a/Telegram/SourceFiles/media/player/media_player_volume_controller.cpp +++ b/Telegram/SourceFiles/media/player/media_player_volume_controller.cpp @@ -19,7 +19,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Media { namespace Player { -VolumeController::VolumeController(QWidget *parent) : TWidget(parent) +VolumeController::VolumeController(QWidget *parent) +: TWidget(parent) , _slider(this, st::mediaPlayerPanelPlayback) { _slider->setMoveByWheel(true); _slider->setChangeProgressCallback([this](float64 volume) { @@ -68,7 +69,8 @@ void VolumeController::applyVolumeChange(float64 volume) { } } -VolumeWidget::VolumeWidget(QWidget *parent) : TWidget(parent) +VolumeWidget::VolumeWidget(QWidget *parent) +: RpWidget(parent) , _controller(this) { hide(); _controller->setIsVertical(true); @@ -79,9 +81,12 @@ VolumeWidget::VolumeWidget(QWidget *parent) : TWidget(parent) _showTimer.setSingleShot(true); connect(&_showTimer, SIGNAL(timeout()), this, SLOT(onShowStart())); - if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) { - connect(App::wnd()->windowHandle(), SIGNAL(activeChanged()), this, SLOT(onWindowActiveChanged())); - } + macWindowDeactivateEvents( + ) | rpl::filter([=] { + return !isHidden(); + }) | rpl::start_with_next([=] { + leaveEvent(nullptr); + }, lifetime()); hide(); auto margin = getMargin(); @@ -102,12 +107,6 @@ bool VolumeWidget::overlaps(const QRect &globalRect) { return rect().marginsRemoved(getMargin()).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size())); } -void VolumeWidget::onWindowActiveChanged() { - if (!App::wnd()->windowHandle()->isActive() && !isHidden()) { - leaveEvent(nullptr); - } -} - void VolumeWidget::resizeEvent(QResizeEvent *e) { auto inner = rect().marginsRemoved(getMargin()); _controller->setGeometry(inner.x(), inner.y() - st::lineWidth, inner.width(), inner.height() + st::lineWidth - ((st::mediaPlayerVolumeSize.width() - st::mediaPlayerPanelPlayback.width) / 2)); @@ -147,7 +146,7 @@ void VolumeWidget::enterEventHook(QEvent *e) { } else { _showTimer.start(0); } - return TWidget::enterEventHook(e); + return RpWidget::enterEventHook(e); } void VolumeWidget::leaveEventHook(QEvent *e) { @@ -157,7 +156,7 @@ void VolumeWidget::leaveEventHook(QEvent *e) { } else { _hideTimer.start(300); } - return TWidget::leaveEventHook(e); + return RpWidget::leaveEventHook(e); } void VolumeWidget::otherEnter() { diff --git a/Telegram/SourceFiles/media/player/media_player_volume_controller.h b/Telegram/SourceFiles/media/player/media_player_volume_controller.h index 7d5e761aea..5a324a4595 100644 --- a/Telegram/SourceFiles/media/player/media_player_volume_controller.h +++ b/Telegram/SourceFiles/media/player/media_player_volume_controller.h @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "ui/effects/animations.h" +#include "ui/rp_widget.h" namespace Ui { class IconButton; @@ -34,7 +35,7 @@ private: }; -class VolumeWidget : public TWidget { +class VolumeWidget : public Ui::RpWidget { Q_OBJECT public: @@ -55,7 +56,6 @@ protected: private slots: void onShowStart(); void onHideStart(); - void onWindowActiveChanged(); private: void otherEnter(); diff --git a/Telegram/SourceFiles/ui/rp_widget.h b/Telegram/SourceFiles/ui/rp_widget.h index 16d50f369d..e7f9e4939f 100644 --- a/Telegram/SourceFiles/ui/rp_widget.h +++ b/Telegram/SourceFiles/ui/rp_widget.h @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include #include "base/unique_qptr.h" +#include "core/qt_signal_producer.h" namespace Ui { namespace details { @@ -173,6 +174,25 @@ public: visibilityChangedHook(wasVisible, !this->isHidden()); } + auto windowDeactivateEvents() const { + Expects(Widget::window()->windowHandle() != nullptr); + + const auto window = Widget::window()->windowHandle(); + return Core::QtSignalProducer( + window, + &QWindow::activeChanged + ) | rpl::filter([=] { + return !window->isActive(); + }); + } + auto macWindowDeactivateEvents() const { +#ifdef Q_OS_MAC + return windowDeactivateEvents(); +#else // Q_OS_MAC + return rpl::never(); +#endif // Q_OS_MAC + } + ~RpWidgetWrap() { base::take(_lifetime); base::take(_eventStreams); diff --git a/Telegram/SourceFiles/ui/widgets/inner_dropdown.cpp b/Telegram/SourceFiles/ui/widgets/inner_dropdown.cpp index deb9a427ec..43e03d180b 100644 --- a/Telegram/SourceFiles/ui/widgets/inner_dropdown.cpp +++ b/Telegram/SourceFiles/ui/widgets/inner_dropdown.cpp @@ -22,7 +22,10 @@ constexpr int kFadeAlphaMax = 160; namespace Ui { -InnerDropdown::InnerDropdown(QWidget *parent, const style::InnerDropdown &st) : TWidget(parent) +InnerDropdown::InnerDropdown( + QWidget *parent, + const style::InnerDropdown &st) +: RpWidget(parent) , _st(st) , _scroll(this, _st.scroll) { _hideTimer.setSingleShot(true); @@ -30,11 +33,21 @@ InnerDropdown::InnerDropdown(QWidget *parent, const style::InnerDropdown &st) : connect(_scroll, SIGNAL(scrolled()), this, SLOT(onScroll())); - if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) { - connect(App::wnd()->windowHandle(), SIGNAL(activeChanged()), this, SLOT(onWindowActiveChanged())); - } - hide(); + + shownValue( + ) | rpl::filter([](bool shown) { + return shown; + }) | rpl::take(1) | rpl::map([=] { + // We can't invoke this before the window is created. + // So instead we start handling them on the first show(). + return macWindowDeactivateEvents(); + }) | rpl::flatten_latest( + ) | rpl::filter([=] { + return !isHidden(); + }) | rpl::start_with_next([=] { + leaveEvent(nullptr); + }, lifetime()); } QPointer InnerDropdown::doSetOwnedWidget(object_ptr widget) { @@ -71,12 +84,6 @@ void InnerDropdown::resizeToContent() { } } -void InnerDropdown::onWindowActiveChanged() { - if (!App::wnd()->windowHandle()->isActive() && !isHidden()) { - leaveEvent(nullptr); - } -} - void InnerDropdown::resizeEvent(QResizeEvent *e) { _scroll->setGeometry(rect().marginsRemoved(_st.padding).marginsRemoved(_st.scrollMargin)); if (auto widget = static_cast(_scroll->widget())) { @@ -124,7 +131,7 @@ void InnerDropdown::enterEventHook(QEvent *e) { if (_autoHiding) { showAnimated(_origin); } - return TWidget::enterEventHook(e); + return RpWidget::enterEventHook(e); } void InnerDropdown::leaveEventHook(QEvent *e) { @@ -135,7 +142,7 @@ void InnerDropdown::leaveEventHook(QEvent *e) { _hideTimer.start(300); } } - return TWidget::leaveEventHook(e); + return RpWidget::leaveEventHook(e); } void InnerDropdown::otherEnter() { diff --git a/Telegram/SourceFiles/ui/widgets/inner_dropdown.h b/Telegram/SourceFiles/ui/widgets/inner_dropdown.h index 49cd886d42..862ae04ebf 100644 --- a/Telegram/SourceFiles/ui/widgets/inner_dropdown.h +++ b/Telegram/SourceFiles/ui/widgets/inner_dropdown.h @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "styles/style_widgets.h" +#include "ui/rp_widget.h" #include "ui/effects/animations.h" #include "ui/effects/panel_animation.h" @@ -15,7 +16,7 @@ namespace Ui { class ScrollArea; -class InnerDropdown : public TWidget { +class InnerDropdown : public Ui::RpWidget { Q_OBJECT public: @@ -81,7 +82,6 @@ private slots: void onHideAnimated() { hideAnimated(); } - void onWindowActiveChanged(); void onScroll(); void onWidgetHeightUpdated() { resizeToContent(); diff --git a/Telegram/SourceFiles/ui/widgets/tooltip.cpp b/Telegram/SourceFiles/ui/widgets/tooltip.cpp index d9623d8015..61dd7ab1e2 100644 --- a/Telegram/SourceFiles/ui/widgets/tooltip.cpp +++ b/Telegram/SourceFiles/ui/widgets/tooltip.cpp @@ -8,8 +8,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/tooltip.h" #include "mainwindow.h" -#include "styles/style_widgets.h" #include "platform/platform_specific.h" +#include "core/qt_signal_producer.h" +#include "styles/style_widgets.h" namespace Ui { @@ -33,7 +34,7 @@ AbstractTooltipShower::~AbstractTooltipShower() { } } -Tooltip::Tooltip() : TWidget(nullptr) { +Tooltip::Tooltip() : RpWidget(nullptr) { TooltipInstance = this; setWindowFlags(Qt::WindowFlags(Qt::FramelessWindowHint) | Qt::BypassWindowManagerHint | Qt::NoDropShadowWindowHint | Qt::ToolTip); @@ -43,7 +44,10 @@ Tooltip::Tooltip() : TWidget(nullptr) { _showTimer.setCallback([=] { performShow(); }); _hideByLeaveTimer.setCallback([=] { Hide(); }); - connect(App::wnd()->windowHandle(), SIGNAL(activeChanged()), this, SLOT(onWndActiveChanged())); + App::wnd()->windowDeactivateEvents( + ) | rpl::start_with_next([=] { + Hide(); + }, lifetime()); } void Tooltip::performShow() { @@ -57,12 +61,6 @@ void Tooltip::performShow() { } } -void Tooltip::onWndActiveChanged() { - if (!App::wnd() || !App::wnd()->windowHandle() || !App::wnd()->windowHandle()->isActive()) { - Hide(); - } -} - bool Tooltip::eventFilter(QObject *o, QEvent *e) { if (e->type() == QEvent::Leave) { _hideByLeaveTimer.callOnce(10); @@ -73,7 +71,7 @@ bool Tooltip::eventFilter(QObject *o, QEvent *e) { Hide(); } } - return TWidget::eventFilter(o, e); + return RpWidget::eventFilter(o, e); } Tooltip::~Tooltip() { diff --git a/Telegram/SourceFiles/ui/widgets/tooltip.h b/Telegram/SourceFiles/ui/widgets/tooltip.h index f0f03fd7a9..be0146537a 100644 --- a/Telegram/SourceFiles/ui/widgets/tooltip.h +++ b/Telegram/SourceFiles/ui/widgets/tooltip.h @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/timer.h" #include "ui/effects/animations.h" +#include "ui/rp_widget.h" namespace style { struct Tooltip; @@ -27,16 +28,11 @@ public: }; -class Tooltip : public TWidget { - Q_OBJECT - +class Tooltip : public Ui::RpWidget { public: static void Show(int32 delay, const AbstractTooltipShower *shower); static void Hide(); -private slots: - void onWndActiveChanged(); - protected: void paintEvent(QPaintEvent *e) override; void hideEvent(QHideEvent *e) override; diff --git a/Telegram/SourceFiles/window/main_window.cpp b/Telegram/SourceFiles/window/main_window.cpp index af296e3c16..ee552f085f 100644 --- a/Telegram/SourceFiles/window/main_window.cpp +++ b/Telegram/SourceFiles/window/main_window.cpp @@ -273,8 +273,18 @@ void MainWindow::init() { initHook(); updateWindowIcon(); - connect(windowHandle(), &QWindow::activeChanged, this, [this] { handleActiveChanged(); }, Qt::QueuedConnection); - connect(windowHandle(), &QWindow::windowStateChanged, this, [this](Qt::WindowState state) { handleStateChanged(state); }); + // Non-queued activeChanged handlers must use QtSignalProducer. + connect( + windowHandle(), + &QWindow::activeChanged, + this, + [=] { handleActiveChanged(); }, + Qt::QueuedConnection); + connect( + windowHandle(), + &QWindow::windowStateChanged, + this, + [=](Qt::WindowState state) { handleStateChanged(state); }); updatePalette(); diff --git a/Telegram/SourceFiles/window/window_main_menu.cpp b/Telegram/SourceFiles/window/window_main_menu.cpp index 234ed9c4d6..779d6b8bb2 100644 --- a/Telegram/SourceFiles/window/window_main_menu.cpp +++ b/Telegram/SourceFiles/window/window_main_menu.cpp @@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "storage/localstorage.h" #include "support/support_templates.h" #include "settings/settings_common.h" +#include "core/qt_signal_producer.h" #include "boxes/about_box.h" #include "boxes/peer_list_controllers.h" #include "calls/calls_box_controller.h" @@ -33,32 +34,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_boxes.h" namespace Window { -namespace { - -template -auto qtSignalProducer( - Object *object, - void(Other::*signal)(Value)) { - using Produced = std::remove_const_t>; - const auto guarded = make_weak(object); - return rpl::make_producer([=](auto consumer) { - if (!guarded) { - return rpl::lifetime(); - } - auto listener = Ui::CreateChild(guarded.data()); - QObject::connect(guarded, signal, listener, [=](Value value) { - consumer.put_next_copy(value); - }); - const auto weak = make_weak(listener); - return rpl::lifetime([=] { - if (weak) { - delete weak; - } - }); - }); -} - -} // namespace class MainMenu::ResetScaleButton : public Ui::AbstractButton { public: @@ -311,15 +286,15 @@ void MainMenu::initResetScaleButton() { rpl::single( handle->screen() ) | rpl::then( - qtSignalProducer(handle, &QWindow::screenChanged) + Core::QtSignalProducer(handle, &QWindow::screenChanged) ) | rpl::map([](QScreen *screen) { return rpl::single( screen->availableGeometry() ) | rpl::then( #ifdef OS_MAC_OLD - qtSignalProducer(screen, &QScreen::virtualGeometryChanged) + Core::QtSignalProducer(screen, &QScreen::virtualGeometryChanged) #else // OS_MAC_OLD - qtSignalProducer(screen, &QScreen::availableGeometryChanged) + Core::QtSignalProducer(screen, &QScreen::availableGeometryChanged) #endif // OS_MAC_OLD ); }) | rpl::flatten_latest( diff --git a/Telegram/gyp/telegram_sources.txt b/Telegram/gyp/telegram_sources.txt index 0ff932daab..3f8547dcf9 100644 --- a/Telegram/gyp/telegram_sources.txt +++ b/Telegram/gyp/telegram_sources.txt @@ -146,6 +146,7 @@ <(src_loc)/core/media_active_cache.h <(src_loc)/core/mime_type.cpp <(src_loc)/core/mime_type.h +<(src_loc)/core/qt_signal_producer.h <(src_loc)/core/sandbox.cpp <(src_loc)/core/sandbox.h <(src_loc)/core/shortcuts.cpp