diff --git a/frontend/widgets/OBSProjector.cpp b/frontend/widgets/OBSProjector.cpp index 7d6beb0d8024b0..e762fca6a29182 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) @@ -125,9 +136,9 @@ void OBSProjector::SetMonitor(int monitor) { savedMonitor = monitor; screen = QGuiApplication::screens()[monitor]; - setGeometry(screen->geometry()); showFullScreen(); SetHideCursor(); + update(); } void OBSProjector::SetHideCursor() @@ -224,7 +235,7 @@ void OBSProjector::OBSSourceDestroyed(void *data, calldata_t *) void OBSProjector::mouseDoubleClickEvent(QMouseEvent *event) { - OBSQTDisplay::mouseDoubleClickEvent(event); + QWidget::mouseDoubleClickEvent(event); if (!mouseSwitching) return; @@ -253,19 +264,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); } @@ -415,20 +427,20 @@ 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))); - screen = nullptr; } void OBSProjector::ResizeToContent() @@ -478,6 +490,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 417192ee01f2f4..e54094a4dae7a3 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;