/* Copyright 2019 niltea
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include QMK_KEYBOARD_H
#ifdef OLED_DRIVER_ENABLE
#include
#include "lib/oled_helper.h"
#endif
///////////////////////////////////
// PAE ver 7.00 by OOOKA Toshihiko
///////////////////////////////////
// Adobe PremiereとAfter Effectsをどちらも似た操作感で使う為の左手マクロパッド配列
//// このファイルの全体構成
// 変数の定義
// レイヤー名の定義
// マクロ名の定義
// コンボ名の定義、コンボ本体の定義
// キーマップ本体の定義
// エンコーダーの定義
// マクロ本体の定義
// 普通のマクロ、ダブルホールドマクロなどあります
// 全体にサブルーチン化していない、都度継ぎ足したものなので、見にくくてすいません
///////// 色々変数定義
// フラグの定義
// Win/Mac, Premiere/After Effectsを都度切り替えて使います
// Win or Mac 初期値はWin 1
static bool Win_or_Mac = true;
//Premiere or AfterEffects 初期値はプレミア 1
static bool P_or_AE = true;
// これを変えたければこのフラグ初期値と、このあとのenum layerIDで、デフォルトを何にしたいかで変えること
// ツール切替トグル用のフラグ、初期値はVツール1
static bool V_toggle = true;
// キーカウント用(レイヤーキーなのか単打なのか見分ける用)
static int key_count = 0;
// ダブルホールド用のフラグ 二つキーを押したらShift, Ctrl, Altになる機能
// Shiftを押しながらマウス、などに対応させるため。
// ダブルホールドがあるか、それぞれのキーが押されたかのフラグ、初期値は何もしていないので0
static bool Double_Hold = false;
static bool CL_on = false;
static bool CR_on = false;
static bool SL_on = false;
static bool SR_on = false;
static bool AL_on = false;
static bool AR_on = false;
// タイマー(時間判定用)
// 離したときにタッピングターム以内なら単打とみなす、それ以上時間がたっていたらおしまい
// static uint32_t timer10 = 0;
// static uint32_t timer11 = 0;
////////// LAYER
//Premiereに3レイヤー、AEに3レイヤー、それぞれWinMacで計12レイヤー。あとテンキーとスペシャル(切り替え用)レイヤー
enum layerID {
// Win
_0_Win_P = 0, // default layer Win/Premiere
_1_Win_P,
_2_Win_P,
// 3レイヤーごとにペアになっているので、デフォにしたいものを3レイヤーごとここにもってくるとデフォを変えられるよ
// 最後の切り替えマクロベースレイヤーをどれにしたかで処理を変えること
_0_Win_AE,
_1_Win_AE,
_2_Win_AE,
// Mac
_0_Mac_P,
_1_Mac_P,
_2_Mac_P,
_0_Mac_AE,
_1_Mac_AE,
_2_Mac_AE,
// 切り替えレイヤーとテンキーレイヤー
_SPECIAL,
_ten,
};
// keymap内にしこむマクロ
enum custom_keycodes {
// Win/Mac Premiere/AfrerEffects切り替えマクロ
MC_Win_P = SAFE_RANGE,
MC_Mac_P,
MC_Win_AE,
MC_Mac_AE,
// ダブルホールドでモデファイア、その他で単打になるマクロ
DHS_L,
DHS_R,
DHC_L,
DHC_R,
DHA_L,
DHA_R,
// Afterで5F単位で移動するマクロ
MC_L5,
MC_R5,
// Premiereクリップのネスト(Winのみ対応)
MC_CLIP_NEST,
// 後方全選択ツールと前方全選択ツールを起動させて、選択ツールのトグルフラグをクリアする
MC_SELECTALL_AFTER,
MC_SELECTALL_BEFORE,
// 単打でcvツール切り替え、押しっぱなしでレイヤー2になるもの
MC_CV_L2,
// 単打で何か、押しっぱなしでテンキー
MC_TAP_LTten,
};
// 同時押し定義部
// その1……アンドゥとBSの同時押しで英数発行
// その2……テンキーの同時押しで、透明度などによく使う数字を入れ込む
// 100 enter, 50 enter, 0 enterを発生させる
enum combo_events {
EISU_Win,
EISU_Mac,
// WinとMacでアンドゥキーがC()G()で違うので2種定義
ZERO_ent,
HALF_ent,
FULL_ent,
};
// 789 8+9...100ent
// 456 5+6...50ent
// 1230 2+3...0ent
// 定義部
const uint16_t PROGMEM EISU_Win_combo[] = {
C(KC_Z), KC_BSPC, COMBO_END};
const uint16_t PROGMEM EISU_Mac_combo[] = {
G(KC_Z), KC_BSPC, COMBO_END};
const uint16_t PROGMEM ZERO_combo[] = {
KC_2, KC_3, COMBO_END};
const uint16_t PROGMEM HALF_combo[] = {
KC_5, KC_6, COMBO_END};
const uint16_t PROGMEM FULL_combo[] = {
KC_8, KC_9, COMBO_END};
combo_t key_combos[COMBO_COUNT] = {
[EISU_Win] = COMBO_ACTION(EISU_Win_combo),
[EISU_Mac] = COMBO_ACTION(EISU_Mac_combo),
[FULL_ent] = COMBO_ACTION(FULL_combo),
[HALF_ent] = COMBO_ACTION(HALF_combo),
[ZERO_ent] = COMBO_ACTION(ZERO_combo),
};
// 同時押し本体
void process_combo_event(uint8_t combo_index, bool pressed) {
switch(combo_index) {
case EISU_Win:
if (pressed) {
SEND_STRING(SS_TAP(X_LANG2));
// 英数を発行(レイヤー名などを打ったあと大抵戻っていないので結構必要)
}
break;
case EISU_Mac:
if (pressed) {
SEND_STRING(SS_TAP(X_LANG2));
// 同様
}
break;
case ZERO_ent:
if (pressed) {
SEND_STRING("0"SS_TAP(X_ENTER));
}
break;
case HALF_ent:
if (pressed) {
SEND_STRING("50"SS_TAP(X_ENTER));
}
break;
case FULL_ent:
if (pressed) {
SEND_STRING("100"SS_TAP(X_ENTER));
}
break;
}
}
// KEYMAP 本体//////////////////////////////////////////////////////////////
// 一段目 1,2,3,4, 上のエンコのクリック,
// 二段目 1,2,3,4, 下のエンコのクリック,
// 親指 1,2,3, 4
// エンコーダーの回転はキーマップ以外で定義
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/////Premiere///////////////////
// Basic: 基本的な移動と再生と編集。エンコーダーはタイムラインの拡大と縮小、アンドゥリスト
// In点へ /Alt | Out点へ /Alt | 前の編集点 /Ctl | 次の編集点 /Ctl || Undo (( Save )) Redo
// Copy | Paste | 1F ← /Sft | 1F → /Sft || TL Zoom In(( TL全体 )) TL Zoom Out
// | Undo | BS | 選択/カミソリ || 再生、停止
//
// Edit: 編集
// In点設定 | Out点設定 |前の編集点までカット|次の編集点までカット|| ((このレイヤーでInOut))
// In点クリア | Out点クリア | 5F ← | 5F → || Vol - (( Mute )) Vol +
// | Redo | 全レイヤーに編集点 | 編集点追加 || **ここを押しながら**
//
// Move: 再生や移動選択
// 前のマーカー | 次のマーカー | InOut再生 | 前後を再生 || ((アクティブウィンドウ最大化))
// マーカー消去 | マーク | 巻き戻し | 早送り || ((ネスト(Winのみ)))
// | マッチフレーム | 前方全選択 |**ここを押しながら**|| 後方全選択
//
// 注:LT(),MT()の中のキーは、Basic Keycodesでないといけない制約がある。なのでレイヤーキーの単キーは、単純なキーという縛りがあるよ。
// なので自由にしたいときはたいていコードを書いています。ソースが見にくくてすいません。
///////////////////Windows
// Win Premiere
[_0_Win_P] = LAYOUT(
DHA_L, DHA_R, DHC_L, DHC_R, C(KC_S),
MC_TAP_LTten, C(KC_V), DHS_L, DHS_R, LT(_SPECIAL, KC_JYEN),
C(KC_Z), KC_BSPC, MC_CV_L2, LT(_1_Win_P, KC_SPC)
),
[_1_Win_P] = LAYOUT(
KC_I, KC_O, KC_Q, KC_W, KC_SLSH,
S(C(KC_I)), S(C(KC_O)), S(KC_LEFT), S(KC_RIGHT), KC_MUTE,
S(C(KC_Z)), S(C(KC_K)), C(KC_K), _______
),
[_2_Win_P] = LAYOUT(
S(C(KC_M)), S(KC_M), C(S(KC_SPC)), S(KC_K), KC_LBRC,
C(S(A(KC_M))), KC_M, KC_J, KC_L, MC_CLIP_NEST,
KC_F, MC_SELECTALL_BEFORE, _______, MC_SELECTALL_AFTER
),
/////After Effects///////////////////
// Basic: Premiereと同様、基本的な移動と再生。同じ機能で使えるようにした。
// ワークIn点へ/Alt | ワークOut点へ/Alt| 前の編集点/Ctl | 次の編集点/Ctl || Undo (( Save )) Redo
// Copy | Paste | 1F ← /Sft | 1F → /Sft || TL Zoom In(( TL全体 )) TL Zoom Out
// | Undo | BS | 選択/てのひら || 再生、停止
//
// Edit: レイヤーの編集
// ワークIn点設定 | ワークOut点設定 |Inからここまで消去 |ここからOutまで消去|| ((このレイヤーでInOut))
// Inをここへ移動 | Outをここへ移動 | 5F ← | 5F → || Vol - (( Mute )) Vol +
// | Redo | Dupe | レイヤー分割 || **ここを押しながら**
//
// Tab: タブを開いたり閉じたり
// R 回転タブ | S スケールタブ | P 位置タブ | T 透明度タブ || ((アクティブウィンドウ最大化))
// E エフェクトタブ | M マスクタブ | 前のキーF | 次のキーF || ((プリコンポ―ズ))
// | Uタブ全ひらき、とじ|スナップショット表示|**ここを押しながら**||スナップショット
// // Win AfterEffects
[_0_Win_AE] = LAYOUT(
DHA_L, DHA_R, DHC_L, DHC_R, C(KC_S),
MC_TAP_LTten, C(KC_V), DHS_L, DHS_R, LT(_SPECIAL, KC_SCLN),
C(KC_Z), KC_BSPC, MC_CV_L2, LT(_1_Win_AE, KC_SPC)
),
[_1_Win_AE] = LAYOUT(
KC_B, KC_N, A(KC_RBRC), A(KC_BSLS), C(A(KC_B)),
KC_RBRC, KC_BSLS, MC_L5, MC_R5, KC_MUTE,
S(C(KC_Z)), C(KC_D), C(S(KC_D)), _______
),
[_2_Win_AE] = LAYOUT(
KC_R, KC_S, KC_P, KC_T, KC_LBRC,
KC_E, KC_M, KC_J, KC_K, C(S(KC_C)),
KC_U, KC_F5, _______, S(KC_F5)
),
/////////////////////Mac
// Mac Premiere
[_0_Mac_P] = LAYOUT(
DHA_L, DHA_R, DHC_L, DHC_R, G(KC_S),
MC_TAP_LTten, G(KC_V), DHS_L, DHS_R, LT(_SPECIAL, KC_JYEN),
G(KC_Z), KC_BSPC, MC_CV_L2, LT(_1_Mac_P, KC_SPC)
),
[_1_Mac_P] = LAYOUT(
KC_I, KC_O, KC_Q, KC_W, KC_SLSH,
S(G(KC_I)), S(G(KC_O)), S(KC_LEFT), S(KC_RIGHT), KC_MUTE,
S(G(KC_Z)), S(G(KC_K)), G(KC_K), _______
),
[_2_Mac_P] = LAYOUT(
S(G(KC_M)), S(KC_M), A(KC_K), S(KC_K), KC_LBRC,
G(S(A(KC_M))), KC_M, KC_J, KC_L, _______,
KC_F, MC_SELECTALL_BEFORE, _______, MC_SELECTALL_AFTER
),
// Macにはネスト化がないです。Winは強引にAlt、C、Nと強引にコマンドをおしているため
// InOut再生だけWinとMacでショートカットが違う Win C(S(KC_SPC)) Mac A(KC_K)
// Mac AfterEffects
[_0_Mac_AE] = LAYOUT(
DHA_L, DHA_R, DHC_L, DHC_R, G(KC_S),
MC_TAP_LTten, G(KC_V), DHS_L, DHS_R, LT(_SPECIAL, KC_SCLN),
G(KC_Z), KC_BSPC, MC_CV_L2, LT(_1_Mac_AE, KC_SPC)
),
[_1_Mac_AE] = LAYOUT(
KC_B, KC_N, A(KC_RBRC), A(KC_BSLS), G(A(KC_B)),
KC_RBRC, KC_BSLS, MC_L5, MC_R5, KC_MUTE,
S(G(KC_Z)), G(KC_D), G(S(KC_D)), _______
),
[_2_Mac_AE] = LAYOUT(
KC_R, KC_S, KC_P, KC_T, KC_LBRC,
KC_E, KC_M, KC_J, KC_K, G(S(KC_C)),
KC_U, KC_F5, _______, S(KC_F5)
),
/////// Win/Mac Premiere/After Effects切り替え
[_SPECIAL] = LAYOUT(
XXXXXXX, XXXXXXX, MC_Mac_AE, MC_Mac_P, XXXXXXX,
MC_Mac_AE, MC_Mac_P, MC_Win_AE, MC_Win_P, _______,
XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX
),
// テンキー
[_ten] = LAYOUT(
KC_ENTER, KC_7, KC_8, KC_9, KC_DOT,
_______, KC_4, KC_5, KC_6, KC_MINUS,
KC_1, KC_2, KC_3, KC_0
),
};
//////////////////////
// エンコーダ― Mac/Win, Premiere/AfterEffectsでキーバインド切り替える
// 上のエンコーダー
// 右に回したとき
// フラグで場合わけ
// 左に回したとき
// フラグで場合わけ
// 下のエンコーダー、以下同様
// フラグで場合わけして、エンコーダーで場合わけして、左右で場合分けしたほうが分かりやすかったかも
void encoder_update_user(uint8_t index, bool clockwise) {
if (index == 0) {
// 上のエンコーダ―(P/AEで、Undo/Redo共通)
// 右に回したとき
if (clockwise) {
if (layer_state_is(_ten)) {
// テンキーのときには上
SEND_STRING(SS_TAP(X_UP));
} else {
// それ以外はRedo
if (Win_or_Mac) {
// win
SEND_STRING(SS_LSFT(SS_LCTL(SS_TAP(X_Z))));
} else {
// mac
SEND_STRING(SS_LSFT(SS_LGUI(SS_TAP(X_Z))));
}
}
} else {
// 左に回したとき
if (layer_state_is(_ten)) {
// テンキーのときには下
SEND_STRING(SS_TAP(X_DOWN));
} else {
// それ以外はUndo
if (Win_or_Mac) {
// win
SEND_STRING(SS_LCTL(SS_TAP(X_Z)));
} else {
// mac
SEND_STRING(SS_LGUI(SS_TAP(X_Z)));
}
}
}
} else if (index == 1) {
//////////
//下のエンコーダー
// 右に回したとき
if (clockwise) {
if (layer_state_is(_ten)) {
// テンキーのときにはシフト上
SEND_STRING(SS_LSFT(SS_TAP(X_UP)));
// レイヤーなどで場合分け
} else if (layer_state_is(_1_Win_P) ==1 || layer_state_is(_1_Win_AE) ==1 || layer_state_is(_1_Mac_P) ==1 || layer_state_is(_1_Mac_AE) ==1) {
// Layer 1 ON (Win/Mac, P/AE)で Vol+
SEND_STRING(SS_TAP(X_VOLU));
} else {
// タイムラインの拡大縮小PremiereとAfterでバインドがちがう!!!
if (P_or_AE) {
///// Premiere 日本語の:キーをUSで打っているので。
SEND_STRING("'");
} else {
////// AfterEffects 日本語の^キーをUSで打っているので。
SEND_STRING("=");
}
}
// 左に回したとき
} else {
if (layer_state_is(_ten)) {
// テンキーのときにはシフト下
SEND_STRING(SS_LSFT(SS_TAP(X_DOWN)));
// レイヤーなどで場合分け
} else if (layer_state_is(_1_Win_P) ==1 || layer_state_is(_1_Win_AE) ==1 || layer_state_is(_1_Mac_P) ==1 || layer_state_is(_1_Mac_AE) ==1) {
// Layer 1 ON (Win/Mac, P/AE)で Vol-
SEND_STRING(SS_TAP(X_VOLD));
} else {
// タイムラインの拡大縮小(Win/Mac)
///// Premiere, After ともに-バインド
SEND_STRING("-");
}
}
}
}
// Macros ///////////////////////////////////////////
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
// 何かを押されるごとにキーカウンターを1増やす(リセットされるのはCVキーを押したときのみ)
if (record->event.pressed) {
key_count = key_count + 1;
}
switch (keycode) {
/////////////////////////////////////////////////
// Win/Mac, Premiere/AfterEffectsのレイヤーの切り替え
/////////////////////////////////////////////////
case MC_Win_P:
if (record->event.pressed) {
layer_clear();
//Windows/Premiereはベースレイヤーなのでクリアするだけでよい
// もしベースレイヤーを変更したら以下を生かしてね
// layer_on(_0_Win_P);
Win_or_Mac = true;
P_or_AE = true;
}
break;
case MC_Win_AE:
if (record->event.pressed) {
layer_clear();
layer_on(_0_Win_AE);
Win_or_Mac = true;
P_or_AE = false;
}
break;
case MC_Mac_P:
if (record->event.pressed) {
layer_clear();
layer_on(_0_Mac_P);
Win_or_Mac = false;
P_or_AE = true;
}
break;
case MC_Mac_AE:
if (record->event.pressed) {
layer_clear();
layer_on(_0_Mac_AE);
Win_or_Mac = false;
P_or_AE = false;
}
break;
/////////////////////////////////////////////////
/////////////////////////////////////////////////
// Afterで5F戻るマクロ
case MC_L5:
if (record->event.pressed) {
SEND_STRING(SS_TAP(X_PGUP));
SEND_STRING(SS_TAP(X_PGUP));
SEND_STRING(SS_TAP(X_PGUP));
SEND_STRING(SS_TAP(X_PGUP));
SEND_STRING(SS_TAP(X_PGUP));
}
break;
// Afterで5F戻るマクロ
case MC_R5:
if (record->event.pressed) {
SEND_STRING(SS_TAP(X_PGDOWN));
SEND_STRING(SS_TAP(X_PGDOWN));
SEND_STRING(SS_TAP(X_PGDOWN));
SEND_STRING(SS_TAP(X_PGDOWN));
SEND_STRING(SS_TAP(X_PGDOWN));
}
break;
///// クリップのネスト
case MC_CLIP_NEST:
if (record->event.pressed) {
// クリップのネスト化、強引にAlt, C, Nとコマンドを押しているだけなので、Macではできない
// 間に空ループ入れて早すぎないように。
SEND_STRING(SS_TAP(X_LALT));
while (timer_elapsed(record->event.time) <= 100) {}
SEND_STRING(SS_TAP(X_C));
while (timer_elapsed(record->event.time) <= 100) {}
SEND_STRING(SS_TAP(X_N));
}
break;
// 後方選択、前方選択ツールを使ったあと、次に必ず選択ツールになるようにフラグを立てるマクロ
case MC_SELECTALL_AFTER:
if (record->event.pressed) {
SEND_STRING(SS_TAP(X_A));
V_toggle = false;
}
break;
case MC_SELECTALL_BEFORE:
if (record->event.pressed) {
SEND_STRING(SS_LSFT(SS_TAP(X_A)));
V_toggle = false;
}
break;
//////////////////////////////////////
//////////////////////////////////////
//////////////////////////////////////
// 単打で何か、押しっぱなしでレイヤーキーになる
// C/Vの切り替え /レイヤー2
case MC_CV_L2:
if (record->event.pressed) {
key_count = 0;
// とりあえずレイヤー2をオンにする
if (Win_or_Mac) {
if (P_or_AE) {
layer_on(_2_Win_P);
} else {
layer_on(_2_Win_AE);
}
} else {
if (P_or_AE) {
layer_on(_2_Mac_P);
} else {
layer_on(_2_Mac_AE);
}
}
} else {
// レイヤー2をオフ
if (Win_or_Mac) {
if (P_or_AE) {
layer_off(_2_Win_P);
} else {
layer_off(_2_Win_AE);
}
} else {
if (P_or_AE) {
layer_off(_2_Mac_P);
} else {
layer_off(_2_Mac_AE);
}
}
// 離された時点で他のキーを押していないなら単打と判断
if (key_count == 0) {
if (P_or_AE) {
//V(選択)とC(カミソリ)をトグル Permiere
if (V_toggle) {
SEND_STRING(SS_TAP(X_C));
V_toggle = false;
} else {
SEND_STRING(SS_TAP(X_V));
V_toggle = true;
}
} else {
//V(選択)とH(手のひら)をトグル After
if (V_toggle) {
SEND_STRING(SS_TAP(X_H));
V_toggle = false;
} else {
SEND_STRING(SS_TAP(X_V));
V_toggle = true;
}
}
}
}
break;
// Copy /テンキーレイヤー
case MC_TAP_LTten:
if (record->event.pressed) {
key_count = 0;
layer_on(_ten);
// 押されたらとりあえずテンキーをオンにしておく
} else {
layer_off(_ten);
// 離された時点で他のキーを押していないなら単打と判断
if (key_count == 0) {
// Copy
if (Win_or_Mac) {
SEND_STRING(SS_LCTL(SS_TAP(X_C)));
} else {
SEND_STRING(SS_LGUI(SS_TAP(X_C)));
}
}
}
break;
/////////////////////////////////////////////////
// ダブルホールドキー 単打でいろいろ、両方押したらモデファイアになるもの
/////////////////////////////////////////////////
//////////////////
case DHS_L:
if (record->event.pressed) {
// 押したとき
SL_on = true;
///// R側も押されていたらShift発行
if (SR_on) {
SEND_STRING(SS_DOWN(X_LSHIFT));
Double_Hold = true;
}
} else {
// 離したとき
SL_on = false;
if (CR_on) {
// もう一方がまだ押されているなら何もしない
} else {
// もう一方は今オフ、ダブルホールドがあったか単押しかで場合分け
if (Double_Hold) {
SEND_STRING(SS_UP(X_LSHIFT));
Double_Hold = false;
} else {
// 単押し、単離し
// 前1F移動
if (P_or_AE) {
SEND_STRING(SS_TAP(X_LEFT));
} else {
SEND_STRING(SS_TAP(X_PGUP));
}
}
}
}
break;
case DHS_R:
if (record->event.pressed) {
// 押したとき
SR_on = true;
///// L側も押されていたらShift発行
if (SL_on) {
SEND_STRING(SS_DOWN(X_LSHIFT));
Double_Hold = true;
}
} else {
// 離したとき
SR_on = false;
if (SL_on) {
// もう一方がまだ押されているなら何もしない
} else {
// もう一方は今オフ、ダブルホールドがあったか単押しかで場合分け
if (Double_Hold) {
SEND_STRING(SS_UP(X_LSHIFT));
Double_Hold = false;
} else {
// 単押し、単離し
// あと1F移動
if (P_or_AE) {
SEND_STRING(SS_TAP(X_RIGHT));
} else {
SEND_STRING(SS_TAP(X_PGDOWN));
}
}
}
}
break;
//////////////////
case DHC_L:
if (record->event.pressed) {
// 押したとき
CL_on = true;
///// R側も押されていたらCtrl発行
if (CR_on) {
SEND_STRING(SS_DOWN(X_LCTRL));
Double_Hold = true;
}
} else {
// 離したとき
CL_on = false;
if (CR_on) {
// もう一方がまだ押されているなら何もしない
} else {
// もう一方は今オフ、ダブルホールドがあったか単押しかで場合分け
if (Double_Hold) {
SEND_STRING(SS_UP(X_LCTRL));
Double_Hold = false;
} else {
// 単押し、単離し
// 前の編集点へ P KC_UP / AE C(S(A(KC_LEFT)))
if (P_or_AE) {
SEND_STRING(SS_TAP(X_UP));
} else {
if (Win_or_Mac) {
SEND_STRING(SS_LCTL(SS_LSFT(SS_LALT(SS_TAP(X_LEFT)))));
} else {
SEND_STRING(SS_LGUI(SS_LSFT(SS_LALT(SS_TAP(X_LEFT)))));
}
}
}
}
}
break;
case DHC_R:
if (record->event.pressed) {
// 押したとき
CR_on = true;
///// L側も押されていたらCTRL発行
if (CL_on) {
SEND_STRING(SS_DOWN(X_LCTRL));
Double_Hold = true;
}
} else {
// 離したとき
CR_on = false;
if (CL_on) {
// もう一方がまだ押されているなら何もしない
} else {
// もう一方は今オフ、ダブルホールドがあったか単押しかで場合分け
if (Double_Hold) {
SEND_STRING(SS_UP(X_LCTRL));
Double_Hold = false;
} else {
// 単押し、単離し
// 次の編集点へ P KC_DOWN / AE C(S(A(KC_RIGHT)))
if (P_or_AE) {
SEND_STRING(SS_TAP(X_DOWN));
} else {
if (Win_or_Mac) {
SEND_STRING(SS_LCTL(SS_LSFT(SS_LALT(SS_TAP(X_RIGHT)))));
} else {
SEND_STRING(SS_LGUI(SS_LSFT(SS_LALT(SS_TAP(X_RIGHT)))));
}
}
}
}
}
break;
///////////////////
case DHA_L:
if (record->event.pressed) {
// 押したとき
AL_on = true;
///// R側も押されていたらAlt発行
if (AR_on) {
SEND_STRING(SS_DOWN(X_LALT));
Double_Hold = true;
}
} else {
// 離したとき
AL_on = false;
if (AR_on) {
// もう一方がまだ押されているなら何もしない
} else {
// もう一方は今オフ、ダブルホールドがあったか単押しかで場合分け
if (Double_Hold) {
SEND_STRING(SS_UP(X_LALT));
SEND_STRING(SS_TAP(X_LALT));
// ただupすると単押しALTが発動するのでタップしてオフっておく
Double_Hold = false;
} else {
// 単押し、単離し
// 現在のアクティブレイヤーによって処理を場合わけ
// In点へ移動(P)、ワークエリアIn点へ移動(AE)
if (P_or_AE) {
SEND_STRING(SS_LSFT(SS_TAP(X_I)));
} else {
SEND_STRING(SS_LSFT(SS_TAP(X_HOME)));
}
}
}
}
break;
case DHA_R:
if (record->event.pressed) {
// 押したとき
AR_on = true;
///// R側も押されていたらAlt発行
if (AL_on) {
SEND_STRING(SS_DOWN(X_LALT));
Double_Hold = true;
}
} else {
// 離したとき
AR_on = false;
if (AL_on) {
// もう一方がまだ押されているなら何もしない
} else {
// もう一方は今オフ、ダブルホールドがあったか単押しかで場合分け
if (Double_Hold) {
SEND_STRING(SS_UP(X_LALT));
SEND_STRING(SS_TAP(X_LALT));
// ただupすると単押しALTが発動するのでタップしてオフっておく
Double_Hold = false;
} else {
// 単押し、単離し
// 現在のアクティブレイヤーによって処理を場合わけ
// Out点へ移動(P)、ワークエリアOut点へ移動(AE)
if (P_or_AE) {
SEND_STRING(SS_LSFT(SS_TAP(X_O)));
} else {
SEND_STRING(SS_LSFT(SS_TAP(X_END)));
}
}
}
}
break;
}
return true;
};