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