mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Animated zoom+rotate in OpenGL media viewer.
This commit is contained in:
parent
5324a626be
commit
23c2bce1bb
8 changed files with 156 additions and 86 deletions
|
@ -451,7 +451,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_settings_system_integration" = "System integration";
|
"lng_settings_system_integration" = "System integration";
|
||||||
"lng_settings_performance" = "Performance";
|
"lng_settings_performance" = "Performance";
|
||||||
"lng_settings_enable_animations" = "Enable animations";
|
"lng_settings_enable_animations" = "Enable animations";
|
||||||
"lng_settings_enable_opengl" = "Enable OpenGL rendering for video";
|
"lng_settings_enable_opengl" = "Enable OpenGL rendering for media";
|
||||||
"lng_settings_sensitive_title" = "Sensitive content";
|
"lng_settings_sensitive_title" = "Sensitive content";
|
||||||
"lng_settings_sensitive_disable_filtering" = "Disable filtering";
|
"lng_settings_sensitive_disable_filtering" = "Disable filtering";
|
||||||
"lng_settings_sensitive_about" = "Display sensitive media in public channels on all your Telegram devices.";
|
"lng_settings_sensitive_about" = "Display sensitive media in public channels on all your Telegram devices.";
|
||||||
|
|
|
@ -185,9 +185,6 @@ void OverlayWidget::RendererGL::paintBackground() {
|
||||||
? st::mediaviewVideoBg
|
? st::mediaviewVideoBg
|
||||||
: st::mediaviewBg;
|
: st::mediaviewBg;
|
||||||
auto fill = QRegion(QRect(QPoint(), _viewport));
|
auto fill = QRegion(QRect(QPoint(), _viewport));
|
||||||
if (_owner->opaqueContentShown()) {
|
|
||||||
fill -= _owner->contentRect();
|
|
||||||
}
|
|
||||||
toggleBlending(false);
|
toggleBlending(false);
|
||||||
_background.fill(
|
_background.fill(
|
||||||
*_f,
|
*_f,
|
||||||
|
@ -199,19 +196,14 @@ void OverlayWidget::RendererGL::paintBackground() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverlayWidget::RendererGL::paintTransformedVideoFrame(
|
void OverlayWidget::RendererGL::paintTransformedVideoFrame(
|
||||||
QRect rect,
|
ContentGeometry geometry) {
|
||||||
int rotation) {
|
|
||||||
const auto data = _owner->videoFrameWithInfo();
|
const auto data = _owner->videoFrameWithInfo();
|
||||||
if (data.format == Streaming::FrameFormat::None) {
|
if (data.format == Streaming::FrameFormat::None) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (data.format == Streaming::FrameFormat::ARGB32) {
|
if (data.format == Streaming::FrameFormat::ARGB32) {
|
||||||
Assert(!data.original.isNull());
|
Assert(!data.original.isNull());
|
||||||
paintTransformedStaticContent(
|
paintTransformedStaticContent(data.original, geometry, false);
|
||||||
data.original,
|
|
||||||
rect,
|
|
||||||
rotation,
|
|
||||||
false);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Assert(data.format == Streaming::FrameFormat::YUV420);
|
Assert(data.format == Streaming::FrameFormat::YUV420);
|
||||||
|
@ -265,13 +257,12 @@ void OverlayWidget::RendererGL::paintTransformedVideoFrame(
|
||||||
_yuv420Program->setUniformValue("u_texture", GLint(1));
|
_yuv420Program->setUniformValue("u_texture", GLint(1));
|
||||||
_yuv420Program->setUniformValue("v_texture", GLint(2));
|
_yuv420Program->setUniformValue("v_texture", GLint(2));
|
||||||
|
|
||||||
paintTransformedContent(&*_yuv420Program, rect, rotation);
|
paintTransformedContent(&*_yuv420Program, geometry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverlayWidget::RendererGL::paintTransformedStaticContent(
|
void OverlayWidget::RendererGL::paintTransformedStaticContent(
|
||||||
const QImage &image,
|
const QImage &image,
|
||||||
QRect rect,
|
ContentGeometry geometry,
|
||||||
int rotation,
|
|
||||||
bool fillTransparentBackground) {
|
bool fillTransparentBackground) {
|
||||||
auto &program = fillTransparentBackground
|
auto &program = fillTransparentBackground
|
||||||
? _withTransparencyProgram
|
? _withTransparencyProgram
|
||||||
|
@ -307,38 +298,46 @@ void OverlayWidget::RendererGL::paintTransformedStaticContent(
|
||||||
_rgbaSize = image.size();
|
_rgbaSize = image.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
paintTransformedContent(&*program, rect, rotation);
|
paintTransformedContent(&*program, geometry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverlayWidget::RendererGL::paintTransformedContent(
|
void OverlayWidget::RendererGL::paintTransformedContent(
|
||||||
not_null<QOpenGLShaderProgram*> program,
|
not_null<QOpenGLShaderProgram*> program,
|
||||||
QRect rect,
|
ContentGeometry geometry) {
|
||||||
int rotation) {
|
|
||||||
auto texCoords = std::array<std::array<GLfloat, 2>, 4> { {
|
auto texCoords = std::array<std::array<GLfloat, 2>, 4> { {
|
||||||
{ { 0.f, 1.f } },
|
{ { 0.f, 1.f } },
|
||||||
{ { 1.f, 1.f } },
|
{ { 1.f, 1.f } },
|
||||||
{ { 1.f, 0.f } },
|
{ { 1.f, 0.f } },
|
||||||
{ { 0.f, 0.f } },
|
{ { 0.f, 0.f } },
|
||||||
} };
|
} };
|
||||||
if (const auto shift = (rotation / 90); shift > 0) {
|
const auto rect = transformRect(geometry.rect);
|
||||||
std::rotate(
|
const auto centerx = rect.x() + rect.width() / 2;
|
||||||
texCoords.begin(),
|
const auto centery = rect.y() + rect.height() / 2;
|
||||||
texCoords.begin() + shift,
|
const auto rsin = std::sinf(geometry.rotation * M_PI / 180.);
|
||||||
texCoords.end());
|
const auto rcos = std::cosf(geometry.rotation * M_PI / 180.);
|
||||||
}
|
const auto rotated = [&](float x, float y) -> std::array<float, 2> {
|
||||||
|
x -= centerx;
|
||||||
const auto geometry = transformRect(rect);
|
y -= centery;
|
||||||
|
return {
|
||||||
|
centerx + (x * rcos + y * rsin),
|
||||||
|
centery + (y * rcos - x * rsin)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
const auto topleft = rotated(rect.left(), rect.top());
|
||||||
|
const auto topright = rotated(rect.right(), rect.top());
|
||||||
|
const auto bottomright = rotated(rect.right(), rect.bottom());
|
||||||
|
const auto bottomleft = rotated(rect.left(), rect.bottom());
|
||||||
const GLfloat coords[] = {
|
const GLfloat coords[] = {
|
||||||
geometry.left(), geometry.top(),
|
topleft[0], topleft[1],
|
||||||
texCoords[0][0], texCoords[0][1],
|
texCoords[0][0], texCoords[0][1],
|
||||||
|
|
||||||
geometry.right(), geometry.top(),
|
topright[0], topright[1],
|
||||||
texCoords[1][0], texCoords[1][1],
|
texCoords[1][0], texCoords[1][1],
|
||||||
|
|
||||||
geometry.right(), geometry.bottom(),
|
bottomright[0], bottomright[1],
|
||||||
texCoords[2][0], texCoords[2][1],
|
texCoords[2][0], texCoords[2][1],
|
||||||
|
|
||||||
geometry.left(), geometry.bottom(),
|
bottomleft[0], bottomleft[1],
|
||||||
texCoords[3][0], texCoords[3][1],
|
texCoords[3][0], texCoords[3][1],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -661,6 +660,10 @@ Rect OverlayWidget::RendererGL::transformRect(const Rect &raster) const {
|
||||||
return TransformRect(raster, _viewport, _factor);
|
return TransformRect(raster, _viewport, _factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rect OverlayWidget::RendererGL::transformRect(const QRectF &raster) const {
|
||||||
|
return TransformRect(raster, _viewport, _factor);
|
||||||
|
}
|
||||||
|
|
||||||
Rect OverlayWidget::RendererGL::transformRect(const QRect &raster) const {
|
Rect OverlayWidget::RendererGL::transformRect(const QRect &raster) const {
|
||||||
return TransformRect(Rect(raster), _viewport, _factor);
|
return TransformRect(Rect(raster), _viewport, _factor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,16 +47,14 @@ private:
|
||||||
void setDefaultViewport(QOpenGLFunctions &f);
|
void setDefaultViewport(QOpenGLFunctions &f);
|
||||||
|
|
||||||
void paintBackground();
|
void paintBackground();
|
||||||
void paintTransformedVideoFrame(QRect rect, int rotation) override;
|
void paintTransformedVideoFrame(ContentGeometry geometry) override;
|
||||||
void paintTransformedStaticContent(
|
void paintTransformedStaticContent(
|
||||||
const QImage &image,
|
const QImage &image,
|
||||||
QRect rect,
|
ContentGeometry geometry,
|
||||||
int rotation,
|
|
||||||
bool fillTransparentBackground) override;
|
bool fillTransparentBackground) override;
|
||||||
void paintTransformedContent(
|
void paintTransformedContent(
|
||||||
not_null<QOpenGLShaderProgram*> program,
|
not_null<QOpenGLShaderProgram*> program,
|
||||||
QRect rect,
|
ContentGeometry geometry);
|
||||||
int rotation);
|
|
||||||
void paintRadialLoading(
|
void paintRadialLoading(
|
||||||
QRect inner,
|
QRect inner,
|
||||||
bool radial,
|
bool radial,
|
||||||
|
@ -90,6 +88,7 @@ private:
|
||||||
void toggleBlending(bool enabled);
|
void toggleBlending(bool enabled);
|
||||||
|
|
||||||
[[nodiscard]] Ui::GL::Rect transformRect(const QRect &raster) const;
|
[[nodiscard]] Ui::GL::Rect transformRect(const QRect &raster) const;
|
||||||
|
[[nodiscard]] Ui::GL::Rect transformRect(const QRectF &raster) const;
|
||||||
[[nodiscard]] Ui::GL::Rect transformRect(
|
[[nodiscard]] Ui::GL::Rect transformRect(
|
||||||
const Ui::GL::Rect &raster) const;
|
const Ui::GL::Rect &raster) const;
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ void OverlayWidget::RendererSW::paintFallback(
|
||||||
|
|
||||||
void OverlayWidget::RendererSW::paintBackground() {
|
void OverlayWidget::RendererSW::paintBackground() {
|
||||||
const auto region = _owner->opaqueContentShown()
|
const auto region = _owner->opaqueContentShown()
|
||||||
? (*_clip - _owner->contentRect())
|
? (*_clip - _owner->finalContentRect())
|
||||||
: *_clip;
|
: *_clip;
|
||||||
|
|
||||||
const auto m = _p->compositionMode();
|
const auto m = _p->compositionMode();
|
||||||
|
@ -44,11 +44,30 @@ void OverlayWidget::RendererSW::paintBackground() {
|
||||||
_p->setCompositionMode(m);
|
_p->setCompositionMode(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverlayWidget::RendererSW::paintTransformedVideoFrame(
|
QRect OverlayWidget::RendererSW::TransformRect(
|
||||||
QRect rect,
|
QRectF geometry,
|
||||||
int rotation) {
|
int rotation) {
|
||||||
|
const auto center = geometry.center();
|
||||||
|
const auto rect = ((rotation % 180) == 90)
|
||||||
|
? QRectF(
|
||||||
|
center.x() - geometry.height() / 2.,
|
||||||
|
center.y() - geometry.width() / 2.,
|
||||||
|
geometry.height(),
|
||||||
|
geometry.width())
|
||||||
|
: geometry;
|
||||||
|
return QRect(
|
||||||
|
int(rect.x()),
|
||||||
|
int(rect.y()),
|
||||||
|
int(rect.width()),
|
||||||
|
int(rect.height()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void OverlayWidget::RendererSW::paintTransformedVideoFrame(
|
||||||
|
ContentGeometry geometry) {
|
||||||
Expects(_owner->_streamed != nullptr);
|
Expects(_owner->_streamed != nullptr);
|
||||||
|
|
||||||
|
const auto rotation = int(geometry.rotation);
|
||||||
|
const auto rect = TransformRect(geometry.rect, rotation);
|
||||||
if (!rect.intersects(_clipOuter)) {
|
if (!rect.intersects(_clipOuter)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -57,9 +76,10 @@ void OverlayWidget::RendererSW::paintTransformedVideoFrame(
|
||||||
|
|
||||||
void OverlayWidget::RendererSW::paintTransformedStaticContent(
|
void OverlayWidget::RendererSW::paintTransformedStaticContent(
|
||||||
const QImage &image,
|
const QImage &image,
|
||||||
QRect rect,
|
ContentGeometry geometry,
|
||||||
int rotation,
|
|
||||||
bool fillTransparentBackground) {
|
bool fillTransparentBackground) {
|
||||||
|
const auto rotation = int(geometry.rotation);
|
||||||
|
const auto rect = TransformRect(geometry.rect, rotation);
|
||||||
if (!rect.intersects(_clipOuter)) {
|
if (!rect.intersects(_clipOuter)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,11 +23,10 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void paintBackground() override;
|
void paintBackground() override;
|
||||||
void paintTransformedVideoFrame(QRect rect, int rotation) override;
|
void paintTransformedVideoFrame(ContentGeometry geometry) override;
|
||||||
void paintTransformedStaticContent(
|
void paintTransformedStaticContent(
|
||||||
const QImage &image,
|
const QImage &image,
|
||||||
QRect rect,
|
ContentGeometry geometry,
|
||||||
int rotation,
|
|
||||||
bool fillTransparentBackground) override;
|
bool fillTransparentBackground) override;
|
||||||
void paintTransformedImage(
|
void paintTransformedImage(
|
||||||
const QImage &image,
|
const QImage &image,
|
||||||
|
@ -54,6 +53,8 @@ private:
|
||||||
|
|
||||||
void invalidate() override;
|
void invalidate() override;
|
||||||
|
|
||||||
|
[[nodiscard]] static QRect TransformRect(QRectF geometry, int rotation);
|
||||||
|
|
||||||
const not_null<OverlayWidget*> _owner;
|
const not_null<OverlayWidget*> _owner;
|
||||||
QBrush _transparentBrush;
|
QBrush _transparentBrush;
|
||||||
|
|
||||||
|
|
|
@ -14,11 +14,10 @@ namespace Media::View {
|
||||||
class OverlayWidget::Renderer : public Ui::GL::Renderer {
|
class OverlayWidget::Renderer : public Ui::GL::Renderer {
|
||||||
public:
|
public:
|
||||||
virtual void paintBackground() = 0;
|
virtual void paintBackground() = 0;
|
||||||
virtual void paintTransformedVideoFrame(QRect rect, int rotation) = 0;
|
virtual void paintTransformedVideoFrame(ContentGeometry geometry) = 0;
|
||||||
virtual void paintTransformedStaticContent(
|
virtual void paintTransformedStaticContent(
|
||||||
const QImage &image,
|
const QImage &image,
|
||||||
QRect rect,
|
ContentGeometry geometry,
|
||||||
int rotation,
|
|
||||||
bool fillTransparentBackground) = 0;
|
bool fillTransparentBackground) = 0;
|
||||||
virtual void paintRadialLoading(
|
virtual void paintRadialLoading(
|
||||||
QRect inner,
|
QRect inner,
|
||||||
|
|
|
@ -963,23 +963,62 @@ void OverlayWidget::updateCursor() {
|
||||||
: (_over == OverNone ? style::cur_default : style::cur_pointer));
|
: (_over == OverNone ? style::cur_default : style::cur_pointer));
|
||||||
}
|
}
|
||||||
|
|
||||||
int OverlayWidget::contentRotation() const {
|
int OverlayWidget::finalContentRotation() const {
|
||||||
if (!_streamed) {
|
return _streamed
|
||||||
return _rotation;
|
? ((_rotation + (_streamed
|
||||||
}
|
? _streamed->instance.info().video.rotation
|
||||||
return (_rotation + (_streamed
|
: 0)) % 360)
|
||||||
? _streamed->instance.info().video.rotation
|
: _rotation;
|
||||||
: 0)) % 360;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QRect OverlayWidget::contentRect() const {
|
QRect OverlayWidget::finalContentRect() const {
|
||||||
const auto progress = _zoomAnimation.value(1.);
|
return { _x, _y, _w, _h };
|
||||||
return {
|
}
|
||||||
anim::interpolate(_xOld, _x, progress),
|
|
||||||
anim::interpolate(_yOld, _y, progress),
|
OverlayWidget::ContentGeometry OverlayWidget::contentGeometry() const {
|
||||||
anim::interpolate(_wOld, _w, progress),
|
const auto toRotation = qreal(finalContentRotation());
|
||||||
anim::interpolate(_hOld, _h, progress),
|
const auto toRectRotated = QRectF(finalContentRect());
|
||||||
};
|
const auto toRectCenter = toRectRotated.center();
|
||||||
|
const auto toRect = ((int(toRotation) % 180) == 90)
|
||||||
|
? QRectF(
|
||||||
|
toRectCenter.x() - toRectRotated.height() / 2.,
|
||||||
|
toRectCenter.y() - toRectRotated.width() / 2.,
|
||||||
|
toRectRotated.height(),
|
||||||
|
toRectRotated.width())
|
||||||
|
: toRectRotated;
|
||||||
|
if (!_geometryAnimation.animating()) {
|
||||||
|
return { toRect, toRotation };
|
||||||
|
}
|
||||||
|
const auto fromRect = _oldGeometry.rect;
|
||||||
|
const auto fromRotation = _oldGeometry.rotation;
|
||||||
|
const auto progress = _geometryAnimation.value(1.);
|
||||||
|
const auto rotationDelta = (toRotation - fromRotation);
|
||||||
|
const auto useRotationDelta = (rotationDelta > 180.)
|
||||||
|
? (rotationDelta - 360.)
|
||||||
|
: (rotationDelta <= -180.)
|
||||||
|
? (rotationDelta + 360.)
|
||||||
|
: rotationDelta;
|
||||||
|
const auto rotation = fromRotation + useRotationDelta * progress;
|
||||||
|
const auto useRotation = (rotation > 360.)
|
||||||
|
? (rotation - 360.)
|
||||||
|
: (rotation < 0.)
|
||||||
|
? (rotation + 360.)
|
||||||
|
: rotation;
|
||||||
|
const auto useRect = QRectF(
|
||||||
|
fromRect.x() + (toRect.x() - fromRect.x()) * progress,
|
||||||
|
fromRect.y() + (toRect.y() - fromRect.y()) * progress,
|
||||||
|
fromRect.width() + (toRect.width() - fromRect.width()) * progress,
|
||||||
|
fromRect.height() + (toRect.height() - fromRect.height()) * progress
|
||||||
|
);
|
||||||
|
return { useRect, useRotation };
|
||||||
|
}
|
||||||
|
|
||||||
|
void OverlayWidget::updateContentRect() {
|
||||||
|
if (_opengl) {
|
||||||
|
update();
|
||||||
|
} else {
|
||||||
|
update(finalContentRect());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverlayWidget::contentSizeChanged() {
|
void OverlayWidget::contentSizeChanged() {
|
||||||
|
@ -1035,7 +1074,7 @@ void OverlayWidget::resizeContentByScreenSize() {
|
||||||
}
|
}
|
||||||
_x = (width() - _w) / 2;
|
_x = (width() - _w) / 2;
|
||||||
_y = (height() - _h) / 2;
|
_y = (height() - _h) / 2;
|
||||||
_zoomAnimation.stop();
|
_geometryAnimation.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
float64 OverlayWidget::radialProgress() const {
|
float64 OverlayWidget::radialProgress() const {
|
||||||
|
@ -2612,13 +2651,13 @@ void OverlayWidget::streamingReady(Streaming::Information &&info) {
|
||||||
if (videoShown()) {
|
if (videoShown()) {
|
||||||
applyVideoSize();
|
applyVideoSize();
|
||||||
}
|
}
|
||||||
update(contentRect());
|
updateContentRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverlayWidget::applyVideoSize() {
|
void OverlayWidget::applyVideoSize() {
|
||||||
const auto contentSize = style::ConvertScale(videoSize());
|
const auto contentSize = style::ConvertScale(videoSize());
|
||||||
if (contentSize != QSize(_width, _height)) {
|
if (contentSize != QSize(_width, _height)) {
|
||||||
update(contentRect());
|
updateContentRect();
|
||||||
_w = contentSize.width();
|
_w = contentSize.width();
|
||||||
_h = contentSize.height();
|
_h = contentSize.height();
|
||||||
contentSizeChanged();
|
contentSizeChanged();
|
||||||
|
@ -2668,7 +2707,7 @@ bool OverlayWidget::createStreamingObjects() {
|
||||||
QImage OverlayWidget::transformedShownContent() const {
|
QImage OverlayWidget::transformedShownContent() const {
|
||||||
return transformShownContent(
|
return transformShownContent(
|
||||||
videoShown() ? currentVideoFrameImage() : _staticContent,
|
videoShown() ? currentVideoFrameImage() : _staticContent,
|
||||||
contentRotation());
|
finalContentRotation());
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage OverlayWidget::transformShownContent(
|
QImage OverlayWidget::transformShownContent(
|
||||||
|
@ -2697,7 +2736,7 @@ void OverlayWidget::handleStreamingUpdate(Streaming::Update &&update) {
|
||||||
}, [&](const PreloadedVideo &update) {
|
}, [&](const PreloadedVideo &update) {
|
||||||
updatePlaybackState();
|
updatePlaybackState();
|
||||||
}, [&](const UpdateVideo &update) {
|
}, [&](const UpdateVideo &update) {
|
||||||
this->update(contentRect());
|
updateContentRect();
|
||||||
Core::App().updateNonIdle();
|
Core::App().updateNonIdle();
|
||||||
updatePlaybackState();
|
updatePlaybackState();
|
||||||
}, [&](const PreloadedAudio &update) {
|
}, [&](const PreloadedAudio &update) {
|
||||||
|
@ -2874,6 +2913,8 @@ void OverlayWidget::playbackControlsToPictureInPicture() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverlayWidget::playbackControlsRotate() {
|
void OverlayWidget::playbackControlsRotate() {
|
||||||
|
_oldGeometry = contentGeometry();
|
||||||
|
_geometryAnimation.stop();
|
||||||
if (_photo) {
|
if (_photo) {
|
||||||
auto &storage = _photo->owner().mediaRotation();
|
auto &storage = _photo->owner().mediaRotation();
|
||||||
storage.set(_photo, storage.get(_photo) - 90);
|
storage.set(_photo, storage.get(_photo) - 90);
|
||||||
|
@ -2885,11 +2926,19 @@ void OverlayWidget::playbackControlsRotate() {
|
||||||
_rotation = storage.get(_document);
|
_rotation = storage.get(_document);
|
||||||
if (videoShown()) {
|
if (videoShown()) {
|
||||||
applyVideoSize();
|
applyVideoSize();
|
||||||
update(contentRect());
|
updateContentRect();
|
||||||
} else {
|
} else {
|
||||||
redisplayContent();
|
redisplayContent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (_opengl) {
|
||||||
|
_geometryAnimation.start(
|
||||||
|
[=] { update(); },
|
||||||
|
0.,
|
||||||
|
1.,
|
||||||
|
st::widgetFadeDuration/*,
|
||||||
|
st::easeOutCirc*/);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverlayWidget::playbackPauseResume() {
|
void OverlayWidget::playbackPauseResume() {
|
||||||
|
@ -2923,7 +2972,7 @@ void OverlayWidget::restartAtSeekPosition(crl::time position) {
|
||||||
const auto saved = base::take(_rotation);
|
const auto saved = base::take(_rotation);
|
||||||
_staticContent = transformedShownContent();
|
_staticContent = transformedShownContent();
|
||||||
_rotation = saved;
|
_rotation = saved;
|
||||||
update(contentRect());
|
updateContentRect();
|
||||||
}
|
}
|
||||||
auto options = Streaming::PlaybackOptions();
|
auto options = Streaming::PlaybackOptions();
|
||||||
options.position = position;
|
options.position = position;
|
||||||
|
@ -3168,10 +3217,8 @@ Ui::GL::ChosenRenderer OverlayWidget::chooseRenderer(
|
||||||
void OverlayWidget::paint(not_null<Renderer*> renderer) {
|
void OverlayWidget::paint(not_null<Renderer*> renderer) {
|
||||||
renderer->paintBackground();
|
renderer->paintBackground();
|
||||||
if (contentShown()) {
|
if (contentShown()) {
|
||||||
const auto rect = contentRect();
|
|
||||||
const auto rotation = contentRotation();
|
|
||||||
if (videoShown()) {
|
if (videoShown()) {
|
||||||
renderer->paintTransformedVideoFrame(rect, rotation);
|
renderer->paintTransformedVideoFrame(contentGeometry());
|
||||||
if (_streamed->instance.player().ready()) {
|
if (_streamed->instance.player().ready()) {
|
||||||
_streamed->instance.markFrameShown();
|
_streamed->instance.markFrameShown();
|
||||||
}
|
}
|
||||||
|
@ -3183,8 +3230,7 @@ void OverlayWidget::paint(not_null<Renderer*> renderer) {
|
||||||
|| _staticContent.hasAlphaChannel());
|
|| _staticContent.hasAlphaChannel());
|
||||||
renderer->paintTransformedStaticContent(
|
renderer->paintTransformedStaticContent(
|
||||||
_staticContent,
|
_staticContent,
|
||||||
rect,
|
contentGeometry(),
|
||||||
rotation,
|
|
||||||
fillTransparentBackground);
|
fillTransparentBackground);
|
||||||
}
|
}
|
||||||
paintRadialLoading(renderer);
|
paintRadialLoading(renderer);
|
||||||
|
@ -3736,11 +3782,8 @@ void OverlayWidget::setZoomLevel(int newZoom, bool force) {
|
||||||
const auto contentSize = videoShown()
|
const auto contentSize = videoShown()
|
||||||
? style::ConvertScale(videoSize())
|
? style::ConvertScale(videoSize())
|
||||||
: QSize(_width, _height);
|
: QSize(_width, _height);
|
||||||
const auto current = contentRect();
|
_oldGeometry = contentGeometry();
|
||||||
_xOld = current.x();
|
_geometryAnimation.stop();
|
||||||
_yOld = current.y();
|
|
||||||
_wOld = current.width();
|
|
||||||
_hOld = current.height();
|
|
||||||
|
|
||||||
_w = contentSize.width();
|
_w = contentSize.width();
|
||||||
_h = contentSize.height();
|
_h = contentSize.height();
|
||||||
|
@ -3764,15 +3807,14 @@ void OverlayWidget::setZoomLevel(int newZoom, bool force) {
|
||||||
_x = qRound(nx / (-z + 1) + width() / 2.);
|
_x = qRound(nx / (-z + 1) + width() / 2.);
|
||||||
_y = qRound(ny / (-z + 1) + height() / 2.);
|
_y = qRound(ny / (-z + 1) + height() / 2.);
|
||||||
}
|
}
|
||||||
_zoomAnimation.stop();
|
|
||||||
snapXY();
|
snapXY();
|
||||||
if (_opengl) {
|
if (_opengl) {
|
||||||
_zoomAnimation.start(
|
_geometryAnimation.start(
|
||||||
[=] { update(); },
|
[=] { update(); },
|
||||||
0.,
|
0.,
|
||||||
1.,
|
1.,
|
||||||
st::widgetFadeDuration,
|
st::widgetFadeDuration/*,
|
||||||
anim::easeOutCirc);
|
anim::easeOutCirc*/);
|
||||||
}
|
}
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
@ -4197,7 +4239,7 @@ void OverlayWidget::updateOver(QPoint pos) {
|
||||||
updateOverState(OverMore);
|
updateOverState(OverMore);
|
||||||
} else if (_closeNav.contains(pos)) {
|
} else if (_closeNav.contains(pos)) {
|
||||||
updateOverState(OverClose);
|
updateOverState(OverClose);
|
||||||
} else if (documentContentShown() && contentRect().contains(pos)) {
|
} else if (documentContentShown() && finalContentRect().contains(pos)) {
|
||||||
if ((_document->isVideoFile() || _document->isVideoMessage()) && _streamed) {
|
if ((_document->isVideoFile() || _document->isVideoMessage()) && _streamed) {
|
||||||
updateOverState(OverVideo);
|
updateOverState(OverVideo);
|
||||||
} else if (!_streamed && !_documentMedia->loaded()) {
|
} else if (!_streamed && !_documentMedia->loaded()) {
|
||||||
|
|
|
@ -143,6 +143,10 @@ private:
|
||||||
QuickSave,
|
QuickSave,
|
||||||
SaveAs,
|
SaveAs,
|
||||||
};
|
};
|
||||||
|
struct ContentGeometry {
|
||||||
|
QRectF rect;
|
||||||
|
qreal rotation = 0.;
|
||||||
|
};
|
||||||
|
|
||||||
[[nodiscard]] not_null<QWindow*> window() const;
|
[[nodiscard]] not_null<QWindow*> window() const;
|
||||||
[[nodiscard]] int width() const;
|
[[nodiscard]] int width() const;
|
||||||
|
@ -322,8 +326,10 @@ private:
|
||||||
void documentUpdated(DocumentData *doc);
|
void documentUpdated(DocumentData *doc);
|
||||||
void changingMsgId(not_null<HistoryItem*> row, MsgId oldId);
|
void changingMsgId(not_null<HistoryItem*> row, MsgId oldId);
|
||||||
|
|
||||||
[[nodiscard]] int contentRotation() const;
|
[[nodiscard]] int finalContentRotation() const;
|
||||||
[[nodiscard]] QRect contentRect() const;
|
[[nodiscard]] QRect finalContentRect() const;
|
||||||
|
[[nodiscard]] ContentGeometry contentGeometry() const;
|
||||||
|
void updateContentRect();
|
||||||
void contentSizeChanged();
|
void contentSizeChanged();
|
||||||
|
|
||||||
// Radial animation interface.
|
// Radial animation interface.
|
||||||
|
@ -467,14 +473,14 @@ private:
|
||||||
int _zoom = 0; // < 0 - out, 0 - none, > 0 - in
|
int _zoom = 0; // < 0 - out, 0 - none, > 0 - in
|
||||||
float64 _zoomToScreen = 0.; // for documents
|
float64 _zoomToScreen = 0.; // for documents
|
||||||
float64 _zoomToDefault = 0.;
|
float64 _zoomToDefault = 0.;
|
||||||
int _xOld = 0, _yOld = 0, _wOld = 0, _hOld = 0;
|
|
||||||
Ui::Animations::Simple _zoomAnimation;
|
|
||||||
QPoint _mStart;
|
QPoint _mStart;
|
||||||
bool _pressed = false;
|
bool _pressed = false;
|
||||||
int32 _dragging = 0;
|
int32 _dragging = 0;
|
||||||
QImage _staticContent;
|
QImage _staticContent;
|
||||||
bool _blurred = true;
|
bool _blurred = true;
|
||||||
|
|
||||||
|
ContentGeometry _oldGeometry;
|
||||||
|
Ui::Animations::Simple _geometryAnimation;
|
||||||
rpl::lifetime _screenGeometryLifetime;
|
rpl::lifetime _screenGeometryLifetime;
|
||||||
std::unique_ptr<QObject> _applicationEventFilter;
|
std::unique_ptr<QObject> _applicationEventFilter;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue