2021年11月09日

【自キ】ダブルホールドの実装に成功

マクロパッドで、
シングルタップでそのキーを発行、
二つ同時にホールドすることでシフトをホールドするものをつくった。
これをダブルホールドと呼ぶことにする。



QMKでは、TAPPING_TERMだけ待つことでホールド、
その前に離せばタップ、というように分けている。
これを利用して、MT(MOD_LSFT, KC_...)なんかを組めるけど、
TAPPING_TERMだけ待たないといけない問題がある。
この値を短くするとホールドは速くなるが、
タップがとてもシビアになり、
ホールドとタップを使い分けることは難しい。

とくに、
マウスでシフトクリック、シフトホイールなんてやりたいときに、
ちょっと待ってクリックとか結構うざい。
シフトクリックは、複数選択にバインドされているアプリは多く、
複数選択を取りこぼしてイライラするんだよね……

PERMISSIVE_HOLDのオプションは、
ホールド優先になるんだけど、
QMKの制御しているキーボード内限定で有効で、
外部機器、マウスとの連動は難しい。


その両者を解消する、
「二つのキーをホールドしたらシフトキーホールド、
離したらシフト離した、
それぞれを単独でタップするとそれぞれのキー」
という仕組みをマクロでつくった。
これをダブルホールドと呼ぶことにする。


コード例は以下。


以下の例は、単独押しだと左右カーソル、
ダブルホールドだとシフトになるもの。
両方押している間にマウスクリックやホイールを使うと、
シフトクリック、シフトホイールになる。
(AdobeのAfter Effectsでは、
シフトクリックで複数クリップ選択、
シフトホイールでタイムライン移動になるなど、
アプリのショートカットが割り当てられていることが多い)

まずconfig.hで、
#define PERMISSIVE_HOLD
を宣言しておく。
ちなみに、
#define TAPPING_TERM 150
を僕は使っている。


keymap.cで、以下のように。

// 使用フラグ。ダブルホールドしたかしていないか
// LRを押しているかいないか
static bool Double_Hold = false;
static bool L_on = false;
static bool R_on = false;

// マクロの定義
enum custom_keycodes {
...
DHS_L,
DHS_R,
// ダブルホールドでシフトキー、それぞれ単独で左右カーソル
...
};

// キーマップ本体に二つを定義する
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
...
DHS_L, DHS_R,
...
};

// マクロ定義部
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
...

// ダブルホールドキーひとつめ
case DHS_L:
if (record->event.pressed) {
// 押したとき
L_on = true;
///// 反対のR側も押されていたらシフト押しっぱなしにする
if (R_on) {
SEND_STRING(SS_DOWN(X_LSHIFT));
Double_Hold = true;
}
} else {
// 離したとき
L_on = false;
if (R_on) {
// もう一方がまだ押されているなら何もしない
} else {
// もう一方は今オフ、ダブルホールドがあったか単押しかで場合分け
if (Double_Hold) {
// ダブルホールドがあった場合、シフトをオフにする
SEND_STRING(SS_UP(X_LSHIFT));
Double_Hold = false;
} else {
// 単押し、単離し
SEND_STRING(SS_TAP(X_LEFT));
}
}
}
break;

// ダブルホールドキーふたつめ
case DHS_R:
if (record->event.pressed) {
// 押したとき
R_on = true;
///// L側も押されていたらシフト押しっぱなし
if (L_on) {
SEND_STRING(SS_DOWN(X_LSHIFT));
Double_Hold = true;
}
} else {
// 離したとき
R_on = false;
if (L_on) {
// もう一方がまだ押されているなら何もしない
} else {
// もう一方は今オフ、ダブルホールドがあったか単押しかで場合分け
if (Double_Hold) {
SEND_STRING(SS_UP(X_LSHIFT));
Double_Hold = false;
} else {
// 単押し、単離し
SEND_STRING(SS_TAP(X_RIGHT));
}
}
}
break;
...
}
return true;
};

コード自体は単なる場合分けとフラグによる判定なので、
そんなに難しくないだろう。
押したときだけでなく、
離したときにも判定しておかないと、
「二つ押して、一つ離したあと、もう一個を離すとき」と、
「単独で押して離したとき」を区別できないので注意。
そこではまって、一日かかってしまった……。

これだけ場合分けが多いと、
3キー押しは8パターンになり、コードが難しそうだな……。



