#include "macro-action-hotkey.hpp" #include "layout-helpers.hpp" #include "selection-helpers.hpp" #include "source-helpers.hpp" #include #include namespace advss { const std::string MacroActionHotkey::id = "hotkey"; bool MacroActionHotkey::_registered = MacroActionFactory::Register( MacroActionHotkey::id, {MacroActionHotkey::Create, MacroActionHotkeyEdit::Create, "AdvSceneSwitcher.action.hotkey"}); const static std::map actionTypes = { {MacroActionHotkey::Action::OBS_HOTKEY, "AdvSceneSwitcher.action.hotkey.type.obs"}, {MacroActionHotkey::Action::CUSTOM, "AdvSceneSwitcher.action.hotkey.type.custom"}, }; const static std::map hotkeyTypes = { {OBS_HOTKEY_REGISTERER_FRONTEND, "AdvSceneSwitcher.action.hotkey.type.obs.type.frontend"}, {OBS_HOTKEY_REGISTERER_SOURCE, "AdvSceneSwitcher.action.hotkey.type.obs.type.soruce"}, {OBS_HOTKEY_REGISTERER_OUTPUT, "AdvSceneSwitcher.action.hotkey.type.obs.type.output"}, {OBS_HOTKEY_REGISTERER_ENCODER, "AdvSceneSwitcher.action.hotkey.type.obs.type.encoder"}, {OBS_HOTKEY_REGISTERER_SERVICE, "AdvSceneSwitcher.action.hotkey.type.obs.type.service"}, }; static std::unordered_map keyTable = { // Chars {HotkeyType::Key_A, OBS_KEY_A}, {HotkeyType::Key_B, OBS_KEY_B}, {HotkeyType::Key_C, OBS_KEY_C}, {HotkeyType::Key_D, OBS_KEY_D}, {HotkeyType::Key_E, OBS_KEY_E}, {HotkeyType::Key_F, OBS_KEY_F}, {HotkeyType::Key_G, OBS_KEY_G}, {HotkeyType::Key_H, OBS_KEY_H}, {HotkeyType::Key_I, OBS_KEY_I}, {HotkeyType::Key_J, OBS_KEY_J}, {HotkeyType::Key_K, OBS_KEY_K}, {HotkeyType::Key_L, OBS_KEY_L}, {HotkeyType::Key_M, OBS_KEY_M}, {HotkeyType::Key_N, OBS_KEY_N}, {HotkeyType::Key_O, OBS_KEY_O}, {HotkeyType::Key_P, OBS_KEY_P}, {HotkeyType::Key_Q, OBS_KEY_Q}, {HotkeyType::Key_R, OBS_KEY_R}, {HotkeyType::Key_S, OBS_KEY_S}, {HotkeyType::Key_T, OBS_KEY_T}, {HotkeyType::Key_U, OBS_KEY_U}, {HotkeyType::Key_V, OBS_KEY_V}, {HotkeyType::Key_W, OBS_KEY_W}, {HotkeyType::Key_X, OBS_KEY_X}, {HotkeyType::Key_Y, OBS_KEY_Y}, {HotkeyType::Key_Z, OBS_KEY_Z}, // Numbers {HotkeyType::Key_0, OBS_KEY_0}, {HotkeyType::Key_1, OBS_KEY_1}, {HotkeyType::Key_2, OBS_KEY_2}, {HotkeyType::Key_3, OBS_KEY_3}, {HotkeyType::Key_4, OBS_KEY_4}, {HotkeyType::Key_5, OBS_KEY_5}, {HotkeyType::Key_6, OBS_KEY_6}, {HotkeyType::Key_7, OBS_KEY_7}, {HotkeyType::Key_8, OBS_KEY_8}, {HotkeyType::Key_9, OBS_KEY_9}, {HotkeyType::Key_F1, OBS_KEY_F1}, {HotkeyType::Key_F2, OBS_KEY_F2}, {HotkeyType::Key_F3, OBS_KEY_F3}, {HotkeyType::Key_F4, OBS_KEY_F4}, {HotkeyType::Key_F5, OBS_KEY_F5}, {HotkeyType::Key_F6, OBS_KEY_F6}, {HotkeyType::Key_F7, OBS_KEY_F7}, {HotkeyType::Key_F8, OBS_KEY_F8}, {HotkeyType::Key_F9, OBS_KEY_F9}, {HotkeyType::Key_F10, OBS_KEY_F10}, {HotkeyType::Key_F11, OBS_KEY_F11}, {HotkeyType::Key_F12, OBS_KEY_F12}, {HotkeyType::Key_F13, OBS_KEY_F13}, {HotkeyType::Key_F14, OBS_KEY_F14}, {HotkeyType::Key_F15, OBS_KEY_F15}, {HotkeyType::Key_F16, OBS_KEY_F16}, {HotkeyType::Key_F17, OBS_KEY_F17}, {HotkeyType::Key_F18, OBS_KEY_F18}, {HotkeyType::Key_F19, OBS_KEY_F19}, {HotkeyType::Key_F20, OBS_KEY_F20}, {HotkeyType::Key_F21, OBS_KEY_F21}, {HotkeyType::Key_F22, OBS_KEY_F22}, {HotkeyType::Key_F23, OBS_KEY_F23}, {HotkeyType::Key_F24, OBS_KEY_F24}, {HotkeyType::Key_Escape, OBS_KEY_ESCAPE}, {HotkeyType::Key_Space, OBS_KEY_SPACE}, {HotkeyType::Key_Return, OBS_KEY_RETURN}, {HotkeyType::Key_Backspace, OBS_KEY_BACKSPACE}, {HotkeyType::Key_Tab, OBS_KEY_TAB}, {HotkeyType::Key_Shift_L, OBS_KEY_SHIFT}, {HotkeyType::Key_Shift_R, OBS_KEY_SHIFT}, {HotkeyType::Key_Control_L, OBS_KEY_CONTROL}, {HotkeyType::Key_Control_R, OBS_KEY_CONTROL}, {HotkeyType::Key_Alt_L, OBS_KEY_ALT}, {HotkeyType::Key_Alt_R, OBS_KEY_ALT}, {HotkeyType::Key_Win_L, OBS_KEY_META}, {HotkeyType::Key_Win_R, OBS_KEY_META}, {HotkeyType::Key_Apps, OBS_KEY_APPLICATIONLEFT}, {HotkeyType::Key_CapsLock, OBS_KEY_CAPSLOCK}, {HotkeyType::Key_NumLock, OBS_KEY_NUMLOCK}, {HotkeyType::Key_ScrollLock, OBS_KEY_SCROLLLOCK}, {HotkeyType::Key_PrintScreen, OBS_KEY_PRINT}, {HotkeyType::Key_Pause, OBS_KEY_PAUSE}, {HotkeyType::Key_Insert, OBS_KEY_INSERT}, {HotkeyType::Key_Delete, OBS_KEY_DELETE}, {HotkeyType::Key_PageUP, OBS_KEY_PAGEUP}, {HotkeyType::Key_PageDown, OBS_KEY_PAGEDOWN}, {HotkeyType::Key_Home, OBS_KEY_HOME}, {HotkeyType::Key_End, OBS_KEY_END}, {HotkeyType::Key_Left, OBS_KEY_LEFT}, {HotkeyType::Key_Up, OBS_KEY_UP}, {HotkeyType::Key_Right, OBS_KEY_RIGHT}, {HotkeyType::Key_Down, OBS_KEY_DOWN}, {HotkeyType::Key_Numpad0, OBS_KEY_NUM0}, {HotkeyType::Key_Numpad1, OBS_KEY_NUM1}, {HotkeyType::Key_Numpad2, OBS_KEY_NUM2}, {HotkeyType::Key_Numpad3, OBS_KEY_NUM3}, {HotkeyType::Key_Numpad4, OBS_KEY_NUM4}, {HotkeyType::Key_Numpad5, OBS_KEY_NUM5}, {HotkeyType::Key_Numpad6, OBS_KEY_NUM6}, {HotkeyType::Key_Numpad7, OBS_KEY_NUM7}, {HotkeyType::Key_Numpad8, OBS_KEY_NUM8}, {HotkeyType::Key_Numpad9, OBS_KEY_NUM9}, {HotkeyType::Key_NumpadAdd, OBS_KEY_NUMPLUS}, {HotkeyType::Key_NumpadSubtract, OBS_KEY_NUMMINUS}, {HotkeyType::Key_NumpadMultiply, OBS_KEY_NUMASTERISK}, {HotkeyType::Key_NumpadDivide, OBS_KEY_NUMSLASH}, {HotkeyType::Key_NumpadDecimal, OBS_KEY_NUMPERIOD}, //{HotkeyType::Key_NumpadEnter, ???}, }; static obs_key_combination keysToOBSKeycombo(const std::vector &keys) { obs_key_combination combo{}; auto it = keyTable.find(keys.back()); if (it != keyTable.end()) { combo.key = (obs_key_t)it->second; } if (keys.size() == 1) { return combo; } for (uint32_t i = 0; i < keys.size() - 1; i++) { switch (keys[i]) { case HotkeyType::Key_Shift_L: combo.modifiers |= INTERACT_SHIFT_KEY; break; case HotkeyType::Key_Shift_R: combo.modifiers |= INTERACT_SHIFT_KEY; break; case HotkeyType::Key_Control_L: combo.modifiers |= INTERACT_CONTROL_KEY; break; case HotkeyType::Key_Control_R: combo.modifiers |= INTERACT_CONTROL_KEY; break; case HotkeyType::Key_Alt_L: combo.modifiers |= INTERACT_ALT_KEY; break; case HotkeyType::Key_Alt_R: combo.modifiers |= INTERACT_ALT_KEY; break; case HotkeyType::Key_Win_L: combo.modifiers |= INTERACT_COMMAND_KEY; break; case HotkeyType::Key_Win_R: combo.modifiers |= INTERACT_COMMAND_KEY; break; case HotkeyType::Key_CapsLock: combo.modifiers |= INTERACT_CAPS_KEY; break; default: break; } } return combo; } static void InjectKeys(const std::vector &keys, int duration) { auto combo = keysToOBSKeycombo(keys); if (obs_key_combination_is_empty(combo)) { return; } // I am not sure why this is necessary obs_hotkey_inject_event(combo, false); obs_hotkey_inject_event(combo, true); std::this_thread::sleep_for(std::chrono::milliseconds(duration)); obs_hotkey_inject_event(combo, false); } static void addNamePrefix(std::string &name, obs_hotkey_t *hotkey) { const auto type = obs_hotkey_get_registerer_type(hotkey); std::string prefix; if (type == OBS_HOTKEY_REGISTERER_SOURCE) { auto source = reinterpret_cast( obs_hotkey_get_registerer(hotkey)); prefix = "[" + GetWeakSourceName(source) + "] "; } else if (type == OBS_HOTKEY_REGISTERER_OUTPUT) { auto weakOutput = reinterpret_cast( obs_hotkey_get_registerer(hotkey)); std::string name; auto output = obs_weak_output_get_output(weakOutput); if (output) { name = obs_output_get_name(output); obs_output_release(output); } prefix = "[" + name + "] "; } else if (type == OBS_HOTKEY_REGISTERER_ENCODER) { auto weakEncoder = reinterpret_cast( obs_hotkey_get_registerer(hotkey)); std::string name; auto encoder = obs_weak_encoder_get_encoder(weakEncoder); if (encoder) { name = obs_encoder_get_name(encoder); obs_encoder_release(encoder); } prefix = "[" + name + "] "; } else if (type == OBS_HOTKEY_REGISTERER_SERVICE) { auto weakService = reinterpret_cast( obs_hotkey_get_registerer(hotkey)); std::string name; auto service = obs_weak_service_get_service(weakService); if (service) { name = obs_service_get_name(service); obs_service_release(service); } prefix = "[" + name + "] "; } name = prefix + name; } static obs_hotkey_id getHotkeyIdByName(const std::string &name) { struct Parameters { std::string name; obs_hotkey_id id = OBS_INVALID_HOTKEY_ID; } params; auto func = [](void *param, obs_hotkey_id id, obs_hotkey_t *hotkey) { auto params = static_cast(param); std::string name = obs_hotkey_get_name(hotkey); addNamePrefix(name, hotkey); if (name == params->name) { params->id = id; return false; } return true; }; params.name = name; obs_enum_hotkeys(func, ¶ms); return params.id; } void MacroActionHotkey::SendOBSHotkey() { auto id = getHotkeyIdByName(_hotkeyName); if (id == OBS_INVALID_HOTKEY_ID) { blog(LOG_WARNING, "failed to get hotkey id for \"%s\" - key will not be pressed", _hotkeyName.c_str()); return; } obs_queue_task( OBS_TASK_UI, [](void *param) { auto id = (size_t *)param; obs_hotkey_trigger_routed_callback(*id, false); obs_hotkey_trigger_routed_callback(*id, true); obs_hotkey_trigger_routed_callback(*id, false); }, &id, true); } void MacroActionHotkey::SendCustomHotkey() { std::vector keys; if (_leftShift) { keys.push_back(HotkeyType::Key_Shift_L); } if (_rightShift) { keys.push_back(HotkeyType::Key_Shift_R); } if (_leftCtrl) { keys.push_back(HotkeyType::Key_Control_L); } if (_rightCtrl) { keys.push_back(HotkeyType::Key_Control_R); } if (_leftAlt) { keys.push_back(HotkeyType::Key_Alt_L); } if (_rightAlt) { keys.push_back(HotkeyType::Key_Alt_R); } if (_leftMeta) { keys.push_back(HotkeyType::Key_Win_L); } if (_rightMeta) { keys.push_back(HotkeyType::Key_Win_R); } if (_key != HotkeyType::Key_NoKey) { keys.push_back(_key); } if (!keys.empty()) { int dur = _duration.Milliseconds(); if (_onlySendToObs || !CanSimulateKeyPresses()) { std::thread t([keys, dur]() { InjectKeys(keys, dur); }); t.detach(); } else { std::thread t([keys, dur]() { PressKeys(keys, dur); }); t.detach(); } } } bool MacroActionHotkey::PerformAction() { switch (_action) { case advss::MacroActionHotkey::Action::OBS_HOTKEY: SendOBSHotkey(); break; case advss::MacroActionHotkey::Action::CUSTOM: SendCustomHotkey(); break; default: break; } return true; } void MacroActionHotkey::LogAction() const { vblog(LOG_INFO, "sent hotkey type %d", static_cast(_action)); } bool MacroActionHotkey::Save(obs_data_t *obj) const { MacroAction::Save(obj); obs_data_set_int(obj, "action", static_cast(_action)); obs_data_set_int(obj, "hotkeyType", _hotkeyType); obs_data_set_string(obj, "hotkeyName", _hotkeyName.c_str()); obs_data_set_int(obj, "key", static_cast(_key)); obs_data_set_bool(obj, "left_shift", _leftShift); obs_data_set_bool(obj, "right_shift", _rightShift); obs_data_set_bool(obj, "left_ctrl", _leftCtrl); obs_data_set_bool(obj, "right_ctrl", _rightCtrl); obs_data_set_bool(obj, "left_alt", _leftAlt); obs_data_set_bool(obj, "right_alt", _rightAlt); obs_data_set_bool(obj, "left_meta", _leftMeta); obs_data_set_bool(obj, "right_meta", _rightMeta); _duration.Save(obj); obs_data_set_bool(obj, "onlyOBS", _onlySendToObs); obs_data_set_int(obj, "version", 2); return true; } bool MacroActionHotkey::Load(obs_data_t *obj) { MacroAction::Load(obj); int version = obs_data_get_int(obj, "version"); if (version != 2) { _action = Action::CUSTOM; } else { _action = static_cast(obs_data_get_int(obj, "action")); } _hotkeyType = static_cast( obs_data_get_int(obj, "hotkeyType")); _hotkeyName = obs_data_get_string(obj, "hotkeyName"); _key = static_cast(obs_data_get_int(obj, "key")); _leftShift = obs_data_get_bool(obj, "left_shift"); _rightShift = obs_data_get_bool(obj, "right_shift"); _leftCtrl = obs_data_get_bool(obj, "left_ctrl"); _rightCtrl = obs_data_get_bool(obj, "right_ctrl"); _leftAlt = obs_data_get_bool(obj, "left_alt"); _rightAlt = obs_data_get_bool(obj, "right_alt"); _leftMeta = obs_data_get_bool(obj, "left_meta"); _rightMeta = obs_data_get_bool(obj, "right_meta"); if (version == 0) { _duration = obs_data_get_int(obj, "duration") / 1000.0; } else { _duration.Load(obj); } _onlySendToObs = obs_data_get_bool(obj, "onlyOBS"); return true; } static inline void populateKeySelection(QComboBox *list) { list->addItem("No key"); list->addItem("A"); list->addItem("B"); list->addItem("C"); list->addItem("D"); list->addItem("E"); list->addItem("F"); list->addItem("G"); list->addItem("H"); list->addItem("I"); list->addItem("J"); list->addItem("K"); list->addItem("L"); list->addItem("M"); list->addItem("N"); list->addItem("O"); list->addItem("P"); list->addItem("Q"); list->addItem("R"); list->addItem("S"); list->addItem("T"); list->addItem("U"); list->addItem("V"); list->addItem("W"); list->addItem("X"); list->addItem("Y"); list->addItem("Z"); list->addItem("0"); list->addItem("1"); list->addItem("2"); list->addItem("3"); list->addItem("4"); list->addItem("5"); list->addItem("6"); list->addItem("7"); list->addItem("8"); list->addItem("9"); list->addItem("F1"); list->addItem("F2"); list->addItem("F3"); list->addItem("F4"); list->addItem("F5"); list->addItem("F6"); list->addItem("F7"); list->addItem("F8"); list->addItem("F9"); list->addItem("F10"); list->addItem("F11"); list->addItem("F12"); list->addItem("F13"); list->addItem("F14"); list->addItem("F15"); list->addItem("F16"); list->addItem("F17"); list->addItem("F18"); list->addItem("F19"); list->addItem("F20"); list->addItem("F21"); list->addItem("F22"); list->addItem("F23"); list->addItem("F24"); list->addItem("Escape"); list->addItem("Space"); list->addItem("Return"); list->addItem("Backspace"); list->addItem("Tab"); list->addItem("Shift_L"); list->addItem("Shift_R"); list->addItem("Control_L"); list->addItem("Control_R"); list->addItem("Alt_L"); list->addItem("Alt_R"); list->addItem("Win_L"); list->addItem("Win_R"); list->addItem("Apps"); list->addItem("CapsLock"); list->addItem("NumLock"); list->addItem("ScrollLock"); list->addItem("PrintScreen"); list->addItem("Pause"); list->addItem("Insert"); list->addItem("Delete"); list->addItem("PageUP"); list->addItem("PageDown"); list->addItem("Home"); list->addItem("End"); list->addItem("Left"); list->addItem("Right"); list->addItem("Up"); list->addItem("Down"); list->addItem("Numpad0"); list->addItem("Numpad1"); list->addItem("Numpad2"); list->addItem("Numpad3"); list->addItem("Numpad4"); list->addItem("Numpad5"); list->addItem("Numpad6"); list->addItem("Numpad7"); list->addItem("Numpad8"); list->addItem("Numpad9"); list->addItem("NumpadAdd"); list->addItem("NumpadSubtract"); list->addItem("NumpadMultiply"); list->addItem("NumpadDivide"); list->addItem("NumpadDecimal"); list->addItem("NumpadEnter"); } static void populateActionSelection(QComboBox *list) { for (const auto &[_, value] : actionTypes) { list->addItem(obs_module_text(value.c_str())); } } static void populateHotkeyTypeSelection(QComboBox *list) { for (const auto &[_, value] : hotkeyTypes) { list->addItem(obs_module_text(value.c_str())); } } static void addNamePrefix(QString &name, obs_hotkey_t *hotkey) { auto temp = name.toStdString(); addNamePrefix(temp, hotkey); name = QString::fromStdString(temp); } static void populateHotkeyNames(QComboBox *list, obs_hotkey_registerer_type type) { struct Parameters { QStringList names; QStringList descriptions; obs_hotkey_registerer_type type; } params; auto func = [](void *param, obs_hotkey_id, obs_hotkey_t *hotkey) { auto params = static_cast(param); if (obs_hotkey_get_registerer_type(hotkey) == params->type) { QString description(obs_hotkey_get_description(hotkey)); addNamePrefix(description, hotkey); params->descriptions.append(description); QString name(obs_hotkey_get_name(hotkey)); addNamePrefix(name, hotkey); params->names.append(name); } return true; }; params.type = type; obs_enum_hotkeys(func, ¶ms); list->clear(); for (int i = 0; i < params.names.size(); i++) { list->addItem(params.descriptions.at(i), params.names.at(i)); } AddSelectionEntry(list, obs_module_text("AdvSceneSwitcher.selectHotkey")); } MacroActionHotkeyEdit::MacroActionHotkeyEdit( QWidget *parent, std::shared_ptr entryData) : QWidget(parent), _actionType(new QComboBox()), _hotkeyType(new QComboBox()), _obsHotkeys(new QComboBox()), _keys(new QComboBox()), _leftShift(new QCheckBox( obs_module_text("AdvSceneSwitcher.action.hotkey.leftShift"))), _rightShift(new QCheckBox(obs_module_text( "AdvSceneSwitcher.action.hotkey.rightShift"))), _leftCtrl(new QCheckBox( obs_module_text("AdvSceneSwitcher.action.hotkey.leftCtrl"))), _rightCtrl(new QCheckBox( obs_module_text("AdvSceneSwitcher.action.hotkey.rightCtrl"))), _leftAlt(new QCheckBox( obs_module_text("AdvSceneSwitcher.action.hotkey.leftAlt"))), _rightAlt(new QCheckBox( obs_module_text("AdvSceneSwitcher.action.hotkey.rightAlt"))), _leftMeta(new QCheckBox( obs_module_text("AdvSceneSwitcher.action.hotkey.leftMeta"))), _rightMeta(new QCheckBox( obs_module_text("AdvSceneSwitcher.action.hotkey.rightMeta"))), _duration(new DurationSelection(this, false)), _onlySendToOBS(new QCheckBox( obs_module_text("AdvSceneSwitcher.action.hotkey.onlyOBS"))), _noKeyPressSimulationWarning(new QLabel( obs_module_text("AdvSceneSwitcher.action.hotkey.disabled"))), _entryLayout(new QHBoxLayout()), _keyConfigLayout(new QHBoxLayout()) { populateKeySelection(_keys); populateActionSelection(_actionType); populateHotkeyTypeSelection(_hotkeyType); QWidget::connect(_actionType, SIGNAL(currentIndexChanged(int)), this, SLOT(ActionChanged(int))); QWidget::connect(_hotkeyType, SIGNAL(currentIndexChanged(int)), this, SLOT(HotkeyTypeChanged(int))); QWidget::connect(_obsHotkeys, SIGNAL(currentIndexChanged(int)), this, SLOT(OBSHotkeyChanged(int))); QWidget::connect(_keys, SIGNAL(currentIndexChanged(int)), this, SLOT(KeyChanged(int))); QWidget::connect(_leftShift, SIGNAL(stateChanged(int)), this, SLOT(LShiftChanged(int))); QWidget::connect(_rightShift, SIGNAL(stateChanged(int)), this, SLOT(RShiftChanged(int))); QWidget::connect(_leftCtrl, SIGNAL(stateChanged(int)), this, SLOT(LCtrlChanged(int))); QWidget::connect(_rightCtrl, SIGNAL(stateChanged(int)), this, SLOT(RCtrlChanged(int))); QWidget::connect(_leftAlt, SIGNAL(stateChanged(int)), this, SLOT(LAltChanged(int))); QWidget::connect(_rightAlt, SIGNAL(stateChanged(int)), this, SLOT(RAltChanged(int))); QWidget::connect(_leftMeta, SIGNAL(stateChanged(int)), this, SLOT(LMetaChanged(int))); QWidget::connect(_rightMeta, SIGNAL(stateChanged(int)), this, SLOT(RMetaChanged(int))); QWidget::connect(_duration, SIGNAL(DurationChanged(const Duration &)), this, SLOT(DurationChanged(const Duration &))); QWidget::connect(_onlySendToOBS, SIGNAL(stateChanged(int)), this, SLOT(OnlySendToOBSChanged(int))); _entryLayout->setContentsMargins(0, 0, 0, 0); _keyConfigLayout->setContentsMargins(0, 0, 0, 0); _keyConfigLayout->addWidget(_leftShift); _keyConfigLayout->addWidget(_rightShift); _keyConfigLayout->addWidget(_leftCtrl); _keyConfigLayout->addWidget(_rightCtrl); _keyConfigLayout->addWidget(_leftAlt); _keyConfigLayout->addWidget(_rightAlt); _keyConfigLayout->addWidget(_leftMeta); _keyConfigLayout->addWidget(_rightMeta); _keyConfigLayout->addStretch(); auto mainLayout = new QVBoxLayout; mainLayout->addLayout(_entryLayout); mainLayout->addLayout(_keyConfigLayout); mainLayout->addWidget(_onlySendToOBS); mainLayout->addWidget(_noKeyPressSimulationWarning); setLayout(mainLayout); _onlySendToOBS->setEnabled(CanSimulateKeyPresses()); _entryData = entryData; UpdateEntryData(); _loading = false; } void MacroActionHotkeyEdit::RepopulateOBSHotkeySelection() { populateHotkeyNames(_obsHotkeys, _entryData->_hotkeyType); } void MacroActionHotkeyEdit::SetWidgetVisibility() { _entryLayout->removeWidget(_actionType); _entryLayout->removeWidget(_hotkeyType); _entryLayout->removeWidget(_obsHotkeys); _entryLayout->removeWidget(_keys); _entryLayout->removeWidget(_duration); ClearLayout(_entryLayout); PlaceWidgets( obs_module_text( _entryData->_action == MacroActionHotkey::Action::OBS_HOTKEY ? "AdvSceneSwitcher.action.hotkey.entry.obs" : "AdvSceneSwitcher.action.hotkey.entry.custom"), _entryLayout, { {"{{actionType}}", _actionType}, {"{{hotkeyType}}", _hotkeyType}, {"{{obsHotkeys}}", _obsHotkeys}, {"{{keys}}", _keys}, {"{{duration}}", _duration}, }); _noKeyPressSimulationWarning->setVisible(!_entryData->_onlySendToObs && !CanSimulateKeyPresses()); SetLayoutVisible(_keyConfigLayout, _entryData->_action == MacroActionHotkey::Action::CUSTOM); _duration->setVisible(_entryData->_action == MacroActionHotkey::Action::CUSTOM); _keys->setVisible(_entryData->_action == MacroActionHotkey::Action::CUSTOM); _onlySendToOBS->setVisible(_entryData->_action == MacroActionHotkey::Action::CUSTOM); _hotkeyType->setVisible(_entryData->_action == MacroActionHotkey::Action::OBS_HOTKEY); _obsHotkeys->setVisible(_entryData->_action == MacroActionHotkey::Action::OBS_HOTKEY); adjustSize(); updateGeometry(); } static QString getHotkeyDescriptionByName(const std::string &name) { struct Parameters { std::string name; QString description = ""; } params; auto func = [](void *param, obs_hotkey_id, obs_hotkey_t *hotkey) { auto params = static_cast(param); std::string name = obs_hotkey_get_name(hotkey); addNamePrefix(name, hotkey); if (name == params->name) { params->description = obs_hotkey_get_description(hotkey); addNamePrefix(params->description, hotkey); return false; } return true; }; params.name = name; obs_enum_hotkeys(func, ¶ms); return params.description; } void MacroActionHotkeyEdit::UpdateEntryData() { if (!_entryData) { return; } _actionType->setCurrentIndex(static_cast(_entryData->_action)); _hotkeyType->setCurrentIndex(static_cast(_entryData->_hotkeyType)); RepopulateOBSHotkeySelection(); _obsHotkeys->setCurrentText( getHotkeyDescriptionByName(_entryData->_hotkeyName)); _keys->setCurrentIndex(static_cast(_entryData->_key)); _leftShift->setChecked(_entryData->_leftShift); _rightShift->setChecked(_entryData->_rightShift); _leftCtrl->setChecked(_entryData->_leftCtrl); _rightCtrl->setChecked(_entryData->_rightCtrl); _leftAlt->setChecked(_entryData->_leftAlt); _rightAlt->setChecked(_entryData->_rightAlt); _leftMeta->setChecked(_entryData->_leftMeta); _rightMeta->setChecked(_entryData->_rightMeta); _duration->SetDuration(_entryData->_duration); _onlySendToOBS->setChecked(_entryData->_onlySendToObs || !CanSimulateKeyPresses()); SetWidgetVisibility(); } void MacroActionHotkeyEdit::LShiftChanged(int state) { if (_loading || !_entryData) { return; } auto lock = LockContext(); _entryData->_leftShift = state; } void MacroActionHotkeyEdit::RShiftChanged(int state) { if (_loading || !_entryData) { return; } auto lock = LockContext(); _entryData->_rightShift = state; } void MacroActionHotkeyEdit::LCtrlChanged(int state) { if (_loading || !_entryData) { return; } auto lock = LockContext(); _entryData->_leftCtrl = state; } void MacroActionHotkeyEdit::RCtrlChanged(int state) { if (_loading || !_entryData) { return; } auto lock = LockContext(); _entryData->_rightCtrl = state; } void MacroActionHotkeyEdit::LAltChanged(int state) { if (_loading || !_entryData) { return; } auto lock = LockContext(); _entryData->_leftAlt = state; } void MacroActionHotkeyEdit::RAltChanged(int state) { if (_loading || !_entryData) { return; } auto lock = LockContext(); _entryData->_rightAlt = state; } void MacroActionHotkeyEdit::LMetaChanged(int state) { if (_loading || !_entryData) { return; } auto lock = LockContext(); _entryData->_leftMeta = state; } void MacroActionHotkeyEdit::RMetaChanged(int state) { if (_loading || !_entryData) { return; } auto lock = LockContext(); _entryData->_rightMeta = state; } void MacroActionHotkeyEdit::DurationChanged(const Duration &dur) { if (_loading || !_entryData) { return; } auto lock = LockContext(); _entryData->_duration = dur; } void MacroActionHotkeyEdit::OnlySendToOBSChanged(int state) { if (_loading || !_entryData) { return; } auto lock = LockContext(); _entryData->_onlySendToObs = state; SetWidgetVisibility(); } void MacroActionHotkeyEdit::KeyChanged(int key) { if (_loading || !_entryData) { return; } auto lock = LockContext(); _entryData->_key = static_cast(key); } void MacroActionHotkeyEdit::ActionChanged(int value) { if (_loading || !_entryData) { return; } auto lock = LockContext(); _entryData->_action = static_cast(value); SetWidgetVisibility(); } void MacroActionHotkeyEdit::HotkeyTypeChanged(int value) { if (_loading || !_entryData) { return; } { auto lock = LockContext(); _entryData->_hotkeyType = static_cast(value); } RepopulateOBSHotkeySelection(); } void MacroActionHotkeyEdit::OBSHotkeyChanged(int idx) { if (_loading || !_entryData) { return; } auto lock = LockContext(); if (idx == -1) { _entryData->_hotkeyName = ""; return; } _entryData->_hotkeyName = _obsHotkeys->itemData(idx).toString().toStdString(); } } // namespace advss