Browse Source

UI: Add "Always On Top" option to file menu

jp9000 9 years ago
parent
commit
213d8ce154

+ 1 - 0
obs/data/locale/en-US.ini

@@ -250,6 +250,7 @@ Basic.MainMenu.File.Remux="Re&mux Recordings"
 Basic.MainMenu.File.Settings="&Settings"
 Basic.MainMenu.File.ShowSettingsFolder="Show Settings Folder"
 Basic.MainMenu.File.ShowProfileFolder="Show Profile Folder"
+Basic.MainMenu.AlwaysOnTop="&Always On Top"
 Basic.MainMenu.File.Exit="E&xit"
 
 # basic mode edit menu

+ 10 - 0
obs/forms/OBSBasic.ui

@@ -542,6 +542,8 @@
     <addaction name="actionShowSettingsFolder"/>
     <addaction name="actionShowProfileFolder"/>
     <addaction name="separator"/>
+    <addaction name="actionAlwaysOnTop"/>
+    <addaction name="separator"/>
     <addaction name="actionE_xit"/>
    </widget>
    <widget class="QMenu" name="menuBasic_MainMenu_Help">
@@ -975,6 +977,14 @@
     <string>Basic.MainMenu.File.ShowProfileFolder</string>
    </property>
   </action>
+  <action name="actionAlwaysOnTop">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>Basic.MainMenu.AlwaysOnTop</string>
+   </property>
+  </action>
  </widget>
  <customwidgets>
   <customwidget>

+ 18 - 0
obs/platform-osx.mm

@@ -130,3 +130,21 @@ vector<string> GetPreferredLocales()
 
 	return result;
 }
+
+bool IsAlwaysOnTop(QMainWindow *window)
+{
+	return (window->windowFlags() & Qt::WindowStaysOnTopHint) != 0;
+}
+
+void SetAlwaysOnTop(QMainWindow *window, bool enable)
+{
+	Qt::WindowFlags flags = window->windowFlags();
+
+	if (enable)
+		flags |= Qt::WindowStaysOnTopHint;
+	else
+		flags &= ~Qt::WindowStaysOnTopHint;
+
+	window->setWindowFlags(flags);
+	window->show();
+}

+ 13 - 0
obs/platform-windows.cpp

@@ -202,3 +202,16 @@ void SetAeroEnabled(bool enable)
 
 	func(enable ? DWM_EC_ENABLECOMPOSITION : DWM_EC_DISABLECOMPOSITION);
 }
+
+bool IsAlwaysOnTop(QMainWindow *window)
+{
+	DWORD exStyle = GetWindowLong((HWND)window->winId(), GWL_EXSTYLE);
+	return (exStyle & WS_EX_TOPMOST) != 0;
+}
+
+void SetAlwaysOnTop(QMainWindow *window, bool enable)
+{
+	HWND hwnd = (HWND)window->winId();
+	SetWindowPos(hwnd, enable ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0,
+			SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+}

+ 18 - 0
obs/platform-x11.cpp

@@ -147,3 +147,21 @@ vector<string> GetPreferredLocales()
 
 	return {};
 }
+
+bool IsAlwaysOnTop(QMainWindow *window)
+{
+	return (window->windowFlags() & Qt::WindowStaysOnTopHint) != 0;
+}
+
+void SetAlwaysOnTop(QMainWindow *window, bool enable)
+{
+	Qt::WindowFlags flags = window->windowFlags();
+
+	if (enable)
+		flags |= Qt::WindowStaysOnTopHint;
+	else
+		flags &= ~Qt::WindowStaysOnTopHint;
+
+	window->setWindowFlags(flags);
+	window->show();
+}

+ 5 - 0
obs/platform.hpp

@@ -22,6 +22,8 @@
 #include <string>
 #include <vector>
 
