#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"}); static const std::map actionTypes = { {MacroActionHotkey::Action::OBS_HOTKEY, "AdvSceneSwitcher.action.hotkey.type.obs"}, {MacroActionHotkey::Action::CUSTOM, "AdvSceneSwitcher.action.hotkey.type.custom"}, }; static const 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 const 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 weakSource = reinterpret_cast( obs_hotkey_get_registerer(hotkey)); prefix = "[" + GetWeakSourceName(weakSource) + "] "; } else if (type == OBS_HOTKEY_REGISTERER_OUTPUT) { std::string name; auto weakOutput = reinterpret_cast( obs_hotkey_get_registerer(hotkey)); OBSOutputAutoRelease output = obs_weak_output_get_output(weakOutput); if (output) { name = obs_output_get_name(output); } prefix = "[" + name + "] "; } else if (type == OBS_HOTKEY_REGISTERER_ENCODER) { std::string name; auto weakEncoder = reinterpret_cast( obs_hotkey_get_registerer(hotkey)); OBSEncoderAutoRelease encoder = obs_weak_encoder_get_encoder(weakEncoder); if (encoder) { name = obs_encoder_get_name(encoder); } prefix = "[" + name + "] "; } else if (type == OBS_HOTKEY_REGISTERER_SERVICE) { std::string name; auto weakService = reinterpret_cast( obs_hotkey_get_registerer(hotkey)); OBSServiceAutoRelease service = obs_weak_service_get_service(weakService); if (service) { name = obs_service_get_name(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 Action::OBS_HOTKEY: SendOBSHotkey(); break; case Action::CUSTOM: SendCustomHotkey(); break; default: break; } return true; } void MacroActionHotkey::LogAction() const { ablog(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; } std::shared_ptr MacroActionHotkey::Create(Macro *m) { return std::make_shared(m); } std::shared_ptr MacroActionHotkey::Copy() const { return std::make_shared(*this); } static inline void populateKeySelection(QComboBox *list) { list->addItems({"No key", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23", "F24", "Escape", "Space", "Return", "Backspace", "Tab", "Shift_L", "Shift_R", "Control_L", "Control_R", "Alt_L", "Alt_R", "Win_L", "Win_R", "Apps", "CapsLock", "NumLock", "ScrollLock", "PrintScreen", "Pause", "Insert", "Delete", "PageUP", "PageDown", "Home", "End", "Left", "Right", "Up", "Down", "Numpad0", "Numpad1", "Numpad2", "Numpad3", "Numpad4", "Numpad5", "Numpad6", "Numpad7", "Numpad8", "Numpad9", "NumpadAdd", "NumpadSubtract", "NumpadMultiply", "NumpadDivide", "NumpadDecimal", "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