Fix media viewer on macOS multi-monitor setup.

This commit is contained in:
John Preston 2023-03-13 15:58:10 +04:00
parent cc6dfd08fc
commit 42d999922f
11 changed files with 66 additions and 8 deletions

View file

@ -234,7 +234,12 @@ void OverlayWidget::RendererGL::paint(
if (_factor != factor) { if (_factor != factor) {
_factor = factor; _factor = factor;
_controlsImage.invalidate(); _controlsImage.invalidate();
_controlsFadeImage.invalidate();
// We use the fact that fade texture atlas
// takes exactly full texture size. In case we
// just invalidate it we may get larger image
// in case of moving from greater _factor to lesser.
_controlsFadeImage.destroy(&f);
} }
_blendingEnabled = false; _blendingEnabled = false;
_viewport = widget->size(); _viewport = widget->size();
@ -468,10 +473,10 @@ void OverlayWidget::RendererGL::paintTransformedContent(
program->setUniformValue("viewport", _uniformViewport); program->setUniformValue("viewport", _uniformViewport);
const auto &top = st::mediaviewShadowTop.size(); const auto &top = st::mediaviewShadowTop.size();
const auto point = QPoint(_shadowTopFlip ? 0 : (_viewport.width() - top.width()), 0);
program->setUniformValue( program->setUniformValue(
"shadowTopRect", "shadowTopRect",
Uniform(transformRect( Uniform(transformRect(QRect(point, top))));
QRect(QPoint(_viewport.width() - top.width(), 0), top))));
const auto &bottom = st::mediaviewShadowBottom; const auto &bottom = st::mediaviewShadowBottom;
program->setUniformValue( program->setUniformValue(
"shadowBottomAndOpacity", "shadowBottomAndOpacity",
@ -687,9 +692,12 @@ void OverlayWidget::RendererGL::invalidateControls() {
} }
void OverlayWidget::RendererGL::validateControlsFade() { void OverlayWidget::RendererGL::validateControlsFade() {
if (!_controlsFadeImage.image().isNull()) { const auto flip = !_owner->topShadowOnTheRight();
if (!_controlsFadeImage.image().isNull()
&& _shadowTopFlip == flip) {
return; return;
} }
_shadowTopFlip = flip;
const auto width = st::mediaviewShadowTop.width(); const auto width = st::mediaviewShadowTop.width();
const auto bottomTop = st::mediaviewShadowTop.height(); const auto bottomTop = st::mediaviewShadowTop.height();
const auto height = bottomTop + st::mediaviewShadowBottom.height(); const auto height = bottomTop + st::mediaviewShadowBottom.height();
@ -707,6 +715,10 @@ void OverlayWidget::RendererGL::validateControlsFade() {
QRect(0, bottomTop, width, st::mediaviewShadowBottom.height())); QRect(0, bottomTop, width, st::mediaviewShadowBottom.height()));
p.end(); p.end();
if (flip) {
image = std::move(image).mirrored(true, false);
}
_controlsFadeImage.setImage(std::move(image)); _controlsFadeImage.setImage(std::move(image));
_shadowTopTexture = QRect( _shadowTopTexture = QRect(
QPoint(), QPoint(),

View file

@ -142,6 +142,7 @@ private:
QRect _shadowTopTexture; QRect _shadowTopTexture;
QRect _shadowBottomTexture; QRect _shadowBottomTexture;
bool _shadowTopFlip;
bool _blendingEnabled = false; bool _blendingEnabled = false;
rpl::lifetime _lifetime; rpl::lifetime _lifetime;

View file

@ -105,11 +105,22 @@ void OverlayWidget::RendererSW::paintControlsFade(
_p->setClipRect(geometry); _p->setClipRect(geometry);
const auto width = _owner->width(); const auto width = _owner->width();
const auto &top = st::mediaviewShadowTop; const auto &top = st::mediaviewShadowTop;
const auto flip = !_owner->topShadowOnTheRight();
const auto topShadow = QRect( const auto topShadow = QRect(
QPoint(width - top.width(), 0), QPoint(flip ? 0 : (width - top.width()), 0),
top.size()); top.size());
if (topShadow.intersected(geometry).intersects(_clipOuter)) { if (topShadow.intersected(geometry).intersects(_clipOuter)) {
top.paint(*_p, topShadow.topLeft(), width); if (flip) {
if (_topShadowCache.isNull()
|| _topShadowColor != st::windowShadowFg->c) {
_topShadowColor = st::windowShadowFg->c;
_topShadowCache = top.instance(
_topShadowColor).mirrored(true, false);
}
_p->drawImage(0, 0, _topShadowCache);
} else {
top.paint(*_p, topShadow.topLeft(), width);
}
} }
const auto &bottom = st::mediaviewShadowBottom; const auto &bottom = st::mediaviewShadowBottom;
const auto bottomShadow = QRect( const auto bottomShadow = QRect(

View file

@ -66,6 +66,9 @@ private:
QImage _overControlImage; QImage _overControlImage;
QImage _topShadowCache;
QColor _topShadowColor;
}; };
} // namespace Media::View } // namespace Media::View

View file

@ -493,6 +493,12 @@ OverlayWidget::OverlayWidget()
} }
} }
}, lifetime()); }, lifetime());
_topShadowRight = _helper->controlsSideRightValue();
_topShadowRight.changes(
) | rpl::start_with_next([=] {
updateControlsGeometry();
update();
}, lifetime());
_window->setTitle(u"Media viewer"_q); _window->setTitle(u"Media viewer"_q);
_window->setTitleStyle(st::mediaviewTitle); _window->setTitleStyle(st::mediaviewTitle);
@ -822,13 +828,19 @@ void OverlayWidget::updateControlsGeometry() {
const auto bottom = st::mediaviewShadowBottom.height(); const auto bottom = st::mediaviewShadowBottom.height();
const auto top = st::mediaviewShadowTop.size(); const auto top = st::mediaviewShadowTop.size();
_bottomShadowRect = QRect(0, height() - bottom, width(), bottom); _bottomShadowRect = QRect(0, height() - bottom, width(), bottom);
_topShadowRect = QRect(QPoint(width() - top.width(), 0), top); _topShadowRect = QRect(
QPoint(topShadowOnTheRight() ? (width() - top.width()) : 0, 0),
top);
updateControls(); updateControls();
resizeContentByScreenSize(); resizeContentByScreenSize();
update(); update();
} }
bool OverlayWidget::topShadowOnTheRight() const {
return _topShadowRight.current();
}
QSize OverlayWidget::flipSizeByRotation(QSize size) const { QSize OverlayWidget::flipSizeByRotation(QSize size) const {
return FlipSizeByRotation(size, _rotation); return FlipSizeByRotation(size, _rotation);
} }

