From 71c575320755164e26d394af683622948fea2f8e Mon Sep 17 00:00:00 2001 From: cg2121 Date: Wed, 1 Mar 2017 22:08:49 -0600 Subject: [PATCH] UI: Add ability to output to window Closes jp9000/obs-studio#841 --- UI/data/locale/en-US.ini | 3 + UI/window-basic-main.cpp | 124 ++++++++++++++++++++++++++++++++------- UI/window-basic-main.hpp | 8 ++- UI/window-projector.cpp | 44 +++++++++----- UI/window-projector.hpp | 5 +- 5 files changed, 146 insertions(+), 38 deletions(-) diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini index 7a2b73286..d43500cc2 100644 --- a/UI/data/locale/en-US.ini +++ b/UI/data/locale/en-US.ini @@ -36,6 +36,9 @@ DroppedFrames="Dropped Frames %1 (%2%)" PreviewProjector="Fullscreen Projector (Preview)" SceneProjector="Fullscreen Projector (Scene)" SourceProjector="Fullscreen Projector (Source)" +PreviewWindow="Windowed Projector (Preview)" +SceneWindow="Windowed Projector (Scene)" +SourceWindow="Windowed Projector (Source)" Clear="Clear" Revert="Revert" Show="Show" diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index 74703d73b..1b20da971 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -2807,6 +2807,10 @@ void OBSBasic::CloseDialogs() } } + for (QPointer &projector : windowProjectors) { + delete projector; + projector.clear(); + } for (QPointer &projector : projectors) { delete projector; projector.clear(); @@ -3068,6 +3072,12 @@ void OBSBasic::on_scenes_customContextMenuRequested(const QPoint &pos) AddProjectorMenuMonitors(sceneProjectorMenu, this, SLOT(OpenSceneProjector())); popup.addMenu(sceneProjectorMenu); + + QAction *sceneWindow = popup.addAction( + QTStr("SceneWindow"), + this, SLOT(OpenSceneWindow())); + + popup.addAction(sceneWindow); popup.addSeparator(); popup.addAction(QTStr("Filters"), this, SLOT(OpenSceneFilters())); @@ -3335,6 +3345,12 @@ void OBSBasic::CreateSourcePopupMenu(QListWidgetItem *item, bool preview) popup.addMenu(previewProjector); + QAction *previewWindow = popup.addAction( + QTStr("PreviewWindow"), + this, SLOT(OpenPreviewWindow())); + + popup.addAction(previewWindow); + popup.addSeparator(); } @@ -3379,6 +3395,12 @@ void OBSBasic::CreateSourcePopupMenu(QListWidgetItem *item, bool preview) AddProjectorMenuMonitors(sourceProjector, this, SLOT(OpenSourceProjector())); + QAction *sourceWindow = popup.addAction( + QTStr("SourceWindow"), + this, SLOT(OpenSourceWindow())); + + popup.addAction(sourceWindow); + popup.addSeparator(); if (isAsyncVideo) { popup.addMenu(AddDeinterlacingMenu(source)); @@ -3389,6 +3411,7 @@ void OBSBasic::CreateSourcePopupMenu(QListWidgetItem *item, bool preview) popup.addSeparator(); popup.addMenu(sourceProjector); + popup.addAction(sourceWindow); popup.addSeparator(); action = popup.addAction(QTStr("Interact"), this, @@ -4465,7 +4488,12 @@ void OBSBasic::on_previewDisabledLabel_customContextMenuRequested( AddProjectorMenuMonitors(previewProjector, this, SLOT(OpenPreviewProjector())); + QAction *previewWindow = popup.addAction( + QTStr("PreviewWindow"), + this, SLOT(OpenPreviewWindow())); + popup.addMenu(previewProjector); + popup.addAction(previewWindow); popup.exec(QCursor::pos()); UNUSED_PARAMETER(pos); @@ -4901,7 +4929,8 @@ void OBSBasic::NudgeDown() {Nudge(1, MoveDir::Down);} void OBSBasic::NudgeLeft() {Nudge(1, MoveDir::Left);} void OBSBasic::NudgeRight() {Nudge(1, MoveDir::Right);} -void OBSBasic::OpenProjector(obs_source_t *source, int monitor) +void OBSBasic::OpenProjector(obs_source_t *source, int monitor, bool window, + QString title) { /* seriously? 10 monitors? */ if (monitor > 9 || monitor > QGuiApplication::screens().size() - 1) @@ -4912,29 +4941,45 @@ void OBSBasic::OpenProjector(obs_source_t *source, int monitor) if (source == nullptr) isPreview = true; - delete projectors[monitor]; - projectors[monitor].clear(); - - RemoveSavedProjectors(monitor); - - OBSProjector *projector = new OBSProjector(nullptr, source); - - const char *name = obs_source_get_name(source); - - if (isPreview) { - previewProjectorArray.at((size_t)monitor) = 1; - } else { - projectorArray.at((size_t)monitor) = name; + if (!window) { + delete projectors[monitor]; + projectors[monitor].clear(); + RemoveSavedProjectors(monitor); } - projector->Init(monitor); - projectors[monitor] = projector; + OBSProjector *projector = new OBSProjector(nullptr, source, !!window); + const char *name = obs_source_get_name(source); + + if (!window) { + if (isPreview) { + previewProjectorArray.at((size_t)monitor) = 1; + } else { + projectorArray.at((size_t)monitor) = name; + } + } + + if (!window) { + projector->Init(monitor, false, nullptr); + projectors[monitor] = projector; + } else { + projector->Init(monitor, true, title); + + for (auto &projPtr : windowProjectors) { + if (!projPtr) { + projPtr = projector; + projector = nullptr; + } + } + + if (projector) + windowProjectors.push_back(projector); + } } void OBSBasic::OpenPreviewProjector() { int monitor = sender()->property("monitor").toInt(); - OpenProjector(nullptr, monitor); + OpenProjector(nullptr, monitor, false); } void OBSBasic::OpenSourceProjector() @@ -4944,7 +4989,7 @@ void OBSBasic::OpenSourceProjector() if (!item) return; - OpenProjector(obs_sceneitem_get_source(item), monitor); + OpenProjector(obs_sceneitem_get_source(item), monitor, false); } void OBSBasic::OpenSceneProjector() @@ -4954,7 +4999,44 @@ void OBSBasic::OpenSceneProjector() if (!scene) return; - OpenProjector(obs_scene_get_source(scene), monitor); + OpenProjector(obs_scene_get_source(scene), monitor, false); +} + +void OBSBasic::OpenPreviewWindow() +{ + int monitor = sender()->property("monitor").toInt(); + QString title = QTStr("PreviewWindow"); + OpenProjector(nullptr, monitor, true, title); +} + +void OBSBasic::OpenSourceWindow() +{ + int monitor = sender()->property("monitor").toInt(); + OBSSceneItem item = GetCurrentSceneItem(); + OBSSource source = obs_sceneitem_get_source(item); + QString text = QString::fromUtf8(obs_source_get_name(source)); + + QString title = QTStr("SourceWindow") + " - " + text; + + if (!item) + return; + + OpenProjector(obs_sceneitem_get_source(item), monitor, true, title); +} + +void OBSBasic::OpenSceneWindow() +{ + int monitor = sender()->property("monitor").toInt(); + OBSScene scene = GetCurrentScene(); + OBSSource source = obs_scene_get_source(scene); + QString text = QString::fromUtf8(obs_source_get_name(source)); + + QString title = QTStr("SceneWindow") + " - " + text; + + if (!scene) + return; + + OpenProjector(obs_scene_get_source(scene), monitor, true, title); } void OBSBasic::OpenSavedProjectors() @@ -4974,14 +5056,14 @@ void OBSBasic::OpenSavedProjectors() continue; } - OpenProjector(source, (int)i); + OpenProjector(source, (int)i, false); obs_source_release(source); } } for (size_t i = 0; i < previewProjectorArray.size(); i++) { if (previewProjectorArray.at(i) == 1) { - OpenProjector(nullptr, (int)i); + OpenProjector(nullptr, (int)i, false); } } } diff --git a/UI/window-basic-main.hpp b/UI/window-basic-main.hpp index a4e18a87c..c418c5de8 100644 --- a/UI/window-basic-main.hpp +++ b/UI/window-basic-main.hpp @@ -158,6 +158,7 @@ private: ConfigFile basicConfig; QPointer projectors[10]; + QList> windowProjectors; QPointer startStreamMenu; @@ -233,7 +234,8 @@ private: void ClearSceneData(); void Nudge(int dist, MoveDir dir); - void OpenProjector(obs_source_t *source, int monitor); + void OpenProjector(obs_source_t *source, int monitor, bool window, + QString title = nullptr); void GetAudioSourceFilters(); void GetAudioSourceProperties(); @@ -636,6 +638,10 @@ private slots: void OpenSourceProjector(); void OpenSceneProjector(); + void OpenPreviewWindow(); + void OpenSourceWindow(); + void OpenSceneWindow(); + public slots: void on_actionResetTransform_triggered(); diff --git a/UI/window-projector.cpp b/UI/window-projector.cpp index e89489777..134258dbb 100644 --- a/UI/window-projector.cpp +++ b/UI/window-projector.cpp @@ -9,14 +9,18 @@ #include "platform.hpp" #include "obs-app.hpp" -OBSProjector::OBSProjector(QWidget *widget, obs_source_t *source_) +OBSProjector::OBSProjector(QWidget *widget, obs_source_t *source_, bool window) : OBSQTDisplay (widget, - Qt::Window | Qt::FramelessWindowHint | - Qt::X11BypassWindowManagerHint), + Qt::Window), source (source_), removedSignal (obs_source_get_signal_handler(source), "remove", OBSSourceRemoved, this) { + if (!window) { + setWindowFlags(Qt::FramelessWindowHint | + Qt::X11BypassWindowManagerHint); + } + setAttribute(Qt::WA_DeleteOnClose, true); //disable application quit when last window closed @@ -34,13 +38,14 @@ OBSProjector::OBSProjector(QWidget *widget, obs_source_t *source_) bool hideCursor = config_get_bool(GetGlobalConfig(), "BasicWindow", "HideProjectorCursor"); - if (hideCursor) { + if (hideCursor && !window) { QPixmap empty(16, 16); empty.fill(Qt::transparent); setCursor(QCursor(empty)); } App()->IncrementSleepInhibition(); + resize(480, 270); } OBSProjector::~OBSProjector() @@ -50,29 +55,36 @@ OBSProjector::~OBSProjector() App()->DecrementSleepInhibition(); } -void OBSProjector::Init(int monitor) +void OBSProjector::Init(int monitor, bool window, QString title) { QScreen *screen = QGuiApplication::screens()[monitor]; - setGeometry(screen->geometry()); + if (!window) + setGeometry(screen->geometry()); bool alwaysOnTop = config_get_bool(GetGlobalConfig(), "BasicWindow", "ProjectorAlwaysOnTop"); - if (alwaysOnTop) + if (alwaysOnTop && !window) SetAlwaysOnTop(this, true); + if (window) + setWindowTitle(title); + show(); if (source) obs_source_inc_showing(source); - QAction *action = new QAction(this); - action->setShortcut(Qt::Key_Escape); - addAction(action); - - connect(action, SIGNAL(triggered()), this, SLOT(EscapeTriggered())); + if (!window) { + QAction *action = new QAction(this); + action->setShortcut(Qt::Key_Escape); + addAction(action); + connect(action, SIGNAL(triggered()), this, + SLOT(EscapeTriggered())); + } savedMonitor = monitor; + isWindow = window; } void OBSProjector::OBSRender(void *data, uint32_t cx, uint32_t cy) @@ -136,8 +148,12 @@ void OBSProjector::mousePressEvent(QMouseEvent *event) void OBSProjector::EscapeTriggered() { - OBSBasic *main = reinterpret_cast(App()->GetMainWindow()); - main->RemoveSavedProjectors(savedMonitor); + if (!isWindow) { + OBSBasic *main = + reinterpret_cast(App()->GetMainWindow()); + + main->RemoveSavedProjectors(savedMonitor); + } deleteLater(); } diff --git a/UI/window-projector.hpp b/UI/window-projector.hpp index 394d2706f..48205dd7a 100644 --- a/UI/window-projector.hpp +++ b/UI/window-projector.hpp @@ -19,13 +19,14 @@ private: void mousePressEvent(QMouseEvent *event) override; int savedMonitor = 0; + bool isWindow = false; private slots: void EscapeTriggered(); public: - OBSProjector(QWidget *parent, obs_source_t *source); + OBSProjector(QWidget *parent, obs_source_t *source, bool window); ~OBSProjector(); - void Init(int monitor); + void Init(int monitor, bool window, QString title); };