Show shadow below controls in media viewer.
Before Width: | Height: | Size: 513 B After Width: | Height: | Size: 366 B |
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 617 B |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 957 B |
Before Width: | Height: | Size: 296 B After Width: | Height: | Size: 318 B |
Before Width: | Height: | Size: 497 B After Width: | Height: | Size: 591 B |
Before Width: | Height: | Size: 729 B After Width: | Height: | Size: 880 B |
BIN
Telegram/Resources/icons/mediaview/next_shadow.png
Normal file
After Width: | Height: | Size: 435 B |
BIN
Telegram/Resources/icons/mediaview/next_shadow@2x.png
Normal file
After Width: | Height: | Size: 769 B |
BIN
Telegram/Resources/icons/mediaview/next_shadow@3x.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 912 B After Width: | Height: | Size: 680 B |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 210 B After Width: | Height: | Size: 215 B |
Before Width: | Height: | Size: 304 B After Width: | Height: | Size: 312 B |
Before Width: | Height: | Size: 461 B After Width: | Height: | Size: 425 B |
Before Width: | Height: | Size: 300 B After Width: | Height: | Size: 338 B |
Before Width: | Height: | Size: 388 B After Width: | Height: | Size: 485 B |
Before Width: | Height: | Size: 606 B After Width: | Height: | Size: 695 B |
Before Width: | Height: | Size: 360 B After Width: | Height: | Size: 358 B |
Before Width: | Height: | Size: 554 B After Width: | Height: | Size: 572 B |
Before Width: | Height: | Size: 722 B After Width: | Height: | Size: 808 B |
|
@ -101,11 +101,17 @@ mediaviewVolumeToggle: IconButton(mediaviewControlsButton) {
|
|||
}
|
||||
mediaviewVolumeSkip: 4px;
|
||||
|
||||
mediaviewLeft: icon {{ "mediaview/next-flip_horizontal", mediaviewControlFg }};
|
||||
mediaviewRight: icon {{ "mediaview/next", mediaviewControlFg }};
|
||||
mediaviewLeft: icon {
|
||||
{ "mediaview/next_shadow-flip_horizontal", windowShadowFg }
|
||||
{ "mediaview/next-flip_horizontal", mediaviewControlFg }
|
||||
};
|
||||
mediaviewRight: icon {
|
||||
{ "mediaview/next_shadow", windowShadowFg }
|
||||
{ "mediaview/next", mediaviewControlFg }
|
||||
};
|
||||
mediaviewSave: icon {{ "mediaview/download", mediaviewControlFg }};
|
||||
mediaviewRotate: icon {{ "mediaview/rotate", mediaviewControlFg }};
|
||||
mediaviewMore: icon {{ "mediaview/more", mediaviewControlFg }};
|
||||
mediaviewMore: icon {{ "title_menu_dots", mediaviewControlFg }};
|
||||
|
||||
mediaviewFileRed: icon {
|
||||
{ size(25px, 25px), mediaviewFileBg },
|
||||
|
@ -232,15 +238,13 @@ mediaviewThickFont: semiboldFont;
|
|||
mediaviewFont: normalFont;
|
||||
mediaviewTextStyle: defaultTextStyle;
|
||||
|
||||
mediaviewTextLeft: 16px;
|
||||
mediaviewTextLeft: 14px;
|
||||
mediaviewTextSkip: 10px;
|
||||
mediaviewHeaderTop: 48px;
|
||||
mediaviewTextTop: 24px;
|
||||
mediaviewHeaderTop: 47px;
|
||||
mediaviewTextTop: 26px;
|
||||
|
||||
mediaviewIconOpacity: 0.45;
|
||||
mediaviewIconOverOpacity: 1.;
|
||||
mediaviewControlSize: 90px;
|
||||
mediaviewIconSize: size(60px, 56px);
|
||||
mediaviewIconSize: size(46px, 54px);
|
||||
|
||||
mediaviewWaitHide: 2000;
|
||||
mediaviewHideDuration: 1000;
|
||||
|
@ -250,9 +254,9 @@ mediaviewFadeDuration: 150;
|
|||
mediaviewDeltaFromLastAction: 5px;
|
||||
mediaviewSwipeDistance: 80px;
|
||||
|
||||
mediaviewCaptionPadding: margins(18px, 10px, 18px, 10px);
|
||||
mediaviewCaptionPadding: margins(11px, 6px, 11px, 6px);
|
||||
mediaviewCaptionMargin: size(11px, 11px);
|
||||
mediaviewCaptionRadius: 2px;
|
||||
mediaviewCaptionRadius: 6px;
|
||||
|
||||
mediaviewGroupPadding: margins(0px, 14px, 0px, 14px);
|
||||
mediaviewGroupHeight: 80px;
|
||||
|
@ -317,6 +321,8 @@ mediaviewTitle: WindowTitle(defaultWindowTitle) {
|
|||
closeIconActive: mediaviewTitleClose;
|
||||
closeIconActiveOver: mediaviewTitleClose;
|
||||
}
|
||||
mediaviewShadowTop: icon{{ "mediaview/shadow_top", windowShadowFg }};
|
||||
mediaviewShadowBottom: icon{{ "mediaview/shadow_bottom", windowShadowFg }};
|
||||
|
||||
themePreviewSize: size(903px, 584px);
|
||||
themePreviewBg: windowBg;
|
||||
|
|
|
@ -29,6 +29,31 @@ constexpr auto kGroupThumbsOffset = kCaptionOffset + 4;
|
|||
constexpr auto kControlsOffset = kGroupThumbsOffset + 4;
|
||||
constexpr auto kControlValues = 2 * 4 + 4 * 4;
|
||||
|
||||
[[nodiscard]] ShaderPart FragmentApplyControlsFade() {
|
||||
return {
|
||||
.header = R"(
|
||||
uniform sampler2D f_texture;
|
||||
uniform vec4 shadowTopRect;
|
||||
uniform vec2 shadowBottomAndOpacity;
|
||||
)",
|
||||
.body = R"(
|
||||
float topHeight = shadowTopRect.w;
|
||||
float bottomHeight = shadowBottomAndOpacity.x;
|
||||
float opacity = shadowBottomAndOpacity.y;
|
||||
float viewportHeight = shadowTopRect.y + topHeight;
|
||||
float fullHeight = topHeight + bottomHeight;
|
||||
float topY = min(
|
||||
(viewportHeight - gl_FragCoord.y) / fullHeight,
|
||||
topHeight / fullHeight);
|
||||
float topX = (gl_FragCoord.x - shadowTopRect.x) / shadowTopRect.z;
|
||||
vec4 fadeTop = texture2D(f_texture, vec2(topX, topY)) * opacity;
|
||||
float bottomY = max(fullHeight - gl_FragCoord.y, topHeight) / fullHeight;
|
||||
vec4 fadeBottom = texture2D(f_texture, vec2(0.5, bottomY)) * opacity;
|
||||
result.rgb = result.rgb * (1. - fadeTop.a) * (1. - fadeBottom.a);
|
||||
)",
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] ShaderPart FragmentPlaceOnTransparentBackground() {
|
||||
return {
|
||||
.header = R"(
|
||||
|
@ -77,6 +102,7 @@ OverlayWidget::RendererGL::RendererGL(not_null<OverlayWidget*> owner)
|
|||
: _owner(owner) {
|
||||
style::PaletteChanged(
|
||||
) | rpl::start_with_next([=] {
|
||||
_controlsFadeImage.invalidate();
|
||||
_radialImage.invalidate();
|
||||
_documentBubbleImage.invalidate();
|
||||
_themePreviewImage.invalidate();
|
||||
|
@ -118,6 +144,15 @@ void OverlayWidget::RendererGL::init(
|
|||
FragmentSampleARGB32Texture(),
|
||||
})).vertex;
|
||||
|
||||
_staticContentProgram.emplace();
|
||||
LinkProgram(
|
||||
&*_staticContentProgram,
|
||||
_texturedVertexShader,
|
||||
FragmentShader({
|
||||
FragmentSampleARGB32Texture(),
|
||||
FragmentApplyControlsFade()
|
||||
}));
|
||||
|
||||
_withTransparencyProgram.emplace();
|
||||
LinkProgram(
|
||||
&*_withTransparencyProgram,
|
||||
|
@ -125,6 +160,7 @@ void OverlayWidget::RendererGL::init(
|
|||
FragmentShader({
|
||||
FragmentSampleARGB32Texture(),
|
||||
FragmentPlaceOnTransparentBackground(),
|
||||
FragmentApplyControlsFade()
|
||||
}));
|
||||
|
||||
_yuv420Program.emplace();
|
||||
|
@ -133,6 +169,7 @@ void OverlayWidget::RendererGL::init(
|
|||
_texturedVertexShader,
|
||||
FragmentShader({
|
||||
FragmentSampleYUV420Texture(),
|
||||
FragmentApplyControlsFade()
|
||||
}));
|
||||
|
||||
_nv12Program.emplace();
|
||||
|
@ -141,6 +178,7 @@ void OverlayWidget::RendererGL::init(
|
|||
_texturedVertexShader,
|
||||
FragmentShader({
|
||||
FragmentSampleNV12Texture(),
|
||||
FragmentApplyControlsFade()
|
||||
}));
|
||||
|
||||
_fillProgram.emplace();
|
||||
|
@ -195,6 +233,7 @@ void OverlayWidget::RendererGL::paint(
|
|||
if (_factor != factor) {
|
||||
_factor = factor;
|
||||
_controlsImage.invalidate();
|
||||
_controlsFadeImage.invalidate();
|
||||
}
|
||||
_blendingEnabled = false;
|
||||
_viewport = widget->size();
|
||||
|
@ -283,7 +322,12 @@ void OverlayWidget::RendererGL::paintTransformedVideoFrame(
|
|||
}
|
||||
_chromaNV12 = nv12;
|
||||
}
|
||||
if (!nv12) {
|
||||
|
||||
validateControlsFade();
|
||||
if (nv12) {
|
||||
_f->glActiveTexture(GL_TEXTURE2);
|
||||
_controlsFadeImage.bind(*_f);
|
||||
} else {
|
||||
_f->glActiveTexture(GL_TEXTURE2);
|
||||
_textures.bind(*_f, 3);
|
||||
if (upload) {
|
||||
|
@ -297,6 +341,9 @@ void OverlayWidget::RendererGL::paintTransformedVideoFrame(
|
|||
_chromaSize = yuv->chromaSize;
|
||||
_f->glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||
}
|
||||
|
||||
_f->glActiveTexture(GL_TEXTURE3);
|
||||
_controlsFadeImage.bind(*_f);
|
||||
}
|
||||
program->setUniformValue("y_texture", GLint(0));
|
||||
if (nv12) {
|
||||
|
@ -305,6 +352,7 @@ void OverlayWidget::RendererGL::paintTransformedVideoFrame(
|
|||
program->setUniformValue("u_texture", GLint(1));
|
||||
program->setUniformValue("v_texture", GLint(2));
|
||||
}
|
||||
program->setUniformValue("f_texture", GLint(nv12 ? 2 : 3));
|
||||
|
||||
toggleBlending(false);
|
||||
paintTransformedContent(program, geometry);
|
||||
|
@ -325,7 +373,7 @@ void OverlayWidget::RendererGL::paintTransformedStaticContent(
|
|||
|
||||
auto &program = fillTransparentBackground
|
||||
? _withTransparencyProgram
|
||||
: _imageProgram;
|
||||
: _staticContentProgram;
|
||||
program->bind();
|
||||
if (fillTransparentBackground) {
|
||||
program->setUniformValue(
|
||||
|
@ -369,7 +417,13 @@ void OverlayWidget::RendererGL::paintTransformedStaticContent(
|
|||
_rgbaSize = image.size();
|
||||
}
|
||||
}
|
||||
|
||||
validateControlsFade();
|
||||
_f->glActiveTexture(GL_TEXTURE1);
|
||||
_controlsFadeImage.bind(*_f);
|
||||
|
||||
program->setUniformValue("s_texture", GLint(0));
|
||||
program->setUniformValue("f_texture", GLint(1));
|
||||
|
||||
toggleBlending(semiTransparent && !fillTransparentBackground);
|
||||
paintTransformedContent(&*program, geometry);
|
||||
|
@ -412,6 +466,15 @@ void OverlayWidget::RendererGL::paintTransformedContent(
|
|||
_contentBuffer->write(0, coords, sizeof(coords));
|
||||
|
||||
program->setUniformValue("viewport", _uniformViewport);
|
||||
const auto &top = st::mediaviewShadowTop.size();
|
||||
program->setUniformValue(
|
||||
"shadowTopRect",
|
||||
Uniform(transformRect(
|
||||
QRect(QPoint(_viewport.width() - top.width(), 0), top))));
|
||||
const auto &bottom = st::mediaviewShadowBottom;
|
||||
program->setUniformValue(
|
||||
"shadowBottomAndOpacity",
|
||||
QVector2D(bottom.height() * _factor, geometry.controlsOpacity));
|
||||
|
||||
FillTexturedRectangle(*_f, &*program);
|
||||
}
|
||||
|
@ -607,6 +670,36 @@ void OverlayWidget::RendererGL::invalidateControls() {
|
|||
ranges::fill(_controlsTextures, QRect());
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererGL::validateControlsFade() {
|
||||
if (!_controlsFadeImage.image().isNull()) {
|
||||
return;
|
||||
}
|
||||
const auto width = st::mediaviewShadowTop.width();
|
||||
const auto bottomTop = st::mediaviewShadowTop.height();
|
||||
const auto height = bottomTop + st::mediaviewShadowBottom.height();
|
||||
|
||||
auto image = QImage(
|
||||
QSize(width, height) * _factor,
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
image.fill(Qt::transparent);
|
||||
image.setDevicePixelRatio(_factor);
|
||||
|
||||
auto p = QPainter(&image);
|
||||
st::mediaviewShadowTop.paint(p, 0, 0, width);
|
||||
st::mediaviewShadowBottom.fill(
|
||||
p,
|
||||
QRect(0, bottomTop, width, st::mediaviewShadowBottom.height()));
|
||||
p.end();
|
||||
|
||||
_controlsFadeImage.setImage(std::move(image));
|
||||
_shadowTopTexture = QRect(
|
||||
QPoint(),
|
||||
QSize(width, st::mediaviewShadowTop.height()) * _factor);
|
||||
_shadowBottomTexture = QRect(
|
||||
QPoint(0, bottomTop) * _factor,
|
||||
QSize(width, st::mediaviewShadowBottom.height()) * _factor);
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererGL::paintFooter(QRect outer, float64 opacity) {
|
||||
paintUsingRaster(_footerImage, outer, [&](Painter &&p) {
|
||||
const auto newOuter = QRect(QPoint(), outer.size());
|
||||
|
@ -699,25 +792,25 @@ void OverlayWidget::RendererGL::paintRoundedCorners(int radius) {
|
|||
|
||||
_f->glDisableVertexAttribArray(position);
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererGL::invalidate() {
|
||||
_trackFrameIndex = -1;
|
||||
_streamedIndex = -1;
|
||||
const auto images = {
|
||||
&_radialImage,
|
||||
&_documentBubbleImage,
|
||||
&_themePreviewImage,
|
||||
&_saveMsgImage,
|
||||
&_footerImage,
|
||||
&_captionImage,
|
||||
&_groupThumbsImage,
|
||||
&_controlsImage,
|
||||
};
|
||||
for (const auto image : images) {
|
||||
image->setImage(QImage());
|
||||
}
|
||||
invalidateControls();
|
||||
}
|
||||
//
|
||||
//void OverlayWidget::RendererGL::invalidate() {
|
||||
// _trackFrameIndex = -1;
|
||||
// _streamedIndex = -1;
|
||||
// const auto images = {
|
||||
// &_radialImage,
|
||||
// &_documentBubbleImage,
|
||||
// &_themePreviewImage,
|
||||
// &_saveMsgImage,
|
||||
// &_footerImage,
|
||||
// &_captionImage,
|
||||
// &_groupThumbsImage,
|
||||
// &_controlsImage,
|
||||
// };
|
||||
// for (const auto image : images) {
|
||||
// image->setImage(QImage());
|
||||
// }
|
||||
// invalidateControls();
|
||||
//}
|
||||
|
||||
void OverlayWidget::RendererGL::paintUsingRaster(
|
||||
Ui::GL::Image &image,
|
||||
|
|
|
@ -70,7 +70,7 @@ private:
|
|||
void paintGroupThumbs(QRect outer, float64 opacity) override;
|
||||
void paintRoundedCorners(int radius) override;
|
||||
|
||||
void invalidate();
|
||||
//void invalidate();
|
||||
|
||||
void paintUsingRaster(
|
||||
Ui::GL::Image &image,
|
||||
|
@ -79,6 +79,7 @@ private:
|
|||
int bufferOffset,
|
||||
bool transparent = false);
|
||||
|
||||
void validateControlsFade();
|
||||
void validateControls();
|
||||
void invalidateControls();
|
||||
void toggleBlending(bool enabled);
|
||||
|
@ -105,6 +106,7 @@ private:
|
|||
|
||||
std::optional<QOpenGLBuffer> _contentBuffer;
|
||||
std::optional<QOpenGLShaderProgram> _imageProgram;
|
||||
std::optional<QOpenGLShaderProgram> _staticContentProgram;
|
||||
QOpenGLShader *_texturedVertexShader = nullptr;
|
||||
std::optional<QOpenGLShaderProgram> _withTransparencyProgram;
|
||||
std::optional<QOpenGLShaderProgram> _yuv420Program;
|
||||
|
@ -121,6 +123,7 @@ private:
|
|||
int _streamedIndex = 0;
|
||||
bool _chromaNV12 = false;
|
||||
|
||||
Ui::GL::Image _controlsFadeImage;
|
||||
Ui::GL::Image _radialImage;
|
||||
Ui::GL::Image _documentBubbleImage;
|
||||
Ui::GL::Image _themePreviewImage;
|
||||
|
@ -134,6 +137,9 @@ private:
|
|||
[[nodiscard]] static Control ControlMeta(OverState control);
|
||||
std::array<QRect, kControlsCount> _controlsTextures;
|
||||
|
||||
QRect _shadowTopTexture;
|
||||
QRect _shadowBottomTexture;
|
||||
|
||||
bool _blendingEnabled = false;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
|
|
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include "ui/painter.h"
|
||||
#include "media/view/media_view_pip.h"
|
||||
#include "styles/style_media_view.h"
|
||||
|
||||
namespace Media::View {
|
||||
|
||||
|
@ -73,6 +74,7 @@ void OverlayWidget::RendererSW::paintTransformedVideoFrame(
|
|||
return;
|
||||
}
|
||||
paintTransformedImage(_owner->videoFrame(), rect, rotation);
|
||||
paintControlsFade(rect, geometry.controlsOpacity);
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererSW::paintTransformedStaticContent(
|
||||
|
@ -89,10 +91,34 @@ void OverlayWidget::RendererSW::paintTransformedStaticContent(
|
|||
if (fillTransparentBackground) {
|
||||
_p->fillRect(rect, _transparentBrush);
|
||||
}
|
||||
if (image.isNull()) {
|
||||
return;
|
||||
if (!image.isNull()) {
|
||||
paintTransformedImage(image, rect, rotation);
|
||||
}
|
||||
paintTransformedImage(image, rect, rotation);
|
||||
paintControlsFade(rect, geometry.controlsOpacity);
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererSW::paintControlsFade(
|
||||
QRect geometry,
|
||||
float64 opacity) {
|
||||
_p->setOpacity(opacity);
|
||||
_p->setClipRect(geometry);
|
||||
const auto width = _owner->width();
|
||||
const auto &top = st::mediaviewShadowTop;
|
||||
const auto topShadow = QRect(
|
||||
QPoint(width - top.width(), 0),
|
||||
top.size());
|
||||
if (topShadow.intersected(geometry).intersects(_clipOuter)) {
|
||||
top.paint(*_p, topShadow.topLeft(), width);
|
||||
}
|
||||
const auto &bottom = st::mediaviewShadowBottom;
|
||||
const auto bottomShadow = QRect(
|
||||
QPoint(0, _owner->height() - bottom.height()),
|
||||
QSize(width, bottom.height()));
|
||||
if (bottomShadow.intersected(geometry).intersects(_clipOuter)) {
|
||||
bottom.fill(*_p, bottomShadow);
|
||||
}
|
||||
_p->setClipping(false);
|
||||
_p->setOpacity(1.);
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererSW::paintTransformedImage(
|
||||
|
|
|
@ -32,6 +32,7 @@ private:
|
|||
const QImage &image,
|
||||
QRect rect,
|
||||
int rotation);
|
||||
void paintControlsFade(QRect geometry, float64 opacity);
|
||||
void paintRadialLoading(
|
||||
QRect inner,
|
||||
bool radial,
|
||||
|
|
|
@ -790,6 +790,11 @@ void OverlayWidget::updateControlsGeometry() {
|
|||
_saveMsg.moveTo((width() - _saveMsg.width()) / 2, (height() - _saveMsg.height()) / 2);
|
||||
_photoRadialRect = QRect(QPoint((width() - st::radialSize.width()) / 2, (height() - st::radialSize.height()) / 2), st::radialSize);
|
||||
|
||||
const auto bottom = st::mediaviewShadowBottom.height();
|
||||
const auto top = st::mediaviewShadowTop.size();
|
||||
_bottomShadowRect = QRect(0, height() - bottom, width(), bottom);
|
||||
_topShadowRect = QRect(QPoint(width() - top.width(), 0), top);
|
||||
|
||||
updateControls();
|
||||
resizeContentByScreenSize();
|
||||
update();
|
||||
|
@ -1367,6 +1372,7 @@ bool OverlayWidget::updateControlsAnimation(crl::time now) {
|
|||
_controlsOpacity.update(dt, anim::linear);
|
||||
}
|
||||
_helper->setControlsOpacity(_controlsOpacity.current());
|
||||
const auto content = finalContentRect();
|
||||
const auto toUpdate = QRegion()
|
||||
+ (_over == OverLeftNav ? _leftNav : _leftNavIcon)
|
||||
+ (_over == OverRightNav ? _rightNav : _rightNavIcon)
|
||||
|
@ -1377,7 +1383,9 @@ bool OverlayWidget::updateControlsAnimation(crl::time now) {
|
|||
+ _nameNav
|
||||
+ _dateNav
|
||||
+ _captionRect.marginsAdded(st::mediaviewCaptionPadding)
|
||||
+ _groupThumbsRect;
|
||||
+ _groupThumbsRect
|
||||
+ content.intersected(_bottomShadowRect)
|
||||
+ content.intersected(_topShadowRect);
|
||||
update(toUpdate);
|
||||
return (dt < 1);
|
||||
}
|
||||
|
@ -1407,6 +1415,7 @@ QRect OverlayWidget::finalContentRect() const {
|
|||
}
|
||||
|
||||
OverlayWidget::ContentGeometry OverlayWidget::contentGeometry() const {
|
||||
const auto controlsOpacity = _controlsOpacity.current();
|
||||
const auto toRotation = qreal(finalContentRotation());
|
||||
const auto toRectRotated = QRectF(finalContentRect());
|
||||
const auto toRectCenter = toRectRotated.center();
|
||||
|
@ -1418,7 +1427,7 @@ OverlayWidget::ContentGeometry OverlayWidget::contentGeometry() const {
|
|||
toRectRotated.width())
|
||||
: toRectRotated;
|
||||
if (!_geometryAnimation.animating()) {
|
||||
return { toRect, toRotation };
|
||||
return { toRect, toRotation, controlsOpacity };
|
||||
}
|
||||
const auto fromRect = _oldGeometry.rect;
|
||||
const auto fromRotation = _oldGeometry.rotation;
|
||||
|
@ -1441,7 +1450,7 @@ OverlayWidget::ContentGeometry OverlayWidget::contentGeometry() const {
|
|||
fromRect.width() + (toRect.width() - fromRect.width()) * progress,
|
||||
fromRect.height() + (toRect.height() - fromRect.height()) * progress
|
||||
);
|
||||
return { useRect, useRotation };
|
||||
return { useRect, useRotation, controlsOpacity };
|
||||
}
|
||||
|
||||
void OverlayWidget::updateContentRect() {
|
||||
|
@ -4152,6 +4161,7 @@ void OverlayWidget::paintControls(
|
|||
const QRect &outer;
|
||||
const QRect &inner;
|
||||
const style::icon &icon;
|
||||
bool nonbright = false;
|
||||
};
|
||||
const QRect kEmpty;
|
||||
// When adding / removing controls please update RendererGL.
|
||||
|
@ -4161,13 +4171,15 @@ void OverlayWidget::paintControls(
|
|||
_leftNavVisible,
|
||||
_leftNav,
|
||||
_leftNavIcon,
|
||||
st::mediaviewLeft },
|
||||
st::mediaviewLeft,
|
||||
true },
|
||||
{
|
||||
OverRightNav,
|
||||
_rightNavVisible,
|
||||
_rightNav,
|
||||
_rightNavIcon,
|
||||
st::mediaviewRight },
|
||||
st::mediaviewRight,
|
||||
true },
|
||||
{
|
||||
OverSave,
|
||||
_saveVisible,
|
||||
|
@ -4193,9 +4205,9 @@ void OverlayWidget::paintControls(
|
|||
if (!control.visible) {
|
||||
continue;
|
||||
}
|
||||
const auto bg = overLevel(control.state);
|
||||
const auto icon = bg * st::mediaviewIconOverOpacity
|
||||
+ (1 - bg) * st::mediaviewIconOpacity;
|
||||
const auto progress = overLevel(control.state);
|
||||
const auto bg = progress;
|
||||
const auto icon = controlOpacity(progress, control.nonbright);
|
||||
renderer->paintControl(
|
||||
control.state,
|
||||
control.outer,
|
||||
|
@ -4206,6 +4218,15 @@ void OverlayWidget::paintControls(
|
|||
}
|
||||
}
|
||||
|
||||
float64 OverlayWidget::controlOpacity(
|
||||
float64 progress,
|
||||
bool nonbright) const {
|
||||
const auto normal = _windowed
|
||||
? kNormalIconOpacity
|
||||
: kMaximizedIconOpacity;
|
||||
return progress + (1. - progress) * normal;
|
||||
}
|
||||
|
||||
void OverlayWidget::paintFooterContent(
|
||||
Painter &p,
|
||||
QRect outer,
|
||||
|
@ -4221,7 +4242,7 @@ void OverlayWidget::paintFooterContent(
|
|||
const auto date = _dateNav.translated(shift);
|
||||
if (header.intersects(clip)) {
|
||||
auto o = _headerHasLink ? overLevel(OverHeader) : 0;
|
||||
p.setOpacity((o * st::mediaviewIconOverOpacity + (1 - o) * st::mediaviewIconOpacity) * opacity);
|
||||
p.setOpacity(controlOpacity(o) * opacity);
|
||||
p.drawText(header.left(), header.top() + st::mediaviewThickFont->ascent, _headerText);
|
||||
|
||||
if (o > 0) {
|
||||
|
@ -4235,7 +4256,7 @@ void OverlayWidget::paintFooterContent(
|
|||
// name
|
||||
if (_nameNav.isValid() && name.intersects(clip)) {
|
||||
float64 o = _from ? overLevel(OverName) : 0.;
|
||||
p.setOpacity((o * st::mediaviewIconOverOpacity + (1 - o) * st::mediaviewIconOpacity) * opacity);
|
||||
p.setOpacity(controlOpacity(o) * opacity);
|
||||
_fromNameLabel.drawElided(p, name.left(), name.top(), name.width());
|
||||
|
||||
if (o > 0) {
|
||||
|
@ -4247,7 +4268,7 @@ void OverlayWidget::paintFooterContent(
|
|||
// date
|
||||
if (date.intersects(clip)) {
|
||||
float64 o = overLevel(OverDate);
|
||||
p.setOpacity((o * st::mediaviewIconOverOpacity + (1 - o) * st::mediaviewIconOpacity) * opacity);
|
||||
p.setOpacity(controlOpacity(o) * opacity);
|
||||
p.drawText(date.left(), date.top() + st::mediaviewFont->ascent, _dateText);
|
||||
|
||||
if (o > 0) {
|
||||
|
@ -4323,6 +4344,7 @@ void OverlayWidget::handleKeyPress(not_null<QKeyEvent*> e) {
|
|||
} else if (_fullScreenVideo) {
|
||||
if (key == Qt::Key_Escape) {
|
||||
playbackToggleFullScreen();
|
||||
} else if (ctrl) {
|
||||
} else if (key == Qt::Key_0) {
|
||||
activateControls();
|
||||
restartAtSeekPosition(0);
|
||||
|
@ -4337,7 +4359,6 @@ void OverlayWidget::handleKeyPress(not_null<QKeyEvent*> e) {
|
|||
activateControls();
|
||||
seekRelativeTime(kSeekTimeMs);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -4379,8 +4400,6 @@ void OverlayWidget::handleKeyPress(not_null<QKeyEvent*> e) {
|
|||
zoomIn();
|
||||
} else if (key == Qt::Key_Minus || key == Qt::Key_Underscore) {
|
||||
zoomOut();
|
||||
} else if (key == Qt::Key_0) {
|
||||
zoomReset();
|
||||
} else if (key == Qt::Key_I) {
|
||||
update();
|
||||
}
|
||||
|
@ -5090,10 +5109,13 @@ bool OverlayWidget::filterApplicationEvent(
|
|||
not_null<QEvent*> e) {
|
||||
const auto type = e->type();
|
||||
if (type == QEvent::ShortcutOverride) {
|
||||
const auto keyEvent = static_cast<QKeyEvent*>(e.get());
|
||||
const auto ctrl = keyEvent->modifiers().testFlag(Qt::ControlModifier);
|
||||
if (keyEvent->key() == Qt::Key_F && ctrl && _streamed) {
|
||||
const auto event = static_cast<QKeyEvent*>(e.get());
|
||||
const auto key = event->key();
|
||||
const auto ctrl = event->modifiers().testFlag(Qt::ControlModifier);
|
||||
if (key == Qt::Key_F && ctrl && _streamed) {
|
||||
playbackToggleFullScreen();
|
||||
} else if (key == Qt::Key_0 && ctrl) {
|
||||
zoomReset();
|
||||
}
|
||||
return true;
|
||||
} else if (type == QEvent::MouseMove
|
||||
|
|
|
@ -154,6 +154,7 @@ private:
|
|||
struct ContentGeometry {
|
||||
QRectF rect;
|
||||
qreal rotation = 0.;
|
||||
qreal controlsOpacity = 0.;
|
||||
};
|
||||
struct StartStreaming {
|
||||
StartStreaming() : continueStreaming(false), startTime(0) {
|
||||
|
@ -417,6 +418,9 @@ private:
|
|||
QRect clip,
|
||||
float64 opacity);
|
||||
|
||||
[[nodiscard]] float64 controlOpacity(
|
||||
float64 progress,
|
||||
bool nonbright = false) const;
|
||||
[[nodiscard]] bool isSaveMsgShown() const;
|
||||
|
||||
void updateOverRect(OverState state);
|
||||
|
@ -552,6 +556,9 @@ private:
|
|||
object_ptr<Ui::LinkButton> _docSaveAs;
|
||||
object_ptr<Ui::LinkButton> _docCancel;
|
||||
|
||||
QRect _bottomShadowRect;
|
||||
QRect _topShadowRect;
|
||||
|
||||
QRect _photoRadialRect;
|
||||
Ui::RadialAnimation _radial;
|
||||
|
||||
|
|