Help us understand the problem. What is going on with this article?

未知の階層に挑戦Tri-Layers

今回は、翻訳が全く働かないため、手探りでの投稿になる。

結論はOLKB用に開発したと思われるupdate_tri_layer関数についてだ。

様式:update_tri_layer(x, y, z)
挙動1:Xレイヤー変更キーでX階層のレイヤーを使う。
挙動2:Yレイヤー変更キーでY階層のレイヤーを使う。
挙動3:Xレイヤー変更キー押下かつ、Yレイヤー変更キー押下により、Zレイヤー変更が行われることで、Z階層のレイヤーを使うことができる。

結論:少ないキー数のキーボードで有用な機能だと結論づけられる。
要は、2つのキーを同時押しすることで、今までにない階層の操作ができるため、滅多に使わないキーを割り当てることで、キーの節約になる。
例えば、ディスプレイの明度や音量の大小変更などは、1度変更してしまえば、次に使うまで固定のままだろう。
LEDの光量もしかり。
CD-ROMドライブの排出などもしかり。
過去に投稿したFeature Mouse keysFeature Bootmagicなどのように、そのときだけ使うキーコードを設定するのが吉だろう。

以下、本題。

update_tri_layer_state関数

上記とは別の様式が存在する。
それが、以下だ。

関数:update_tri_layer_state(state, x, y, z)

使い方は、以下の通り。

3層目の利用方法

以下のコードを組み込むことで利用ができる。

keymap.c
uint32_t layer_state_set_user(uint32_t state) {
    return update_tri_layer_state(state, _LOWER, _RAISE, _ADJUST);
}

_LOWERキーコード:LOWER階層を操作する。
_RAISEキーコード:_RAISE階層を操作する。
上記2種類の同時押し:
ADJUST階層を操作する。

さして難しいことはない。

応用

上記だけでは_ADJUSTレイヤーのみしか使えない。
ゆえに、以下の方法で、三つ目の階層を複数用意できる。
(なぜ上書きされない?一つ目のstateが二つ目の処理で上書きされて機能しないと思うのだが・・・)

keymap.c
uint32_t layer_state_set_user(uint32_t state) {
    state = update_tri_layer_state(state, _LOWER, _RAISE, _ADJUST);
    state = update_tri_layer_state(state, _RAISE, _SYMB, _SPECIAL);
    return state;
}

今回で言えば、_ADJUSTのほかに、_SPECIALレイヤーが用意され、拡張性がさらに増した。
覚えられるか、使いこなせるかは別問題だが。。。

不可解

しかし、それとは別に、公式ページの解説が難しい。
本当にこの使い方で合っているのか分からないからだ。
実際に使えるのだから合っているのだが、複雑なコーディングをしなければ使えない説明があり、違いが分からないため、疑心暗鬼になっている。

下記の関数と異なる点は、レイヤー変更するたびにこの関数が呼ばれると言うこと。
頻繁な呼び出しが発生するようだ。

update_tri_layer関数

冒頭での説明をここで解説する。

keymap.c
enum custom_layers {
    _QWERTY = 0,
    _LOWER,
    _RAISE,
    _ADJUST
};

enum custom_keycodes {
    QWERTY = SAFE_RANGE,
    LOWER,
    RAISE,
    ADJUST
};

bool process_record_user(uint16_t keycode, keyrecord_t *record) {
    switch (keycode) {
        case LOWER:
            if (record->event.pressed) {
                layer_on(_LOWER);
                update_tri_layer(_LOWER, _RAISE, _ADJUST);
            } else {
                layer_off(_LOWER);
                update_tri_layer(_LOWER, _RAISE, _ADJUST);
            }
            return false;
            break;
        case RAISE:
            if (record->event.pressed) {
                layer_on(_RAISE);
                update_tri_layer(_LOWER, _RAISE, _ADJUST);
            } else {
                layer_off(_RAISE);
                update_tri_layer(_LOWER, _RAISE, _ADJUST);
            }
            return false;
            break;
    }
    return true;
}

やっていることは、上記のupdate_tri_layer_state関数と同じことだろう。

こちらのほうが拡張性は高いが、既存の関数との相性はよろしくない(矛盾した表現に感じる)。

注意点 その1

update_tri_layer_state関数update_tri_layer関数を同時に使う場合、理解不能な挙動をする。

私の場合は、KC_Cがレイヤー変更キーに変わってしまった。
最初理解できずに、ハンダ付けに問題があるのだと思い、付け直してしまった。
そのせいで、付け直したハンダ部分が汚くなってしまった。
無念だ。
私の轍を踏まないでか。

もしかしたら勘違いかもしれないが、一応注意しておいてくれたら幸いだ。
もししたらではなく、本当に勘違いだろう。しかし、後日もう一度検証して、本当に勘違い(間違い)だったら削除する。

注意点 その2

上記とは違う勘違いした挙動だ。
update_tri_layer_state 単体で動かしたのだが、旨く動いてくれなかった。
そのため、引数に問題があるとばかり思っていたのだが、違った。
通常のキーマップ側に問題があった。

第2引数(上記例で言うLOWER)と第3引数(上記例で言うRAISE)のレイヤー指定をするとき、_LOWERからみた_RAISE側のキー配置の場所に独自のキーコードが設定されていた場合、もしくは、RAISEからみた側のキー配置の場所に独自のキーコードが設定されていたとき、うまい具合にupdatetri_layer_state関数が動いてくれない。
要は、レイヤーを変更した先でも継承(KC_TRANS or KC_TRNS or _______)しておかなければ動かないと言うこと。

独自のキーコードを設定していた場合競合するのだろう。全く気づかず、_ADJUSTレイヤーに代わってくれなかったため、かなり焦った。

注意点 その3

かなり重要な注意点だ。
ちょっと試した感じでは、レイヤー移動関数と組み合わせられないようだ。
大変残念だ。

たとえば、LT(_LOWER, KC_A)の場合の _LOWER を今回のキーで置き換えたとしよう。
置き換え後:LT(LOWER, KC_A)
その結果:LOWERレイヤーには遷移せず、全く動かない無効キーとなる。
原因:カスタムキーコードのため、LT関数などでは認識しない。

この原因に気づくまで時間が掛かってしまった。
ちょっとだけ関わらない期間が発生するだけで忘れるとは・・・。

対策:update_tri_layer_state関数を使う。

デメリットしかないのかと言えば、そんなわけない。
メリットがなければ、こんな関数最初から作られていないはずだからな。
そのメリットは、LED点灯や音を出すことを一緒くたに合わせられることにある。
例えば以下のようにする(必要最小限のコードのみ)。

keymap.c
case LOWER:
    if (record->event.pressed) {
        layer_on(_LOWER);
        red_led_on(); // ←これ。
        update_tri_layer(_LOWER, _RAISE, _ADJUST);
    } else {
        layer_off(_LOWER);
        red_led_off();
        update_tri_layer(_LOWER, _RAISE, _ADJUST);
    }
    return false;
    break;

私は、レイヤー移動だけでなく、単体キーとの組み合わせ(LT関数など)で使いたいため、こっちの関数(update_tri_layer)を使うことはないだろう。

感想

悪くない関数だと思う。
普段使わないキーコードを設定するのに便利なため、今後活用すると思う。

全く翻訳サイトが役立たずで、それを読解する力もなかったが、それでも読み取っていただけたなら幸いだ。
(process_record_user関数ではなく、layer_state_set_user関数での利用がだめらしいのも理解できなかった箇所だ)

以上。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away