Skip to content

Commit 1d643ea

Browse files
fix: avoid hiding floating docks when the OBS app is not active.
This PR changes the behavior of floating docks on macOS to have them stay visible while the OBS app is not active. The main change is to set the `NSWindow.hidesOnDeactivate` setting to false. This is enough to keep the docks visible. The remaining changes are just making sure that this setting is consistent across all the different ways OBS creates docks. In macOS, only one app can be "active" (aka "focused") at the time, and "floating panels" (OBS' docks in this case) disappear by default when their parent app is not active. The issue is that disappearing floating panels defy many of the use cases that OBS is great for. For example: - I'm doing game streaming on Twitch. I want to keep track of my chat. - I have a floating panel displaying the "Twitch chat" dock on a side monitor. - I click on my game, which becomes the active app. OBS is not the active app anymore, therefore the chat dock panel disappears. This is a common issue between macOS users: - https://obsproject.com/forum/threads/popped-out-docks-disappear-when-obs-is-not-in-focus.165011/ - https://obsproject.com/forum/threads/keep-dock-windows-visible-even-when-obs-is-not-in-focus.167324/
1 parent 154088b commit 1d643ea

5 files changed

Lines changed: 62 additions & 2 deletions

File tree

frontend/docks/OBSDock.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,26 @@
22

33
#include <widgets/OBSBasic.hpp>
44

5+
#ifdef __APPLE__
6+
#include <utility/platform.hpp>
7+
#endif
8+
59
#include <QCheckBox>
610
#include <QMessageBox>
11+
#include <QTimer>
712

813
#include "moc_OBSDock.cpp"
914

15+
OBSDock::OBSDock(QWidget *parent) : QDockWidget(parent)
16+
{
17+
InstallDockFloatingBehavior(this);
18+
}
19+
20+
OBSDock::OBSDock(const QString &title, QWidget *parent) : QDockWidget(title, parent)
21+
{
22+
InstallDockFloatingBehavior(this);
23+
}
24+
1025
void OBSDock::closeEvent(QCloseEvent *event)
1126
{
1227
auto msgBox = []() {
@@ -43,4 +58,24 @@ void OBSDock::closeEvent(QCloseEvent *event)
4358
void OBSDock::showEvent(QShowEvent *event)
4459
{
4560
QDockWidget::showEvent(event);
61+
#ifdef __APPLE__
62+
SetMacOSDockFloatingBehavior(this, isFloating());
63+
#endif
64+
}
65+
66+
void InstallDockFloatingBehavior(QDockWidget *dock)
67+
{
68+
#ifdef __APPLE__
69+
if (!dock)
70+
return;
71+
72+
QObject::connect(dock, &QDockWidget::topLevelChanged, dock,
73+
[dock](bool) { SetMacOSDockFloatingBehavior(dock, dock->isFloating()); });
74+
75+
if (dock->isFloating()) {
76+
QTimer::singleShot(0, dock, [dock]() { SetMacOSDockFloatingBehavior(dock, dock->isFloating()); });
77+
}
78+
#else
79+
Q_UNUSED(dock);
80+
#endif
4681
}

frontend/docks/OBSDock.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ class OBSDock : public QDockWidget {
1010
Q_OBJECT
1111

1212
public:
13-
inline OBSDock(QWidget *parent = nullptr) : QDockWidget(parent) {}
14-
inline OBSDock(const QString &title, QWidget *parent = nullptr) : QDockWidget(title, parent) {}
13+
OBSDock(QWidget *parent = nullptr);
14+
OBSDock(const QString &title, QWidget *parent = nullptr);
1515

1616
virtual void closeEvent(QCloseEvent *event);
1717
virtual void showEvent(QShowEvent *event);
1818
};
19+
20+
void InstallDockFloatingBehavior(QDockWidget *dock);

frontend/utility/platform-osx.mm

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,24 @@ void SetAlwaysOnTop(QWidget *window, bool enable)
128128
window->show();
129129
}
130130

131+
void SetMacOSDockFloatingBehavior(QWidget *window, bool floating)
132+
{
133+
if (!window)
134+
return;
135+
136+
NSView *view = (__bridge NSView *) reinterpret_cast<void *>(window->winId());
137+
NSWindow *nsWindow = [view window];
138+
if (!nsWindow)
139+
return;
140+
141+
if (floating) {
142+
nsWindow.level = NSFloatingWindowLevel;
143+
nsWindow.hidesOnDeactivate = NO;
144+
} else {
145+
nsWindow.level = NSNormalWindowLevel;
146+
}
147+
}
148+
131149
bool SetDisplayAffinitySupported(void)
132150
{
133151
// Not implemented yet

frontend/utility/platform.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ void InstallNSApplicationSubclass();
101101
void InstallNSThreadLocks();
102102
void disableColorSpaceConversion(QWidget *window);
103103
void SetMacOSDarkMode(bool dark);
104+
void SetMacOSDockFloatingBehavior(QWidget *window, bool floating);
104105

105106
MacPermissionStatus CheckPermissionWithPrompt(MacPermissionType type, bool prompt_for_permission);
106107
#define CheckPermission(x) CheckPermissionWithPrompt(x, false)

frontend/widgets/OBSBasic_Docks.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "OBSBasic.hpp"
2121

22+
#include <docks/OBSDock.hpp>
2223
#include <qt-wrappers.hpp>
2324

2425
void setupDockAction(QDockWidget *dock)
@@ -148,6 +149,7 @@ void OBSBasic::AddDockWidget(QDockWidget *dock, Qt::DockWidgetArea area, bool ex
148149
QDockWidget::DockWidgetFloatable);
149150

150151
setupDockAction(dock);
152+
InstallDockFloatingBehavior(dock);
151153
dock->setFeatures(features);
152154
addDockWidget(area, dock);
153155

@@ -207,6 +209,8 @@ void OBSBasic::AddCustomDockWidget(QDockWidget *dock)
207209
// Prevent the object name from being changed
208210
connect(dock, &QObject::objectNameChanged, this, &OBSBasic::RepairCustomExtraDockName);
209211

212+
InstallDockFloatingBehavior(dock);
213+
210214
bool lock = ui->lockDocks->isChecked();
211215
QDockWidget::DockWidgetFeatures features =
212216
lock ? QDockWidget::NoDockWidgetFeatures

0 commit comments

Comments
 (0)