diff --git a/frontend/widgets/OBSProjector.cpp b/frontend/widgets/OBSProjector.cpp index 5adc235a44c7bf..99cca89628d4af 100644 --- a/frontend/widgets/OBSProjector.cpp +++ b/frontend/widgets/OBSProjector.cpp @@ -18,9 +18,26 @@ static QList multiviewProjectors; static bool updatingMultiview = false, mouseSwitching, transitionOnDoubleClick; OBSProjector::OBSProjector(QWidget *widget, obs_source_t *source_, int monitor, ProjectorType type_) - : OBSQTDisplay(widget, Qt::Window), + : QWidget(widget, Qt::Window), + display(this), weakSource(OBSGetWeakRef(source_)) { + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(&display); + layout->setContentsMargins(0, 0, 0, 0); + this->setLayout(layout); + + // Whether the compositor and qt are able to agree on the current state + // of a native window after transitioning between windowed and + // fullscreen. If not, then we should not allow users to modify existing + // projectors to switch between fullscreen/windowed. + qtFullscreenNativeWorks = true; +#if !defined(_WIN32) && !defined(__APPLE__) + const char *desktop = getenv("XDG_CURRENT_DESKTOP"); + if (desktop && strstr(desktop, "GNOME") != nullptr && QApplication::platformName().contains("wayland")) + qtFullscreenNativeWorks = false; +#endif + OBSSource source = GetSource(); if (source) { sigs.emplace_back(obs_source_get_signal_handler(source), "rename", OBSSourceRenamed, this); @@ -34,12 +51,7 @@ OBSProjector::OBSProjector(QWidget *widget, obs_source_t *source_, int monitor, // Mark the window as a projector so SetDisplayAffinity // can skip it - windowHandle()->setProperty("isOBSProjectorWindow", true); - -#if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__) - // Prevents resizing of projector windows - setAttribute(Qt::WA_PaintOnScreen, false); -#endif + this->setProperty("isOBSProjectorWindow", true); type = type_; #ifdef __APPLE__ @@ -48,10 +60,7 @@ OBSProjector::OBSProjector(QWidget *widget, obs_source_t *source_, int monitor, setWindowIcon(QIcon::fromTheme("obs", QIcon(":/res/images/obs.png"))); #endif - if (monitor == -1) - resize(480, 270); - else - SetMonitor(monitor); + resize(480, 270); if (source) UpdateProjectorTitle(QT_UTF8(obs_source_get_name(source))); @@ -72,11 +81,11 @@ OBSProjector::OBSProjector(QWidget *widget, obs_source_t *source_, int monitor, auto addDrawCallback = [this]() { bool isMultiview = type == ProjectorType::Multiview; - obs_display_add_draw_callback(GetDisplay(), isMultiview ? OBSRenderMultiview : OBSRender, this); - obs_display_set_background_color(GetDisplay(), 0x000000); + obs_display_add_draw_callback(display.GetDisplay(), isMultiview ? OBSRenderMultiview : OBSRender, this); + obs_display_set_background_color(display.GetDisplay(), 0x000000); }; - connect(this, &OBSQTDisplay::DisplayCreated, addDrawCallback); + connect(&display, &OBSQTDisplay::DisplayCreated, addDrawCallback); connect(App(), &QGuiApplication::screenRemoved, this, &OBSProjector::ScreenRemoved); if (type == ProjectorType::Multiview) { @@ -94,6 +103,8 @@ OBSProjector::OBSProjector(QWidget *widget, obs_source_t *source_, int monitor, ready = true; + if (monitor != -1) + SetMonitor(monitor); show(); // We need it here to allow keyboard input in X11 to listen to Escape @@ -105,7 +116,7 @@ OBSProjector::~OBSProjector() sigs.clear(); bool isMultiview = type == ProjectorType::Multiview; - obs_display_remove_draw_callback(GetDisplay(), isMultiview ? OBSRenderMultiview : OBSRender, this); + obs_display_remove_draw_callback(display.GetDisplay(), isMultiview ? OBSRenderMultiview : OBSRender, this); OBSSource source = GetSource(); if (source) @@ -122,9 +133,10 @@ OBSProjector::~OBSProjector() void OBSProjector::SetMonitor(int monitor) { savedMonitor = monitor; - setGeometry(QGuiApplication::screens()[monitor]->geometry()); + screen = QGuiApplication::screens()[monitor]; showFullScreen(); SetHideCursor(); + update(); } void OBSProjector::SetHideCursor() @@ -221,7 +233,7 @@ void OBSProjector::OBSSourceDestroyed(void *data, calldata_t *) void OBSProjector::mouseDoubleClickEvent(QMouseEvent *event) { - OBSQTDisplay::mouseDoubleClickEvent(event); + QWidget::mouseDoubleClickEvent(event); if (!mouseSwitching) return; @@ -250,19 +262,20 @@ void OBSProjector::mouseDoubleClickEvent(QMouseEvent *event) void OBSProjector::mousePressEvent(QMouseEvent *event) { - OBSQTDisplay::mousePressEvent(event); + QWidget::mousePressEvent(event); if (event->button() == Qt::RightButton) { - QMenu *projectorMenu = new QMenu(QTStr("Fullscreen")); - OBSBasic::AddProjectorMenuMonitors(projectorMenu, this, &OBSProjector::OpenFullScreenProjector); - QMenu popup(this); - popup.addMenu(projectorMenu); - - if (GetMonitor() > -1) { - popup.addAction(QTStr("Windowed"), this, &OBSProjector::OpenWindowedProjector); - - } else if (!this->isMaximized()) { + if (qtFullscreenNativeWorks) { + QMenu *projectorMenu = new QMenu(QTStr("Fullscreen")); + OBSBasic::AddProjectorMenuMonitors(projectorMenu, this, &OBSProjector::OpenFullScreenProjector); + popup.addMenu(projectorMenu); + + if (GetMonitor() > -1) { + popup.addAction(QTStr("Windowed"), this, &OBSProjector::OpenWindowedProjector); + } + } + if (!this->isMaximized() && GetMonitor() == -1) { popup.addAction(QTStr("ResizeProjectorWindowToContent"), this, &OBSProjector::ResizeToContent); } @@ -412,16 +425,17 @@ void OBSProjector::OpenFullScreenProjector() void OBSProjector::OpenWindowedProjector() { - showFullScreen(); + + if (!prevGeometry.isNull()) { + display.setGeometry(prevGeometry); + } else + display.resize(480, 270); showNormal(); setCursor(Qt::ArrowCursor); - - if (!prevGeometry.isNull()) - setGeometry(prevGeometry); - else - resize(480, 270); + update(); savedMonitor = -1; + screen = nullptr; OBSSource source = GetSource(); UpdateProjectorTitle(QT_UTF8(obs_source_get_name(source))); @@ -474,6 +488,11 @@ bool OBSProjector::IsAlwaysOnTopOverridden() const return isAlwaysOnTopOverridden; } +bool OBSProjector::nativeEvent(const QByteArray &eventType, void *message, qintptr *result) +{ + return display.nativeEvent(eventType, message, result); +} + void OBSProjector::SetIsAlwaysOnTop(bool isAlwaysOnTop, bool isOverridden) { this->isAlwaysOnTop = isAlwaysOnTop; diff --git a/frontend/widgets/OBSProjector.hpp b/frontend/widgets/OBSProjector.hpp index 7f9cd4a4a100b6..0e20fae4524afe 100644 --- a/frontend/widgets/OBSProjector.hpp +++ b/frontend/widgets/OBSProjector.hpp @@ -12,12 +12,16 @@ enum class ProjectorType { Multiview, }; -class OBSProjector : public OBSQTDisplay { +class QMouseEvent; + +class OBSProjector : public QWidget { Q_OBJECT private: + OBSQTDisplay display; OBSWeakSourceAutoRelease weakSource; std::vector sigs; + bool qtFullscreenNativeWorks; static void OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy); static void OBSRender(void *data, uint32_t cx, uint32_t cy); @@ -27,6 +31,7 @@ class OBSProjector : public OBSQTDisplay { void mousePressEvent(QMouseEvent *event) override; void mouseDoubleClickEvent(QMouseEvent *event) override; void closeEvent(QCloseEvent *event) override; + virtual bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result) override; bool isAlwaysOnTop; bool isAlwaysOnTopOverridden = false; diff --git a/frontend/widgets/OBSQTDisplay.hpp b/frontend/widgets/OBSQTDisplay.hpp index 4c1152ba56f2c9..c7a58cdc64a578 100644 --- a/frontend/widgets/OBSQTDisplay.hpp +++ b/frontend/widgets/OBSQTDisplay.hpp @@ -11,6 +11,8 @@ class OBSQTDisplay : public QWidget { Q_PROPERTY(QColor displayBackgroundColor MEMBER backgroundColor READ GetDisplayBackgroundColor WRITE SetDisplayBackgroundColor) + friend class OBSProjector; + OBSDisplay display; bool destroying = false;