1 /* 2 This file is part of Telegram Desktop, 3 the official desktop application for the Telegram messaging service. 4 5 For license and copyright information please follow this link: 6 https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL 7 */ 8 #pragma once 9 10 #include "ui/rp_widget.h" 11 #include "ui/effects/animations.h" 12 13 namespace Ui { 14 class AbstractButton; 15 class RpWidgetWrap; 16 namespace GL { 17 enum class Backend; 18 struct Capabilities; 19 struct ChosenRenderer; 20 } // namespace GL 21 } // namespace Ui 22 23 namespace Calls { 24 class GroupCall; 25 struct VideoEndpoint; 26 struct VideoQualityRequest; 27 } // namespace Calls 28 29 namespace Webrtc { 30 class VideoTrack; 31 } // namespace Webrtc 32 33 namespace Calls::Group { 34 35 class MembersRow; 36 enum class PanelMode; 37 enum class VideoQuality; 38 39 struct VideoTileTrack { 40 Webrtc::VideoTrack *track = nullptr; 41 MembersRow *row = nullptr; 42 rpl::variable<QSize> trackSize; 43 44 [[nodiscard]] explicit operator bool() const { 45 return track != nullptr; 46 } 47 }; 48 49 [[nodiscard]] inline bool operator==( 50 VideoTileTrack a, 51 VideoTileTrack b) noexcept { 52 return (a.track == b.track) && (a.row == b.row); 53 } 54 55 [[nodiscard]] inline bool operator!=( 56 VideoTileTrack a, 57 VideoTileTrack b) noexcept { 58 return !(a == b); 59 } 60 61 class Viewport final { 62 public: 63 Viewport( 64 not_null<QWidget*> parent, 65 PanelMode mode, 66 Ui::GL::Backend backend); 67 ~Viewport(); 68 69 [[nodiscard]] not_null<QWidget*> widget() const; 70 [[nodiscard]] not_null<Ui::RpWidgetWrap*> rp() const; 71 72 void setMode(PanelMode mode, not_null<QWidget*> parent); 73 void setControlsShown(float64 shown); 74 void setGeometry(QRect geometry); 75 void resizeToWidth(int newWidth); 76 void setScrollTop(int scrollTop); 77 78 void add( 79 const VideoEndpoint &endpoint, 80 VideoTileTrack track, 81 rpl::producer<QSize> trackSize, 82 rpl::producer<bool> pinned); 83 void remove(const VideoEndpoint &endpoint); 84 void showLarge(const VideoEndpoint &endpoint); 85 86 [[nodiscard]] bool requireARGB32() const; 87 [[nodiscard]] int fullHeight() const; 88 [[nodiscard]] rpl::producer<int> fullHeightValue() const; 89 [[nodiscard]] rpl::producer<bool> pinToggled() const; 90 [[nodiscard]] rpl::producer<VideoEndpoint> clicks() const; 91 [[nodiscard]] rpl::producer<VideoQualityRequest> qualityRequests() const; 92 [[nodiscard]] rpl::producer<bool> mouseInsideValue() const; 93 94 [[nodiscard]] rpl::lifetime &lifetime(); 95 96 static constexpr auto kShadowMaxAlpha = 80; 97 98 private: 99 struct Textures; 100 class VideoTile; 101 class RendererSW; 102 class RendererGL; 103 using TileId = quintptr; 104 105 struct Geometry { 106 VideoTile *tile = nullptr; 107 QSize size; 108 QRect rows; 109 QRect columns; 110 }; 111 112 struct Layout { 113 std::vector<Geometry> list; 114 QSize outer; 115 bool useColumns = false; 116 }; 117 118 struct TileAnimation { 119 QSize from; 120 QSize to; 121 float64 ratio = -1.; 122 }; 123 124 struct Selection { 125 enum class Element { 126 None, 127 Tile, 128 PinButton, 129 BackButton, 130 }; 131 VideoTile *tile = nullptr; 132 Element element = Element::None; 133 134 inline bool operator==(Selection other) const { 135 return (tile == other.tile) && (element == other.element); 136 } 137 }; 138 139 void setup(); 140 [[nodiscard]] bool wide() const; 141 142 void updateCursor(); 143 void updateTilesGeometry(); 144 void updateTilesGeometry(int outerWidth); 145 void updateTilesGeometryWide(int outerWidth, int outerHeight); 146 void updateTilesGeometryNarrow(int outerWidth); 147 void updateTilesGeometryColumn(int outerWidth); 148 void setTileGeometry(not_null<VideoTile*> tile, QRect geometry); 149 void refreshHasTwoOrMore(); 150 void updateTopControlsVisibility(); 151 152 void prepareLargeChangeAnimation(); 153 void startLargeChangeAnimation(); 154 void updateTilesAnimated(); 155 [[nodiscard]] Layout countWide(int outerWidth, int outerHeight) const; 156 [[nodiscard]] Layout applyLarge(Layout layout) const; 157 158 void setSelected(Selection value); 159 void setPressed(Selection value); 160 161 void handleMousePress(QPoint position, Qt::MouseButton button); 162 void handleMouseRelease(QPoint position, Qt::MouseButton button); 163 void handleMouseMove(QPoint position); 164 void updateSelected(QPoint position); 165 void updateSelected(); 166 167 [[nodiscard]] Ui::GL::ChosenRenderer chooseRenderer( 168 Ui::GL::Backend backend); 169 170 PanelMode _mode = PanelMode(); 171 bool _opengl = false; 172 bool _geometryStaleAfterModeChange = false; 173 const std::unique_ptr<Ui::RpWidgetWrap> _content; 174 std::vector<std::unique_ptr<VideoTile>> _tiles; 175 std::vector<not_null<VideoTile*>> _tilesForOrder; 176 rpl::variable<int> _fullHeight = 0; 177 bool _hasTwoOrMore = false; 178 int _scrollTop = 0; 179 QImage _shadow; 180 rpl::event_stream<VideoEndpoint> _clicks; 181 rpl::event_stream<bool> _pinToggles; 182 rpl::event_stream<VideoQualityRequest> _qualityRequests; 183 float64 _controlsShownRatio = 1.; 184 VideoTile *_large = nullptr; 185 Fn<void()> _updateLargeScheduled; 186 Ui::Animations::Simple _largeChangeAnimation; 187 Layout _startTilesLayout; 188 Layout _finishTilesLayout; 189 Selection _selected; 190 Selection _pressed; 191 rpl::variable<bool> _mouseInside = false; 192 193 }; 194 195 [[nodiscard]] QImage GenerateShadow( 196 int height, 197 int topAlpha, 198 int bottomAlpha, 199 QColor color = QColor(0, 0, 0)); 200 201 [[nodiscard]] rpl::producer<QString> MuteButtonTooltip( 202 not_null<GroupCall*> call); 203 204 } // namespace Calls::Group 205