+class QMainWindow;
+
 struct MonitorInfo {
 	int32_t  x, y;
 	uint32_t cx, cy;
@@ -43,6 +45,9 @@ std::string GetDefaultVideoSavePath();
 
 std::vector<std::string> GetPreferredLocales();
 
+bool IsAlwaysOnTop(QMainWindow *window);
+void SetAlwaysOnTop(QMainWindow *window, bool enable);
+
 #ifdef _WIN32
 uint32_t GetWindowsVersion();
 void SetAeroEnabled(bool enable);

+ 38 - 0
obs/window-basic-main.cpp

@@ -928,7 +928,20 @@ void OBSBasic::OBSInit()
 
 	connect(ui->preview, &OBSQTDisplay::DisplayCreated, addDisplay);
 
+#ifdef _WIN32
+	show();
+#endif
+
+	bool alwaysOnTop = config_get_bool(App()->GlobalConfig(), "BasicWindow",
+			"AlwaysOnTop");
+	if (alwaysOnTop) {
+		SetAlwaysOnTop(this, true);
+		ui->actionAlwaysOnTop->setChecked(true);
+	}
+
+#ifndef _WIN32
 	show();
+#endif
 
 	QList<int> defSizes;
 
@@ -1177,6 +1190,7 @@ OBSBasic::~OBSBasic()
 
 	QRect lastGeom = normalGeometry();
 	QList<int> splitterSizes = ui->mainSplitter->sizes();
+	bool alwaysOnTop = IsAlwaysOnTop(this);
 
 	config_set_int(App()->GlobalConfig(), "BasicWindow", "cx",
 			lastGeom.width());
@@ -1192,6 +1206,8 @@ OBSBasic::~OBSBasic()
 			splitterSizes[1]);
 	config_set_bool(App()->GlobalConfig(), "BasicWindow", "PreviewEnabled",
 			previewEnabled);
+	config_set_bool(App()->GlobalConfig(), "BasicWindow", "AlwaysOnTop",
+			alwaysOnTop);
 	config_save_safe(App()->GlobalConfig(), "tmp", nullptr);
 
 #ifdef _WIN32
@@ -3326,6 +3342,28 @@ void OBSBasic::on_previewDisabledLabel_customContextMenuRequested(
 	UNUSED_PARAMETER(pos);
 }
 
+void OBSBasic::on_actionAlwaysOnTop_triggered()
+{
+	CloseDialogs();
+
+	/* Make sure all dialogs are safely and successfully closed before
+	 * switching the always on top mode due to the fact that windows all
+	 * have to be recreated, so queue the actual toggle to happen after
+	 * all events related to closing the dialogs have finished */
+	QMetaObject::invokeMethod(this, "ToggleAlwaysOnTop",
+			Qt::QueuedConnection);
+}
+
+void OBSBasic::ToggleAlwaysOnTop()
+{
+	bool isAlwaysOnTop = IsAlwaysOnTop(this);
+
+	ui->actionAlwaysOnTop->setChecked(!isAlwaysOnTop);
+	SetAlwaysOnTop(this, !isAlwaysOnTop);
+
+	show();
+}
+
 void OBSBasic::GetFPSCommon(uint32_t &num, uint32_t &den) const
 {
 	const char *val = config_get_string(basicConfig, "Video", "FPSCommon");

+ 4 - 0
obs/window-basic-main.hpp

@@ -229,6 +229,8 @@ private slots:
 	void RemoveSelectedScene();
 	void RemoveSelectedSceneItem();
 
+	void ToggleAlwaysOnTop();
+
 	void ReorderSources(OBSScene scene);
 
 	void ProcessHotkey(obs_hotkey_id id, bool pressed);
@@ -377,6 +379,8 @@ private slots:
 	void on_actionShowSettingsFolder_triggered();
 	void on_actionShowProfileFolder_triggered();
 
+	void on_actionAlwaysOnTop_triggered();
+
 	void logUploadFinished(const QString &text, const QString &error);
 
 	void updateFileFinished(const QString &text, const QString &error);