mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-15 21:57:10 +02:00
Choose OpenGL / Raster surface at runtime.
This commit is contained in:
parent
9510ba07f7
commit
a45064257a
10 changed files with 343 additions and 236 deletions
|
@ -29,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/wrap/fade_wrap.h"
|
||||
#include "ui/wrap/padding_wrap.h"
|
||||
#include "ui/platform/ui_platform_utility.h"
|
||||
#include "ui/gl/gl_surface.h"
|
||||
#include "ui/toast/toast.h"
|
||||
#include "ui/empty_userpic.h"
|
||||
#include "ui/emoji_config.h"
|
||||
|
@ -50,35 +51,27 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include <QtGui/QWindow>
|
||||
|
||||
namespace Calls {
|
||||
namespace {
|
||||
|
||||
#if 1
|
||||
#define USE_OPENGL_OVERLAY_WIDGET 1
|
||||
#else // Q_OS_MAC && !OS_MAC_OLD
|
||||
#define USE_OPENGL_OVERLAY_WIDGET 0
|
||||
#endif // Q_OS_MAC && !OS_MAC_OLD
|
||||
|
||||
#if USE_OPENGL_OVERLAY_WIDGET
|
||||
using IncomingParent = Ui::RpWidgetWrap<QOpenGLWidget>;
|
||||
#else // USE_OPENGL_OVERLAY_WIDGET
|
||||
using IncomingParent = Ui::RpWidget;
|
||||
#endif // USE_OPENGL_OVERLAY_WIDGET
|
||||
|
||||
} // namespace
|
||||
|
||||
class Panel::Incoming final : public IncomingParent {
|
||||
class Panel::Incoming final {
|
||||
public:
|
||||
Incoming(
|
||||
not_null<QWidget*> parent,
|
||||
not_null<Webrtc::VideoTrack*> track);
|
||||
|
||||
[[nodiscard]] not_null<QWidget*> widget() const;
|
||||
[[nodiscard]] not_null<Ui::RpWidgetWrap* > rp() const;
|
||||
|
||||
private:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void paint(QPainter &p, const QRegion &clip, bool opengl);
|
||||
|
||||
void initBottomShadow();
|
||||
void fillTopShadow(QPainter &p);
|
||||
void fillBottomShadow(QPainter &p);
|
||||
|
||||
[[nodiscard]] Ui::GL::ChosenRenderer chooseRenderer(
|
||||
Ui::GL::Capabilities capabilities);
|
||||
|
||||
const std::unique_ptr<Ui::RpWidgetWrap> _surface;
|
||||
const not_null<Webrtc::VideoTrack*> _track;
|
||||
QPixmap _bottomShadow;
|
||||
|
||||
|
@ -87,35 +80,76 @@ private:
|
|||
Panel::Incoming::Incoming(
|
||||
not_null<QWidget*> parent,
|
||||
not_null<Webrtc::VideoTrack*> track)
|
||||
: IncomingParent(parent)
|
||||
: _surface(Ui::GL::CreateSurface(
|
||||
parent,
|
||||
[=](Ui::GL::Capabilities capabilities) {
|
||||
return chooseRenderer(capabilities);
|
||||
}))
|
||||
, _track(track) {
|
||||
initBottomShadow();
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
widget()->setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
widget()->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
}
|
||||
|
||||
void Panel::Incoming::paintEvent(QPaintEvent *e) {
|
||||
QPainter p(this);
|
||||
not_null<QWidget*> Panel::Incoming::widget() const {
|
||||
return _surface->rpWidget();
|
||||
}
|
||||
|
||||
not_null<Ui::RpWidgetWrap*> Panel::Incoming::rp() const {
|
||||
return _surface.get();
|
||||
}
|
||||
|
||||
Ui::GL::ChosenRenderer Panel::Incoming::chooseRenderer(
|
||||
Ui::GL::Capabilities capabilities) {
|
||||
class Renderer : public Ui::GL::Renderer {
|
||||
public:
|
||||
Renderer(not_null<Panel::Incoming*> owner) : _owner(owner) {
|
||||
}
|
||||
|
||||
void paintFallback(
|
||||
QPainter &&p,
|
||||
const QRegion &clip,
|
||||
Ui::GL::Backend backend) override {
|
||||
_owner->paint(
|
||||
p,
|
||||
clip.boundingRect(),
|
||||
backend == Ui::GL::Backend::OpenGL);
|
||||
}
|
||||
|
||||
private:
|
||||
const not_null<Panel::Incoming*> _owner;
|
||||
|
||||
};
|
||||
|
||||
return {
|
||||
.renderer = std::make_unique<Renderer>(this),
|
||||
.backend = (capabilities.supported
|
||||
? Ui::GL::Backend::OpenGL
|
||||
: Ui::GL::Backend::Raster),
|
||||
};
|
||||
}
|
||||
|
||||
void Panel::Incoming::paint(QPainter &p, const QRegion &clip, bool opengl) {
|
||||
const auto [image, rotation] = _track->frameOriginalWithRotation();
|
||||
if (image.isNull()) {
|
||||
p.fillRect(e->rect(), Qt::black);
|
||||
p.fillRect(clip.boundingRect(), Qt::black);
|
||||
} else {
|
||||
const auto rect = widget()->rect();
|
||||
using namespace Media::View;
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
if (UsePainterRotation(rotation, USE_OPENGL_OVERLAY_WIDGET)) {
|
||||
if (UsePainterRotation(rotation, opengl)) {
|
||||
if (rotation) {
|
||||
p.save();
|
||||
p.rotate(rotation);
|
||||
}
|
||||
p.drawImage(RotatedRect(rect(), rotation), image);
|
||||
p.drawImage(RotatedRect(rect, rotation), image);
|
||||
if (rotation) {
|
||||
p.restore();
|
||||
}
|
||||
} else if (rotation) {
|
||||
p.drawImage(rect(), RotateFrameImage(image, rotation));
|
||||
p.drawImage(rect, RotateFrameImage(image, rotation));
|
||||
} else {
|
||||
p.drawImage(rect(), image);
|
||||
p.drawImage(rect, image);
|
||||
}
|
||||
fillBottomShadow(p);
|
||||
fillTopShadow(p);
|
||||
|
@ -146,18 +180,19 @@ void Panel::Incoming::initBottomShadow() {
|
|||
|
||||
void Panel::Incoming::fillTopShadow(QPainter &p) {
|
||||
#ifdef Q_OS_WIN
|
||||
const auto width = parentWidget()->width();
|
||||
const auto width = widget()->parentWidget()->width();
|
||||
const auto position = QPoint(width - st::callTitleShadow.width(), 0);
|
||||
const auto shadowArea = QRect(
|
||||
position,
|
||||
st::callTitleShadow.size());
|
||||
const auto fill = shadowArea.intersected(geometry()).translated(-pos());
|
||||
const auto fill = shadowArea.intersected(
|
||||
widget()->geometry()).translated(-widget()->pos());
|
||||
if (fill.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
p.save();
|
||||
p.setClipRect(fill);
|
||||
st::callTitleShadow.paint(p, position - pos(), width);
|
||||
st::callTitleShadow.paint(p, position - widget()->pos(), width);
|
||||
p.restore();
|
||||
#endif // Q_OS_WIN
|
||||
}
|
||||
|
@ -165,10 +200,11 @@ void Panel::Incoming::fillTopShadow(QPainter &p) {
|
|||
void Panel::Incoming::fillBottomShadow(QPainter &p) {
|
||||
const auto shadowArea = QRect(
|
||||
0,
|
||||
parentWidget()->height() - st::callBottomShadowSize,
|
||||
parentWidget()->width(),
|
||||
widget()->parentWidget()->height() - st::callBottomShadowSize,
|
||||
widget()->parentWidget()->width(),
|
||||
st::callBottomShadowSize);
|
||||
const auto fill = shadowArea.intersected(geometry()).translated(-pos());
|
||||
const auto fill = shadowArea.intersected(
|
||||
widget()->geometry()).translated(-widget()->pos());
|
||||
if (fill.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -178,7 +214,8 @@ void Panel::Incoming::fillBottomShadow(QPainter &p) {
|
|||
_bottomShadow,
|
||||
QRect(
|
||||
0,
|
||||
factor * (fill.y() - shadowArea.translated(-pos()).y()),
|
||||
(factor
|
||||
* (fill.y() - shadowArea.translated(-widget()->pos()).y())),
|
||||
factor,
|
||||
factor * fill.height()));
|
||||
}
|
||||
|
@ -394,7 +431,7 @@ void Panel::refreshIncomingGeometry() {
|
|||
Expects(_incoming != nullptr);
|
||||
|
||||
if (_incomingFrameSize.isEmpty()) {
|
||||
_incoming->hide();
|
||||
_incoming->widget()->hide();
|
||||
return;
|
||||
}
|
||||
const auto to = widget()->size();
|
||||
|
@ -411,8 +448,8 @@ void Panel::refreshIncomingGeometry() {
|
|||
const auto pos = QPoint(
|
||||
(to.width() - use.width()) / 2,
|
||||
(to.height() - use.height()) / 2);
|
||||
_incoming->setGeometry(QRect(pos, use));
|
||||
_incoming->show();
|
||||
_incoming->widget()->setGeometry(QRect(pos, use));
|
||||
_incoming->widget()->show();
|
||||
}
|
||||
|
||||
void Panel::reinitWithCall(Call *call) {
|
||||
|
@ -449,7 +486,7 @@ void Panel::reinitWithCall(Call *call) {
|
|||
_incoming = std::make_unique<Incoming>(
|
||||
widget(),
|
||||
_call->videoIncoming());
|
||||
_incoming->hide();
|
||||
_incoming->widget()->hide();
|
||||
|
||||
_call->mutedValue(
|
||||
) | rpl::start_with_next([=](bool mute) {
|
||||
|
@ -480,12 +517,12 @@ void Panel::reinitWithCall(Call *call) {
|
|||
setIncomingSize((rotation == 90 || rotation == 270)
|
||||
? QSize(frame.height(), frame.width())
|
||||
: frame.size());
|
||||
if (_incoming->isHidden()) {
|
||||
if (_incoming->widget()->isHidden()) {
|
||||
return;
|
||||
}
|
||||
const auto incoming = incomingFrameGeometry();
|
||||
const auto outgoing = outgoingFrameGeometry();
|
||||
_incoming->update();
|
||||
_incoming->widget()->update();
|
||||
if (incoming.intersects(outgoing)) {
|
||||
widget()->update(outgoing);
|
||||
}
|
||||
|
@ -497,7 +534,7 @@ void Panel::reinitWithCall(Call *call) {
|
|||
const auto outgoing = outgoingFrameGeometry();
|
||||
widget()->update(outgoing);
|
||||
if (incoming.intersects(outgoing)) {
|
||||
_incoming->update();
|
||||
_incoming->widget()->update();
|
||||
}
|
||||
}, _callLifetime);
|
||||
|
||||
|
@ -541,7 +578,7 @@ void Panel::reinitWithCall(Call *call) {
|
|||
_name->setText(_user->name);
|
||||
updateStatusText(_call->state());
|
||||
|
||||
_incoming->lower();
|
||||
_incoming->widget()->lower();
|
||||
}
|
||||
|
||||
void Panel::createRemoteAudioMute() {
|
||||
|
@ -606,7 +643,7 @@ void Panel::showControls() {
|
|||
_cancel->setVisible(_cancel->toggled());
|
||||
|
||||
const auto shown = !_incomingFrameSize.isEmpty();
|
||||
_incoming->setVisible(shown);
|
||||
_incoming->widget()->setVisible(shown);
|
||||
_name->setVisible(!shown);
|
||||
_status->setVisible(!shown);
|
||||
_userpic->setVisible(!shown);
|
||||
|
@ -650,9 +687,9 @@ void Panel::toggleFullScreen(bool fullscreen) {
|
|||
}
|
||||
|
||||
QRect Panel::incomingFrameGeometry() const {
|
||||
return (!_incoming || _incoming->isHidden())
|
||||
return (!_incoming || _incoming->widget()->isHidden())
|
||||
? QRect()
|
||||
: _incoming->geometry();
|
||||
: _incoming->widget()->geometry();
|
||||
}
|
||||
|
||||
QRect Panel::outgoingFrameGeometry() const {
|
||||
|
@ -788,13 +825,13 @@ void Panel::paint(QRect clip) {
|
|||
Painter p(widget());
|
||||
|
||||
auto region = QRegion(clip);
|
||||
if (!_incoming->isHidden()) {
|
||||
region = region.subtracted(QRegion(_incoming->geometry()));
|
||||
if (!_incoming->widget()->isHidden()) {
|
||||
region = region.subtracted(QRegion(_incoming->widget()->geometry()));
|
||||
}
|
||||
for (const auto rect : region) {
|
||||
p.fillRect(rect, st::callBgOpaque);
|
||||
}
|
||||
if (_incoming && _incoming->isHidden()) {
|
||||
if (_incoming && _incoming->widget()->isHidden()) {
|
||||
_call->videoIncoming()->markFrameShown();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,11 +13,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "webrtc/webrtc_video_track.h"
|
||||
#include "ui/painter.h"
|
||||
#include "ui/abstract_button.h"
|
||||
#include "ui/gl/gl_surface.h"
|
||||
#include "ui/effects/animations.h"
|
||||
#include "ui/effects/cross_line.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "styles/style_calls.h"
|
||||
|
||||
#include <QtGui/QWindow>
|
||||
|
||||
namespace Calls::Group {
|
||||
namespace {
|
||||
|
||||
|
@ -57,31 +60,64 @@ LargeVideo::LargeVideo(
|
|||
bool visible,
|
||||
rpl::producer<LargeVideoTrack> track,
|
||||
rpl::producer<bool> pinned)
|
||||
: _content(parent, [=](QRect clip) { paint(clip); })
|
||||
: _content(Ui::GL::CreateSurface(
|
||||
parent,
|
||||
[=](Ui::GL::Capabilities capabilities) {
|
||||
return chooseRenderer(capabilities);
|
||||
}))
|
||||
, _st(st)
|
||||
, _pinButton((_st.pinPosition.x() >= 0)
|
||||
? std::make_unique<PinButton>(&_content, st)
|
||||
? std::make_unique<PinButton>(widget(), st)
|
||||
: nullptr)
|
||||
, _smallLayout(!_pinButton) {
|
||||
_content.setVisible(visible);
|
||||
widget()->setVisible(visible);
|
||||
if (_smallLayout) {
|
||||
_content.setCursor(style::cur_pointer);
|
||||
widget()->setCursor(style::cur_pointer);
|
||||
}
|
||||
setup(std::move(track), std::move(pinned));
|
||||
}
|
||||
|
||||
LargeVideo::~LargeVideo() = default;
|
||||
|
||||
Ui::GL::ChosenRenderer LargeVideo::chooseRenderer(
|
||||
Ui::GL::Capabilities capabilities) {
|
||||
class Renderer : public Ui::GL::Renderer {
|
||||
public:
|
||||
Renderer(not_null<LargeVideo*> owner) : _owner(owner) {
|
||||
}
|
||||
|
||||
void paintFallback(
|
||||
QPainter &&p,
|
||||
const QRegion &clip,
|
||||
Ui::GL::Backend backend) override {
|
||||
_owner->paint(
|
||||
clip.boundingRect(),
|
||||
backend == Ui::GL::Backend::OpenGL);
|
||||
}
|
||||
|
||||
private:
|
||||
const not_null<LargeVideo*> _owner;
|
||||
|
||||
};
|
||||
|
||||
return {
|
||||
.renderer = std::make_unique<Renderer>(this),
|
||||
.backend = (capabilities.supported
|
||||
? Ui::GL::Backend::OpenGL
|
||||
: Ui::GL::Backend::Raster),
|
||||
};
|
||||
}
|
||||
|
||||
void LargeVideo::raise() {
|
||||
_content.raise();
|
||||
widget()->raise();
|
||||
}
|
||||
|
||||
void LargeVideo::setVisible(bool visible) {
|
||||
_content.setVisible(visible);
|
||||
widget()->setVisible(visible);
|
||||
}
|
||||
|
||||
void LargeVideo::setGeometry(int x, int y, int width, int height) {
|
||||
_content.setGeometry(x, y, width, height);
|
||||
widget()->setGeometry(x, y, width, height);
|
||||
if (width > 0 && height > 0) {
|
||||
const auto kMedium = style::ConvertScale(380);
|
||||
const auto kSmall = style::ConvertScale(200);
|
||||
|
@ -98,7 +134,7 @@ void LargeVideo::setControlsShown(float64 shown) {
|
|||
return;
|
||||
}
|
||||
_controlsShownRatio = shown;
|
||||
_content.update();
|
||||
widget()->update();
|
||||
updateControlsGeometry();
|
||||
}
|
||||
|
||||
|
@ -119,19 +155,27 @@ rpl::producer<QSize> LargeVideo::trackSizeValue() const {
|
|||
rpl::producer<VideoQuality> LargeVideo::requestedQuality() const {
|
||||
using namespace rpl::mappers;
|
||||
return rpl::combine(
|
||||
_content.shownValue(),
|
||||
_content->shownValue(),
|
||||
_requestedQuality.value()
|
||||
) | rpl::filter([=](bool shown, auto) {
|
||||
return shown;
|
||||
}) | rpl::map(_2);
|
||||
}
|
||||
|
||||
rpl::lifetime &LargeVideo::lifetime() {
|
||||
return _content->lifetime();
|
||||
}
|
||||
|
||||
not_null<QWidget*> LargeVideo::widget() const {
|
||||
return _content->rpWidget();
|
||||
}
|
||||
|
||||
void LargeVideo::setup(
|
||||
rpl::producer<LargeVideoTrack> track,
|
||||
rpl::producer<bool> pinned) {
|
||||
_content.setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
widget()->setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
|
||||
_content.events(
|
||||
_content->events(
|
||||
) | rpl::start_with_next([=](not_null<QEvent*> e) {
|
||||
const auto type = e->type();
|
||||
if (type == QEvent::Enter && _pinButton) {
|
||||
|
@ -147,21 +191,21 @@ void LargeVideo::setup(
|
|||
e.get())->button() == Qt::LeftButton
|
||||
&& _mouseDown) {
|
||||
_mouseDown = false;
|
||||
if (!_content.isHidden()) {
|
||||
if (!widget()->isHidden()) {
|
||||
_clicks.fire({});
|
||||
}
|
||||
}
|
||||
}, _content.lifetime());
|
||||
}, _content->lifetime());
|
||||
|
||||
rpl::combine(
|
||||
_content.shownValue(),
|
||||
_content->shownValue(),
|
||||
std::move(track)
|
||||
) | rpl::map([=](bool shown, LargeVideoTrack track) {
|
||||
return shown ? track : LargeVideoTrack();
|
||||
}) | rpl::distinct_until_changed(
|
||||
) | rpl::start_with_next([=](LargeVideoTrack track) {
|
||||
_track = track;
|
||||
_content.update();
|
||||
widget()->update();
|
||||
|
||||
_trackLifetime.destroy();
|
||||
if (!track.track) {
|
||||
|
@ -176,12 +220,12 @@ void LargeVideo::setup(
|
|||
} else {
|
||||
_trackSize = size;
|
||||
}
|
||||
_content.update();
|
||||
widget()->update();
|
||||
}, _trackLifetime);
|
||||
if (const auto size = track.track->frameSize(); !size.isEmpty()) {
|
||||
_trackSize = size;
|
||||
}
|
||||
}, _content.lifetime());
|
||||
}, _content->lifetime());
|
||||
|
||||
setupControls(std::move(pinned));
|
||||
}
|
||||
|
@ -194,7 +238,7 @@ void LargeVideo::togglePinShown(bool shown) {
|
|||
}
|
||||
_pinButton->shown = shown;
|
||||
_pinButton->shownAnimation.start(
|
||||
[=] { updateControlsGeometry(); _content.update(); },
|
||||
[=] { updateControlsGeometry(); widget()->update(); },
|
||||
shown ? 0. : 1.,
|
||||
shown ? 1. : 0.,
|
||||
st::slideWrapDuration);
|
||||
|
@ -211,13 +255,13 @@ void LargeVideo::setupControls(rpl::producer<bool> pinned) {
|
|||
: tr::lng_pinned_pin)(tr::now));
|
||||
updateControlsGeometry();
|
||||
}
|
||||
_content.update();
|
||||
}, _content.lifetime());
|
||||
widget()->update();
|
||||
}, _content->lifetime());
|
||||
|
||||
_content.sizeValue(
|
||||
_content->sizeValue(
|
||||
) | rpl::start_with_next([=](QSize size) {
|
||||
updateControlsGeometry();
|
||||
}, _content.lifetime());
|
||||
}, _content->lifetime());
|
||||
}
|
||||
|
||||
void LargeVideo::updateControlsGeometry() {
|
||||
|
@ -236,20 +280,20 @@ void LargeVideo::updateControlsGeometry() {
|
|||
0,
|
||||
_pinButton->shownAnimation.value(_pinButton->shown ? 1. : 0.));
|
||||
_pinButton->rect = QRect(
|
||||
_content.width() - _st.pinPosition.x() - buttonWidth,
|
||||
widget()->width() - _st.pinPosition.x() - buttonWidth,
|
||||
_st.pinPosition.y() - slide,
|
||||
buttonWidth,
|
||||
buttonHeight);
|
||||
_pinButton->area.setGeometry(
|
||||
_content.width() - fullWidth,
|
||||
widget()->width() - fullWidth,
|
||||
-slide,
|
||||
fullWidth,
|
||||
fullHeight);
|
||||
}
|
||||
}
|
||||
|
||||
void LargeVideo::paint(QRect clip) {
|
||||
auto p = Painter(&_content);
|
||||
void LargeVideo::paint(QRect clip, bool opengl) {
|
||||
auto p = Painter(widget());
|
||||
const auto fill = [&](QRect rect) {
|
||||
if (rect.intersects(clip)) {
|
||||
p.fillRect(rect.intersected(clip), st::groupCallMembersBg);
|
||||
|
@ -264,7 +308,7 @@ void LargeVideo::paint(QRect clip) {
|
|||
}
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
using namespace Media::View;
|
||||
const auto size = _content.size();
|
||||
const auto size = widget()->size();
|
||||
const auto scaled = FlipSizeByRotation(
|
||||
image.size(),
|
||||
rotation
|
||||
|
@ -272,7 +316,7 @@ void LargeVideo::paint(QRect clip) {
|
|||
const auto left = (size.width() - scaled.width()) / 2;
|
||||
const auto top = (size.height() - scaled.height()) / 2;
|
||||
const auto target = QRect(QPoint(left, top), scaled);
|
||||
if (UsePainterRotation(rotation, USE_OPENGL_LARGE_VIDEO)) {
|
||||
if (UsePainterRotation(rotation, opengl)) {
|
||||
if (rotation) {
|
||||
p.save();
|
||||
p.rotate(rotation);
|
||||
|
@ -307,8 +351,8 @@ void LargeVideo::paint(QRect clip) {
|
|||
}
|
||||
|
||||
void LargeVideo::paintControls(Painter &p, QRect clip) {
|
||||
const auto width = _content.width();
|
||||
const auto height = _content.height();
|
||||
const auto width = widget()->width();
|
||||
const auto height = widget()->height();
|
||||
|
||||
// Pin.
|
||||
if (_pinButton && _pinButton->rect.intersects(clip)) {
|
||||
|
|
|
@ -9,12 +9,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include "ui/rp_widget.h"
|
||||
|
||||
#if 1
|
||||
#define USE_OPENGL_LARGE_VIDEO 1
|
||||
#else
|
||||
#define USE_OPENGL_LARGE_VIDEO 0
|
||||
#endif // Q_OS_MAC
|
||||
|
||||
namespace style {
|
||||
struct GroupCallLargeVideo;
|
||||
} // namespace style
|
||||
|
@ -25,6 +19,11 @@ class VideoTrack;
|
|||
|
||||
namespace Ui {
|
||||
class AbstractButton;
|
||||
class RpWidgetWrap;
|
||||
namespace GL {
|
||||
struct Capabilities;
|
||||
struct ChosenRenderer;
|
||||
} // namespace GL
|
||||
} // namespace Ui
|
||||
|
||||
namespace Calls::Group {
|
||||
|
@ -77,45 +76,26 @@ public:
|
|||
[[nodiscard]] rpl::producer<QSize> trackSizeValue() const;
|
||||
[[nodiscard]] rpl::producer<VideoQuality> requestedQuality() const;
|
||||
|
||||
[[nodiscard]] rpl::lifetime &lifetime() {
|
||||
return _content.lifetime();
|
||||
}
|
||||
[[nodiscard]] rpl::lifetime &lifetime();
|
||||
|
||||
private:
|
||||
#if USE_OPENGL_LARGE_VIDEO
|
||||
using ContentParent = Ui::RpWidgetWrap<QOpenGLWidget>;
|
||||
#else // USE_OPENGL_OVERLAY_WIDGET
|
||||
using ContentParent = Ui::RpWidget;
|
||||
#endif // USE_OPENGL_OVERLAY_WIDGET
|
||||
|
||||
class Content final : public ContentParent {
|
||||
public:
|
||||
Content(QWidget *parent, Fn<void(QRect)> paint)
|
||||
: ContentParent(parent), _paint(std::move(paint)) {
|
||||
Expects(_paint != nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
void paintEvent(QPaintEvent *e) override {
|
||||
_paint(e->rect());
|
||||
}
|
||||
|
||||
Fn<void(QRect)> _paint;
|
||||
|
||||
};
|
||||
|
||||
struct PinButton;
|
||||
|
||||
[[nodiscard]] not_null<QWidget*> widget() const;
|
||||
|
||||
void setup(
|
||||
rpl::producer<LargeVideoTrack> track,
|
||||
rpl::producer<bool> pinned);
|
||||
void setupControls(rpl::producer<bool> pinned);
|
||||
void paint(QRect clip);
|
||||
void paint(QRect clip, bool opengl);
|
||||
void paintControls(Painter &p, QRect clip);
|
||||
void updateControlsGeometry();
|
||||
void togglePinShown(bool shown);
|
||||
|
||||
Content _content;
|
||||
[[nodiscard]] Ui::GL::ChosenRenderer chooseRenderer(
|
||||
Ui::GL::Capabilities capabilities);
|
||||
|
||||
const std::unique_ptr<Ui::RpWidgetWrap> _content;
|
||||
const style::GroupCallLargeVideo &_st;
|
||||
LargeVideoTrack _track;
|
||||
QImage _shadow;
|
||||
|
|
|
@ -1263,11 +1263,9 @@ void Panel::setupPinnedVideo() {
|
|||
raw->events(
|
||||
) | rpl::start_with_next([=](not_null<QEvent*> e) {
|
||||
if (e->type() == QEvent::Enter) {
|
||||
LOG(("Track Enter"));
|
||||
Ui::Integration::Instance().registerLeaveSubscription(raw);
|
||||
toggleWideControls(true);
|
||||
} else if (e->type() == QEvent::Leave) {
|
||||
LOG(("Track Leave"));
|
||||
Ui::Integration::Instance().unregisterLeaveSubscription(raw);
|
||||
toggleWideControls(false);
|
||||
}
|
||||
|
@ -1281,12 +1279,10 @@ void Panel::toggleWideControls(bool shown) {
|
|||
return;
|
||||
}
|
||||
_showWideControls = shown;
|
||||
LOG(("On Main Scheduled"));
|
||||
crl::on_main(widget(), [=] {
|
||||
if (_wideControlsShown == _showWideControls) {
|
||||
return;
|
||||
}
|
||||
LOG(("On Main Fired: %1").arg(Logs::b(_showWideControls)));
|
||||
_wideControlsShown = _showWideControls;
|
||||
_wideControlsAnimation.start(
|
||||
[=] { updateButtonsGeometry(); },
|
||||
|
@ -1343,7 +1339,7 @@ void Panel::setupAllowedToSpeakToasts() {
|
|||
Ui::ShowMultilineToast({
|
||||
.parentOverride = widget(),
|
||||
.text = { tr::lng_group_call_can_speak_here(tr::now) },
|
||||
});
|
||||
});
|
||||
} else {
|
||||
const auto real = _call->lookupReal();
|
||||
const auto name = (real && !real->title().isEmpty())
|
||||
|
@ -1355,7 +1351,7 @@ void Panel::setupAllowedToSpeakToasts() {
|
|||
lt_chat,
|
||||
Ui::Text::Bold(name),
|
||||
Ui::Text::WithEntities),
|
||||
});
|
||||
});
|
||||
}
|
||||
}, widget()->lifetime());
|
||||
}
|
||||
|
@ -1866,10 +1862,8 @@ void Panel::trackControls(bool track) {
|
|||
raw->events(
|
||||
) | rpl::start_with_next([=](not_null<QEvent*> e) {
|
||||
if (e->type() == QEvent::Enter) {
|
||||
LOG(("Track Enter"));
|
||||
toggleWideControls(true);
|
||||
} else if (e->type() == QEvent::Leave) {
|
||||
LOG(("Track Leave"));
|
||||
toggleWideControls(false);
|
||||
}
|
||||
}, _trackControlsOverStateLifetime);
|
||||
|
|
|
@ -300,6 +300,8 @@ public:
|
|||
[[nodiscard]] ImageLocation userpicLocation() const {
|
||||
return _userpic.location();
|
||||
}
|
||||
|
||||
static constexpr auto kUnknownPhotoId = PhotoId(0xFFFFFFFFFFFFFFFFULL);
|
||||
[[nodiscard]] bool userpicPhotoUnknown() const {
|
||||
return (_userpicPhotoId == kUnknownPhotoId);
|
||||
}
|
||||
|
@ -411,8 +413,6 @@ private:
|
|||
|
||||
void setUserpicChecked(PhotoId photoId, const ImageLocation &location);
|
||||
|
||||
static constexpr auto kUnknownPhotoId = PhotoId(0xFFFFFFFFFFFFFFFFULL);
|
||||
|
||||
const not_null<Data::Session*> _owner;
|
||||
|
||||
mutable Data::CloudImage _userpic;
|
||||
|
|
|
@ -474,7 +474,9 @@ void OverlayWidget::updateGeometry() {
|
|||
const auto useSizeHack = (USE_OPENGL_OVERLAY_WIDGET
|
||||
&& Platform::IsWindows());
|
||||
const auto use = available.marginsAdded({ 0, 0, 0, 1 });
|
||||
const auto mask = useSizeHack ? QRegion(available) : QRegion();
|
||||
const auto mask = useSizeHack
|
||||
? QRegion(QRect(QPoint(), available.size()))
|
||||
: QRegion();
|
||||
if ((geometry() == use)
|
||||
&& (!useSizeHack || (window && window->mask() == mask))) {
|
||||
return;
|
||||
|
|
|
@ -63,9 +63,9 @@ struct OverlayParentTraits : Ui::RpWidgetDefaultTraits {
|
|||
};
|
||||
|
||||
#if USE_OPENGL_OVERLAY_WIDGET
|
||||
using OverlayParent = Ui::RpWidgetWrap<QOpenGLWidget, OverlayParentTraits>;
|
||||
using OverlayParent = Ui::RpWidgetBase<QOpenGLWidget, OverlayParentTraits>;
|
||||
#else // USE_OPENGL_OVERLAY_WIDGET
|
||||
using OverlayParent = Ui::RpWidgetWrap<QWidget, OverlayParentTraits>;
|
||||
using OverlayParent = Ui::RpWidgetBase<QWidget, OverlayParentTraits>;
|
||||
#endif // USE_OPENGL_OVERLAY_WIDGET
|
||||
|
||||
class OverlayWidget final
|
||||
|
|
|
@ -26,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/wrap/fade_wrap.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
#include "ui/text/format_values.h"
|
||||
#include "ui/gl/gl_surface.h"
|
||||
#include "window/window_controller.h"
|
||||
#include "styles/style_widgets.h"
|
||||
#include "styles/style_window.h"
|
||||
|
@ -372,35 +373,77 @@ QImage RotateFrameImage(QImage image, int rotation) {
|
|||
|
||||
PipPanel::PipPanel(
|
||||
QWidget *parent,
|
||||
Fn<void(QPainter&, FrameRequest)> paint)
|
||||
: _parent(parent)
|
||||
Fn<void(QPainter&, FrameRequest, bool)> paint)
|
||||
: _content(Ui::GL::CreateSurface(
|
||||
parent,
|
||||
[=](Ui::GL::Capabilities capabilities) {
|
||||
return chooseRenderer(capabilities);
|
||||
}))
|
||||
, _parent(parent)
|
||||
, _paint(std::move(paint)) {
|
||||
}
|
||||
|
||||
Ui::GL::ChosenRenderer PipPanel::chooseRenderer(
|
||||
Ui::GL::Capabilities capabilities) {
|
||||
class Renderer : public Ui::GL::Renderer {
|
||||
public:
|
||||
Renderer(not_null<PipPanel*> owner) : _owner(owner) {
|
||||
}
|
||||
|
||||
void paintFallback(
|
||||
QPainter &&p,
|
||||
const QRegion &clip,
|
||||
Ui::GL::Backend backend) override {
|
||||
_owner->paint(
|
||||
p,
|
||||
clip,
|
||||
backend == Ui::GL::Backend::OpenGL);
|
||||
}
|
||||
|
||||
private:
|
||||
const not_null<PipPanel*> _owner;
|
||||
|
||||
};
|
||||
|
||||
return {
|
||||
.renderer = std::make_unique<Renderer>(this),
|
||||
.backend = (capabilities.supported
|
||||
? Ui::GL::Backend::OpenGL
|
||||
: Ui::GL::Backend::Raster),
|
||||
};
|
||||
}
|
||||
|
||||
void PipPanel::init() {
|
||||
setWindowFlags(Qt::Tool
|
||||
widget()->setWindowFlags(Qt::Tool
|
||||
| Qt::WindowStaysOnTopHint
|
||||
| Qt::FramelessWindowHint
|
||||
| Qt::WindowDoesNotAcceptFocus);
|
||||
setAttribute(Qt::WA_ShowWithoutActivating);
|
||||
setAttribute(Qt::WA_MacAlwaysShowToolWindow);
|
||||
setAttribute(Qt::WA_NoSystemBackground);
|
||||
setAttribute(Qt::WA_TranslucentBackground);
|
||||
Ui::Platform::IgnoreAllActivation(this);
|
||||
Ui::Platform::InitOnTopPanel(this);
|
||||
setMouseTracking(true);
|
||||
resize(0, 0);
|
||||
hide();
|
||||
createWinId();
|
||||
widget()->setAttribute(Qt::WA_ShowWithoutActivating);
|
||||
widget()->setAttribute(Qt::WA_MacAlwaysShowToolWindow);
|
||||
widget()->setAttribute(Qt::WA_NoSystemBackground);
|
||||
widget()->setAttribute(Qt::WA_TranslucentBackground);
|
||||
Ui::Platform::IgnoreAllActivation(widget());
|
||||
Ui::Platform::InitOnTopPanel(widget());
|
||||
widget()->setMouseTracking(true);
|
||||
widget()->resize(0, 0);
|
||||
widget()->hide();
|
||||
widget()->createWinId();
|
||||
|
||||
rp()->shownValue(
|
||||
) | rpl::filter([=](bool shown) {
|
||||
return shown;
|
||||
}) | rpl::start_with_next([=] {
|
||||
// Workaround Qt's forced transient parent.
|
||||
Ui::Platform::ClearTransientParent(widget());
|
||||
}, rp()->lifetime());
|
||||
}
|
||||
|
||||
void PipPanel::setVisibleHook(bool visible) {
|
||||
PipParent::setVisibleHook(visible);
|
||||
not_null<QWidget*> PipPanel::widget() const {
|
||||
return _content->rpWidget();
|
||||
}
|
||||
|
||||
// workaround Qt's forced transient parent
|
||||
if (visible) {
|
||||
Ui::Platform::ClearTransientParent(this);
|
||||
}
|
||||
not_null<Ui::RpWidgetWrap*> PipPanel::rp() const {
|
||||
return _content.get();
|
||||
}
|
||||
|
||||
void PipPanel::setAspectRatio(QSize ratio) {
|
||||
|
@ -411,7 +454,7 @@ void PipPanel::setAspectRatio(QSize ratio) {
|
|||
if (_ratio.isEmpty()) {
|
||||
_ratio = QSize(1, 1);
|
||||
}
|
||||
if (!size().isEmpty()) {
|
||||
if (!widget()->size().isEmpty()) {
|
||||
setPosition(countPosition());
|
||||
}
|
||||
}
|
||||
|
@ -429,7 +472,7 @@ void PipPanel::setPosition(Position position) {
|
|||
}
|
||||
|
||||
QRect PipPanel::inner() const {
|
||||
return rect().marginsRemoved(_padding);
|
||||
return widget()->rect().marginsRemoved(_padding);
|
||||
}
|
||||
|
||||
RectParts PipPanel::attached() const {
|
||||
|
@ -452,7 +495,10 @@ rpl::producer<> PipPanel::saveGeometryRequests() const {
|
|||
}
|
||||
|
||||
QScreen *PipPanel::myScreen() const {
|
||||
return windowHandle() ? windowHandle()->screen() : nullptr;
|
||||
if (const auto window = widget()->windowHandle()) {
|
||||
return window->screen();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PipPanel::Position PipPanel::countPosition() const {
|
||||
|
@ -462,7 +508,7 @@ PipPanel::Position PipPanel::countPosition() const {
|
|||
}
|
||||
auto result = Position();
|
||||
result.screen = screen->geometry();
|
||||
result.geometry = geometry().marginsRemoved(_padding);
|
||||
result.geometry = widget()->geometry().marginsRemoved(_padding);
|
||||
const auto available = screen->availableGeometry();
|
||||
const auto skip = st::pipBorderSkip;
|
||||
const auto left = result.geometry.x();
|
||||
|
@ -501,9 +547,9 @@ void PipPanel::setPositionDefault() {
|
|||
return nullptr;
|
||||
};
|
||||
const auto parentScreen = widgetScreen(_parent);
|
||||
const auto myScreen = widgetScreen(this);
|
||||
const auto myScreen = widgetScreen(widget());
|
||||
if (parentScreen && myScreen && myScreen != parentScreen) {
|
||||
windowHandle()->setScreen(parentScreen);
|
||||
widget()->windowHandle()->setScreen(parentScreen);
|
||||
}
|
||||
const auto screen = parentScreen
|
||||
? parentScreen
|
||||
|
@ -583,21 +629,19 @@ void PipPanel::setPositionOnScreen(Position position, QRect available) {
|
|||
|
||||
geometry += _padding;
|
||||
|
||||
setGeometry(geometry);
|
||||
setMinimumSize(minimalSize);
|
||||
setMaximumSize(
|
||||
widget()->setGeometry(geometry);
|
||||
widget()->setMinimumSize(minimalSize);
|
||||
widget()->setMaximumSize(
|
||||
std::max(minimalSize.width(), maximalSize.width()),
|
||||
std::max(minimalSize.height(), maximalSize.height()));
|
||||
updateDecorations();
|
||||
update();
|
||||
widget()->update();
|
||||
}
|
||||
|
||||
void PipPanel::paintEvent(QPaintEvent *e) {
|
||||
QPainter p(this);
|
||||
|
||||
if (_useTransparency && USE_OPENGL_PIP_WIDGET) {
|
||||
void PipPanel::paint(QPainter &p, const QRegion &clip, bool opengl) {
|
||||
if (_useTransparency && opengl) {
|
||||
p.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
for (const auto rect : e->region()) {
|
||||
for (const auto rect : clip) {
|
||||
p.fillRect(rect, Qt::transparent);
|
||||
}
|
||||
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
||||
|
@ -622,27 +666,27 @@ void PipPanel::paintEvent(QPaintEvent *e) {
|
|||
request.radius = ImageRoundRadius::Large;
|
||||
if (_useTransparency) {
|
||||
const auto sides = RectPart::AllSides & ~_attached;
|
||||
Ui::Shadow::paint(p, inner, width(), st::callShadow);
|
||||
Ui::Shadow::paint(p, inner, widget()->width(), st::callShadow);
|
||||
}
|
||||
_paint(p, request);
|
||||
_paint(p, request, opengl);
|
||||
}
|
||||
|
||||
void PipPanel::mousePressEvent(QMouseEvent *e) {
|
||||
if (e->button() != Qt::LeftButton) {
|
||||
void PipPanel::handleMousePress(QPoint position, Qt::MouseButton button) {
|
||||
if (button != Qt::LeftButton) {
|
||||
return;
|
||||
}
|
||||
updateOverState(e->pos());
|
||||
updateOverState(position);
|
||||
_pressState = _overState;
|
||||
_pressPoint = e->globalPos();
|
||||
_pressPoint = QCursor::pos();
|
||||
}
|
||||
|
||||
void PipPanel::mouseReleaseEvent(QMouseEvent *e) {
|
||||
if (e->button() != Qt::LeftButton || !base::take(_pressState)) {
|
||||
void PipPanel::handleMouseRelease(QPoint position, Qt::MouseButton button) {
|
||||
if (button != Qt::LeftButton || !base::take(_pressState)) {
|
||||
return;
|
||||
} else if (!base::take(_dragState)) {
|
||||
//playbackPauseResume();
|
||||
} else {
|
||||
finishDrag(e->globalPos());
|
||||
finishDrag(QCursor::pos());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -656,26 +700,28 @@ void PipPanel::updateOverState(QPoint point) {
|
|||
const auto top = count(RectPart::Top, _padding.top());
|
||||
const auto right = count(RectPart::Right, _padding.right());
|
||||
const auto bottom = count(RectPart::Bottom, _padding.bottom());
|
||||
const auto width = widget()->width();
|
||||
const auto height = widget()->height();
|
||||
const auto overState = [&] {
|
||||
if (point.x() < left) {
|
||||
if (point.y() < top) {
|
||||
return RectPart::TopLeft;
|
||||
} else if (point.y() >= height() - bottom) {
|
||||
} else if (point.y() >= height - bottom) {
|
||||
return RectPart::BottomLeft;
|
||||
} else {
|
||||
return RectPart::Left;
|
||||
}
|
||||
} else if (point.x() >= width() - right) {
|
||||
} else if (point.x() >= width - right) {
|
||||
if (point.y() < top) {
|
||||
return RectPart::TopRight;
|
||||
} else if (point.y() >= height() - bottom) {
|
||||
} else if (point.y() >= height - bottom) {
|
||||
return RectPart::BottomRight;
|
||||
} else {
|
||||
return RectPart::Right;
|
||||
}
|
||||
} else if (point.y() < top) {
|
||||
return RectPart::Top;
|
||||
} else if (point.y() >= height() - bottom) {
|
||||
} else if (point.y() >= height - bottom) {
|
||||
return RectPart::Bottom;
|
||||
} else {
|
||||
return RectPart::Center;
|
||||
|
@ -683,7 +729,7 @@ void PipPanel::updateOverState(QPoint point) {
|
|||
}();
|
||||
if (_overState != overState) {
|
||||
_overState = overState;
|
||||
setCursor([&] {
|
||||
widget()->setCursor([&] {
|
||||
switch (_overState) {
|
||||
case RectPart::Center:
|
||||
return style::cur_pointer;
|
||||
|
@ -705,19 +751,19 @@ void PipPanel::updateOverState(QPoint point) {
|
|||
}
|
||||
}
|
||||
|
||||
void PipPanel::mouseMoveEvent(QMouseEvent *e) {
|
||||
void PipPanel::handleMouseMove(QPoint position) {
|
||||
if (!_pressState) {
|
||||
updateOverState(e->pos());
|
||||
updateOverState(position);
|
||||
return;
|
||||
}
|
||||
const auto point = e->globalPos();
|
||||
const auto point = QCursor::pos();
|
||||
const auto distance = QApplication::startDragDistance();
|
||||
if (!_dragState
|
||||
&& (point - _pressPoint).manhattanLength() > distance
|
||||
&& !_dragDisabled) {
|
||||
_dragState = _pressState;
|
||||
updateDecorations();
|
||||
_dragStartGeometry = geometry().marginsRemoved(_padding);
|
||||
_dragStartGeometry = widget()->geometry().marginsRemoved(_padding);
|
||||
}
|
||||
if (_dragState) {
|
||||
if (Platform::IsWayland()) {
|
||||
|
@ -733,9 +779,9 @@ void PipPanel::startSystemDrag() {
|
|||
|
||||
const auto stateEdges = RectPartToQtEdges(*_dragState);
|
||||
if (stateEdges) {
|
||||
windowHandle()->startSystemResize(stateEdges);
|
||||
widget()->windowHandle()->startSystemResize(stateEdges);
|
||||
} else {
|
||||
windowHandle()->startSystemMove();
|
||||
widget()->windowHandle()->startSystemMove();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -780,14 +826,14 @@ void PipPanel::processDrag(QPoint point) {
|
|||
} else {
|
||||
const auto newGeometry = valid.marginsAdded(_padding);
|
||||
_positionAnimation.stop();
|
||||
setGeometry(newGeometry);
|
||||
widget()->setGeometry(newGeometry);
|
||||
}
|
||||
}
|
||||
|
||||
void PipPanel::finishDrag(QPoint point) {
|
||||
const auto screen = ScreenFromPosition(point);
|
||||
const auto inner = geometry().marginsRemoved(_padding);
|
||||
const auto position = pos();
|
||||
const auto inner = widget()->geometry().marginsRemoved(_padding);
|
||||
const auto position = widget()->pos();
|
||||
const auto clamped = [&] {
|
||||
auto result = position;
|
||||
if (Platform::IsWayland()) {
|
||||
|
@ -818,7 +864,8 @@ void PipPanel::finishDrag(QPoint point) {
|
|||
void PipPanel::updatePositionAnimated() {
|
||||
const auto progress = _positionAnimation.value(1.);
|
||||
if (!_positionAnimation.animating()) {
|
||||
move(_positionAnimationTo - QPoint(_padding.left(), _padding.top()));
|
||||
widget()->move(_positionAnimationTo
|
||||
- QPoint(_padding.left(), _padding.top()));
|
||||
if (!_dragState) {
|
||||
updateDecorations();
|
||||
}
|
||||
|
@ -826,7 +873,7 @@ void PipPanel::updatePositionAnimated() {
|
|||
}
|
||||
const auto from = QPointF(_positionAnimationFrom);
|
||||
const auto to = QPointF(_positionAnimationTo);
|
||||
move((from + (to - from) * progress).toPoint()
|
||||
widget()->move((from + (to - from) * progress).toPoint()
|
||||
- QPoint(_padding.left(), _padding.top()));
|
||||
}
|
||||
|
||||
|
@ -835,7 +882,8 @@ void PipPanel::moveAnimated(QPoint to) {
|
|||
return;
|
||||
}
|
||||
_positionAnimationTo = to;
|
||||
_positionAnimationFrom = pos() + QPoint(_padding.left(), _padding.top());
|
||||
_positionAnimationFrom = widget()->pos()
|
||||
+ QPoint(_padding.left(), _padding.top());
|
||||
_positionAnimation.stop();
|
||||
_positionAnimation.start(
|
||||
[=] { updatePositionAnimated(); },
|
||||
|
@ -868,9 +916,9 @@ void PipPanel::updateDecorations() {
|
|||
_attached = position.attached;
|
||||
_padding = padding;
|
||||
_useTransparency = use;
|
||||
setAttribute(Qt::WA_OpaquePaintEvent, !_useTransparency);
|
||||
setGeometry(newGeometry);
|
||||
update();
|
||||
widget()->setAttribute(Qt::WA_OpaquePaintEvent, !_useTransparency);
|
||||
widget()->setGeometry(newGeometry);
|
||||
widget()->update();
|
||||
}
|
||||
|
||||
Pip::Pip(
|
||||
|
@ -886,7 +934,9 @@ Pip::Pip(
|
|||
, _instance(std::move(shared), [=] { waitingAnimationCallback(); })
|
||||
, _panel(
|
||||
_delegate->pipParentWidget(),
|
||||
[=](QPainter &p, const FrameRequest &request) { paint(p, request); })
|
||||
[=](QPainter &p, const FrameRequest &request, bool opengl) {
|
||||
paint(p, request, opengl);
|
||||
})
|
||||
, _playbackProgress(std::make_unique<PlaybackProgress>())
|
||||
, _rotation(data->owner().mediaRotation().get(data))
|
||||
, _roundRect(ImageRoundRadius::Large, st::radialBg)
|
||||
|
@ -899,7 +949,7 @@ Pip::Pip(
|
|||
_data->session().account().sessionChanges(
|
||||
) | rpl::start_with_next([=] {
|
||||
_destroy();
|
||||
}, _panel.lifetime());
|
||||
}, _panel.rp()->lifetime());
|
||||
}
|
||||
|
||||
Pip::~Pip() = default;
|
||||
|
@ -920,14 +970,14 @@ void Pip::setupPanel() {
|
|||
}();
|
||||
_panel.setAspectRatio(FlipSizeByRotation(size, _rotation));
|
||||
_panel.setPosition(Deserialize(_delegate->pipLoadGeometry()));
|
||||
_panel.show();
|
||||
_panel.widget()->show();
|
||||
|
||||
_panel.saveGeometryRequests(
|
||||
) | rpl::start_with_next([=] {
|
||||
saveGeometry();
|
||||
}, _panel.lifetime());
|
||||
}, _panel.rp()->lifetime());
|
||||
|
||||
_panel.events(
|
||||
_panel.rp()->events(
|
||||
) | rpl::start_with_next([=](not_null<QEvent*> e) {
|
||||
const auto mousePosition = [&] {
|
||||
return static_cast<QMouseEvent*>(e.get())->pos();
|
||||
|
@ -951,11 +1001,11 @@ void Pip::setupPanel() {
|
|||
handleDoubleClick(mouseButton());
|
||||
break;
|
||||
}
|
||||
}, _panel.lifetime());
|
||||
}, _panel.rp()->lifetime());
|
||||
}
|
||||
|
||||
void Pip::handleClose() {
|
||||
crl::on_main(&_panel, [=] {
|
||||
crl::on_main(_panel.widget(), [=] {
|
||||
_destroy();
|
||||
});
|
||||
}
|
||||
|
@ -965,6 +1015,7 @@ void Pip::handleLeave() {
|
|||
}
|
||||
|
||||
void Pip::handleMouseMove(QPoint position) {
|
||||
_panel.handleMouseMove(position);
|
||||
setOverState(computeState(position));
|
||||
seekUpdate(position);
|
||||
}
|
||||
|
@ -978,7 +1029,7 @@ void Pip::setOverState(OverState state) {
|
|||
const auto nowShown = (_over != OverState::None);
|
||||
if ((was != OverState::None) != nowShown) {
|
||||
_controlsShown.start(
|
||||
[=] { _panel.update(); },
|
||||
[=] { _panel.widget()->update(); },
|
||||
nowShown ? 0. : 1.,
|
||||
nowShown ? 1. : 0.,
|
||||
st::fadeWrapDuration,
|
||||
|
@ -987,7 +1038,7 @@ void Pip::setOverState(OverState state) {
|
|||
if (!_pressed) {
|
||||
updateActiveState(was);
|
||||
}
|
||||
_panel.update();
|
||||
_panel.widget()->update();
|
||||
}
|
||||
|
||||
void Pip::setPressedState(std::optional<OverState> state) {
|
||||
|
@ -1012,7 +1063,7 @@ void Pip::updateActiveState(OverState was) {
|
|||
const auto now = (activeState() == button.state);
|
||||
if ((was == button.state) != now) {
|
||||
button.active.start(
|
||||
[=, &button] { _panel.update(button.icon); },
|
||||
[=, &button] { _panel.widget()->update(button.icon); },
|
||||
now ? 0. : 1.,
|
||||
now ? 1. : 0.,
|
||||
st::fadeWrapDuration,
|
||||
|
@ -1026,6 +1077,7 @@ void Pip::updateActiveState(OverState was) {
|
|||
}
|
||||
|
||||
void Pip::handleMousePress(QPoint position, Qt::MouseButton button) {
|
||||
_panel.handleMousePress(position, button);
|
||||
if (button != Qt::LeftButton) {
|
||||
return;
|
||||
}
|
||||
|
@ -1037,6 +1089,7 @@ void Pip::handleMousePress(QPoint position, Qt::MouseButton button) {
|
|||
}
|
||||
|
||||
void Pip::handleMouseRelease(QPoint position, Qt::MouseButton button) {
|
||||
_panel.handleMouseRelease(position, button);
|
||||
if (button != Qt::LeftButton) {
|
||||
return;
|
||||
}
|
||||
|
@ -1053,7 +1106,7 @@ void Pip::handleMouseRelease(QPoint position, Qt::MouseButton button) {
|
|||
|
||||
_lastHandledPress = _over;
|
||||
switch (_over) {
|
||||
case OverState::Close: _panel.close(); break;
|
||||
case OverState::Close: _panel.widget()->close(); break;
|
||||
case OverState::Enlarge: _closeAndContinue(); break;
|
||||
case OverState::Other: playbackPauseResume(); break;
|
||||
}
|
||||
|
@ -1120,7 +1173,7 @@ void Pip::setupButtons() {
|
|||
_enlarge.state = OverState::Enlarge;
|
||||
_playback.state = OverState::Playback;
|
||||
_play.state = OverState::Other;
|
||||
_panel.sizeValue(
|
||||
_panel.rp()->sizeValue(
|
||||
) | rpl::map([=] {
|
||||
return _panel.inner();
|
||||
}) | rpl::start_with_next([=](QRect rect) {
|
||||
|
@ -1162,12 +1215,12 @@ void Pip::setupButtons() {
|
|||
playbackHeight);
|
||||
_playback.icon = _playback.area.marginsRemoved(
|
||||
{ playbackSkip, playbackSkip, playbackSkip, playbackSkip });
|
||||
}, _panel.lifetime());
|
||||
}, _panel.rp()->lifetime());
|
||||
|
||||
_playbackProgress->setValueChangedCallback([=](
|
||||
float64 value,
|
||||
float64 receivedTill) {
|
||||
_panel.update(_playback.area);
|
||||
_panel.widget()->update(_playback.area);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1179,7 +1232,7 @@ void Pip::updatePlayPauseResumeState(const Player::TrackState &state) {
|
|||
auto showPause = Player::ShowPauseIcon(state.state);
|
||||
if (showPause != _showPause) {
|
||||
_showPause = showPause;
|
||||
_panel.update();
|
||||
_panel.widget()->update();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1196,7 +1249,7 @@ void Pip::setupStreaming() {
|
|||
updatePlaybackState();
|
||||
}
|
||||
|
||||
void Pip::paint(QPainter &p, FrameRequest request) {
|
||||
void Pip::paint(QPainter &p, FrameRequest request, bool opengl) {
|
||||
const auto image = videoFrameForDirectPaint(
|
||||
UnrotateRequest(request, _rotation));
|
||||
const auto inner = _panel.inner();
|
||||
|
@ -1204,7 +1257,7 @@ void Pip::paint(QPainter &p, FrameRequest request) {
|
|||
inner.topLeft(),
|
||||
request.outer / style::DevicePixelRatio()
|
||||
};
|
||||
if (UsePainterRotation(_rotation, USE_OPENGL_PIP_WIDGET)) {
|
||||
if (UsePainterRotation(_rotation, opengl)) {
|
||||
if (_rotation) {
|
||||
p.save();
|
||||
p.rotate(_rotation);
|
||||
|
@ -1257,7 +1310,7 @@ void Pip::paintFade(QPainter &p) const {
|
|||
|
||||
void Pip::paintButtons(QPainter &p) const {
|
||||
const auto opacity = p.opacity();
|
||||
const auto outer = _panel.width();
|
||||
const auto outer = _panel.widget()->width();
|
||||
const auto drawOne = [&](
|
||||
const Button &button,
|
||||
const style::icon &icon,
|
||||
|
@ -1344,7 +1397,7 @@ void Pip::handleStreamingUpdate(Streaming::Update &&update) {
|
|||
}, [&](const PreloadedVideo &update) {
|
||||
updatePlaybackState();
|
||||
}, [&](const UpdateVideo &update) {
|
||||
_panel.update();
|
||||
_panel.widget()->update();
|
||||
Core::App().updateNonIdle();
|
||||
updatePlaybackState();
|
||||
}, [&](const PreloadedAudio &update) {
|
||||
|
@ -1399,7 +1452,7 @@ void Pip::updatePlaybackTexts(
|
|||
_timeAlready = already;
|
||||
_timeLeft = left;
|
||||
_timeLeftWidth = st::pipPlaybackFont->width(_timeLeft);
|
||||
_panel.update(QRect(
|
||||
_panel.widget()->update(QRect(
|
||||
_playback.area.x(),
|
||||
_playback.icon.y() - st::pipPlaybackFont->height,
|
||||
_playback.area.width(),
|
||||
|
@ -1407,12 +1460,12 @@ void Pip::updatePlaybackTexts(
|
|||
}
|
||||
|
||||
void Pip::handleStreamingError(Streaming::Error &&error) {
|
||||
_panel.close();
|
||||
_panel.widget()->close();
|
||||
}
|
||||
|
||||
void Pip::playbackPauseResume() {
|
||||
if (_instance.player().failed()) {
|
||||
_panel.close();
|
||||
_panel.widget()->close();
|
||||
} else if (_instance.player().finished()
|
||||
|| !_instance.player().active()) {
|
||||
_startPaused = false;
|
||||
|
@ -1602,7 +1655,7 @@ void Pip::paintRadialLoadingContent(QPainter &p, const QRect &inner) const {
|
|||
_instance.waitingState(),
|
||||
arc.topLeft(),
|
||||
arc.size(),
|
||||
_panel.width(),
|
||||
_panel.widget()->width(),
|
||||
st::radialFg,
|
||||
st::radialLine);
|
||||
}
|
||||
|
@ -1632,7 +1685,7 @@ Pip::OverState Pip::computeState(QPoint position) const {
|
|||
}
|
||||
|
||||
void Pip::waitingAnimationCallback() {
|
||||
_panel.update(countRadialRect());
|
||||
_panel.widget()->update(countRadialRect());
|
||||
}
|
||||
|
||||
} // namespace View
|
||||
|
|
|
@ -22,6 +22,10 @@ namespace Ui {
|
|||
class IconButton;
|
||||
template <typename Widget>
|
||||
class FadeWrap;
|
||||
namespace GL {
|
||||
struct ChosenRenderer;
|
||||
struct Capabilities;
|
||||
} // namespace GL
|
||||
} // namespace Ui
|
||||
|
||||
namespace Media {
|
||||
|
@ -38,19 +42,7 @@ class PlaybackProgress;
|
|||
[[nodiscard]] QSize FlipSizeByRotation(QSize size, int rotation);
|
||||
[[nodiscard]] QImage RotateFrameImage(QImage image, int rotation);
|
||||
|
||||
#if 1
|
||||
#define USE_OPENGL_PIP_WIDGET 1
|
||||
#else
|
||||
#define USE_OPENGL_PIP_WIDGET 0
|
||||
#endif // Q_OS_MAC && !OS_MAC_OLD
|
||||
|
||||
#if USE_OPENGL_PIP_WIDGET
|
||||
using PipParent = Ui::RpWidgetWrap<QOpenGLWidget>;
|
||||
#else // USE_OPENGL_PIP_WIDGET
|
||||
using PipParent = Ui::RpWidget;
|
||||
#endif // USE_OPENGL_PIP_WIDGET
|
||||
|
||||
class PipPanel final : public PipParent {
|
||||
class PipPanel final {
|
||||
public:
|
||||
struct Position {
|
||||
RectParts attached = RectPart(0);
|
||||
|
@ -62,9 +54,12 @@ public:
|
|||
|
||||
PipPanel(
|
||||
QWidget *parent,
|
||||
Fn<void(QPainter&, FrameRequest)> paint);
|
||||
Fn<void(QPainter&, FrameRequest, bool)> paint);
|
||||
void init();
|
||||
|
||||
[[nodiscard]] not_null<QWidget*> widget() const;
|
||||
[[nodiscard]] not_null<Ui::RpWidgetWrap*> rp() const;
|
||||
|
||||
void setAspectRatio(QSize ratio);
|
||||
[[nodiscard]] Position countPosition() const;
|
||||
void setPosition(Position position);
|
||||
|
@ -73,17 +68,15 @@ public:
|
|||
void setDragDisabled(bool disabled);
|
||||
[[nodiscard]] bool dragging() const;
|
||||
|
||||
void handleMousePress(QPoint position, Qt::MouseButton button);
|
||||
void handleMouseRelease(QPoint position, Qt::MouseButton button);
|
||||
void handleMouseMove(QPoint position);
|
||||
|
||||
[[nodiscard]] rpl::producer<> saveGeometryRequests() const;
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
void mouseMoveEvent(QMouseEvent *e) override;
|
||||
|
||||
void setVisibleHook(bool visible) override;
|
||||
|
||||
private:
|
||||
void paint(QPainter &p, const QRegion &clip, bool opengl);
|
||||
|
||||
void setPositionDefault();
|
||||
void setPositionOnScreen(Position position, QRect available);
|
||||
|
||||
|
@ -96,8 +89,12 @@ private:
|
|||
void moveAnimated(QPoint to);
|
||||
void updateDecorations();
|
||||
|
||||
[[nodiscard]] Ui::GL::ChosenRenderer chooseRenderer(
|
||||
Ui::GL::Capabilities capabilities);
|
||||
|
||||
std::unique_ptr<Ui::RpWidgetWrap> _content;
|
||||
QPointer<QWidget> _parent;
|
||||
Fn<void(QPainter&, FrameRequest)> _paint;
|
||||
Fn<void(QPainter&, FrameRequest, bool)> _paint;
|
||||
RectParts _attached = RectParts();
|
||||
RectParts _snapped = RectParts();
|
||||
QSize _ratio;
|
||||
|
@ -164,7 +161,7 @@ private:
|
|||
void setupPanel();
|
||||
void setupButtons();
|
||||
void setupStreaming();
|
||||
void paint(QPainter &p, FrameRequest request);
|
||||
void paint(QPainter &p, FrameRequest request, bool opengl);
|
||||
void playbackPauseResume();
|
||||
void waitingAnimationCallback();
|
||||
void handleStreamingUpdate(Streaming::Update &&update);
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit e9fcbfcbacfe9f2f454a7bd34f1a3c5403245523
|
||||
Subproject commit 95ee92088e62dfa20eb11d6fe59b0fb1834a1207
|
Loading…
Add table
Reference in a new issue