View file

@ -458,6 +458,7 @@ private:
void clearStreaming(bool savePosition = true); void clearStreaming(bool savePosition = true);
bool canInitStreaming() const; bool canInitStreaming() const;
[[nodiscard]] bool topShadowOnTheRight() const;
void applyHideWindowWorkaround(); void applyHideWindowWorkaround();
Window::SessionController *findWindow(bool switchTo = true) const; Window::SessionController *findWindow(bool switchTo = true) const;
@ -561,6 +562,7 @@ private:
QRect _bottomShadowRect; QRect _bottomShadowRect;
QRect _topShadowRect; QRect _topShadowRect;
rpl::variable<bool> _topShadowRight = false;
QRect _photoRadialRect; QRect _photoRadialRect;
Ui::RadialAnimation _radial; Ui::RadialAnimation _radial;

View file

@ -35,6 +35,7 @@ public:
void minimize(not_null<Ui::RpWindow*> window) override; void minimize(not_null<Ui::RpWindow*> window) override;
void clearState() override; void clearState() override;
void setControlsOpacity(float64 opacity) override; void setControlsOpacity(float64 opacity) override;
rpl::producer<bool> controlsSideRightValue() override;
private: private:
using Control = Ui::Platform::TitleControl; using Control = Ui::Platform::TitleControl;

View file

@ -148,6 +148,10 @@ void MacOverlayWidgetHelper::setControlsOpacity(float64 opacity) {
_data->masterOpacity = opacity; _data->masterOpacity = opacity;
} }
rpl::producer<bool> MacOverlayWidgetHelper::controlsSideRightValue() {
return rpl::single(false);
}
object_ptr<Ui::AbstractButton> MacOverlayWidgetHelper::create( object_ptr<Ui::AbstractButton> MacOverlayWidgetHelper::create(
not_null<QWidget*> parent, not_null<QWidget*> parent,
Control control) { Control control) {

View file

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/effects/animations.h" #include "ui/effects/animations.h"
#include "ui/platform/ui_platform_window_title.h" #include "ui/platform/ui_platform_window_title.h"
#include "ui/platform/ui_platform_utility.h"
#include "ui/widgets/rp_window.h" #include "ui/widgets/rp_window.h"
#include "ui/abstract_button.h" #include "ui/abstract_button.h"
#include "styles/style_media_view.h" #include "styles/style_media_view.h"
@ -222,6 +223,13 @@ rpl::producer<> DefaultOverlayWidgetHelper::controlsActivations() {
return _buttons->activations(); return _buttons->activations();
} }
rpl::producer<bool> DefaultOverlayWidgetHelper::controlsSideRightValue() {
return Ui::Platform::TitleControlsLayoutValue() | rpl::map([=] {
return _controls->controls.geometry().center().x()
> _controls->wrap.geometry().center().x();
}) | rpl::distinct_until_changed();
}
void DefaultOverlayWidgetHelper::beforeShow(bool fullscreen) { void DefaultOverlayWidgetHelper::beforeShow(bool fullscreen) {
_buttons->clearState(); _buttons->clearState();
} }

View file

@ -38,6 +38,9 @@ public:
[[nodiscard]] virtual rpl::producer<> controlsActivations() { [[nodiscard]] virtual rpl::producer<> controlsActivations() {
return rpl::never<>(); return rpl::never<>();
} }
[[nodiscard]] virtual rpl::producer<bool> controlsSideRightValue() {
return rpl::single(true);
}
virtual void beforeShow(bool fullscreen) { virtual void beforeShow(bool fullscreen) {
} }
virtual void afterShow(bool fullscreen) { virtual void afterShow(bool fullscreen) {
@ -72,6 +75,7 @@ public:
void beforeShow(bool fullscreen) override; void beforeShow(bool fullscreen) override;
void clearState() override; void clearState() override;
void setControlsOpacity(float64 opacity) override; void setControlsOpacity(float64 opacity) override;
rpl::producer<bool> controlsSideRightValue() override;
rpl::producer<not_null<QMouseEvent*>> mouseEvents() const override; rpl::producer<not_null<QMouseEvent*>> mouseEvents() const override;
private: private:

@ -1 +1 @@
Subproject commit 849a84050356a1321eedc36eb5296374e42fadd6 Subproject commit c80df2cdd2d2838d5e4aab50075e4f6e7c05e380