123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- #include "qt-display.hpp"
- #include "qt-wrappers.hpp"
- #include "display-helpers.hpp"
- #include <QWindow>
- #include <QScreen>
- #include <QResizeEvent>
- #include <QShowEvent>
- #include <obs-config.h>
- #ifdef _WIN32
- #define WIN32_LEAN_AND_MEAN
- #include <Windows.h>
- #endif
- #ifdef ENABLE_WAYLAND
- #include <obs-nix-platform.h>
- 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;
- case QEvent::Expose:
- createOBSDisplay();
- break;
- default:
- break;
- }
- return result;
- }
- void timerEvent(QTimerEvent *) { createOBSDisplay(true); }
- private:
- void createOBSDisplay(bool force = false)
- {
- display->CreateDisplay(force);
- if (mTimerId > 0) {
- killTimer(mTimerId);
- mTimerId = 0;
- }
- }
- };
- #endif
- 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);
- }
- 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);
- #ifdef ENABLE_WAYLAND
- if (obs_get_nix_platform() == OBS_NIX_PLATFORM_WAYLAND)
- windowHandle()->installEventFilter(
- new SurfaceEventFilter(this));
- #endif
- }
- 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(bool force)
- {
- if (display)
- return;
- if (!windowHandle()->isExposed() && !force)
- 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();
- }
- #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();
- }
- #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);
- }
|