From 52938748cf21cc1aa2f310ab911bee1b59d04588 Mon Sep 17 00:00:00 2001 From: "David R. Myers" Date: Sun, 16 Jan 2022 14:46:01 -0500 Subject: [PATCH] UI: Allow hiding projector window frames --- UI/data/locale/en-US.ini | 2 ++ UI/forms/OBSBasicSettings.ui | 12 ++++++-- UI/window-basic-main.cpp | 6 ++++ UI/window-basic-main.hpp | 1 + UI/window-basic-settings.cpp | 13 +++++++++ UI/window-projector.cpp | 53 +++++++++++++++++++++++++++++++++++- UI/window-projector.hpp | 2 ++ 7 files changed, 86 insertions(+), 3 deletions(-) diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini index b9325190d..0518008c4 100644 --- a/UI/data/locale/en-US.ini +++ b/UI/data/locale/en-US.ini @@ -119,6 +119,7 @@ Grid="Grid" # warning for plugin load failures PluginsFailedToLoad.Title="Plugin Load Error" PluginsFailedToLoad.Text="The following OBS plugins failed to load:\n\n%1\nPlease update or remove these plugins." +HideProjectorFrame="Hide the window frame" # warning if program already open AlreadyRunning.Title="OBS is already running" @@ -877,6 +878,7 @@ Basic.Settings.General.WarnBeforeStoppingStream="Show confirmation dialog when s Basic.Settings.General.WarnBeforeStoppingRecord="Show confirmation dialog when stopping recording" Basic.Settings.General.Projectors="Projectors" Basic.Settings.General.HideProjectorCursor="Hide cursor over projectors" +Basic.Settings.General.HideProjectorFrame="Hide window frames on projectors" Basic.Settings.General.ProjectorAlwaysOnTop="Make projectors always on top" Basic.Settings.General.Snapping="Source Alignment Snapping" Basic.Settings.General.ScreenSnapping="Snap Sources to edge of screen" diff --git a/UI/forms/OBSBasicSettings.ui b/UI/forms/OBSBasicSettings.ui index da5591e1e..6a4b31122 100644 --- a/UI/forms/OBSBasicSettings.ui +++ b/UI/forms/OBSBasicSettings.ui @@ -544,20 +544,27 @@ + + + Basic.Settings.General.HideProjectorFrame + + + + Basic.Settings.General.ProjectorAlwaysOnTop - + Basic.Settings.General.SaveProjectors - + Basic.Settings.General.CloseExistingProjectors @@ -8012,6 +8019,7 @@ sourceSnapping centerSnapping hideProjectorCursor + hideProjectorFrame projectorAlwaysOnTop saveProjectors closeProjectors diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index e3e03023a..71a8fab66 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -11011,6 +11011,12 @@ void OBSBasic::UpdateProjectorHideCursor() projectors[i]->SetHideCursor(); } +void OBSBasic::UpdateProjectorHideFrame(bool hideFrame) +{ + for (size_t i = 0; i < projectors.size(); i++) + projectors[i]->SetHideFrame(hideFrame); +} + void OBSBasic::UpdateProjectorAlwaysOnTop(bool top) { for (size_t i = 0; i < projectors.size(); i++) diff --git a/UI/window-basic-main.hpp b/UI/window-basic-main.hpp index 7a15f13f9..1480aa188 100644 --- a/UI/window-basic-main.hpp +++ b/UI/window-basic-main.hpp @@ -626,6 +626,7 @@ private: int GetOverrideTransitionDuration(OBSSource source); void UpdateProjectorHideCursor(); + void UpdateProjectorHideFrame(bool hideFrame); void UpdateProjectorAlwaysOnTop(bool top); void ResetProjectors(); diff --git a/UI/window-basic-settings.cpp b/UI/window-basic-settings.cpp index 6d1b4ae94..f7d4ea03e 100644 --- a/UI/window-basic-settings.cpp +++ b/UI/window-basic-settings.cpp @@ -378,6 +378,7 @@ OBSBasicSettings::OBSBasicSettings(QWidget *parent) HookWidget(ui->warnBeforeStreamStop, CHECK_CHANGED, GENERAL_CHANGED); HookWidget(ui->warnBeforeRecordStop, CHECK_CHANGED, GENERAL_CHANGED); HookWidget(ui->hideProjectorCursor, CHECK_CHANGED, GENERAL_CHANGED); + HookWidget(ui->hideProjectorFrame, CHECK_CHANGED, GENERAL_CHANGED); HookWidget(ui->projectorAlwaysOnTop, CHECK_CHANGED, GENERAL_CHANGED); HookWidget(ui->recordWhenStreaming, CHECK_CHANGED, GENERAL_CHANGED); HookWidget(ui->keepRecordStreamStops,CHECK_CHANGED, GENERAL_CHANGED); @@ -1443,6 +1444,10 @@ void OBSBasicSettings::LoadGeneralSettings() GetGlobalConfig(), "BasicWindow", "HideProjectorCursor"); ui->hideProjectorCursor->setChecked(hideProjectorCursor); + bool hideProjectorFrame = config_get_bool( + GetGlobalConfig(), "BasicWindow", "HideProjectorFrame"); + ui->hideProjectorFrame->setChecked(hideProjectorFrame); + bool projectorAlwaysOnTop = config_get_bool( GetGlobalConfig(), "BasicWindow", "ProjectorAlwaysOnTop"); ui->projectorAlwaysOnTop->setChecked(projectorAlwaysOnTop); @@ -3410,6 +3415,14 @@ void OBSBasicSettings::SaveGeneralSettings() main->UpdateProjectorHideCursor(); } + if (WidgetChanged(ui->hideProjectorFrame)) { + config_set_bool(GetGlobalConfig(), "BasicWindow", + "HideProjectorFrame", + ui->hideProjectorFrame->isChecked()); + main->UpdateProjectorHideFrame( + ui->hideProjectorFrame->isChecked()); + } + if (WidgetChanged(ui->projectorAlwaysOnTop)) { config_set_bool(GetGlobalConfig(), "BasicWindow", "ProjectorAlwaysOnTop", diff --git a/UI/window-projector.cpp b/UI/window-projector.cpp index 24793d553..e355cbcd8 100644 --- a/UI/window-projector.cpp +++ b/UI/window-projector.cpp @@ -29,7 +29,13 @@ OBSProjector::OBSProjector(QWidget *widget, obs_source_t *source_, int monitor, "ProjectorAlwaysOnTop"); if (isAlwaysOnTop) - setWindowFlags(Qt::WindowStaysOnTopHint); + setWindowFlag(Qt::WindowStaysOnTopHint, isAlwaysOnTop); + + hideFrame = config_get_bool(GetGlobalConfig(), "BasicWindow", + "HideProjectorFrame"); + + if (hideFrame) + setWindowFlag(Qt::FramelessWindowHint, hideFrame); // Mark the window as a projector so SetDisplayAffinity // can skip it @@ -148,6 +154,38 @@ void OBSProjector::SetHideCursor() setCursor(Qt::ArrowCursor); } +void OBSProjector::SetHideFrame(bool hideFrame) +{ + if (isFullScreen()) + return; + + // Calculate the current content position. + QRect contentBox = geometry(); + + // Calculate the current window geometry position. + QPoint contentPos = pos(); + + // Only update window if setting changed. + if (this->hideFrame != hideFrame) { + setWindowFlag(Qt::FramelessWindowHint, hideFrame); + + // Restore the window. + showNormal(); + + // Keep content in the same screen location. + if (hideFrame) { + move(contentPos.x(), contentPos.y()); + } else { + QPoint offset = QPoint(contentPos.x() - geometry().x(), + contentPos.y() - geometry().y()); + move(contentPos.x() + offset.x(), + contentPos.y() + offset.y()); + } + } + + this->hideFrame = hideFrame; +} + void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy) { OBSProjector *window = (OBSProjector *)data; @@ -273,6 +311,19 @@ void OBSProjector::mousePressEvent(QMouseEvent *event) this, &OBSProjector::ResizeToContent); } + QAction *hideFrameAction = + new QAction(QTStr("HideProjectorFrame"), this); + hideFrameAction->setCheckable(true); + hideFrameAction->setChecked(hideFrame); + if (isFullScreen()) { + hideFrameAction->setDisabled(true); + } + + connect(hideFrameAction, &QAction::toggled, this, + &OBSProjector::SetHideFrame); + + popup.addAction(hideFrameAction); + QAction *alwaysOnTopButton = new QAction( QTStr("Basic.MainMenu.View.AlwaysOnTop"), this); alwaysOnTopButton->setCheckable(true); diff --git a/UI/window-projector.hpp b/UI/window-projector.hpp index 2a4bdd6d1..5339e0c11 100644 --- a/UI/window-projector.hpp +++ b/UI/window-projector.hpp @@ -29,6 +29,7 @@ private: void mouseDoubleClickEvent(QMouseEvent *event) override; void closeEvent(QCloseEvent *event) override; + bool hideFrame; bool isAlwaysOnTop; bool isAlwaysOnTopOverridden = false; int savedMonitor = -1; @@ -68,5 +69,6 @@ public: bool IsAlwaysOnTop() const; bool IsAlwaysOnTopOverridden() const; + void SetHideFrame(bool hideFrame); void SetIsAlwaysOnTop(bool isAlwaysOnTop, bool isOverridden); };