2015-08-01 20:38:12 -07:00
|
|
|
#include "qt-display.hpp"
|
|
|
|
#include "qt-wrappers.hpp"
|
|
|
|
#include "display-helpers.hpp"
|
|
|
|
#include <QWindow>
|
|
|
|
#include <QScreen>
|
|
|
|
#include <QResizeEvent>
|
|
|
|
#include <QShowEvent>
|
|
|
|
|
2020-08-18 15:38:29 -07:00
|
|
|
#include <obs-config.h>
|
|
|
|
|
2022-02-08 23:34:45 -08:00
|
|
|
#ifdef _WIN32
|
|
|
|
#define WIN32_LEAN_AND_MEAN
|
|
|
|
#include <Windows.h>
|
|
|
|
#endif
|
|
|
|
|
2020-08-18 15:38:29 -07:00
|
|
|
#ifdef ENABLE_WAYLAND
|
|
|
|
#include <obs-nix-platform.h>
|
2020-08-20 07:58:45 -07:00
|
|
|
|
|
|
|
class SurfaceEventFilter : public QObject {
|
|
|
|
OBSQTDisplay *display;
|
|
|
|
int mTimerId;
|
|
|
|
|
|
|
|
public:
|
|
|
|
SurfaceEventFilter(OBSQTDisplay *src) : display(src), mTimerId(0) {}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
bool eventFilter(QObject *obj, QEvent *event) override
|
|
|
|
{
|
|
|
|
bool result = QObject::eventFilter(obj, event);
|
|
|
|
QPlatformSurfaceEvent *surfaceEvent;
|
|
|
|
|
|
|
|
switch (event->type()) {
|
|
|
|
case QEvent::PlatformSurface:
|
|
|
|
surfaceEvent =
|
|
|
|
static_cast<QPlatformSurfaceEvent *>(event);
|
|
|
|
if (surfaceEvent->surfaceEventType() !=
|
|
|
|
QPlatformSurfaceEvent::SurfaceCreated)
|
|
|
|
return result;
|
|
|
|
|
|
|
|
if (display->windowHandle()->isExposed())
|
|
|
|
createOBSDisplay();
|
|
|
|
else
|
|
|
|
mTimerId = startTimer(67); // Arbitrary
|
|
|
|
break;
|
2022-05-15 17:54:24 -07:00
|
|
|
case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
|
|
|
|
display->DestroyDisplay();
|
|
|
|
break;
|
2020-08-20 07:58:45 -07:00
|
|
|
case QEvent::Expose:
|
|
|
|
createOBSDisplay();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2022-05-15 17:54:24 -07:00
|
|
|
void timerEvent(QTimerEvent *)
|
|
|
|
{
|
|
|
|
createOBSDisplay(display->isVisible());
|
|
|
|
}
|
2020-08-20 07:58:45 -07:00
|
|
|
|
|
|
|
private:
|
|
|
|
void createOBSDisplay(bool force = false)
|
|
|
|
{
|
|
|
|
display->CreateDisplay(force);
|
|
|
|
if (mTimerId > 0) {
|
|
|
|
killTimer(mTimerId);
|
|
|
|
mTimerId = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-08-18 15:38:29 -07:00
|
|
|
#endif
|
|
|
|
|
2019-07-24 08:09:37 -07:00
|
|
|
static inline long long color_to_int(const QColor &color)
|
2018-08-30 13:17:49 -07:00
|
|
|
{
|
2019-06-22 22:13:45 -07:00
|
|
|
auto shift = [&](unsigned val, int shift) {
|
2018-08-30 13:17:49 -07:00
|
|
|
return ((val & 0xff) << shift);
|
|
|
|
};
|
|
|
|
|
2019-06-22 22:13:45 -07:00
|
|
|
return shift(color.red(), 0) | shift(color.green(), 8) |
|
|
|
|
shift(color.blue(), 16) | shift(color.alpha(), 24);
|
2018-08-30 13:17:49 -07:00
|
|
|
}
|
|
|
|
|
2019-01-23 07:05:48 -08:00
|
|
|
static inline QColor rgba_to_color(uint32_t rgba)
|
|
|
|
{
|
2019-06-22 22:13:45 -07:00
|
|
|
return QColor::fromRgb(rgba & 0xFF, (rgba >> 8) & 0xFF,
|
|
|
|
(rgba >> 16) & 0xFF, (rgba >> 24) & 0xFF);
|
2019-01-23 07:05:48 -08:00
|
|
|
}
|
2018-08-30 13:17:49 -07:00
|
|
|
|
2015-08-01 20:38:12 -07:00
|
|
|
OBSQTDisplay::OBSQTDisplay(QWidget *parent, Qt::WindowFlags flags)
|
|
|
|
: QWidget(parent, flags)
|
|
|
|
{
|
|
|
|
setAttribute(Qt::WA_PaintOnScreen);
|
|
|
|
setAttribute(Qt::WA_StaticContents);
|
|
|
|
setAttribute(Qt::WA_NoSystemBackground);
|
|
|
|
setAttribute(Qt::WA_OpaquePaintEvent);
|
|
|
|
setAttribute(Qt::WA_DontCreateNativeAncestors);
|
|
|
|
setAttribute(Qt::WA_NativeWindow);
|
|
|
|
|
2019-06-22 22:13:45 -07:00
|
|
|
auto windowVisible = [this](bool visible) {
|
2020-08-18 15:38:29 -07:00
|
|
|
if (!visible) {
|
2021-11-20 23:02:52 -08:00
|
|
|
#if !defined(_WIN32) && !defined(__APPLE__)
|
|
|
|
display = nullptr;
|
2020-08-18 15:38:29 -07:00
|
|
|
#endif
|
2015-08-01 20:38:12 -07:00
|
|
|
return;
|
2020-08-18 15:38:29 -07:00
|
|
|
}
|
2015-08-01 20:38:12 -07:00
|
|
|
|
|
|
|
if (!display) {
|
|
|
|
CreateDisplay();
|
|
|
|
} else {
|
|
|
|
QSize size = GetPixelSize(this);
|
2019-06-22 22:13:45 -07:00
|
|
|
obs_display_resize(display, size.width(),
|
|
|
|
size.height());
|
2015-08-01 20:38:12 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-08-19 09:08:01 -07:00
|
|
|
auto screenChanged = [this](QScreen *) {
|
2015-08-01 20:38:12 -07:00
|
|
|
CreateDisplay();
|
|
|
|
|
|
|
|
QSize size = GetPixelSize(this);
|
|
|
|
obs_display_resize(display, size.width(), size.height());
|
|
|
|
};
|
|
|
|
|
|
|
|
connect(windowHandle(), &QWindow::visibleChanged, windowVisible);
|
2020-08-19 09:08:01 -07:00
|
|
|
connect(windowHandle(), &QWindow::screenChanged, screenChanged);
|
2020-08-20 07:58:45 -07:00
|
|
|
|
|
|
|
#ifdef ENABLE_WAYLAND
|
|
|
|
if (obs_get_nix_platform() == OBS_NIX_PLATFORM_WAYLAND)
|
|
|
|
windowHandle()->installEventFilter(
|
|
|
|
new SurfaceEventFilter(this));
|
|
|
|
#endif
|
2019-01-23 07:05:48 -08:00
|
|
|
}
|
2018-08-30 13:17:49 -07:00
|
|
|
|
2019-01-23 07:05:48 -08:00
|
|
|
QColor OBSQTDisplay::GetDisplayBackgroundColor() const
|
|
|
|
{
|
|
|
|
return rgba_to_color(backgroundColor);
|
2018-08-30 13:17:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void OBSQTDisplay::SetDisplayBackgroundColor(const QColor &color)
|
|
|
|
{
|
2019-01-23 07:05:48 -08:00
|
|
|
uint32_t newBackgroundColor = (uint32_t)color_to_int(color);
|
|
|
|
|
|
|
|
if (newBackgroundColor != backgroundColor) {
|
|
|
|
backgroundColor = newBackgroundColor;
|
|
|
|
UpdateDisplayBackgroundColor();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSQTDisplay::UpdateDisplayBackgroundColor()
|
|
|
|
{
|
2018-08-30 13:17:49 -07:00
|
|
|
obs_display_set_background_color(display, backgroundColor);
|
2015-08-01 20:38:12 -07:00
|
|
|
}
|
|
|
|
|
2020-08-20 07:57:19 -07:00
|
|
|
void OBSQTDisplay::CreateDisplay(bool force)
|
2015-08-01 20:38:12 -07:00
|
|
|
{
|
2020-08-20 07:57:19 -07:00
|
|
|
if (display)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!windowHandle()->isExposed() && !force)
|
2015-08-01 20:38:12 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
QSize size = GetPixelSize(this);
|
|
|
|
|
2019-06-22 22:13:45 -07:00
|
|
|
gs_init_data info = {};
|
|
|
|
info.cx = size.width();
|
|
|
|
info.cy = size.height();
|
2019-09-05 22:47:20 -07:00
|
|
|
info.format = GS_BGRA;
|
2019-06-22 22:13:45 -07:00
|
|
|
info.zsformat = GS_ZS_NONE;
|
2015-08-01 20:38:12 -07:00
|
|
|
|
2020-08-19 06:11:08 -07:00
|
|
|
if (!QTToGSWindow(windowHandle(), info.window))
|
|
|
|
return;
|
2015-08-01 20:38:12 -07:00
|
|
|
|
2018-08-30 13:17:49 -07:00
|
|
|
display = obs_display_create(&info, backgroundColor);
|
2015-08-01 20:38:12 -07:00
|
|
|
|
|
|
|
emit DisplayCreated(this);
|
|
|
|
}
|
|
|
|
|
2022-02-08 23:34:45 -08:00
|
|
|
void OBSQTDisplay::paintEvent(QPaintEvent *event)
|
|
|
|
{
|
|
|
|
CreateDisplay();
|
|
|
|
|
|
|
|
QWidget::paintEvent(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBSQTDisplay::moveEvent(QMoveEvent *event)
|
|
|
|
{
|
|
|
|
QWidget::moveEvent(event);
|
|
|
|
|
|
|
|
OnMove();
|
|
|
|
}
|
|
|
|
|
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
|
|
|
bool OBSQTDisplay::nativeEvent(const QByteArray &, void *message, qintptr *)
|
|
|
|
#else
|
|
|
|
bool OBSQTDisplay::nativeEvent(const QByteArray &, void *message, long *)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
|
|
|
const MSG &msg = *static_cast<MSG *>(message);
|
|
|
|
switch (msg.message) {
|
|
|
|
case WM_DISPLAYCHANGE:
|
|
|
|
OnDisplayChange();
|
|
|
|
}
|
2022-04-19 11:47:37 -07:00
|
|
|
#else
|
|
|
|
UNUSED_PARAMETER(message);
|
2022-02-08 23:34:45 -08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-08-01 20:38:12 -07:00
|
|
|
void OBSQTDisplay::resizeEvent(QResizeEvent *event)
|
|
|
|
{
|
|
|
|
QWidget::resizeEvent(event);
|
|
|
|
|
|
|
|
CreateDisplay();
|
|
|
|
|
|
|
|
if (isVisible() && display) {
|
|
|
|
QSize size = GetPixelSize(this);
|
|
|
|
obs_display_resize(display, size.width(), size.height());
|
|
|
|
}
|
|
|
|
|
|
|
|
emit DisplayResized();
|
|
|
|
}
|
|
|
|
|
|
|
|
QPaintEngine *OBSQTDisplay::paintEngine() const
|
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
2022-02-08 23:34:45 -08:00
|
|
|
|
2022-02-07 23:24:10 -08:00
|
|
|
void OBSQTDisplay::OnMove()
|
|
|
|
{
|
|
|
|
if (display)
|
|
|
|
obs_display_update_color_space(display);
|
|
|
|
}
|
2022-02-08 23:34:45 -08:00
|
|
|
|
2022-02-07 23:24:10 -08:00
|
|
|
void OBSQTDisplay::OnDisplayChange()
|
|
|
|
{
|
|
|
|
if (display)
|
|
|
|
obs_display_update_color_space(display);
|
|
|
|
}
|