Allow choosing OpenGL / Raster in runtime.
This commit is contained in:
parent
e9fcbfcbac
commit
95ee92088e
11 changed files with 334 additions and 69 deletions
|
|
@ -57,6 +57,10 @@ PRIVATE
|
||||||
ui/effects/ripple_animation.h
|
ui/effects/ripple_animation.h
|
||||||
ui/effects/slide_animation.cpp
|
ui/effects/slide_animation.cpp
|
||||||
ui/effects/slide_animation.h
|
ui/effects/slide_animation.h
|
||||||
|
ui/gl/gl_detection.cpp
|
||||||
|
ui/gl/gl_detection.h
|
||||||
|
ui/gl/gl_surface.cpp
|
||||||
|
ui/gl/gl_surface.h
|
||||||
ui/image/image_prepare.cpp
|
ui/image/image_prepare.cpp
|
||||||
ui/image/image_prepare.h
|
ui/image/image_prepare.h
|
||||||
ui/layers/box_content.cpp
|
ui/layers/box_content.cpp
|
||||||
|
|
|
||||||
85
ui/gl/gl_detection.cpp
Normal file
85
ui/gl/gl_detection.cpp
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
// This file is part of Desktop App Toolkit,
|
||||||
|
// a set of libraries for developing nice desktop applications.
|
||||||
|
//
|
||||||
|
// For license and copyright information please follow this link:
|
||||||
|
// https://github.com/desktop-app/legal/blob/master/LEGAL
|
||||||
|
//
|
||||||
|
#include "ui/gl/gl_detection.h"
|
||||||
|
|
||||||
|
#include "base/debug_log.h"
|
||||||
|
|
||||||
|
#include <QtGui/QWindow>
|
||||||
|
#include <QtGui/QOpenGLContext>
|
||||||
|
#include <QtGui/QOpenGLFunctions>
|
||||||
|
#include <QtWidgets/QOpenGLWidget>
|
||||||
|
|
||||||
|
#define LOG_ONCE(x) static auto logged = [&] { LOG(x); return true; };
|
||||||
|
|
||||||
|
namespace Ui::GL {
|
||||||
|
|
||||||
|
Capabilities CheckCapabilities(QWidget *widget) {
|
||||||
|
auto created = QOpenGLContext();
|
||||||
|
auto format = QSurfaceFormat();
|
||||||
|
format.setAlphaBufferSize(8);
|
||||||
|
if (widget) {
|
||||||
|
if (!widget->window()->windowHandle()) {
|
||||||
|
widget->window()->createWinId();
|
||||||
|
}
|
||||||
|
if (!widget->window()->windowHandle()) {
|
||||||
|
LOG(("OpenGL: Could not create window for widget."));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (!widget->window()->windowHandle()->supportsOpenGL()) {
|
||||||
|
LOG_ONCE(("OpenGL: Not supported for window."));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
created.setFormat(format);
|
||||||
|
if (!created.create()) {
|
||||||
|
LOG_ONCE(("OpenGL: Could not create context with alpha."));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto tester = QOpenGLWidget(widget);
|
||||||
|
if (widget) {
|
||||||
|
tester.setFormat(format);
|
||||||
|
tester.grabFramebuffer(); // Force initialize().
|
||||||
|
}
|
||||||
|
const auto context = (widget ? tester.context() : &created);
|
||||||
|
if (!context) {
|
||||||
|
LOG_ONCE(("OpenGL: Could not create widget in a window."));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const auto functions = context->functions();
|
||||||
|
using Feature = QOpenGLFunctions;
|
||||||
|
if (!functions->hasOpenGLFeature(Feature::NPOTTextures)) {
|
||||||
|
LOG_ONCE(("OpenGL: NPOT textures not supported."));
|
||||||
|
return {};
|
||||||
|
} else if (!functions->hasOpenGLFeature(Feature::Framebuffers)) {
|
||||||
|
LOG_ONCE(("OpenGL: Framebuffers not supported."));
|
||||||
|
return {};
|
||||||
|
} else if (!functions->hasOpenGLFeature(Feature::Shaders)) {
|
||||||
|
LOG_ONCE(("OpenGL: Shaders not supported."));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const auto supported = context->format();
|
||||||
|
if (supported.profile() == QSurfaceFormat::NoProfile) {
|
||||||
|
LOG_ONCE(("OpenGL: NoProfile received in final format."));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const auto version = u"%1.%2"_q
|
||||||
|
.arg(supported.majorVersion())
|
||||||
|
.arg(supported.majorVersion());
|
||||||
|
auto result = Capabilities{ .supported = true };
|
||||||
|
if (supported.alphaBufferSize() >= 8) {
|
||||||
|
result.transparency = true;
|
||||||
|
LOG_ONCE(("OpenGL: QOpenGLContext created, version: %1."
|
||||||
|
).arg(version));
|
||||||
|
} else {
|
||||||
|
LOG_ONCE(("OpenGL: QOpenGLContext without alpha created, version: %1"
|
||||||
|
).arg(version));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Ui::GL
|
||||||
20
ui/gl/gl_detection.h
Normal file
20
ui/gl/gl_detection.h
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
// This file is part of Desktop App Toolkit,
|
||||||
|
// a set of libraries for developing nice desktop applications.
|
||||||
|
//
|
||||||
|
// For license and copyright information please follow this link:
|
||||||
|
// https://github.com/desktop-app/legal/blob/master/LEGAL
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "base/flags.h"
|
||||||
|
|
||||||
|
namespace Ui::GL {
|
||||||
|
|
||||||
|
struct Capabilities {
|
||||||
|
bool supported = false;
|
||||||
|
bool transparency = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] Capabilities CheckCapabilities(QWidget *widget = nullptr);
|
||||||
|
|
||||||
|
} // namespace Ui::GL
|
||||||
103
ui/gl/gl_surface.cpp
Normal file
103
ui/gl/gl_surface.cpp
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
// This file is part of Desktop App Toolkit,
|
||||||
|
// a set of libraries for developing nice desktop applications.
|
||||||
|
//
|
||||||
|
// For license and copyright information please follow this link:
|
||||||
|
// https://github.com/desktop-app/legal/blob/master/LEGAL
|
||||||
|
//
|
||||||
|
#include "ui/gl/gl_surface.h"
|
||||||
|
|
||||||
|
#include "ui/rp_widget.h"
|
||||||
|
|
||||||
|
#include <QtGui/QPainter>
|
||||||
|
#include <QtGui/QtEvents>
|
||||||
|
#include <QtGui/QOpenGLContext>
|
||||||
|
#include <QtWidgets/QOpenGLWidget>
|
||||||
|
|
||||||
|
namespace Ui::GL {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct SurfaceTraits : RpWidgetDefaultTraits {
|
||||||
|
static constexpr bool kSetZeroGeometry = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SurfaceOpenGL final
|
||||||
|
: public RpWidgetBase<QOpenGLWidget, SurfaceTraits> {
|
||||||
|
public:
|
||||||
|
SurfaceOpenGL(QWidget *parent, std::unique_ptr<Renderer> renderer);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initializeGL() override;
|
||||||
|
void resizeGL(int w, int h) override;
|
||||||
|
void paintGL() override;
|
||||||
|
|
||||||
|
const std::unique_ptr<Renderer> _renderer;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class SurfaceRaster final : public RpWidgetBase<QWidget, SurfaceTraits> {
|
||||||
|
public:
|
||||||
|
SurfaceRaster(QWidget *parent, std::unique_ptr<Renderer> renderer);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
|
||||||
|
const std::unique_ptr<Renderer> _renderer;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
SurfaceOpenGL::SurfaceOpenGL(
|
||||||
|
QWidget *parent,
|
||||||
|
std::unique_ptr<Renderer> renderer)
|
||||||
|
: RpWidgetBase<QOpenGLWidget, SurfaceTraits>(parent)
|
||||||
|
, _renderer(std::move(renderer)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void SurfaceOpenGL::initializeGL() {
|
||||||
|
_renderer->init(this, context()->functions());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SurfaceOpenGL::resizeGL(int w, int h) {
|
||||||
|
_renderer->resize(this, context()->functions(), w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SurfaceOpenGL::paintGL() {
|
||||||
|
_renderer->paint(this, context()->functions());
|
||||||
|
}
|
||||||
|
|
||||||
|
SurfaceRaster::SurfaceRaster(
|
||||||
|
QWidget *parent,
|
||||||
|
std::unique_ptr<Renderer> renderer)
|
||||||
|
: RpWidgetBase<QWidget, SurfaceTraits>(parent)
|
||||||
|
, _renderer(std::move(renderer)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void SurfaceRaster::paintEvent(QPaintEvent *e) {
|
||||||
|
_renderer->paintFallback(QPainter(this), e->region(), Backend::Raster);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void Renderer::paint(
|
||||||
|
not_null<QOpenGLWidget*> widget,
|
||||||
|
not_null<QOpenGLFunctions*> f) {
|
||||||
|
paintFallback(QPainter(widget.get()), widget->rect(), Backend::OpenGL);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<RpWidgetWrap> CreateSurface(
|
||||||
|
QWidget *parent,
|
||||||
|
Fn<ChosenRenderer(Capabilities)> chooseRenderer) {
|
||||||
|
auto chosen = chooseRenderer(CheckCapabilities(parent));
|
||||||
|
switch (chosen.backend) {
|
||||||
|
case Backend::OpenGL:
|
||||||
|
return std::make_unique<SurfaceOpenGL>(
|
||||||
|
parent,
|
||||||
|
std::move(chosen.renderer));
|
||||||
|
case Backend::Raster:
|
||||||
|
return std::make_unique<SurfaceRaster>(
|
||||||
|
parent,
|
||||||
|
std::move(chosen.renderer));
|
||||||
|
}
|
||||||
|
Unexpected("Backend value in Ui::GL::CreateSurface.");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Ui::GL
|
||||||
62
ui/gl/gl_surface.h
Normal file
62
ui/gl/gl_surface.h
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
// This file is part of Desktop App Toolkit,
|
||||||
|
// a set of libraries for developing nice desktop applications.
|
||||||
|
//
|
||||||
|
// For license and copyright information please follow this link:
|
||||||
|
// https://github.com/desktop-app/legal/blob/master/LEGAL
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ui/gl/gl_detection.h"
|
||||||
|
|
||||||
|
class QPainter;
|
||||||
|
class QOpenGLWidget;
|
||||||
|
class QOpenGLFunctions;
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class RpWidgetWrap;
|
||||||
|
} // namespace Ui
|
||||||
|
|
||||||
|
namespace Ui::GL {
|
||||||
|
|
||||||
|
enum class Backend {
|
||||||
|
OpenGL,
|
||||||
|
Raster,
|
||||||
|
};
|
||||||
|
|
||||||
|
class Renderer {
|
||||||
|
public:
|
||||||
|
virtual void init(
|
||||||
|
not_null<QOpenGLWidget*> widget,
|
||||||
|
not_null<QOpenGLFunctions*> f) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void resize(
|
||||||
|
not_null<QOpenGLWidget*> widget,
|
||||||
|
not_null<QOpenGLFunctions*> f,
|
||||||
|
int w,
|
||||||
|
int h) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void paint(
|
||||||
|
not_null<QOpenGLWidget*> widget,
|
||||||
|
not_null<QOpenGLFunctions*> f);
|
||||||
|
|
||||||
|
virtual void paintFallback(
|
||||||
|
QPainter &&p,
|
||||||
|
const QRegion &clip,
|
||||||
|
Backend backend) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~Renderer() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ChosenRenderer {
|
||||||
|
std::unique_ptr<Renderer> renderer;
|
||||||
|
Backend backend = Backend::Raster;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] std::unique_ptr<RpWidgetWrap> CreateSurface(
|
||||||
|
QWidget *parent,
|
||||||
|
Fn<ChosenRenderer(Capabilities)> chooseRenderer);
|
||||||
|
|
||||||
|
} // namespace Ui::GL
|
||||||
|
|
@ -27,71 +27,71 @@ void ResizeFitChild(
|
||||||
}, child->lifetime());
|
}, child->lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<not_null<QEvent*>> RpWidgetMethods::events() const {
|
rpl::producer<not_null<QEvent*>> RpWidgetWrap::events() const {
|
||||||
auto &stream = eventStreams().events;
|
auto &stream = eventStreams().events;
|
||||||
return stream.events();
|
return stream.events();
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<QRect> RpWidgetMethods::geometryValue() const {
|
rpl::producer<QRect> RpWidgetWrap::geometryValue() const {
|
||||||
auto &stream = eventStreams().geometry;
|
auto &stream = eventStreams().geometry;
|
||||||
return stream.events_starting_with_copy(callGetGeometry());
|
return stream.events_starting_with_copy(rpWidget()->geometry());
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<QSize> RpWidgetMethods::sizeValue() const {
|
rpl::producer<QSize> RpWidgetWrap::sizeValue() const {
|
||||||
return geometryValue()
|
return geometryValue()
|
||||||
| rpl::map([](QRect &&value) { return value.size(); })
|
| rpl::map([](QRect &&value) { return value.size(); })
|
||||||
| rpl::distinct_until_changed();
|
| rpl::distinct_until_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<int> RpWidgetMethods::heightValue() const {
|
rpl::producer<int> RpWidgetWrap::heightValue() const {
|
||||||
return geometryValue()
|
return geometryValue()
|
||||||
| rpl::map([](QRect &&value) { return value.height(); })
|
| rpl::map([](QRect &&value) { return value.height(); })
|
||||||
| rpl::distinct_until_changed();
|
| rpl::distinct_until_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<int> RpWidgetMethods::widthValue() const {
|
rpl::producer<int> RpWidgetWrap::widthValue() const {
|
||||||
return geometryValue()
|
return geometryValue()
|
||||||
| rpl::map([](QRect &&value) { return value.width(); })
|
| rpl::map([](QRect &&value) { return value.width(); })
|
||||||
| rpl::distinct_until_changed();
|
| rpl::distinct_until_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<QPoint> RpWidgetMethods::positionValue() const {
|
rpl::producer<QPoint> RpWidgetWrap::positionValue() const {
|
||||||
return geometryValue()
|
return geometryValue()
|
||||||
| rpl::map([](QRect &&value) { return value.topLeft(); })
|
| rpl::map([](QRect &&value) { return value.topLeft(); })
|
||||||
| rpl::distinct_until_changed();
|
| rpl::distinct_until_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<int> RpWidgetMethods::leftValue() const {
|
rpl::producer<int> RpWidgetWrap::leftValue() const {
|
||||||
return geometryValue()
|
return geometryValue()
|
||||||
| rpl::map([](QRect &&value) { return value.left(); })
|
| rpl::map([](QRect &&value) { return value.left(); })
|
||||||
| rpl::distinct_until_changed();
|
| rpl::distinct_until_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<int> RpWidgetMethods::topValue() const {
|
rpl::producer<int> RpWidgetWrap::topValue() const {
|
||||||
return geometryValue()
|
return geometryValue()
|
||||||
| rpl::map([](QRect &&value) { return value.top(); })
|
| rpl::map([](QRect &&value) { return value.top(); })
|
||||||
| rpl::distinct_until_changed();
|
| rpl::distinct_until_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<int> RpWidgetMethods::desiredHeightValue() const {
|
rpl::producer<int> RpWidgetWrap::desiredHeightValue() const {
|
||||||
return heightValue();
|
return heightValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<bool> RpWidgetMethods::shownValue() const {
|
rpl::producer<bool> RpWidgetWrap::shownValue() const {
|
||||||
auto &stream = eventStreams().shown;
|
auto &stream = eventStreams().shown;
|
||||||
return stream.events_starting_with(!callIsHidden());
|
return stream.events_starting_with(!rpWidget()->isHidden());
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<QRect> RpWidgetMethods::paintRequest() const {
|
rpl::producer<QRect> RpWidgetWrap::paintRequest() const {
|
||||||
return eventStreams().paint.events();
|
return eventStreams().paint.events();
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<> RpWidgetMethods::alive() const {
|
rpl::producer<> RpWidgetWrap::alive() const {
|
||||||
return eventStreams().alive.events();
|
return eventStreams().alive.events();
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<> RpWidgetMethods::windowDeactivateEvents() const {
|
rpl::producer<> RpWidgetWrap::windowDeactivateEvents() const {
|
||||||
const auto window = callGetWidget()->window()->windowHandle();
|
const auto window = rpWidget()->window()->windowHandle();
|
||||||
Assert(window != nullptr);
|
Assert(window != nullptr);
|
||||||
|
|
||||||
return base::qt_signal_producer(
|
return base::qt_signal_producer(
|
||||||
|
|
@ -102,7 +102,7 @@ rpl::producer<> RpWidgetMethods::windowDeactivateEvents() const {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::producer<> RpWidgetMethods::macWindowDeactivateEvents() const {
|
rpl::producer<> RpWidgetWrap::macWindowDeactivateEvents() const {
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
return windowDeactivateEvents();
|
return windowDeactivateEvents();
|
||||||
#else // Q_OS_MAC
|
#else // Q_OS_MAC
|
||||||
|
|
@ -110,20 +110,21 @@ rpl::producer<> RpWidgetMethods::macWindowDeactivateEvents() const {
|
||||||
#endif // Q_OS_MAC
|
#endif // Q_OS_MAC
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl::lifetime &RpWidgetMethods::lifetime() {
|
rpl::lifetime &RpWidgetWrap::lifetime() {
|
||||||
return _lifetime;
|
return _lifetime;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RpWidgetMethods::handleEvent(QEvent *event) {
|
bool RpWidgetWrap::handleEvent(QEvent *event) {
|
||||||
Expects(event != nullptr);
|
Expects(event != nullptr);
|
||||||
|
|
||||||
auto streams = _eventStreams.get();
|
auto streams = _eventStreams.get();
|
||||||
if (!streams) {
|
if (!streams) {
|
||||||
return eventHook(event);
|
return eventHook(event);
|
||||||
}
|
}
|
||||||
auto that = QPointer<QObject>();
|
auto that = QPointer<QWidget>();
|
||||||
if (streams->events.has_consumers()) {
|
const auto allAreObserved = streams->events.has_consumers();
|
||||||
that = callCreateWeak();
|
if (allAreObserved) {
|
||||||
|
that = rpWidget();
|
||||||
streams->events.fire_copy(event);
|
streams->events.fire_copy(event);
|
||||||
if (!that) {
|
if (!that) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -133,10 +134,10 @@ bool RpWidgetMethods::handleEvent(QEvent *event) {
|
||||||
case QEvent::Move:
|
case QEvent::Move:
|
||||||
case QEvent::Resize:
|
case QEvent::Resize:
|
||||||
if (streams->geometry.has_consumers()) {
|
if (streams->geometry.has_consumers()) {
|
||||||
if (!that) {
|
if (!allAreObserved) {
|
||||||
that = callCreateWeak();
|
that = rpWidget();
|
||||||
}
|
}
|
||||||
streams->geometry.fire_copy(callGetGeometry());
|
streams->geometry.fire_copy(rpWidget()->geometry());
|
||||||
if (!that) {
|
if (!that) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -145,8 +146,8 @@ bool RpWidgetMethods::handleEvent(QEvent *event) {
|
||||||
|
|
||||||
case QEvent::Paint:
|
case QEvent::Paint:
|
||||||
if (streams->paint.has_consumers()) {
|
if (streams->paint.has_consumers()) {
|
||||||
if (!that) {
|
if (!allAreObserved) {
|
||||||
that = callCreateWeak();
|
that = rpWidget();
|
||||||
}
|
}
|
||||||
const auto rect = static_cast<QPaintEvent*>(event)->rect();
|
const auto rect = static_cast<QPaintEvent*>(event)->rect();
|
||||||
streams->paint.fire_copy(rect);
|
streams->paint.fire_copy(rect);
|
||||||
|
|
@ -160,13 +161,13 @@ bool RpWidgetMethods::handleEvent(QEvent *event) {
|
||||||
return eventHook(event);
|
return eventHook(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
RpWidgetMethods::Initer::Initer(QWidget *parent, bool setZeroGeometry) {
|
RpWidgetWrap::Initer::Initer(QWidget *parent, bool setZeroGeometry) {
|
||||||
if (setZeroGeometry) {
|
if (setZeroGeometry) {
|
||||||
parent->setGeometry(0, 0, 0, 0);
|
parent->setGeometry(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RpWidgetMethods::visibilityChangedHook(bool wasVisible, bool nowVisible) {
|
void RpWidgetWrap::visibilityChangedHook(bool wasVisible, bool nowVisible) {
|
||||||
if (nowVisible != wasVisible) {
|
if (nowVisible != wasVisible) {
|
||||||
if (auto streams = _eventStreams.get()) {
|
if (auto streams = _eventStreams.get()) {
|
||||||
streams->shown.fire_copy(nowVisible);
|
streams->shown.fire_copy(nowVisible);
|
||||||
|
|
@ -174,7 +175,7 @@ void RpWidgetMethods::visibilityChangedHook(bool wasVisible, bool nowVisible) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto RpWidgetMethods::eventStreams() const -> EventStreams& {
|
auto RpWidgetWrap::eventStreams() const -> EventStreams& {
|
||||||
if (!_eventStreams) {
|
if (!_eventStreams) {
|
||||||
_eventStreams = std::make_unique<EventStreams>();
|
_eventStreams = std::make_unique<EventStreams>();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -244,10 +244,13 @@ using RpWidgetParent = std::conditional_t<
|
||||||
TWidgetHelper<Widget>>;
|
TWidgetHelper<Widget>>;
|
||||||
|
|
||||||
template <typename Widget, typename Traits>
|
template <typename Widget, typename Traits>
|
||||||
class RpWidgetWrap;
|
class RpWidgetBase;
|
||||||
|
|
||||||
class RpWidgetMethods {
|
class RpWidgetWrap {
|
||||||
public:
|
public:
|
||||||
|
virtual QWidget *rpWidget() = 0;
|
||||||
|
virtual const QWidget *rpWidget() const = 0;
|
||||||
|
|
||||||
rpl::producer<not_null<QEvent*>> events() const;
|
rpl::producer<not_null<QEvent*>> events() const;
|
||||||
rpl::producer<QRect> geometryValue() const;
|
rpl::producer<QRect> geometryValue() const;
|
||||||
rpl::producer<QSize> sizeValue() const;
|
rpl::producer<QSize> sizeValue() const;
|
||||||
|
|
@ -274,7 +277,7 @@ public:
|
||||||
|
|
||||||
rpl::lifetime &lifetime();
|
rpl::lifetime &lifetime();
|
||||||
|
|
||||||
virtual ~RpWidgetMethods() = default;
|
virtual ~RpWidgetWrap() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool handleEvent(QEvent *event);
|
bool handleEvent(QEvent *event);
|
||||||
|
|
@ -282,7 +285,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename Widget, typename Traits>
|
template <typename Widget, typename Traits>
|
||||||
friend class RpWidgetWrap;
|
friend class RpWidgetBase;
|
||||||
|
|
||||||
struct EventStreams {
|
struct EventStreams {
|
||||||
rpl::event_stream<not_null<QEvent*>> events;
|
rpl::event_stream<not_null<QEvent*>> events;
|
||||||
|
|
@ -296,11 +299,6 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void callSetVisible(bool visible) = 0;
|
virtual void callSetVisible(bool visible) = 0;
|
||||||
virtual QWidget *callGetWidget() = 0;
|
|
||||||
virtual const QWidget *callGetWidget() const = 0;
|
|
||||||
virtual QPointer<QObject> callCreateWeak() = 0;
|
|
||||||
virtual QRect callGetGeometry() const = 0;
|
|
||||||
virtual bool callIsHidden() const = 0;
|
|
||||||
|
|
||||||
void visibilityChangedHook(bool wasVisible, bool nowVisible);
|
void visibilityChangedHook(bool wasVisible, bool nowVisible);
|
||||||
EventStreams &eventStreams() const;
|
EventStreams &eventStreams() const;
|
||||||
|
|
@ -315,22 +313,28 @@ struct RpWidgetDefaultTraits {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Widget, typename Traits = RpWidgetDefaultTraits>
|
template <typename Widget, typename Traits = RpWidgetDefaultTraits>
|
||||||
class RpWidgetWrap
|
class RpWidgetBase
|
||||||
: public RpWidgetParent<Widget>
|
: public RpWidgetParent<Widget>
|
||||||
, public RpWidgetMethods {
|
, public RpWidgetWrap {
|
||||||
using Self = RpWidgetWrap<Widget, Traits>;
|
using Self = RpWidgetBase<Widget, Traits>;
|
||||||
using Parent = RpWidgetParent<Widget>;
|
using Parent = RpWidgetParent<Widget>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using Parent::Parent;
|
using Parent::Parent;
|
||||||
|
|
||||||
|
QWidget *rpWidget() final override {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
const QWidget *rpWidget() const final override {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
void setVisible(bool visible) final override {
|
void setVisible(bool visible) final override {
|
||||||
auto wasVisible = !this->isHidden();
|
auto wasVisible = !this->isHidden();
|
||||||
setVisibleHook(visible);
|
setVisibleHook(visible);
|
||||||
visibilityChangedHook(wasVisible, !this->isHidden());
|
visibilityChangedHook(wasVisible, !this->isHidden());
|
||||||
}
|
}
|
||||||
|
|
||||||
~RpWidgetWrap() {
|
~RpWidgetBase() {
|
||||||
base::take(_lifetime);
|
base::take(_lifetime);
|
||||||
base::take(_eventStreams);
|
base::take(_eventStreams);
|
||||||
}
|
}
|
||||||
|
|
@ -347,32 +351,17 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void callSetVisible(bool visible) override {
|
void callSetVisible(bool visible) final override {
|
||||||
Self::setVisible(visible);
|
Self::setVisible(visible); // Save one virtual method invocation.
|
||||||
}
|
|
||||||
QWidget *callGetWidget() override {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
const QWidget *callGetWidget() const override {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
QPointer<QObject> callCreateWeak() override {
|
|
||||||
return QPointer<QObject>((QObject*)this);
|
|
||||||
}
|
|
||||||
QRect callGetGeometry() const override {
|
|
||||||
return this->geometry();
|
|
||||||
}
|
|
||||||
bool callIsHidden() const override {
|
|
||||||
return this->isHidden();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Initer _initer = { this, Traits::kSetZeroGeometry };
|
Initer _initer = { this, Traits::kSetZeroGeometry };
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class RpWidget : public RpWidgetWrap<QWidget> {
|
class RpWidget : public RpWidgetBase<QWidget> {
|
||||||
public:
|
public:
|
||||||
using RpWidgetWrap<QWidget>::RpWidgetWrap;
|
using RpWidgetBase<QWidget>::RpWidgetBase;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -910,7 +910,7 @@ FlatInput::FlatInput(
|
||||||
const style::FlatInput &st,
|
const style::FlatInput &st,
|
||||||
rpl::producer<QString> placeholder,
|
rpl::producer<QString> placeholder,
|
||||||
const QString &v)
|
const QString &v)
|
||||||
: RpWidgetWrap<QLineEdit>(v, parent)
|
: Parent(v, parent)
|
||||||
, _oldtext(v)
|
, _oldtext(v)
|
||||||
, _placeholderFull(std::move(placeholder))
|
, _placeholderFull(std::move(placeholder))
|
||||||
, _placeholderVisible(!v.length())
|
, _placeholderVisible(!v.length())
|
||||||
|
|
|
||||||
|
|
@ -54,11 +54,11 @@ enum class InputSubmitSettings {
|
||||||
None,
|
None,
|
||||||
};
|
};
|
||||||
|
|
||||||
class FlatInput : public RpWidgetWrap<QLineEdit> {
|
class FlatInput : public RpWidgetBase<QLineEdit> {
|
||||||
// The Q_OBJECT meta info is used for qobject_cast!
|
// The Q_OBJECT meta info is used for qobject_cast!
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
using Parent = RpWidgetWrap<QLineEdit>;
|
using Parent = RpWidgetBase<QLineEdit>;
|
||||||
public:
|
public:
|
||||||
FlatInput(
|
FlatInput(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
|
|
@ -545,11 +545,11 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class MaskedInputField : public RpWidgetWrap<QLineEdit> {
|
class MaskedInputField : public RpWidgetBase<QLineEdit> {
|
||||||
// The Q_OBJECT meta info is used for qobject_cast!
|
// The Q_OBJECT meta info is used for qobject_cast!
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
using Parent = RpWidgetWrap<QLineEdit>;
|
using Parent = RpWidgetBase<QLineEdit>;
|
||||||
public:
|
public:
|
||||||
MaskedInputField(
|
MaskedInputField(
|
||||||
QWidget *parent,
|
QWidget *parent,
|
||||||
|
|
|
||||||
|
|
@ -272,7 +272,7 @@ void ScrollBar::resizeEvent(QResizeEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ScrollArea::ScrollArea(QWidget *parent, const style::ScrollArea &st, bool handleTouch)
|
ScrollArea::ScrollArea(QWidget *parent, const style::ScrollArea &st, bool handleTouch)
|
||||||
: RpWidgetWrap<QScrollArea>(parent)
|
: Parent(parent)
|
||||||
, _st(st)
|
, _st(st)
|
||||||
, _horizontalBar(this, false, &_st)
|
, _horizontalBar(this, false, &_st)
|
||||||
, _verticalBar(this, true, &_st)
|
, _verticalBar(this, true, &_st)
|
||||||
|
|
|
||||||
|
|
@ -125,9 +125,10 @@ private:
|
||||||
QRect _bar;
|
QRect _bar;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ScrollArea : public RpWidgetWrap<QScrollArea> {
|
class ScrollArea : public RpWidgetBase<QScrollArea> {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
using Parent = RpWidgetBase<QScrollArea>;
|
||||||
public:
|
public:
|
||||||
ScrollArea(QWidget *parent, const style::ScrollArea &st = st::defaultScrollArea, bool handleTouch = true);
|
ScrollArea(QWidget *parent, const style::ScrollArea &st = st::defaultScrollArea, bool handleTouch = true);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue