Ver código fonte

UI: Add basic hotkey integration

Palana 11 anos atrás
pai
commit
9cda23f4b9

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

@@ -350,3 +350,49 @@ Basic.AdvAudio.Mono="Downmix to Mono"
 Basic.AdvAudio.Panning="Panning"
 Basic.AdvAudio.SyncOffset="Sync Offset (ms)"
 Basic.AdvAudio.AudioTracks="Tracks"
+
+# hotkeys that may lack translation on certain operating systems
+Hotkeys.Insert="Insert"
+Hotkeys.Delete="Delete"
+Hotkeys.Home="Home"
+Hotkeys.End="End"
+Hotkeys.PageUp="Page Up"
+Hotkeys.PageDown="Page Down"
+Hotkeys.NumLock="Num Lock"
+Hotkeys.ScrollLock="Scroll Lock"
+Hotkeys.CapsLock="Caps Lock"
+Hotkeys.Backspace="Backspace"
+Hotkeys.Tab="Tab"
+Hotkeys.Print="Print"
+Hotkeys.Pause="Pause"
+Hotkeys.Left="Left"
+Hotkeys.Right="Right"
+Hotkeys.Up="Up"
+Hotkeys.Down="Down"
+Hotkeys.Windows="Windows"
+Hotkeys.Super="Super"
+Hotkeys.Menu="Menu"
+Hotkeys.Space="Space"
+Hotkeys.NumpadNum="Numpad %1"
+Hotkeys.NumpadMultiply="Numpad Multiply"
+Hotkeys.NumpadDivide="Numpad Divide"
+Hotkeys.NumpadAdd="Numpad Add"
+Hotkeys.NumpadSubtract="Numpad Subtract"
+Hotkeys.NumpadDecimal="Numpad Decimal"
+Hotkeys.AppleKeypadNum="%1 (Keypad)"
+Hotkeys.AppleKeypadMultiply="* (Keypad)"
+Hotkeys.AppleKeypadDivide="/ (Keypad)"
+Hotkeys.AppleKeypadAdd="+ (Keypad)"
+Hotkeys.AppleKeypadSubtract="- (Keypad)"
+Hotkeys.AppleKeypadDecimal=". (Keypad)"
+Hotkeys.AppleKeypadEqual="= (Keypad)"
+Hotkeys.MouseButton="Mouse %1"
+
+# audio hotkeys
+Mute="Mute"
+Unmute="Unmute"
+Push-to-talk="Push-to-talk"
+
+# scene item hotkeys
+SceneItemShow="Show '%1'"
+SceneItemHide="Hide '%1'"

+ 114 - 0
obs/obs-app.cpp

@@ -52,6 +52,112 @@ static log_handler_t def_log_handler;
 static string currentLogFile;
 static string lastLogFile;
 
+QObject *CreateShortcutFilter()
+{
+	return new OBSEventFilter([](QObject *, QEvent *event)
+	{
+		auto mouse_event = [](QMouseEvent &event)
+		{
+			obs_key_combination_t hotkey = {0, OBS_KEY_NONE};
+			bool pressed = event.type() == QEvent::MouseButtonPress;
+
+			switch (event.button()) {
+			case Qt::NoButton:
+			case Qt::LeftButton:
+			case Qt::RightButton:
+			case Qt::AllButtons:
+			case Qt::MouseButtonMask:
+				return false;
+
+			case Qt::MidButton:
+				hotkey.key = OBS_KEY_MOUSE3;
+				break;
+
+#define MAP_BUTTON(i, j) case Qt::ExtraButton ## i: \
+		hotkey.key = OBS_KEY_MOUSE ## j; break;
+			MAP_BUTTON( 1,  4);
+			MAP_BUTTON( 2,  5);
+			MAP_BUTTON( 3,  6);
+			MAP_BUTTON( 4,  7);
+			MAP_BUTTON( 5,  8);
+			MAP_BUTTON( 6,  9);
+			MAP_BUTTON( 7, 10);
+			MAP_BUTTON( 8, 11);
+			MAP_BUTTON( 9, 12);
+			MAP_BUTTON(10, 13);
+			MAP_BUTTON(11, 14);
+			MAP_BUTTON(12, 15);
+			MAP_BUTTON(13, 16);
+			MAP_BUTTON(14, 17);
+			MAP_BUTTON(15, 18);
+			MAP_BUTTON(16, 19);
+			MAP_BUTTON(17, 20);
+			MAP_BUTTON(18, 21);
+			MAP_BUTTON(19, 22);
+			MAP_BUTTON(20, 23);
+			MAP_BUTTON(21, 24);
+			MAP_BUTTON(22, 25);
+			MAP_BUTTON(23, 26);
+			MAP_BUTTON(24, 27);
+#undef MAP_BUTTON
+			}
+
+			hotkey.modifiers = TranslateQtKeyboardEventModifiers(
+							event.modifiers());
+
+			obs_hotkey_inject_event(hotkey, pressed);
+			return true;
+		};
+
+		auto key_event = [](QKeyEvent *event)
+		{
+			obs_key_combination_t hotkey = {0, OBS_KEY_NONE};
+			bool pressed = event->type() == QEvent::KeyPress;
+
+			switch (event->key()) {
+			case Qt::Key_Shift:
+			case Qt::Key_Control:
+			case Qt::Key_Alt:
+			case Qt::Key_Meta:
+				break;
+
+#ifdef __APPLE__
+			case Qt::Key_CapsLock:
+				// kVK_CapsLock == 57
+				hotkey.key = obs_key_from_virtual_key(57);
+				pressed = true;
+				break;
+#endif
+
+			default:
+				hotkey.key = obs_key_from_virtual_key(
+					event->nativeVirtualKey());
+			}
+
+			hotkey.modifiers = TranslateQtKeyboardEventModifiers(
+							event->modifiers());
+
+			obs_hotkey_inject_event(hotkey, pressed);
+		};
+
+		switch (event->type()) {
+		case QEvent::MouseButtonPress:
+		case QEvent::MouseButtonRelease:
+			return mouse_event(*static_cast<QMouseEvent*>(event));
+
+		/*case QEvent::MouseButtonDblClick:
+		case QEvent::Wheel:*/
+		case QEvent::KeyPress:
+		case QEvent::KeyRelease:
+			key_event(static_cast<QKeyEvent*>(event));
+			return true;
+
+		default:
+			return false;
+		}
+	});
+}
+
 string CurrentTimeString()
 {
 	time_t     now = time(0);
@@ -330,6 +436,14 @@ bool OBSApp::OBSInit()
 
 		mainWindow->OBSInit();
 
+		connect(this, &QGuiApplication::applicationStateChanged,
+				[](Qt::ApplicationState state)
+				{
+					obs_hotkey_enable_background_press(
+						state != Qt::ApplicationActive);
+				});
+		obs_hotkey_enable_background_press(
+				applicationState() != Qt::ApplicationActive);
 		return true;
 	} else {
 		return false;

+ 1 - 0
obs/obs-app.hpp

@@ -31,6 +31,7 @@
 std::string CurrentTimeString();
 std::string CurrentDateTimeString();
 std::string GenerateTimeDateFilename(const char *extension);
+QObject *CreateShortcutFilter();
 
 struct BaseLexer {
 	lexer lex;

+ 2 - 0
obs/window-basic-adv-audio.cpp

@@ -63,6 +63,8 @@ OBSBasicAdvAudio::OBSBasicAdvAudio(QWidget *parent)
 	vlayout->addWidget(scrollArea);
 	setLayout(vlayout);
 
+	installEventFilter(CreateShortcutFilter());
+
 	/* get global audio sources */
 	for (uint32_t i = 1; i <= 10; i++) {
 		obs_source_t *source = obs_get_output_source(i);

+ 2 - 0
obs/window-basic-filters.cpp

@@ -66,6 +66,8 @@ OBSBasicFilters::OBSBasicFilters(QWidget *parent, OBSSource source_)
 	const char *name = obs_source_get_name(source);
 	setWindowTitle(QTStr("Basic.Filters.Title").arg(QT_UTF8(name)));
 
+	installEventFilter(CreateShortcutFilter());
+
 	connect(ui->preview, SIGNAL(DisplayResized()),
 			this, SLOT(OnPreviewResized()));
 

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

@@ -118,6 +118,7 @@ OBSBasic::OBSBasic(QWidget *parent)
 	qRegisterMetaType<OBSScene>    ("OBSScene");
 	qRegisterMetaType<OBSSceneItem>("OBSSceneItem");
 	qRegisterMetaType<OBSSource>   ("OBSSource");
+	qRegisterMetaType<obs_hotkey_id>("obs_hotkey_id");
 
 	ui->scenes->setAttribute(Qt::WA_MacShowFocusRect, false);
 	ui->sources->setAttribute(Qt::WA_MacShowFocusRect, false);
@@ -132,6 +133,8 @@ OBSBasic::OBSBasic(QWidget *parent)
 	stringstream name;
 	name << "OBS " << App()->GetVersionString();
 
+	installEventFilter(CreateShortcutFilter());
+
 	blog(LOG_INFO, "%s", name.str().c_str());
 	setWindowTitle(QT_UTF8(name.str().c_str()));
 
@@ -653,6 +656,7 @@ void OBSBasic::OBSInit()
 	}
 
 	InitOBSCallbacks();
+	InitHotkeys();
 
 	AddExtraModulePaths();
 	obs_load_all_modules();
@@ -681,6 +685,71 @@ void OBSBasic::OBSInit()
 				Qt::QueuedConnection);
 }
 
+void OBSBasic::InitHotkeys()
+{
+	struct obs_hotkeys_translations t = {};
+	t.insert                       = Str("Hotkeys.Insert");
+	t.del                          = Str("Hotkeys.Delete");
+	t.home                         = Str("Hotkeys.Home");
+	t.end                          = Str("Hotkeys.End");
+	t.page_up                      = Str("Hotkeys.PageUp");
+	t.page_down                    = Str("Hotkeys.PageDown");
+	t.num_lock                     = Str("Hotkeys.NumLock");
+	t.scroll_lock                  = Str("Hotkeys.ScrollLock");
+	t.caps_lock                    = Str("Hotkeys.CapsLock");
+	t.backspace                    = Str("Hotkeys.Backspace");
+	t.tab                          = Str("Hotkeys.Tab");
+	t.print                        = Str("Hotkeys.Print");
+	t.pause                        = Str("Hotkeys.Pause");
+	t.left                         = Str("Hotkeys.Left");
+	t.right                        = Str("Hotkeys.Right");
+	t.up                           = Str("Hotkeys.Up");
+	t.down                         = Str("Hotkeys.Down");
+#ifdef _WIN32
+	t.meta                         = Str("Hotkeys.Windows");
+#else
+	t.meta                         = Str("Hotkeys.Super");
+#endif
+	t.menu                         = Str("Hotkeys.Menu");
+	t.space                        = Str("Hotkeys.Space");
+	t.numpad_num                   = Str("Hotkeys.NumpadNum");
+	t.numpad_multiply              = Str("Hotkeys.NumpadMultiply");
+	t.numpad_divide                = Str("Hotkeys.NumpadDivide");
+	t.numpad_plus                  = Str("Hotkeys.NumpadAdd");
+	t.numpad_minus                 = Str("Hotkeys.NumpadSubtract");
+	t.numpad_decimal               = Str("Hotkeys.NumpadDecimal");
+	t.apple_keypad_num             = Str("Hotkeys.AppleKeypadNum");
+	t.apple_keypad_multiply        = Str("Hotkeys.AppleKeypadMultiply");
+	t.apple_keypad_divide          = Str("Hotkeys.AppleKeypadDivide");
+	t.apple_keypad_plus            = Str("Hotkeys.AppleKeypadAdd");
+	t.apple_keypad_minus           = Str("Hotkeys.AppleKeypadSubtract");
+	t.apple_keypad_decimal         = Str("Hotkeys.AppleKeypadDecimal");
+	t.apple_keypad_equal           = Str("Hotkeys.AppleKeypadEqual");
+	t.mouse_num                    = Str("Hotkeys.MouseButton");
+	obs_hotkeys_set_translations(&t);
+
+	obs_hotkeys_set_audio_hotkeys_translations(Str("Mute"), Str("Unmute"),
+			Str("Push-to-talk"), Str("Push-to-mute"));
+
+	obs_hotkeys_set_sceneitem_hotkeys_translations(
+			Str("SceneItemShow"), Str("SceneItemHide"));
+
+	obs_hotkey_enable_callback_rerouting(true);
+	obs_hotkey_set_callback_routing_func(OBSBasic::HotkeyTriggered, this);
+}
+
+void OBSBasic::ProcessHotkey(obs_hotkey_id id, bool pressed)
+{
+	obs_hotkey_trigger_routed_callback(id, pressed);
+}
+
+void OBSBasic::HotkeyTriggered(void *data, obs_hotkey_id id, bool pressed)
+{
+	OBSBasic &basic = *static_cast<OBSBasic*>(data);
+	QMetaObject::invokeMethod(&basic, "ProcessHotkey",
+			Q_ARG(obs_hotkey_id, id), Q_ARG(bool, pressed));
+}
+
 OBSBasic::~OBSBasic()
 {
 	bool previewEnabled = obs_preview_enabled();
@@ -694,6 +763,8 @@ OBSBasic::~OBSBasic()
 	delete cpuUsageTimer;
 	os_cpu_usage_info_destroy(cpuUsageInfo);
 
+	obs_hotkey_set_callback_routing_func(nullptr, nullptr);
+
 	service = nullptr;
 	outputHandler.reset();
 

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

@@ -112,6 +112,8 @@ private:
 	void          Save(const char *file);
 	void          Load(const char *file);
 
+	void          InitHotkeys();
+
 	bool          InitService();
 
 	bool          InitBasicConfigDefaults();
@@ -177,6 +179,8 @@ private slots:
 
 	void ReorderSources(OBSScene scene);
 
+	void ProcessHotkey(obs_hotkey_id id, bool pressed);
+
 private:
 	/* OBS Callbacks */
 	static void SceneReordered(void *data, calldata_t *params);
@@ -199,6 +203,8 @@ private:
 	void AddSourcePopupMenu(const QPoint &pos);
 	void copyActionsDynamicProperties();
 
+	static void HotkeyTriggered(void *data, obs_hotkey_id id, bool pressed);
+
 public:
 	OBSScene      GetCurrentScene();
 

+ 2 - 0
obs/window-basic-properties.cpp

@@ -78,6 +78,8 @@ OBSBasicProperties::OBSBasicProperties(QWidget *parent, OBSSource source_)
 	view->setMinimumHeight(150);
 	view->show();
 
+	installEventFilter(CreateShortcutFilter());
+
 	connect(view, SIGNAL(PropertiesResized()),
 			this, SLOT(OnPropertiesResized()));
 

+ 2 - 0
obs/window-basic-settings.cpp

@@ -307,6 +307,8 @@ OBSBasicSettings::OBSBasicSettings(QWidget *parent)
 	// Initialize libff library
 	ff_init();
 
+	installEventFilter(CreateShortcutFilter());
+
 	LoadServiceTypes();
 	LoadEncoderTypes();
 	LoadColorRanges();

+ 2 - 0
obs/window-basic-source-select.cpp

@@ -181,5 +181,7 @@ OBSBasicSourceSelect::OBSBasicSourceSelect(OBSBasic *parent, const char *id_)
 	ui->sourceName->setFocus();	//Fixes deselect of text.
 	ui->sourceName->selectAll();
 
+	installEventFilter(CreateShortcutFilter());
+
 	obs_enum_sources(EnumSources, this);
 }

+ 2 - 0
obs/window-basic-transform.cpp

@@ -50,6 +50,8 @@ OBSBasicTransform::OBSBasicTransform(OBSBasic *parent)
 	HookWidget(ui->boundsWidth,  DSCROLL_CHANGED, SLOT(OnControlChanged()));
 	HookWidget(ui->boundsHeight, DSCROLL_CHANGED, SLOT(OnControlChanged()));
 
+	installEventFilter(CreateShortcutFilter());
+
 	OBSScene curScene = main->GetCurrentScene();
 	SetScene(curScene);
 	SetItem(FindASelectedItem(curScene));

+ 3 - 0
obs/window-log-reply.cpp

@@ -17,6 +17,7 @@
 
 #include <QClipboard>
 #include "window-log-reply.hpp"
+#include "obs-app.hpp"
 
 OBSLogReply::OBSLogReply(QWidget *parent, const QString &url)
 	: QDialog (parent),
@@ -24,6 +25,8 @@ OBSLogReply::OBSLogReply(QWidget *parent, const QString &url)
 {
 	ui->setupUi(this);
 	ui->urlEdit->setText(url);
+
+	installEventFilter(CreateShortcutFilter());
 }
 
 void OBSLogReply::on_copyURL_clicked()

+ 3 - 0
obs/window-namedialog.cpp

@@ -17,6 +17,7 @@
 
 #include "window-namedialog.hpp"
 #include "ui_NameDialog.h"
+#include "obs-app.hpp"
 
 using namespace std;
 
@@ -25,6 +26,8 @@ NameDialog::NameDialog(QWidget *parent)
 	  ui      (new Ui::NameDialog)
 {
 	ui->setupUi(this);
+
+	installEventFilter(CreateShortcutFilter());
 }
 
 bool NameDialog::AskForName(QWidget *parent, const QString &title,

+ 2 - 0
obs/window-projector.cpp

@@ -15,6 +15,8 @@ OBSProjector::OBSProjector(QWidget *widget, obs_source_t *source_)
 	                                "removed", OBSSourceRemoved, this)
 {
 	setAttribute(Qt::WA_DeleteOnClose, true);
+
+	installEventFilter(CreateShortcutFilter());
 }
 
 OBSProjector::~OBSProjector()

+ 3 - 1
obs/window-remux.cpp

@@ -47,7 +47,9 @@ OBSRemux::OBSRemux(const char *path, QWidget *parent)
 	ui->progressBar->setMinimum(0);
 	ui->progressBar->setMaximum(1000);
 	ui->progressBar->setValue(0);
-	
+
+	installEventFilter(CreateShortcutFilter());
+
 	connect(ui->browseSource, &QPushButton::clicked,
 			[&]() { BrowseInput(); });
 	connect(ui->browseTarget, &QPushButton::clicked,