Skip to content

Commit

Permalink
use the new delay functions with macros
Browse files Browse the repository at this point in the history
This implementation adds some UI Elements to the Binding tab.

When recording a macro, the timing (the time between changes the
Keyboard receives) are noted with the key values.

When saved with the detailled timing information, you may choose between
- running the macro witghout any delay
- running it with the standard delay
    - 0ms for the first 20 changes (normally 10 Keys),
    - then 30ms for up to 100 keys (200 status-changes)
    - and then 200ms for any further change)
- running the key delays, which had been recorded.

After recording (or after saving) you may change the timing values.
This might be useful, if you want to generate slow keystrokes, but you
do not want unneccessary long wait times (e.g. when sending longer macro
content to a virtual machine or a remote desktop tool, the maximum speed
is often too high. So include a short delay and all is fine).
  • Loading branch information
frickler24 committed Sep 22, 2016
1 parent d880766 commit fdf73e2
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 34 deletions.
2 changes: 1 addition & 1 deletion src/ckb-daemon/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ static void inputupdate_keys(usbdevice* kb){
usleep(action->delay);
} else if (kb->delay != UINT_MAX) { // use default global delay
usleep(kb->delay);
} else { // use old long macro delay code
} else if (a < (macro->actioncount - 1)) { // use delays depending on macro length
if (a > 200) {
usleep (100);
} else if (a > 20) {
Expand Down
4 changes: 2 additions & 2 deletions src/ckb/keyaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -498,8 +498,8 @@ void KeyAction::adjustDisplay(){
/// macroAction ist called while being in the macro pane
/// and clicking Apply with something in the Macro Text Box.
/// It tags that input with "$macro:" for further recognition.
/// \param macroDef holds the String containing parts 2-4 of a complete macro definition.
/// \return QString holding the complete G-Key macro definition (parts 1-4)
/// \param macroDef holds the String containing parts 2-5 of a complete macro definition.
/// \return QString holding the complete G-Key macro definition (parts 1-5)
///
QString KeyAction::macroAction(QString macroDef) {
return QString ("$macro:%1").arg(macroDef);
Expand Down
22 changes: 17 additions & 5 deletions src/ckb/keyaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class KeyAction : public QObject
/// returns the complete string except the leading "$"
/// (the $ may confuse some caller).
/// \return QString
/// All 4 parts are returned in one QString.
/// All 5 parts are returned in one QString.
/// If no definition exists, return ""
///
inline QString macroFullLine() const {
Expand All @@ -47,15 +47,15 @@ class KeyAction : public QObject
//////////
/// \brief isValidMacro checks whether a keyAction contains a valid macro.
/// This is done easily: If the macro action starts with $macro:
/// and has four elements, delimited by ":", we may assume,
/// and has five elements, delimited by ":", we may assume,
/// that is a structural correct macro action.
/// \return bool as true iff the macro definition contains all four elements.
///
inline bool isValidMacro() const {
if (isMacro()) {
QStringList ret;
ret =_value.split(":");
return (ret.count() == 4);
return (ret.count() == 5);
} else {
return false;
}
Expand All @@ -64,8 +64,10 @@ class KeyAction : public QObject
//////////
/// \brief macroLine returns all interresting content for a macro definition.
/// \return QStringList returns the Macro Key Definition,
/// Readble Macro String and
/// Readable Macro Comment as QStringList.
/// Readble Macro String,
/// Readable Macro Comment and
/// the original timing information
/// as QStringList.
///
inline QStringList macroLine() const {
if (isValidMacro()) {
Expand All @@ -84,6 +86,15 @@ class KeyAction : public QObject
return isValidMacro() ? _value.split(":")[1] : "";
}

//////////
/// \brief macroTiming returns the macro key definition with original timing infos
/// (the fifth and up to now last part of the macro action).
/// \return QString macroTiming
///
inline QString macroTiming() const {
return isValidMacro() ? _value.split(":")[4] : "";
}

//////////
/// \brief Debug output for invalid macro Definitions
///
Expand All @@ -94,6 +105,7 @@ class KeyAction : public QObject
/// This sequence will program the keyboard and is hardly readable
/// 3. Readable Macro String: This is displayed in pteMacroText
/// 4. Readable Macro Comment:This is displayed in pteMacroComment
/// 5. completely unreadable original macro information with timing values
///
void macroDisplay();

Expand Down
79 changes: 57 additions & 22 deletions src/ckb/rebindwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ RebindWidget::RebindWidget(QWidget *parent) :
ui->modeWrapBox->hide();
ui->programKpExtra->hide();
ui->programKrExtra->hide();
macroSafe = "";

// Populate key lists
modKeys << "caps" << "lshift" << "rshift" << "lctrl" << "rctrl" << "lwin" << "rwin" << "lalt" << "ralt" << "rmenu" << "fn";
Expand Down Expand Up @@ -193,6 +192,7 @@ void RebindWidget::setSelection(const QStringList& newSelection, bool applyPrevi
ui->pteMacroBox->setPlainText("");
ui->pteMacroText->setPlainText("");
ui->pteMacroComment->setPlainText("");
ui->txtBuffer->setText("");
// Fill in field and select tab according to action type
bool mouse = act.isMouse();
if(mouse){
Expand Down Expand Up @@ -295,6 +295,12 @@ void RebindWidget::setSelection(const QStringList& newSelection, bool applyPrevi
ui->pteMacroBox->setPlainText(act.macroContent());
ui->pteMacroText->setPlainText(act.macroLine()[1].replace("&das_IST_31N_col0n;", ":"));
ui->pteMacroComment->setPlainText(act.macroLine()[2].replace("&das_IST_31N_col0n;", ":"));
// Set the invisible Buffer to the original timing information.
// For convenience / Migration from older versions:
// If the timing information is only "x", then ignore it by setting it to an empty QString.
ui->txtBuffer->setText("");
if (act.macroTiming() != "x") ui->txtBuffer->setText(act.macroTiming());
setCorrectRadioButton(act.macroContent());
} else {
qDebug("RebindWidget::setSelection found invalid macro definition.");
act.macroDisplay();
Expand Down Expand Up @@ -371,13 +377,25 @@ void RebindWidget::applyChanges(const QStringList& keys, bool doUnbind){
}
bind->setAction(keys, KeyAction::programAction(ui->programKpBox->text(), ui->programKrBox->text(), kpStop | krStop));
} else if (ui->pteMacroBox->toPlainText().length() > 0) {
// G-key macro handling:
// Set the macro definiton for all keys selected (indeed, it may be multiple keys).
// First, concat the Macro Key Definion and the Macro plain text
// after escaping possible colos in the parts for Macro Text and Macro Comment.
/// G-key macro handling:
/// Set the macro definiton for all keys selected (indeed, it may be multiple keys).
/// First, concat the Macro Key Definion and the Macro plain text
/// after escaping possible colos in the parts for Macro Text and Macro Comment.

/// But first, there is a special condition to handle:
/// You have recorded a macro with timing infos.
/// Afterwards you changed manually the timing infos in the pteMacroBox and press Apply.
/// In that case we must overwrite the txtBuffer to remember your changes.
if (ui->rb_delay_asTyped->isChecked()) ui->txtBuffer->setText(ui->pteMacroBox->toPlainText());

/// \todo There is still a bug in the state machine:
/// If you record a macro in asTyped-mode, switch to another mode
/// and change the vontent of the pteMacroBox manually,
/// then the changes are not saved in the timing buffer.
/// But anyhow, let's do more relevant things...
QString mac;
mac = ui->txtBuffer->text();
mac = ui->pteMacroComment->toPlainText().replace(":", "&das_IST_31N_col0n;");// + ":" + mac;
mac = ui->pteMacroComment->toPlainText().replace(":", "&das_IST_31N_col0n;") + ":" + mac;
mac = ui->pteMacroText->toPlainText().replace(":", "&das_IST_31N_col0n;") + ":" + mac;
mac = ui->pteMacroBox->toPlainText() + ":" + mac;
bind->setAction(keys, KeyAction::macroAction(mac));
Expand Down Expand Up @@ -435,6 +453,7 @@ void RebindWidget::setBox(QWidget* box){
// Clear macro panel
if (box != ui->pteMacroBox) {
ui->pteMacroBox->setPlainText("");
ui->txtBuffer->setText("");
helpStatus(1);
}
}
Expand Down Expand Up @@ -803,23 +822,21 @@ void RebindWidget::convertMacroBox() {
// How to deal with the delay params?
// Because the three radio buttons are mututally exclusive,
// we can run through the if-chain w/o conflicts.
// If rb_delay_asTyped is checked, do nothing, because that's the standard.

if (ui->rb_delay_asTyped->isChecked()) {
// Do nothing, because the timing parameters are added by default into the strings.
} else {
in.replace(QRegExp("=\\d*,"), ","); // Delete the timing infos
in.replace(QRegExp("^delay o..?,"), ""); // Delete older delay defaulting infos, if available

if (ui->rb_delay_default->isChecked()) {
in = "delay on\n" + in;
}
if (ui->rb_delay_no->isChecked()) {
in = "delay off\n" + in;
}
if (ui->rb_delay_default->isChecked()) {
in.replace(QRegExp("=\\d+,"), ","); // Delete the timing infos, use default value
in.replace(QRegExp("=\\d+$"), ""); // The last entry is without comma
}
if (ui->rb_delay_no->isChecked()) {
in.replace(QRegExp("=\\d+,"), "=0,"); // Set timing infos to zero for no delay
in.replace(QRegExp("=\\d+$"), "=0"); // Again the last entry w/o comma
in.replace(QRegExp("([\\+\\-]\\w+),"), "\\1=0,"); // If no delay is given, force it to zero
in.replace(QRegExp("([\\+\\-]\\w+)$"), "\\1=0");
}

// Show the new format by replacing the older one.
ui->pteMacroBox->setPlainText(in);
ui->pteMacroText->setPlainText(ui->txtBuffer->text());
}

//////////
Expand All @@ -832,7 +849,6 @@ void RebindWidget::convertMacroBox() {
///
void RebindWidget::on_rb_delay_no_toggled(bool checked)
{
ui->pteMacroText->setPlainText("Delay_no was toggled\n");
convertMacroBox();
}

Expand All @@ -845,7 +861,6 @@ void RebindWidget::on_rb_delay_no_toggled(bool checked)
///
void RebindWidget::on_rb_delay_asTyped_toggled(bool checked)
{
ui->pteMacroText->setPlainText("Delay_asTyped was toggled\n");
convertMacroBox();
}

Expand All @@ -857,6 +872,26 @@ void RebindWidget::on_rb_delay_asTyped_toggled(bool checked)
///
void RebindWidget::on_rb_delay_default_toggled(bool checked)
{
ui->pteMacroText->setPlainText("Delay_default was toggled\n");
convertMacroBox();
}

//////////
/// \brief RebindWidget::setCorrectRadioButton
/// \param macdef
/// Set the radiobutton for timing paramters according to
/// the context.
/// If no "=" followed by a number and comma can be found, it is the default button.
/// If "=" can be found and numbers with more than one digit (means: > 9), it is the "asTyped" button
/// Otherwise it is the "no" button.
///
void RebindWidget::setCorrectRadioButton (QString macdef) {
if (!macdef.contains(QRegExp("=\\d+,"))) {
ui->rb_delay_default->setChecked(true);
return;
}
if (macdef.contains(QRegExp("=\\d\\d+,"))) {
ui->rb_delay_asTyped->setChecked(true);
return;
}
ui->rb_delay_no->setChecked(true);
}
5 changes: 2 additions & 3 deletions src/ckb/rebindwidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,12 @@ private slots:
// Show some help info
void helpStatus(int status);

void setCorrectRadioButton (QString macdef);

KbBind* bind;
KbProfile* profile;
QStringList selection;

// Hold complete macro information while fiddling with delay params
QString macroSafe;

QStringList typingKeys;
QStringList modKeys;
QStringList fnKeys;
Expand Down
2 changes: 1 addition & 1 deletion src/ckb/rebindwidget.ui
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>5</number>
<number>0</number>
</property>
<property name="usesScrollButtons">
<bool>false</bool>
Expand Down

0 comments on commit fdf73e2

Please sign in to comment.