headless: userscript bind hotkey

This commit is contained in:
lededev 2021-05-01 00:20:40 +08:00
parent 5e77cb4577
commit 7709db832b
7 changed files with 177 additions and 4 deletions

View File

@ -26,7 +26,8 @@ const char* Action::m_ActionTypeNames[] =
"keyDown", "keyUp", "keystroke", "keyDown", "keyUp", "keystroke",
"switchToScreen", "toggleScreen", "switchToScreen", "toggleScreen",
"switchInDirection", "lockCursorToScreen", "switchInDirection", "lockCursorToScreen",
"mouseDown", "mouseUp", "mousebutton" "userScript",
"mouseDown", "mouseUp", "mousebutton",
}; };
const char* Action::m_SwitchDirectionNames[] = { "left", "right", "up", "down" }; const char* Action::m_SwitchDirectionNames[] = { "left", "right", "up", "down" };
@ -37,6 +38,7 @@ Action::Action() :
m_Type(keystroke), m_Type(keystroke),
m_TypeScreenNames(), m_TypeScreenNames(),
m_SwitchScreenName(), m_SwitchScreenName(),
m_UserScriptCommand(),
m_SwitchDirection(switchLeft), m_SwitchDirection(switchLeft),
m_LockCursorMode(lockCursorToggle), m_LockCursorMode(lockCursorToggle),
m_ActiveOnRelease(false), m_ActiveOnRelease(false),
@ -105,6 +107,11 @@ QString Action::text() const
text += ")"; text += ")";
break; break;
case userScript:
text += "(";
text += userScriptCommand();
text += ")";
break;
default: default:
Q_ASSERT(0); Q_ASSERT(0);
break; break;
@ -133,6 +140,7 @@ void Action::loadSettings(QSettings& settings)
setLockCursorMode(settings.value("lockCursorToScreen", lockCursorToggle).toInt()); setLockCursorMode(settings.value("lockCursorToScreen", lockCursorToggle).toInt());
setActiveOnRelease(settings.value("activeOnRelease", false).toBool()); setActiveOnRelease(settings.value("activeOnRelease", false).toBool());
setHaveScreens(settings.value("hasScreens", false).toBool()); setHaveScreens(settings.value("hasScreens", false).toBool());
setUserScriptCommand(settings.value("userScriptCommand").toString());
} }
void Action::saveSettings(QSettings& settings) const void Action::saveSettings(QSettings& settings) const
@ -153,6 +161,7 @@ void Action::saveSettings(QSettings& settings) const
settings.setValue("lockCursorToScreen", lockCursorMode()); settings.setValue("lockCursorToScreen", lockCursorMode());
settings.setValue("activeOnRelease", activeOnRelease()); settings.setValue("activeOnRelease", activeOnRelease());
settings.setValue("hasScreens", haveScreens()); settings.setValue("hasScreens", haveScreens());
settings.setValue("userScriptCommand", userScriptCommand());
} }
QTextStream& operator<<(QTextStream& outStream, const Action& action) QTextStream& operator<<(QTextStream& outStream, const Action& action)

View File

@ -35,7 +35,8 @@ class Action
public: public:
enum ActionType { keyDown, keyUp, keystroke, enum ActionType { keyDown, keyUp, keystroke,
switchToScreen, toggleScreen, switchInDirection, switchToScreen, toggleScreen, switchInDirection,
lockCursorToScreen, mouseDown, mouseUp, mousebutton }; lockCursorToScreen, userScript,
mouseDown, mouseUp, mousebutton };
enum SwitchDirection { switchLeft, switchRight, switchUp, switchDown }; enum SwitchDirection { switchLeft, switchRight, switchUp, switchDown };
enum LockCursorMode { lockCursorToggle, lockCursonOn, lockCursorOff }; enum LockCursorMode { lockCursorToggle, lockCursonOn, lockCursorOff };
@ -72,11 +73,15 @@ class Action
bool haveScreens() const { return m_HasScreens; } bool haveScreens() const { return m_HasScreens; }
void setHaveScreens(bool b) { m_HasScreens = b; } void setHaveScreens(bool b) { m_HasScreens = b; }
const QString& userScriptCommand() const { return m_UserScriptCommand; }
void setUserScriptCommand(const QString& n) { m_UserScriptCommand = n; }
private: private:
KeySequence m_KeySequence; KeySequence m_KeySequence;
int m_Type; int m_Type;
QStringList m_TypeScreenNames; QStringList m_TypeScreenNames;
QString m_SwitchScreenName; QString m_SwitchScreenName;
QString m_UserScriptCommand;
int m_SwitchDirection; int m_SwitchDirection;
int m_LockCursorMode; int m_LockCursorMode;
bool m_ActiveOnRelease; bool m_ActiveOnRelease;

