mirror of
https://github.com/obsproject/obs-studio.git
synced 2024-09-19 20:32:15 +02:00
710d99ef4d
When a source file contains an explicit include with a filename following the "moc_<actual-filename>.cpp" pattern, then CMake's AUTOMOC generation tool will recognize the matching pair and generate the replacement header file and add the required include directory entries. For all files which do contain Q_OBJECT or similar declarations but do not have an explicit include directive, the global mocs_compilation.cpp file will still be generated (which groups all "missing" generated headers). The larger this global file is, the more expensive incremental compilation will be as this file (and all its contained generated headers) will be re-generated regardless of whether actual changes occurred.
251 lines
5.0 KiB
C++
251 lines
5.0 KiB
C++
#include "moc_qt-display.cpp"
|
|
#include "display-helpers.hpp"
|
|
#include <QWindow>
|
|
#include <QScreen>
|
|
#include <QResizeEvent>
|
|
#include <QShowEvent>
|
|
|
|
#include <qt-wrappers.hpp>
|
|
#include <obs-config.h>
|
|
|
|
#ifdef _WIN32
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#include <Windows.h>
|
|
#endif
|
|
|
|
#if !defined(_WIN32) && !defined(__APPLE__)
|
|
#include <obs-nix-platform.h>
|
|
#endif
|
|
|
|
#ifdef ENABLE_WAYLAND
|
|
#include <qpa/qplatformnativeinterface.h>
|
|
#endif
|
|
|
|
class SurfaceEventFilter : public QObject {
|
|
OBSQTDisplay *display;
|
|
|
|
public:
|
|
SurfaceEventFilter(OBSQTDisplay *src) : QObject(src), display(src) {}
|
|
|
|
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);
|
|
|
|
switch (surfaceEvent->surfaceEventType()) {
|
|
case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
|
|
display->DestroyDisplay();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
};
|
|
|
|
static inline long long color_to_int(const QColor &color)
|
|
{
|
|
auto shift = [&](unsigned val, int shift) {
|
|
return ((val & 0xff) << shift);
|
|
};
|
|
|
|
return shift(color.red(), 0) | shift(color.green(), 8) |
|
|
shift(color.blue(), 16) | shift(color.alpha(), 24);
|
|
}
|
|
|
|
static inline QColor rgba_to_color(uint32_t rgba)
|
|
{
|
|
return QColor::fromRgb(rgba & 0xFF, (rgba >> 8) & 0xFF,
|
|
(rgba >> 16) & 0xFF, (rgba >> 24) & 0xFF);
|
|
}
|
|
|
|
static bool QTToGSWindow(QWindow *window, gs_window &gswindow)
|
|
{
|
|
bool success = true;
|
|
|
|
#ifdef _WIN32
|
|
gswindow.hwnd = (HWND)window->winId();
|
|
#elif __APPLE__
|
|
gswindow.view = (id)window->winId();
|
|
#else
|
|
switch (obs_get_nix_platform()) {
|
|
case OBS_NIX_PLATFORM_X11_EGL:
|
|
gswindow.id = window->winId();
|
|
gswindow.display = obs_get_nix_platform_display();
|
|
break;
|
|
#ifdef ENABLE_WAYLAND
|
|
case OBS_NIX_PLATFORM_WAYLAND: {
|
|
QPlatformNativeInterface *native =
|
|
QGuiApplication::platformNativeInterface();
|
|
gswindow.display =
|
|
native->nativeResourceForWindow("surface", window);
|
|
success = gswindow.display != nullptr;
|
|
break;
|
|
}
|
|
#endif
|
|
default:
|
|
success = false;
|
|
break;
|
|
}
|
|
#endif
|
|
return success;
|
|
}
|
|
|
|
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);
|
|
|
|
auto windowVisible = [this](bool visible) {
|
|
if (!visible) {
|
|
#if !defined(_WIN32) && !defined(__APPLE__)
|
|
display = nullptr;
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
if (!display) {
|
|
CreateDisplay();
|
|
} else {
|
|
QSize size = GetPixelSize(this);
|
|
obs_display_resize(display, size.width(),
|
|
size.height());
|
|
}
|
|
};
|
|
|
|
auto screenChanged = [this](QScreen *) {
|
|
CreateDisplay();
|
|
|
|
QSize size = GetPixelSize(this);
|
|
obs_display_resize(display, size.width(), size.height());
|
|
};
|
|
|
|
connect(windowHandle(), &QWindow::visibleChanged, windowVisible);
|
|
connect(windowHandle(), &QWindow::screenChanged, screenChanged);
|
|
|
|
windowHandle()->installEventFilter(new SurfaceEventFilter(this));
|
|
}
|
|
|
|
QColor OBSQTDisplay::GetDisplayBackgroundColor() const
|
|
{
|
|
return rgba_to_color(backgroundColor);
|
|
}
|
|
|
|
void OBSQTDisplay::SetDisplayBackgroundColor(const QColor &color)
|
|
{
|
|
uint32_t newBackgroundColor = (uint32_t)color_to_int(color);
|
|
|
|
if (newBackgroundColor != backgroundColor) {
|
|
backgroundColor = newBackgroundColor;
|
|
UpdateDisplayBackgroundColor();
|
|
}
|
|
}
|
|
|
|
void OBSQTDisplay::UpdateDisplayBackgroundColor()
|
|
{
|
|
obs_display_set_background_color(display, backgroundColor);
|
|
}
|
|
|
|
void OBSQTDisplay::CreateDisplay()
|
|
{
|
|
if (display)
|
|
return;
|
|
|
|
if (destroying)
|
|
return;
|
|
|
|
if (!windowHandle()->isExposed())
|
|
return;
|
|
|
|
QSize size = GetPixelSize(this);
|
|
|
|
gs_init_data info = {};
|
|
info.cx = size.width();
|
|
info.cy = size.height();
|
|
info.format = GS_BGRA;
|
|
info.zsformat = GS_ZS_NONE;
|
|
|
|
if (!QTToGSWindow(windowHandle(), info.window))
|
|
return;
|
|
|
|
display = obs_display_create(&info, backgroundColor);
|
|
|
|
emit DisplayCreated(this);
|
|
}
|
|
|
|
void OBSQTDisplay::paintEvent(QPaintEvent *event)
|
|
{
|
|
CreateDisplay();
|
|
|
|
QWidget::paintEvent(event);
|
|
}
|
|
|
|
void OBSQTDisplay::moveEvent(QMoveEvent *event)
|
|
{
|
|
QWidget::moveEvent(event);
|
|
|
|
OnMove();
|
|
}
|
|
|
|
bool OBSQTDisplay::nativeEvent(const QByteArray &, void *message, qintptr *)
|
|
{
|
|
#ifdef _WIN32
|
|
const MSG &msg = *static_cast<MSG *>(message);
|
|
switch (msg.message) {
|
|
case WM_DISPLAYCHANGE:
|
|
OnDisplayChange();
|
|
}
|
|
#else
|
|
UNUSED_PARAMETER(message);
|
|
#endif
|
|
|
|
return false;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
void OBSQTDisplay::OnMove()
|
|
{
|
|
if (display)
|
|
obs_display_update_color_space(display);
|
|
}
|
|
|
|
void OBSQTDisplay::OnDisplayChange()
|
|
{
|
|
if (display)
|
|
obs_display_update_color_space(display);
|
|
}
|