From 370971433927685f43076ee21c3c6896301e9e64 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 27 May 2021 09:34:33 +0400 Subject: [PATCH] Make '[un]registerLeaveSubscription' work in all windows. --- .../calls/group/calls_group_panel.cpp | 17 ++++++- Telegram/SourceFiles/core/application.cpp | 50 +++++++++++++------ Telegram/SourceFiles/core/application.h | 14 ++---- .../ui/controls/call_mute_button.cpp | 4 ++ .../ui/controls/call_mute_button.h | 1 + 5 files changed, 60 insertions(+), 26 deletions(-) diff --git a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp index e822089d34..5ba925bd21 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp @@ -1948,11 +1948,26 @@ void Panel::setupControlsBackgroundWide() { template void Panel::trackControl(WidgetPointer &widget, rpl::lifetime &lifetime) { if (widget) { - widget->events( + const auto raw = &*widget; + raw->events( ) | rpl::start_with_next([=](not_null e) { + using Type = std::remove_cvref_t; + constexpr auto mute = std::is_same_v; if (e->type() == QEvent::Enter) { + auto &integration = Ui::Integration::Instance(); + if constexpr (mute) { + integration.registerLeaveSubscription(raw->outer()); + } else { + integration.registerLeaveSubscription(raw); + } toggleWideControls(true); } else if (e->type() == QEvent::Leave) { + auto &integration = Ui::Integration::Instance(); + if constexpr (mute) { + integration.unregisterLeaveSubscription(raw->outer()); + } else { + integration.unregisterLeaveSubscription(raw); + } toggleWideControls(false); } }, lifetime); diff --git a/Telegram/SourceFiles/core/application.cpp b/Telegram/SourceFiles/core/application.cpp index e35b78cbb2..7415ec8174 100644 --- a/Telegram/SourceFiles/core/application.cpp +++ b/Telegram/SourceFiles/core/application.cpp @@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_session.h" #include "data/data_user.h" #include "base/timer.h" +#include "base/event_filter.h" #include "base/concurrent_timer.h" #include "base/qt_signal_producer.h" #include "base/unixtime.h" @@ -997,30 +998,49 @@ QPoint Application::getPointForCallPanelCenter() const { // macOS Qt bug workaround, sometimes no leaveEvent() gets to the nested widgets. void Application::registerLeaveSubscription(not_null widget) { #ifdef Q_OS_MAC - if (const auto topLevel = widget->window()) { - if (topLevel == _window->widget()) { - auto weak = Ui::MakeWeak(widget); - auto subscription = _window->widget()->leaveEvents( - ) | rpl::start_with_next([weak] { - if (const auto window = weak.data()) { - QEvent ev(QEvent::Leave); - QGuiApplication::sendEvent(window, &ev); + if (const auto window = widget->window()) { + auto i = _leaveFilters.find(window); + if (i == end(_leaveFilters)) { + const auto check = [=](not_null e) { + if (e->type() == QEvent::Leave) { + if (const auto taken = _leaveFilters.take(window)) { + for (const auto weak : taken->registered) { + if (const auto widget = weak.data()) { + QEvent ev(QEvent::Leave); + QCoreApplication::sendEvent(widget, &ev); + } + } + delete taken->filter.data(); + } } + return base::EventFilterResult::Continue; + }; + const auto filter = base::install_event_filter(window, check); + QObject::connect(filter, &QObject::destroyed, [=] { + _leaveFilters.remove(window); }); - _leaveSubscriptions.emplace_back(weak, std::move(subscription)); + i = _leaveFilters.emplace( + window, + LeaveFilter{ .filter = filter.get() }).first; } + i->second.registered.push_back(widget.get()); } #endif // Q_OS_MAC } void Application::unregisterLeaveSubscription(not_null widget) { #ifdef Q_OS_MAC - _leaveSubscriptions = std::move( - _leaveSubscriptions - ) | ranges::actions::remove_if([&](const LeaveSubscription &subscription) { - auto pointer = subscription.pointer.data(); - return !pointer || (pointer == widget); - }); + if (const auto topLevel = widget->window()) { + const auto i = _leaveFilters.find(topLevel); + if (i != end(_leaveFilters)) { + i->second.registered = std::move( + i->second.registered + ) | ranges::actions::remove_if([&](QPointer widget) { + const auto pointer = widget.data(); + return !pointer || (pointer == widget); + }); + } + } #endif // Q_OS_MAC } diff --git a/Telegram/SourceFiles/core/application.h b/Telegram/SourceFiles/core/application.h index eb0dc9ef2c..586c27ad08 100644 --- a/Telegram/SourceFiles/core/application.h +++ b/Telegram/SourceFiles/core/application.h @@ -369,17 +369,11 @@ private: std::optional _saveSettingsTimer; - struct LeaveSubscription { - LeaveSubscription( - QPointer pointer, - rpl::lifetime &&subscription) - : pointer(pointer), subscription(std::move(subscription)) { - } - - QPointer pointer; - rpl::lifetime subscription; + struct LeaveFilter { + std::vector> registered; + QPointer filter; }; - std::vector _leaveSubscriptions; + base::flat_map, LeaveFilter> _leaveFilters; rpl::lifetime _lifetime; diff --git a/Telegram/SourceFiles/ui/controls/call_mute_button.cpp b/Telegram/SourceFiles/ui/controls/call_mute_button.cpp index db83849fc1..98b7e4a502 100644 --- a/Telegram/SourceFiles/ui/controls/call_mute_button.cpp +++ b/Telegram/SourceFiles/ui/controls/call_mute_button.cpp @@ -1140,6 +1140,10 @@ rpl::producer CallMuteButton::colorOverrides() const { return _colorOverrides.events(); } +not_null CallMuteButton::outer() const { + return _content.get(); +} + rpl::lifetime &CallMuteButton::lifetime() { return _blobs->lifetime(); } diff --git a/Telegram/SourceFiles/ui/controls/call_mute_button.h b/Telegram/SourceFiles/ui/controls/call_mute_button.h index 8e261aa3f5..044ce907cd 100644 --- a/Telegram/SourceFiles/ui/controls/call_mute_button.h +++ b/Telegram/SourceFiles/ui/controls/call_mute_button.h @@ -81,6 +81,7 @@ public: void raise(); void lower(); + [[nodiscard]] not_null outer() const; [[nodiscard]] rpl::producer colorOverrides() const; [[nodiscard]] rpl::lifetime &lifetime();