View File

@ -39,7 +39,7 @@ ActionDialog::ActionDialog(QWidget* parent, ServerConfig& config, Hotkey& hotkey
// work around Qt Designer's lack of a QButtonGroup; we need it to get // work around Qt Designer's lack of a QButtonGroup; we need it to get
// at the button id of the checked radio button // at the button id of the checked radio button
QRadioButton* const typeButtons[] = { m_pRadioPress, m_pRadioRelease, m_pRadioPressAndRelease, m_pRadioSwitchToScreen, m_pRadioToggleScreen, m_pRadioSwitchInDirection, m_pRadioLockCursorToScreen }; QRadioButton* const typeButtons[] = { m_pRadioPress, m_pRadioRelease, m_pRadioPressAndRelease, m_pRadioSwitchToScreen, m_pRadioToggleScreen, m_pRadioSwitchInDirection, m_pRadioLockCursorToScreen, m_pRadioUserScript };
for (unsigned int i = 0; i < sizeof(typeButtons) / sizeof(typeButtons[0]); i++) for (unsigned int i = 0; i < sizeof(typeButtons) / sizeof(typeButtons[0]); i++)
m_pButtonGroupType->addButton(typeButtons[i], i); m_pButtonGroupType->addButton(typeButtons[i], i);
@ -49,6 +49,7 @@ ActionDialog::ActionDialog(QWidget* parent, ServerConfig& config, Hotkey& hotkey
m_pButtonGroupType->button(m_Action.type())->setChecked(true); m_pButtonGroupType->button(m_Action.type())->setChecked(true);
m_pComboSwitchInDirection->setCurrentIndex(m_Action.switchDirection()); m_pComboSwitchInDirection->setCurrentIndex(m_Action.switchDirection());
m_pComboLockCursorToScreen->setCurrentIndex(m_Action.lockCursorMode()); m_pComboLockCursorToScreen->setCurrentIndex(m_Action.lockCursorMode());
m_pUserScriptCommand->setText(m_Action.userScriptCommand());
if (m_Action.activeOnRelease()) if (m_Action.activeOnRelease())
m_pRadioHotkeyReleased->setChecked(true); m_pRadioHotkeyReleased->setChecked(true);
@ -93,6 +94,7 @@ void ActionDialog::accept()
m_Action.setSwitchDirection(m_pComboSwitchInDirection->currentIndex()); m_Action.setSwitchDirection(m_pComboSwitchInDirection->currentIndex());
m_Action.setLockCursorMode(m_pComboLockCursorToScreen->currentIndex()); m_Action.setLockCursorMode(m_pComboLockCursorToScreen->currentIndex());
m_Action.setActiveOnRelease(m_pRadioHotkeyReleased->isChecked()); m_Action.setActiveOnRelease(m_pRadioHotkeyReleased->isChecked());
m_Action.setUserScriptCommand(m_pUserScriptCommand->text());
QDialog::accept(); QDialog::accept();
} }

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>372</width> <width>372</width>
<height>484</height> <height>508</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -250,6 +250,37 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QRadioButton" name="m_pRadioUserScript">
<property name="text">
<string>User Script</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLineEdit" name="m_pUserScriptCommand">
<property name="text">
<string>script1</string>
</property>
</widget>
</item>
</layout>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@ -588,5 +619,53 @@
</hint> </hint>
</hints> </hints>
</connection> </connection>
<connection>
<sender>m_pRadioUserScript</sender>
<signal>toggled(bool)</signal>
<receiver>m_pUserScriptCommand</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>63</x>
<y>385</y>
</hint>
<hint type="destinationlabel">
<x>291</x>
<y>385</y>
</hint>
</hints>
</connection>
<connection>
<sender>m_pRadioUserScript</sender>
<signal>toggled(bool)</signal>
<receiver>m_pKeySequenceWidgetHotkey</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>63</x>
<y>385</y>
</hint>
<hint type="destinationlabel">
<x>185</x>
<y>118</y>
</hint>
</hints>
</connection>
<connection>
<sender>m_pRadioUserScript</sender>
<signal>toggled(bool)</signal>
<receiver>m_pGroupBoxScreens</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>63</x>
<y>385</y>
</hint>
<hint type="destinationlabel">
<x>185</x>
<y>189</y>
</hint>
</hints>
</connection>
</connections> </connections>
</ui> </ui>

