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