From ef64d9c188c1fbd30cf2e1a61480dba26b1417e6 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 5 Nov 2018 17:18:54 +0400 Subject: [PATCH] Show round videos in Info layer. --- .../SourceFiles/info/info_layer_widget.cpp | 36 ++++++++ Telegram/SourceFiles/info/info_layer_widget.h | 17 +++- Telegram/SourceFiles/mainwidget.cpp | 49 ++++++----- Telegram/SourceFiles/mainwidget.h | 4 +- .../media/player/media_player_float.cpp | 69 +++++++++++++-- .../media/player/media_player_float.h | 85 +++++++++++++++++-- .../SourceFiles/window/window_controller.cpp | 34 ++++++++ .../SourceFiles/window/window_controller.h | 13 +++ 8 files changed, 267 insertions(+), 40 deletions(-) diff --git a/Telegram/SourceFiles/info/info_layer_widget.cpp b/Telegram/SourceFiles/info/info_layer_widget.cpp index 87aaa48fb..0ab65d2d8 100644 --- a/Telegram/SourceFiles/info/info_layer_widget.cpp +++ b/Telegram/SourceFiles/info/info_layer_widget.cpp @@ -29,6 +29,7 @@ LayerWidget::LayerWidget( : _controller(controller) , _content(this, controller, Wrap::Layer, memento) { setupHeightConsumers(); + _controller->replaceFloatPlayerDelegate(floatPlayerDelegate()); } LayerWidget::LayerWidget( @@ -37,6 +38,35 @@ LayerWidget::LayerWidget( : _controller(controller) , _content(memento->takeContent(this, Wrap::Layer)) { setupHeightConsumers(); + _controller->replaceFloatPlayerDelegate(floatPlayerDelegate()); +} + +auto LayerWidget::floatPlayerDelegate() +-> not_null<::Media::Player::FloatDelegate*> { + return static_cast<::Media::Player::FloatDelegate*>(this); +} + +not_null LayerWidget::floatPlayerWidget() { + return this; +} + +not_null LayerWidget::floatPlayerController() { + return _controller; +} + +not_null LayerWidget::floatPlayerGetSection( + Window::Column column) { + return _content; +} + +void LayerWidget::floatPlayerEnumerateSections(Fn widget, + Window::Column widgetColumn)> callback) { + callback(_content, Window::Column::Second); +} + +bool LayerWidget::floatPlayerIsVisible(not_null item) { + return false; } void LayerWidget::setupHeightConsumers() { @@ -56,6 +86,7 @@ void LayerWidget::setupHeightConsumers() { } void LayerWidget::showFinished() { + floatPlayerShowVisible(); } void LayerWidget::parentResized() { @@ -189,6 +220,7 @@ int LayerWidget::resizeGetHeight(int newWidth) { move(newGeometry.topLeft()); } + floatPlayerUpdatePositions(); return desiredHeight; } @@ -221,4 +253,8 @@ void LayerWidget::paintEvent(QPaintEvent *e) { } } +LayerWidget::~LayerWidget() { + _controller->restoreFloatPlayerDelegate(floatPlayerDelegate()); +} + } // namespace Info diff --git a/Telegram/SourceFiles/info/info_layer_widget.h b/Telegram/SourceFiles/info/info_layer_widget.h index 58cf63f62..ff67fd4c3 100644 --- a/Telegram/SourceFiles/info/info_layer_widget.h +++ b/Telegram/SourceFiles/info/info_layer_widget.h @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "window/layer_widget.h" +#include "media/player/media_player_float.h" namespace Window { class Controller; @@ -20,7 +21,9 @@ class MoveMemento; class WrapWidget; class TopBar; -class LayerWidget : public Window::LayerWidget { +class LayerWidget + : public Window::LayerWidget + , private ::Media::Player::FloatDelegate { public: LayerWidget( not_null controller, @@ -41,6 +44,8 @@ public: static int MinimalSupportedWidth(); + ~LayerWidget(); + protected: int resizeGetHeight(int newWidth) override; void doSetInnerFocus() override; @@ -48,6 +53,16 @@ protected: void paintEvent(QPaintEvent *e) override; private: + not_null<::Media::Player::FloatDelegate*> floatPlayerDelegate(); + not_null floatPlayerWidget() override; + not_null floatPlayerController() override; + not_null floatPlayerGetSection( + Window::Column column) override; + void floatPlayerEnumerateSections(Fn widget, + Window::Column widgetColumn)> callback) override; + bool floatPlayerIsVisible(not_null item) override; + void setupHeightConsumers(); not_null _controller; diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index dbece8c09..bd082b287 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -228,11 +228,16 @@ MainWidget::MainWidget( this, _controller, Media::Player::Panel::Layout::OnlyPlaylist) -, _playerPanel(this, _controller, Media::Player::Panel::Layout::Full) -, _playerFloats(floatPlayerDelegate()) { +, _playerPanel(this, _controller, Media::Player::Panel::Layout::Full) { Messenger::Instance().mtp()->setUpdatesHandler(rpcDone(&MainWidget::updateReceived)); Messenger::Instance().mtp()->setGlobalFailHandler(rpcFail(&MainWidget::updateFail)); + _controller->setDefaultFloatPlayerDelegate(floatPlayerDelegate()); + _controller->floatPlayerClosed( + ) | rpl::start_with_next([=](FullMsgId itemId) { + floatPlayerClosed(itemId); + }, lifetime()); + _ptsWaiter.setRequesting(true); updateScrollColors(); setupConnectingWidget(); @@ -435,7 +440,13 @@ void MainWidget::floatPlayerEnumerateSections(Fn item) { + auto isVisible = false; + Auth().data().queryItemVisibility().notify({ item, &isVisible }, true); + return isVisible; +} + +void MainWidget::floatPlayerClosed(FullMsgId itemId) { if (_player) { const auto voiceData = Media::Player::instance()->current( AudioMsgId::Type::Voice); @@ -649,7 +660,7 @@ void MainWidget::noHider(HistoryHider *destroyed) { } else { _history->showAnimated(Window::SlideDirection::FromRight, animationParams); } - _playerFloats.checkVisibility(); + floatPlayerCheckVisibility(); } } else { if (_forwardConfirm) { @@ -688,7 +699,7 @@ void MainWidget::hiderLayer(object_ptr h) { updateControlsGeometry(); _dialogs->activate(); } - _playerFloats.checkVisibility(); + floatPlayerCheckVisibility(); } void MainWidget::showForwardLayer(MessageIdsList &&items) { @@ -1820,7 +1831,7 @@ void MainWidget::ui_showPeerHistory( _dialogs->update(); } - _playerFloats.checkVisibility(); + floatPlayerCheckVisibility(); } PeerData *MainWidget::ui_getPeerForMouseAction() { @@ -1905,10 +1916,10 @@ Window::SectionSlideParams MainWidget::prepareThirdSectionAnimation(Window::Sect if (!_thirdSection->hasTopBarShadow()) { result.withTopBarShadow = false; } - _playerFloats.hideAll(); + floatPlayerHideAll(); auto sectionTop = getThirdSectionTop(); result.oldContentCache = _thirdSection->grabForShowAnimation(result); - _playerFloats.showVisible(); + floatPlayerShowVisible(); return result; } @@ -1926,7 +1937,7 @@ Window::SectionSlideParams MainWidget::prepareShowAnimation( result.withTopBarShadow = false; } - _playerFloats.hideAll(); + floatPlayerHideAll(); if (_player) { _player->hideShadow(); } @@ -1974,7 +1985,7 @@ Window::SectionSlideParams MainWidget::prepareShowAnimation( if (_player) { _player->showShadow(); } - _playerFloats.showVisible(); + floatPlayerShowVisible(); return result; } @@ -2116,7 +2127,7 @@ void MainWidget::showNewSection( } } - _playerFloats.checkVisibility(); + floatPlayerCheckVisibility(); orderWidgets(); } @@ -2223,7 +2234,7 @@ void MainWidget::orderWidgets() { _connecting->raise(); _playerPlaylist->raise(); _playerPanel->raise(); - _playerFloats.raiseAll(); + floatPlayerRaiseAll(); if (_hider) _hider->raise(); } @@ -2236,7 +2247,7 @@ QRect MainWidget::historyRect() const { QPixmap MainWidget::grabForShowAnimation(const Window::SectionSlideParams ¶ms) { QPixmap result; - _playerFloats.hideAll(); + floatPlayerHideAll(); if (_player) { _player->hideShadow(); } @@ -2287,7 +2298,7 @@ QPixmap MainWidget::grabForShowAnimation(const Window::SectionSlideParams ¶m if (_player) { _player->showShadow(); } - _playerFloats.showVisible(); + floatPlayerShowVisible(); return result; } @@ -2424,7 +2435,7 @@ void MainWidget::hideAll() { _player->setVisible(false); _playerHeight = 0; } - _playerFloats.hideAll(); + floatPlayerHideAll(); } void MainWidget::showAll() { @@ -2497,8 +2508,8 @@ void MainWidget::showAll() { _playerHeight = _player->contentHeight(); } updateControlsGeometry(); - _playerFloats.checkVisibility(); - _playerFloats.showVisible(); + floatPlayerCheckVisibility(); + floatPlayerShowVisible(); App::wnd()->checkHistoryActivation(); } @@ -2609,7 +2620,7 @@ void MainWidget::updateControlsGeometry() { updateMediaPlaylistPosition(_playerPlaylist->x()); _contentScrollAddToY = 0; - _playerFloats.updatePositions(); + floatPlayerUpdatePositions(); } void MainWidget::refreshResizeAreas() { @@ -2852,7 +2863,7 @@ bool MainWidget::eventFilter(QObject *o, QEvent *e) { return true; } } else if (e->type() == QEvent::Wheel) { - if (const auto result = _playerFloats.filterWheelEvent(o, e)) { + if (const auto result = floatPlayerFilterWheelEvent(o, e)) { return *result; } } diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 238c649e5..0a8f90acd 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -470,7 +470,8 @@ private: void floatPlayerEnumerateSections(Fn widget, Window::Column widgetColumn)> callback) override; - void floatPlayerCloseHook(FullMsgId itemId) override; + bool floatPlayerIsVisible(not_null item) override; + void floatPlayerClosed(FullMsgId itemId); bool getDifferenceTimeChanged(ChannelData *channel, int32 ms, ChannelGetDifferenceTime &channelCurTime, TimeMs &curTime); @@ -523,7 +524,6 @@ private: object_ptr _playerPlaylist; object_ptr _playerPanel; bool _playerUsingPanel = false; - Media::Player::FloatController _playerFloats; QPointer _forwardConfirm; // for single column layout object_ptr _hider = { nullptr }; diff --git a/Telegram/SourceFiles/media/player/media_player_float.cpp b/Telegram/SourceFiles/media/player/media_player_float.cpp index 5e260b583..e8eb4375b 100644 --- a/Telegram/SourceFiles/media/player/media_player_float.cpp +++ b/Telegram/SourceFiles/media/player/media_player_float.cpp @@ -305,6 +305,58 @@ FloatController::FloatController(not_null delegate) checkCurrent(); } }); + + startDelegateHandling(); +} + +void FloatController::replaceDelegate(not_null delegate) { + _delegateLifetime.destroy(); + + _delegate = delegate; + _parent = _delegate->floatPlayerWidget(); + + // Currently moving floats between windows is not supported. + Assert(_controller == _delegate->floatPlayerController()); + + startDelegateHandling(); + + for (const auto &item : _items) { + item->widget->setParent(_parent); + } + checkVisibility(); +} + +void FloatController::startDelegateHandling() { + _delegate->floatPlayerCheckVisibilityRequests( + ) | rpl::start_with_next([=] { + checkVisibility(); + }, _delegateLifetime); + + _delegate->floatPlayerHideAllRequests( + ) | rpl::start_with_next([=] { + hideAll(); + }, _delegateLifetime); + + _delegate->floatPlayerShowVisibleRequests( + ) | rpl::start_with_next([=] { + showVisible(); + }, _delegateLifetime); + + _delegate->floatPlayerRaiseAllRequests( + ) | rpl::start_with_next([=] { + raiseAll(); + }, _delegateLifetime); + + _delegate->floatPlayerUpdatePositionsRequests( + ) | rpl::start_with_next([=] { + updatePositions(); + }, _delegateLifetime); + + _delegate->floatPlayerFilterWheelEventRequests( + ) | rpl::start_with_next([=]( + const FloatDelegate::FloatPlayerFilterWheelEventRequest &request) { + *request.result = filterWheelEvent(request.object, request.event); + }, _delegateLifetime); } void FloatController::checkCurrent() { @@ -364,16 +416,15 @@ void FloatController::toggle(not_null instance) { } void FloatController::checkVisibility() { - auto instance = current(); + const auto instance = current(); if (!instance) { return; } - auto amVisible = false; - if (auto item = instance->widget->item()) { - Auth().data().queryItemVisibility().notify({ item, &amVisible }, true); - } - instance->hiddenByHistory = amVisible; + const auto item = instance->widget->item(); + instance->hiddenByHistory = item + ? _delegate->floatPlayerIsVisible(item) + : false; toggle(instance); updatePosition(instance); } @@ -405,8 +456,8 @@ void FloatController::updatePositions() { } std::optional FloatController::filterWheelEvent( - QObject *object, - QEvent *event) { + not_null object, + not_null event) { for (const auto &instance : _items) { if (instance->widget == object) { const auto section = _delegate->floatPlayerGetSection( @@ -575,7 +626,7 @@ void FloatController::finishDrag(not_null instance, bool closed) { if (closed) { if (const auto item = instance->widget->item()) { - _delegate->floatPlayerCloseHook(item->fullId()); + _closeEvents.fire(item->fullId()); } instance->widget->detach(); } diff --git a/Telegram/SourceFiles/media/player/media_player_float.h b/Telegram/SourceFiles/media/player/media_player_float.h index e3fd94ab3..67973caf9 100644 --- a/Telegram/SourceFiles/media/player/media_player_float.h +++ b/Telegram/SourceFiles/media/player/media_player_float.h @@ -104,7 +104,65 @@ public: virtual void floatPlayerEnumerateSections(Fn widget, Window::Column widgetColumn)> callback) = 0; - virtual void floatPlayerCloseHook(FullMsgId itemId) = 0; + virtual bool floatPlayerIsVisible(not_null item) = 0; + + virtual rpl::producer<> floatPlayerCheckVisibilityRequests() { + return _checkVisibility.events(); + } + virtual rpl::producer<> floatPlayerHideAllRequests() { + return _hideAll.events(); + } + virtual rpl::producer<> floatPlayerShowVisibleRequests() { + return _showVisible.events(); + } + virtual rpl::producer<> floatPlayerRaiseAllRequests() { + return _raiseAll.events(); + } + virtual rpl::producer<> floatPlayerUpdatePositionsRequests() { + return _updatePositions.events();; + } + + struct FloatPlayerFilterWheelEventRequest { + not_null object; + not_null event; + not_null*> result; + }; + virtual auto floatPlayerFilterWheelEventRequests() + -> rpl::producer { + return _filterWheelEvent.events(); + } + +protected: + void floatPlayerCheckVisibility() { + _checkVisibility.fire({}); + } + void floatPlayerHideAll() { + _hideAll.fire({}); + } + void floatPlayerShowVisible() { + _showVisible.fire({}); + } + void floatPlayerRaiseAll() { + _raiseAll.fire({}); + } + void floatPlayerUpdatePositions() { + _updatePositions.fire({}); + } + std::optional floatPlayerFilterWheelEvent( + not_null object, + not_null event) { + auto result = std::optional(); + _filterWheelEvent.fire({ object, event, &result }); + return result; + } + +private: + rpl::event_stream<> _checkVisibility; + rpl::event_stream<> _hideAll; + rpl::event_stream<> _showVisible; + rpl::event_stream<> _raiseAll; + rpl::event_stream<> _updatePositions; + rpl::event_stream _filterWheelEvent; }; @@ -112,14 +170,10 @@ class FloatController : private base::Subscriber { public: explicit FloatController(not_null delegate); - void checkVisibility(); - void hideAll(); - void showVisible(); - void raiseAll(); - void updatePositions(); - std::optional filterWheelEvent( - QObject *object, - QEvent *event); + void replaceDelegate(not_null delegate); + rpl::producer closeEvents() const { + return _closeEvents.events(); + } private: struct Item { @@ -163,11 +217,24 @@ private: RectPart side) const; RectPart getSide(QPoint center) const; + void startDelegateHandling(); + void checkVisibility(); + void hideAll(); + void showVisible(); + void raiseAll(); + void updatePositions(); + std::optional filterWheelEvent( + not_null object, + not_null event); + not_null _delegate; not_null _parent; not_null _controller; std::vector> _items; + rpl::event_stream _closeEvents; + rpl::lifetime _delegateLifetime; + }; } // namespace Player diff --git a/Telegram/SourceFiles/window/window_controller.cpp b/Telegram/SourceFiles/window/window_controller.cpp index 5fc85d296..f142e7ce1 100644 --- a/Telegram/SourceFiles/window/window_controller.cpp +++ b/Telegram/SourceFiles/window/window_controller.cpp @@ -551,6 +551,40 @@ void Controller::roundVideoFinished(not_null video) { } } +void Controller::setDefaultFloatPlayerDelegate( + not_null delegate) { + Expects(_defaultFloatPlayerDelegate == nullptr); + + _defaultFloatPlayerDelegate = delegate; + _floatPlayers = std::make_unique( + delegate); + _floatPlayers->closeEvents(); +} + +void Controller::replaceFloatPlayerDelegate( + not_null replacement) { + Expects(_floatPlayers != nullptr); + + _replacementFloatPlayerDelegate = replacement; + _floatPlayers->replaceDelegate(replacement); +} + +void Controller::restoreFloatPlayerDelegate( + not_null replacement) { + Expects(_floatPlayers != nullptr); + + if (_replacementFloatPlayerDelegate == replacement) { + _replacementFloatPlayerDelegate = nullptr; + _floatPlayers->replaceDelegate(_defaultFloatPlayerDelegate); + } +} + +rpl::producer Controller::floatPlayerClosed() const { + Expects(_floatPlayers != nullptr); + + return _floatPlayers->closeEvents(); +} + Controller::~Controller() = default; } // namespace Window diff --git a/Telegram/SourceFiles/window/window_controller.h b/Telegram/SourceFiles/window/window_controller.h index 54935a203..e71496ce3 100644 --- a/Telegram/SourceFiles/window/window_controller.h +++ b/Telegram/SourceFiles/window/window_controller.h @@ -22,6 +22,8 @@ enum class Type; namespace Media { namespace Player { class RoundController; +class FloatController; +class FloatDelegate; } // namespace Player } // namespace Media @@ -242,6 +244,14 @@ public: RoundController *roundVideo(FullMsgId contextId) const; void roundVideoFinished(not_null video); + void setDefaultFloatPlayerDelegate( + not_null delegate); + void replaceFloatPlayerDelegate( + not_null replacement); + void restoreFloatPlayerDelegate( + not_null replacement); + rpl::producer floatPlayerClosed() const; + rpl::lifetime &lifetime() { return _lifetime; } @@ -275,6 +285,9 @@ private: base::Variable _dialogsListDisplayForced = { false }; std::unique_ptr _roundVideo; + std::unique_ptr _floatPlayers; + Media::Player::FloatDelegate *_defaultFloatPlayerDelegate = nullptr; + Media::Player::FloatDelegate *_replacementFloatPlayerDelegate = nullptr; rpl::lifetime _lifetime;