From e832b42f07a12c20e87a326f4a035862a07330f8 Mon Sep 17 00:00:00 2001 From: Clayton Groeneveld Date: Tue, 8 Oct 2019 00:43:10 -0500 Subject: [PATCH] UI: Add ability to change projector type --- UI/data/locale/en-US.ini | 2 + UI/window-basic-main.cpp | 115 +++++++++++------------------ UI/window-basic-main.hpp | 9 ++- UI/window-projector.cpp | 153 ++++++++++++++++++++++++++++----------- UI/window-projector.hpp | 15 ++-- 5 files changed, 172 insertions(+), 122 deletions(-) diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini index 12b91a537..488be1c80 100644 --- a/UI/data/locale/en-US.ini +++ b/UI/data/locale/en-US.ini @@ -88,6 +88,8 @@ Group="Group" DoNotShowAgain="Do not show again" Default="(Default)" Calculating="Calculating..." +Fullscreen="Fullscreen" +Windowed="Windowed" # warning if program already open AlreadyRunning.Title="OBS is already running" diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index 1e4ca2a6b..315909206 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -601,11 +601,8 @@ obs_data_array_t *OBSBasic::SaveProjectors() obs_data_release(data); }; - for (QPointer &proj : projectors) - saveProjector(static_cast(proj.data())); - - for (QPointer &proj : windowProjectors) - saveProjector(static_cast(proj.data())); + for (size_t i = 0; i < projectors.size(); i++) + saveProjector(static_cast(projectors[i])); return savedProjectors; } @@ -2678,7 +2675,10 @@ void OBSBasic::RenameSources(OBSSource source, QString newName, volumes[i]->SetName(newName); } - OBSProjector::RenameProjector(prevName, newName); + for (size_t i = 0; i < projectors.size(); i++) { + if (projectors[i]->GetSource() == source) + projectors[i]->RenameProjector(prevName, newName); + } SaveProject(); @@ -3738,15 +3738,6 @@ void OBSBasic::CloseDialogs() } } - for (QPointer &projector : windowProjectors) { - delete projector; - projector.clear(); - } - for (QPointer &projector : projectors) { - delete projector; - projector.clear(); - } - if (!stats.isNull()) stats->close(); //call close to save Stats geometry if (!remux.isNull()) @@ -3788,6 +3779,13 @@ void OBSBasic::ClearSceneData() ClearQuickTransitions(); ui->transitions->clear(); + for (size_t i = 0; i < projectors.size(); i++) { + if (projectors[i]) + delete projectors[i]; + } + + projectors.clear(); + obs_set_output_source(0, nullptr); obs_set_output_source(1, nullptr); obs_set_output_source(2, nullptr); @@ -4017,8 +4015,8 @@ void OBSBasic::EditSceneName() item->setFlags(flags); } -static void AddProjectorMenuMonitors(QMenu *parent, QObject *target, - const char *slot) +void OBSBasic::AddProjectorMenuMonitors(QMenu *parent, QObject *target, + const char *slot) { QAction *action; QList screens = QGuiApplication::screens(); @@ -6438,32 +6436,29 @@ void OBSBasic::NudgeRight() Nudge(1, MoveDir::Right); } +void OBSBasic::DeleteProjector(OBSProjector *projector) +{ + for (size_t i = 0; i < projectors.size(); i++) { + if (projectors[i] == projector) { + projectors[i]->deleteLater(); + projectors.erase(projectors.begin() + i); + break; + } + } +} + OBSProjector *OBSBasic::OpenProjector(obs_source_t *source, int monitor, - QString title, ProjectorType type) + ProjectorType type) { /* seriously? 10 monitors? */ if (monitor > 9 || monitor > QGuiApplication::screens().size() - 1) return nullptr; OBSProjector *projector = - new OBSProjector(nullptr, source, monitor, title, type); + new OBSProjector(nullptr, source, monitor, type); - if (monitor < 0) { - for (auto &projPtr : windowProjectors) { - if (!projPtr) { - projPtr = projector; - projector = nullptr; - } - } - - if (projector) - windowProjectors.push_back(projector); - } else { - delete projectors[monitor]; - projectors[monitor].clear(); - - projectors[monitor] = projector; - } + if (projector) + projectors.emplace_back(projector); return projector; } @@ -6471,13 +6466,13 @@ OBSProjector *OBSBasic::OpenProjector(obs_source_t *source, int monitor, void OBSBasic::OpenStudioProgramProjector() { int monitor = sender()->property("monitor").toInt(); - OpenProjector(nullptr, monitor, nullptr, ProjectorType::StudioProgram); + OpenProjector(nullptr, monitor, ProjectorType::StudioProgram); } void OBSBasic::OpenPreviewProjector() { int monitor = sender()->property("monitor").toInt(); - OpenProjector(nullptr, monitor, nullptr, ProjectorType::Preview); + OpenProjector(nullptr, monitor, ProjectorType::Preview); } void OBSBasic::OpenSourceProjector() @@ -6487,14 +6482,14 @@ void OBSBasic::OpenSourceProjector() if (!item) return; - OpenProjector(obs_sceneitem_get_source(item), monitor, nullptr, + OpenProjector(obs_sceneitem_get_source(item), monitor, ProjectorType::Source); } void OBSBasic::OpenMultiviewProjector() { int monitor = sender()->property("monitor").toInt(); - OpenProjector(nullptr, monitor, nullptr, ProjectorType::Multiview); + OpenProjector(nullptr, monitor, ProjectorType::Multiview); } void OBSBasic::OpenSceneProjector() @@ -6504,20 +6499,18 @@ void OBSBasic::OpenSceneProjector() if (!scene) return; - OpenProjector(obs_scene_get_source(scene), monitor, nullptr, + OpenProjector(obs_scene_get_source(scene), monitor, ProjectorType::Scene); } void OBSBasic::OpenStudioProgramWindow() { - OpenProjector(nullptr, -1, QTStr("StudioProgramWindow"), - ProjectorType::StudioProgram); + OpenProjector(nullptr, -1, ProjectorType::StudioProgram); } void OBSBasic::OpenPreviewWindow() { - OpenProjector(nullptr, -1, QTStr("PreviewWindow"), - ProjectorType::Preview); + OpenProjector(nullptr, -1, ProjectorType::Preview); } void OBSBasic::OpenSourceWindow() @@ -6527,16 +6520,14 @@ void OBSBasic::OpenSourceWindow() return; OBSSource source = obs_sceneitem_get_source(item); - QString title = QString::fromUtf8(obs_source_get_name(source)); - OpenProjector(obs_sceneitem_get_source(item), -1, title, + OpenProjector(obs_sceneitem_get_source(item), -1, ProjectorType::Source); } void OBSBasic::OpenMultiviewWindow() { - OpenProjector(nullptr, -1, QTStr("MultiviewWindowed"), - ProjectorType::Multiview); + OpenProjector(nullptr, -1, ProjectorType::Multiview); } void OBSBasic::OpenSceneWindow() @@ -6546,10 +6537,8 @@ void OBSBasic::OpenSceneWindow() return; OBSSource source = obs_scene_get_source(scene); - QString title = QString::fromUtf8(obs_source_get_name(source)); - OpenProjector(obs_scene_get_source(scene), -1, title, - ProjectorType::Scene); + OpenProjector(obs_scene_get_source(scene), -1, ProjectorType::Scene); } void OBSBasic::OpenSavedProjectors() @@ -6564,33 +6553,15 @@ void OBSBasic::OpenSavedProjectors() if (!source) continue; - QString title = nullptr; - if (info->monitor < 0) - title = QString::fromUtf8( - obs_source_get_name(source)); - - projector = OpenProjector(source, info->monitor, title, + projector = OpenProjector(source, info->monitor, info->type); obs_source_release(source); break; } - case ProjectorType::Preview: { + default: { projector = OpenProjector(nullptr, info->monitor, - QTStr("PreviewWindow"), - ProjectorType::Preview); - break; - } - case ProjectorType::StudioProgram: { - projector = OpenProjector(nullptr, info->monitor, - QTStr("StudioProgramWindow"), - ProjectorType::StudioProgram); - break; - } - case ProjectorType::Multiview: { - projector = OpenProjector(nullptr, info->monitor, - QTStr("MultiviewWindowed"), - ProjectorType::Multiview); + info->type); break; } } diff --git a/UI/window-basic-main.hpp b/UI/window-basic-main.hpp index 0a0c6208b..17db92e1c 100644 --- a/UI/window-basic-main.hpp +++ b/UI/window-basic-main.hpp @@ -199,8 +199,7 @@ private: ConfigFile basicConfig; std::vector savedProjectorsArray; - QPointer projectors[10]; - QList> windowProjectors; + std::vector projectors; QPointer stats; QPointer remux; @@ -305,7 +304,7 @@ private: void Nudge(int dist, MoveDir dir); OBSProjector *OpenProjector(obs_source_t *source, int monitor, - QString title, ProjectorType type); + ProjectorType type); void GetAudioSourceFilters(); void GetAudioSourceProperties(); @@ -689,6 +688,10 @@ public: const char *GetCurrentOutputPath(); + void DeleteProjector(OBSProjector *projector); + void AddProjectorMenuMonitors(QMenu *parent, QObject *target, + const char *slot); + protected: virtual void closeEvent(QCloseEvent *event) override; virtual void changeEvent(QEvent *event) override; diff --git a/UI/window-projector.cpp b/UI/window-projector.cpp index 68f70d549..20358ef71 100644 --- a/UI/window-projector.cpp +++ b/UI/window-projector.cpp @@ -9,7 +9,6 @@ #include "qt-wrappers.hpp" #include "platform.hpp" -static QList windowedProjectors; static QList multiviewProjectors; static bool updatingMultiview = false, drawLabel, drawSafeArea, mouseSwitching, transitionOnDoubleClick; @@ -17,38 +16,26 @@ static MultiviewLayout multiviewLayout; static size_t maxSrcs, numSrcs; OBSProjector::OBSProjector(QWidget *widget, obs_source_t *source_, int monitor, - QString title, ProjectorType type_) + ProjectorType type_) : OBSQTDisplay(widget, Qt::Window), source(source_), removedSignal(obs_source_get_signal_handler(source), "remove", OBSSourceRemoved, this) { - projectorTitle = std::move(title); - savedMonitor = monitor; - isWindow = savedMonitor < 0; type = type_; - if (isWindow) { - setWindowIcon( - QIcon::fromTheme("obs", QIcon(":/res/images/obs.png"))); - - UpdateProjectorTitle(projectorTitle); - windowedProjectors.push_back(this); + setWindowIcon(QIcon::fromTheme("obs", QIcon(":/res/images/obs.png"))); + UpdateProjectorTitle(QT_UTF8(obs_source_get_name(source))); + if (monitor == -1) resize(480, 270); - } else { - setWindowFlags(Qt::FramelessWindowHint | - Qt::X11BypassWindowManagerHint); + else + SetMonitor(monitor); - QScreen *screen = QGuiApplication::screens()[savedMonitor]; - setGeometry(screen->geometry()); - - QAction *action = new QAction(this); - action->setShortcut(Qt::Key_Escape); - addAction(action); - connect(action, SIGNAL(triggered()), this, - SLOT(EscapeTriggered())); - } + QAction *action = new QAction(this); + action->setShortcut(Qt::Key_Escape); + addAction(action); + connect(action, SIGNAL(triggered()), this, SLOT(EscapeTriggered())); SetAlwaysOnTop(this, config_get_bool(GetGlobalConfig(), "BasicWindow", "ProjectorAlwaysOnTop")); @@ -70,13 +57,8 @@ OBSProjector::OBSProjector(QWidget *widget, obs_source_t *source_, int monitor, connect(this, &OBSQTDisplay::DisplayCreated, addDrawCallback); - bool hideCursor = config_get_bool(GetGlobalConfig(), "BasicWindow", - "HideProjectorCursor"); - if (hideCursor && !isWindow && type != ProjectorType::Multiview) { - QPixmap empty(16, 16); - empty.fill(Qt::transparent); - setCursor(QCursor(empty)); - } + if (isFullScreen()) + SetHideCursor(); if (type == ProjectorType::Multiview) { obs_enter_graphics(); @@ -146,8 +128,7 @@ OBSProjector::OBSProjector(QWidget *widget, obs_source_t *source_, int monitor, show(); // We need it here to allow keyboard input in X11 to listen to Escape - if (!isWindow) - activateWindow(); + activateWindow(); } OBSProjector::~OBSProjector() @@ -180,12 +161,28 @@ OBSProjector::~OBSProjector() if (type == ProjectorType::Multiview) multiviewProjectors.removeAll(this); - if (isWindow) - windowedProjectors.removeAll(this); - App()->DecrementSleepInhibition(); } +void OBSProjector::SetMonitor(int monitor) +{ + savedMonitor = monitor; + QScreen *screen = QGuiApplication::screens()[monitor]; + showFullScreen(); + setGeometry(screen->geometry()); +} + +void OBSProjector::SetHideCursor() +{ + bool hideCursor = config_get_bool(GetGlobalConfig(), "BasicWindow", + "HideProjectorCursor"); + + if (hideCursor && type != ProjectorType::Multiview) + setCursor(Qt::BlankCursor); + else + setCursor(Qt::ArrowCursor); +} + static OBSSource CreateLabel(const char *name, size_t h) { obs_data_t *settings = obs_data_create(); @@ -820,7 +817,19 @@ void OBSProjector::mousePressEvent(QMouseEvent *event) OBSQTDisplay::mousePressEvent(event); if (event->button() == Qt::RightButton) { + OBSBasic *main = + reinterpret_cast(App()->GetMainWindow()); QMenu popup(this); + + QMenu *projectorMenu = new QMenu(QTStr("Fullscreen")); + main->AddProjectorMenuMonitors(projectorMenu, this, + SLOT(OpenFullScreenProjector())); + popup.addMenu(projectorMenu); + + if (GetMonitor() > -1) + popup.addAction(QTStr("Windowed"), this, + SLOT(OpenWindowedProjector())); + popup.addAction(QTStr("Close"), this, SLOT(EscapeTriggered())); popup.exec(QCursor::pos()); } @@ -844,7 +853,8 @@ void OBSProjector::mousePressEvent(QMouseEvent *event) void OBSProjector::EscapeTriggered() { - deleteLater(); + OBSBasic *main = reinterpret_cast(App()->GetMainWindow()); + main->DeleteProjector(this); } void OBSProjector::UpdateMultiview() @@ -937,15 +947,39 @@ void OBSProjector::UpdateMultiview() void OBSProjector::UpdateProjectorTitle(QString name) { - projectorTitle = name; + bool window = (GetMonitor() == -1); QString title = nullptr; switch (type) { case ProjectorType::Scene: - title = QTStr("SceneWindow") + " - " + name; + if (!window) + title = QTStr("SceneProjector") + " - " + name; + else + title = QTStr("SceneWindow") + " - " + name; break; case ProjectorType::Source: - title = QTStr("SourceWindow") + " - " + name; + if (!window) + title = QTStr("SourceProjector") + " - " + name; + else + title = QTStr("SourceWindow") + " - " + name; + break; + case ProjectorType::Preview: + if (!window) + title = QTStr("PreviewProjector"); + else + title = QTStr("PreviewWindow"); + break; + case ProjectorType::StudioProgram: + if (!window) + title = QTStr("StudioProgramProjector"); + else + title = QTStr("StudioProgramWindow"); + break; + case ProjectorType::Multiview: + if (!window) + title = QTStr("MultiviewProjector"); + else + title = QTStr("MultiviewWindow"); break; default: title = name; @@ -986,7 +1020,42 @@ void OBSProjector::UpdateMultiviewProjectors() void OBSProjector::RenameProjector(QString oldName, QString newName) { - for (auto &projector : windowedProjectors) - if (projector->projectorTitle == oldName) - projector->UpdateProjectorTitle(newName); + if (oldName == newName) + return; + + UpdateProjectorTitle(newName); +} + +void OBSProjector::OpenFullScreenProjector() +{ + if (!isFullScreen()) + prevGeometry = geometry(); + + int monitor = sender()->property("monitor").toInt(); + SetMonitor(monitor); + SetHideCursor(); + + UpdateProjectorTitle(QT_UTF8(obs_source_get_name(source))); +} + +void OBSProjector::OpenWindowedProjector() +{ + showFullScreen(); + showNormal(); + setCursor(Qt::ArrowCursor); + + if (!prevGeometry.isNull()) + setGeometry(prevGeometry); + else + resize(480, 270); + + savedMonitor = -1; + + UpdateProjectorTitle(QT_UTF8(obs_source_get_name(source))); +} + +void OBSProjector::closeEvent(QCloseEvent *event) +{ + EscapeTriggered(); + event->accept(); } diff --git a/UI/window-projector.hpp b/UI/window-projector.hpp index 7ff933678..c1fbb6557 100644 --- a/UI/window-projector.hpp +++ b/UI/window-projector.hpp @@ -34,10 +34,9 @@ private: void mousePressEvent(QMouseEvent *event) override; void mouseDoubleClickEvent(QMouseEvent *event) override; + void closeEvent(QCloseEvent *event) override; - int savedMonitor; - bool isWindow; - QString projectorTitle; + int savedMonitor = -1; ProjectorType type = ProjectorType::Source; std::vector multiviewScenes; std::vector multiviewLabels; @@ -73,17 +72,23 @@ private: void UpdateMultiview(); void UpdateProjectorTitle(QString name); + QRect prevGeometry; + void SetHideCursor(); + void SetMonitor(int monitor); + private slots: void EscapeTriggered(); + void OpenFullScreenProjector(); + void OpenWindowedProjector(); public: OBSProjector(QWidget *widget, obs_source_t *source_, int monitor, - QString title, ProjectorType type_); + ProjectorType type_); ~OBSProjector(); OBSSource GetSource(); ProjectorType GetProjectorType(); int GetMonitor(); static void UpdateMultiviewProjectors(); - static void RenameProjector(QString oldName, QString newName); + void RenameProjector(QString oldName, QString newName); };