View File

@ -1244,6 +1244,20 @@ void Config::parseAction(ConfigReadContext& s, const std::string& name,
action = new InputFilter::KeyboardBroadcastAction(m_events, mode, screens); action = new InputFilter::KeyboardBroadcastAction(m_events, mode, screens);
} }
else if (name == "userScript") {
if (args.size() != 1) {
throw XConfigRead(s, "syntax for action: userScript(scriptCommand)");
}
std::string scriptCommand = args[0];
if (scriptCommand.empty()) {
throw XConfigRead(s, "bad script command in userScript");
}
action = new InputFilter::UserScriptAction(m_events, scriptCommand);
}
else { else {
throw XConfigRead(s, "unknown action argument \"%{1}\"", name); throw XConfigRead(s, "unknown action argument \"%{1}\"", name);
} }

View File

@ -660,6 +660,53 @@ InputFilter::MouseButtonAction::formatName() const
return (m_press ? "mouseDown" : "mouseUp"); return (m_press ? "mouseDown" : "mouseUp");
} }
InputFilter::UserScriptAction::UserScriptAction(IEventQueue* events,
const std::string& scriptCommand) :
m_scriptCommand(scriptCommand),
m_events(events)
{
// do nothing
}
std::string InputFilter::UserScriptAction::getScriptCommand() const
{
return m_scriptCommand;
}
InputFilter::Action*
InputFilter::UserScriptAction::clone() const
{
return new UserScriptAction(*this);
}
std::string InputFilter::UserScriptAction::format() const
{
return barrier::string::sprintf("userScript(%s)", m_scriptCommand.c_str());
}
void
InputFilter::UserScriptAction::perform(const Event& event)
{
// pick screen name. if m_screen is empty then use the screen from
// event if it has one.
std::string scriptCommand = m_scriptCommand;
if (scriptCommand.empty()) {
LOG((CLOG_ERR "script ID empty"));
return;
}
// exec script
#if !defined(_WIN32)
std::string s = barrier::string::sprintf(R"(sh -c '%s')", scriptCommand.c_str());
#else
std::string s = barrier::string::sprintf(R"(cmd.exe /C "%s")", scriptCommand.c_str());
#endif
LOG((CLOG_DEBUG "%s",s.c_str()));
system(s.c_str());
}
// //
// InputFilter::Rule // InputFilter::Rule
// //

View File

@ -270,6 +270,23 @@ public:
IEventQueue* m_events; IEventQueue* m_events;
}; };
// UserScriptAction
class UserScriptAction : public Action {
public:
UserScriptAction(IEventQueue* events, const std::string& scriptCommand);
std::string getScriptCommand() const;
// Action overrides
virtual Action* clone() const;
virtual String format() const;
virtual void perform(const Event&);
private:
std::string m_scriptCommand;
IEventQueue* m_events;
};
class Rule { class Rule {
public: public:
Rule(); Rule();