このやり方ならずっとシフトをホールドしておいて、
それをマウスでノータイムで利用することが可能になる。
僕はシフトとコントロールを採用して、
シフトクリック、シフトホイール、
コントロールクリック(サブメニュー呼び出し)、
なんかに活用しています。

ちなみにAltが厄介で、ただ押して離しただけだと、
単独Alt押しに解釈されて、アプリのメニューがハイライトされるやつになってしまう。
それを避けるために、
Altアップのときにもう一回Altタップを仕込んで、
事実上Altを一回押し離しして、逃れている。
MacだとOptionキーだからそんな心配はないんだが。

参考までに。

posted by おおおかとしひこ at 23:50| Comment(6) | カタナ式 | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
これは使いようによってはかなり便利になりそうなポテンシャルがありますね。
私も掘り下げてみます。
Posted by Yuichi Abe at 2021年11月10日 00:49
>Yuichi Abeさん

ふつうのキーボードならそこまで重要じゃないかもですが、
マクロパッドなどキー数の少ないものでは重宝しそうです。

シフト+クリック、シフト+ドラッグ(拡大で縦横比保存とか)は、
色んなアプリでありそうなので、
シフトのホールドは需要がありそう。
Afterだと、素材をオンにしてAlt(Option)押しながらタイムラインレイヤークリックすれば素材の差し替えなので、
そういう場面でもキーボードなしでいけます。

また、今のところCtrl+Shift+なんとかなど、
多重の組み合わせは、場合わけが組合せ爆発起こすのでやってません。
欲しければC+S用の別キーを作るなど、
マップ上の工夫はいると思います。

あと、ホールドじゃなくてタップで良ければ、
Comboの方が使いやすいと思います。
今テンキーレイヤーで、
1+2同時押しで「0エンター」、4+5同時押しで「50エンター」、
7+8同時押しで「100エンター」をComboでつくっていて、
透明度の入力に重宝しています。
フェード作ったりハーフ重ねを作るときによく使う数値なので。

今PAEのver4を練り直し中なので、
まとまったらまた上げます。
Posted by おおおかとしひこ at 2021年11月10日 01:54
>1+2同時押しで「0エンター」、4+5同時押しで「50エンター」、
>7+8同時押しで「100エンター」

このアイデアはかなり便利そうだなと感じました。
さすがですね。。。

不透明度と合成パターンをサクサク変えられるとAEははかどりますかね。

PAE ver4 楽しみにしております!
Posted by Yuichi Abe at 2021年11月11日 00:33
>Yuichi Abeさん

今親指メインキーのホールドで、
0987ー
入654.
 321●
と左手用反転テンキーバインドにしていて
(入はエンター、●がホールド部)、
結構使い勝手がいいんですが、
100エンター打つのに小指がめんどくせえな、
中指人差し指同時押しにしたろ、
と思ったのが発端です。

そうすると次は、90、-90、180、とか回転数値も?
と思ってバインド悩み中です…そんな使わないかな…
Posted by おおおかとしひこ at 2021年11月11日 01:12
AEの需要はざっくり2パターンかなと考えていてます。
・PRではやっかいなアニメーションをサクッとつくる
・AEだけでゴリゴリのモーショングラフィックスをつくる

前者はそこまでショートカットなどを熟知していなくても効率には影響はないのかもしれませんが、後者はキーフレーム周りや合成パターンだったり、キーフレが入っているパラメーターを表示する2連打のアクションが多いのでオールマウスでポチポチやってるのとショートカットを多用するのでは作業時間にかなり違いがでてくるかと思います。

細かいパーツをたくさん配置するようなプロジェクトでは、回転、アンカーポイント、ポジション等のフローをうまく構築できれば時短効果に期待できそうですね。

レンダリングにかかる時間もばかになりませんし・・・
Posted by Yuichi Abe at 2021年11月12日 00:25
>Yuichi Abeさん

タブを開いたり閉じたり、
キーフレームへ移動したりは、
マウスオンリーだとかなりしんどくて、
アルファベット一文字とはいえ、
不規則なショートカットも結構面倒だったので、
マクロパッドの出番だなと思いました。
とりあえずUで開いてもいいんだけど。

でも全部開く(三角の部分)はショートカットないんだよな…
まあ、あるやつでなんとかする方針です。
Posted by おおおかとしひこ at 2021年11月12日 10:28
コメントを書く
お名前: [必須入力]

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

※ブログオーナーが承認したコメントのみ表示されます。