rkremap 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 04a75325e18cfa14e1eeb93462af309c6d692083c5ef4a2609e6dfd53747a6c8
4
- data.tar.gz: 1f86fc05c3098eed25b0d09bbebfc75fdad37122898ee9762376ce5241f21c60
3
+ metadata.gz: 6476d10293c91c5afb744c6ebe1162d26ab253ad06aade6f5f2568db05bb7631
4
+ data.tar.gz: 35fd73d5a2d71ca797fd626397a789e8f22b5bd54cfa2ef0ca08f46adc6efa7f
5
5
  SHA512:
6
- metadata.gz: 3874c3c1a1c9b78a82faf4c3ceb40f28e1d9d5f1380a8ac3f604ffc904f2dcb4099db5b84f2f9542ae4d104ac8f242f4edd8060c8da0aa4f65e8ddc472a4cab2
7
- data.tar.gz: f9700cd0991fb27fa03de2a402dd1bfebe0f23cc35d128b5b35ca9115608988ce2f1aeea55cd8525a3c645e1b4a465b0aa0995703e4cb0b58f73bdb7e2efda3f
6
+ metadata.gz: bdf4f1364db8aa24dc49dab823e4f16200994058a6ff8d8e3323272d0783139af49f6fcdbb7f22b573dab92554d39d92429d24aa7b5fedf80e27139cf62bd120
7
+ data.tar.gz: d868e6b7af37edfa90324014669ff7de5595f392116bedeaf011cf95cd49ce9621782f1dda6e402c4e6117509ae0a0337322447028975ab743324da318479d0b
data/README.md CHANGED
@@ -22,8 +22,11 @@ KERNEL=="uinput", GROUP="input"
22
22
  ```
23
23
  という内容で作れば `/dev/uinput` のグループを `input` にできるっぽい。
24
24
 
25
+ `$VERBOSE` が真の場合はデバイスを検出したときと切断を検出したときにデバイス名を標準出力に出力する。
25
26
 
26
- ### `Rkremap.new`
27
+ ## Rkremap
28
+
29
+ ### Rkremap.new
27
30
 
28
31
  引数を指定しなければ自動的にキーボードデバイスの検出を試みる。
29
32
 
@@ -40,9 +43,28 @@ sudo evtest /dev/input/eventX
40
43
 
41
44
  ThinkPad 本体のキーボードは `/dev/input/event3` だった。
42
45
 
46
+ ### Rkremap#exclude
47
+
48
+ 無視するデバイス名を正規表現で指定できる。
49
+
50
+
51
+ ```ruby
52
+ rkremap.exclude = /touchpad/i
53
+ ```
54
+
55
+ ### Rkremap#mouse
56
+
57
+ 真を指定するとマウスも対象にする。
58
+
43
59
  ### Rkremap#grab
44
60
 
45
- `true` に設定するとキーイベントを奪う。キーイベントを見るだけでいいなら `false` を設定する。
61
+ `true` を設定するとキーイベントを奪う。キーイベントを見るだけでいいなら `false` を設定する。
62
+
63
+ `:keyboard` を設定するとキーボードデバイスを grab する。
64
+
65
+ `:mouse` を設定するとマウスデバイスを grab する。
66
+
67
+ 正規表現を設定するとデバイス名がマッチした場合にデバイスを grab する。
46
68
 
47
69
  ### Rkremap#x11
48
70
 
@@ -52,7 +74,7 @@ ThinkPad 本体のキーボードは `/dev/input/event3` だった。
52
74
 
53
75
  修飾キーの一覧。これらのキーは単体で押されただけでは `start` ブロックを実行しない。
54
76
 
55
- ### auto_detect
77
+ ### Rkremap#auto_detect
56
78
 
57
79
  `true` の場合はキーボードデバイスの接続を自動検知する。
58
80
  `new` 時にデバイスファイルが指定されない場合は `true` になる。
@@ -65,13 +87,27 @@ ThinkPad 本体のキーボードは `/dev/input/event3` だった。
65
87
 
66
88
  ### Rkremap#match
67
89
 
68
- キーイベントが引数に適合するとブロックを実行する。ブロック引数は Event オブジェクト。
69
- `Event#skip` するとこのイベントはスキップされる。
90
+ キーイベントが引数に適合するとブロックを実行する。ブロック引数は `Rkremap::Event` オブジェクト。
91
+ `Rkremap::Event#skip` するとこのイベントはスキップされる。
92
+
93
+ 複数回指定した場合は記述順に実行される。
70
94
 
71
95
  ### Rkremap#key
72
96
 
73
97
  キーを押したことにする。引数はキーコード(`Integer`)と修飾キー(`Hash`)。
74
98
 
99
+ 修飾キーのハッシュのキーはキーコード(`KEY_LEFTCTRL` 等)、値は `true`, または `false`。
100
+
101
+ ```ruby
102
+ {
103
+ KEY_LEFTSHIFT => false,
104
+ KEY_LEFTCTRL => true,
105
+ }
106
+ ```
107
+
108
+ と指定すると、左シフトは離した状態、左Ctrlは押した状態、それ以外の修飾キーはそのまま。
109
+ `#key()` 処理後は処理前の修飾キーの状態に戻る。
110
+
75
111
  ### Rkremap#event
76
112
 
77
113
  キーイベントを発生させる。`code` 引数はキーコード(`Integer`)。`type` 引数はイベントタイプ(`Symbol`)で `:press`, `:release`。
@@ -84,6 +120,34 @@ ThinkPad 本体のキーボードは `/dev/input/event3` だった。
84
120
 
85
121
  コードからキー名のシンボルに変換するための Hash。
86
122
 
123
+ ## Rkremap::Event
124
+
125
+ ### Rkremap::Event#code
126
+
127
+ キーコード。`Rkremap::KeyCode::KEY_*` に該当。
128
+
129
+ ### Rkremap::Event#type
130
+
131
+ イベントタイプ。 `:press`, `:release`, `:repeat` のいずれか。
132
+
133
+ ### Rkremap::Event#app
134
+
135
+ `Rkremap::App`。イベントが発生したアプリケーション。
136
+
137
+ ### Rkremap::Event#skip
138
+
139
+ このイベントをこれ以降処理しない。
140
+
141
+ ## Rkremap::App
142
+
143
+ ### Rkremap::App#class_name
144
+
145
+ アプリケーションのクラス名。
146
+
147
+ ### Rkremap::App#title
148
+
149
+ アプリケーションのタイトル。
150
+
87
151
  ## 参考
88
152
 
89
153
  * [mooz/xkeysnail: Yet another keyboard remapping tool for X environment](https://github.com/mooz/xkeysnail)
@@ -0,0 +1,52 @@
1
+ # 変換/無変換キーを0.5秒以上押してるとSUPERキーとして扱う。
2
+ # 0.5秒以内でも変換/無変換キーを押しながら他のキーを押すとSUPERキーとして扱う。
3
+
4
+ require 'rkremap'
5
+ require 'tmtms_timer'
6
+
7
+ include Rkremap::KeyCode
8
+
9
+ rk = Rkremap.new
10
+ rk.grab = true
11
+
12
+ timer = Tmtms::Timer.new
13
+ jobs = {
14
+ KEY_HENKAN => nil,
15
+ KEY_MUHENKAN => nil,
16
+ }
17
+
18
+ henkan_map = {
19
+ KEY_HENKAN => KEY_RIGHTMETA,
20
+ KEY_MUHENKAN => KEY_RIGHTMETA, # LEFTMETA だとデスクトップ環境のメニューが開いたりするため
21
+ }
22
+
23
+ rk.match(code: [KEY_HENKAN, KEY_MUHENKAN]) do |event|
24
+ if event.type == :press
25
+ job = timer.set(0.5) do
26
+ rk.synchronize do
27
+ rk.event(code: henkan_map[event.code], type: :press)
28
+ end
29
+ end
30
+ jobs[event.code] = job
31
+ elsif event.type == :release
32
+ if jobs[event.code]&.cancel # 0.5秒以内に離された
33
+ rk.key(event.code)
34
+ else
35
+ rk.event(code: henkan_map[event.code], type: :release)
36
+ end
37
+ end
38
+ event.skip
39
+ end
40
+
41
+ # 何かキーが押されたときに HENKAN, MUHENKAN が押されてれば SUPER が押されてることにする
42
+ rk.match(type: :press) do
43
+ [KEY_HENKAN, KEY_MUHENKAN].each do |code|
44
+ if jobs[code]&.cancel # 0.5秒以内
45
+ rk.event(code: henkan_map[code], type: :press)
46
+ end
47
+ end
48
+ end
49
+
50
+ rk.start do |code, mod|
51
+ rk.key(code, mod)
52
+ end
data/example/keylogger.rb CHANGED
@@ -6,9 +6,9 @@ def code2key(code)
6
6
  Rkremap::CODE_KEY[code].to_s.sub(/\AKEY_/, '')
7
7
  end
8
8
 
9
- rk = Rkremap.new
9
+ rk = Rkremap.new(*ARGV)
10
10
  rk.grab = false
11
- rk.x11 = true
11
+ rk.x11 = true if ENV['DISPLAY']
12
12
  rk.start do |code, mod, app|
13
13
  key = (mod.select{|_, v| v}.keys + [code]).map{|c| code2key(c)}.join('-')
14
14
  key << " at #{app.title} [#{app.class_name}]" if rk.x11
@@ -36,39 +36,82 @@ mod_disable_all = {}.merge(mod_disable_ctrl, mod_disable_shift, mod_disable_alt,
36
36
  rk = Rkremap.new
37
37
  rk.grab = true
38
38
  rk.x11 = true
39
- rk.start do |code, mod, app|
40
- # Emacs や端末等ではそのまま
41
- if app.class_name == 'Emacs' || app.class_name =~ /terminal/i || app.class_name == 'VirtualBox Machine'
39
+
40
+ # Emacs や VirtualBox ではそのまま
41
+ rk.match(app: /Emacs|VirtualBox Machine/) do |event|
42
+ rk.event(code: event.code, type: event.type)
43
+ event.skip
44
+ end
45
+
46
+ # 端末
47
+ rk.match(app: /terminal/i) do |event, mod|
48
+ # Super+Ctrl はそのまま
49
+ if (mod[KEY_LEFTMETA] || mod[KEY_RIGHTMETA]) && (mod[KEY_LEFTCTRL] || mod[KEY_RIGHTCTRL])
50
+ rk.event(code: event.code, type: event.type)
51
+ # Super+0/Minus は Ctrl+0/Minus に変換
52
+ elsif (mod[KEY_LEFTMETA] || mod[KEY_RIGHTMETA]) && Rkremap::CODE_KEY[event.code] =~ /\AKEY_(0|MINUS)\z/
53
+ rk.with_modifier(mod_disable_all.merge(KEY_LEFTCTRL => true)) do
54
+ rk.event(code: event.code, type: event.type)
55
+ end
56
+ # Super+KEY は Ctrl+Shift+KEY に変換
57
+ elsif (mod[KEY_LEFTMETA] || mod[KEY_RIGHTMETA]) && Rkremap::CODE_KEY[event.code] =~ /\AKEY_([A-Z]|EQUAL)\z/
58
+ rk.with_modifier(mod_disable_meta.merge(KEY_LEFTCTRL => true, KEY_LEFTSHIFT => true)) do
59
+ rk.event(code: event.code, type: event.type)
60
+ end
61
+ # それ以外はそのまま
62
+ else # rubocop:disable Lint/DuplicateBranch
63
+ rk.event(code: event.code, type: event.type)
64
+ end
65
+ event.skip
66
+ end
67
+
68
+ # その他のウィンドウ
69
+ rk.start do |code, mod|
70
+ # Super + Ctrl + 何か はそのまま
71
+ if (mod[KEY_LEFTMETA] || mod[KEY_RIGHTMETA]) && (mod[KEY_LEFTCTRL] || mod[KEY_RIGHTCTRL])
42
72
  rk.key(code, mod)
43
73
  next
44
74
  end
45
75
 
46
- # ALT+[A-Z]/Enter を Ctrl+[A-Z]/Enter に変換
47
- if (mod[KEY_LEFTALT] || mod[KEY_RIGHTALT]) && (Rkremap::CODE_KEY[code] =~ /\AKEY_[A-Z]\z/ || code == KEY_ENTER)
48
- mod.merge!(mod_disable_alt, {KEY_LEFTCTRL => true})
49
- mod[KEY_LEFTCTRL] = true
50
- rk.key(code, mod)
76
+ # Super+[A-Z]/Minus/Equal/Enter を Ctrl+[A-Z]/Minus/Equal/Enter に変換
77
+ if (mod[KEY_LEFTMETA] || mod[KEY_RIGHTMETA]) && (Rkremap::CODE_KEY[code] =~ /\AKEY_([0-9A-Z]|MINUS|EQUAL|ENTER)\z/)
78
+ rk.key(code, mod.merge(mod_disable_meta, KEY_LEFTCTRL => true))
79
+ next
80
+ end
81
+
82
+ # Alt + F, B は Ctrl + →, ← に変換
83
+ if (mod[KEY_LEFTALT] || mod[KEY_RIGHTALT]) && (code == KEY_F || code == KEY_B)
84
+ rk.key(code == KEY_F ? KEY_RIGHT : KEY_LEFT, mod.merge(mod_disable_alt, KEY_LEFTCTRL => true))
51
85
  next
52
86
  end
53
87
 
54
88
  # Ctrl は他のキーに変換
55
89
  if mod[KEY_LEFTCTRL] || mod[KEY_RIGHTCTRL]
90
+ # Ctrl+I/O はそのまま
91
+ if code == KEY_I || code == KEY_O
92
+ rk.key(code, mod)
93
+ next
94
+ end
95
+
56
96
  # Ctrl+K は行末まで削除
57
97
  if code == KEY_K
58
- rk.key(KEY_END, mod_disable_all.merge({KEY_LEFTSHIFT => true}))
59
- rk.key(KEY_X, mod_disable_all.merge({KEY_LEFTCTRL => true}))
98
+ rk.key(KEY_END, mod_disable_all.merge(KEY_LEFTSHIFT => true)) # SHIFT+END
99
+ rk.key(KEY_X, mod_disable_all.merge(KEY_LEFTCTRL => true)) # Ctrl+X
60
100
  next
61
101
  end
102
+
62
103
  # 単純な変換
63
104
  if ctrl_map[code]
64
- rk.key(ctrl_map[code], mod_disable_ctrl)
105
+ rk.key(ctrl_map[code], mod.merge(mod_disable_ctrl))
65
106
  next
66
107
  end
108
+
67
109
  # その他の Ctrl+[A-Z] は無視
68
110
  if Rkremap::CODE_KEY[code] =~ /\AKEY_[A-Z]\z/
69
111
  next
70
112
  end
71
113
  end
72
114
 
115
+ # それ以外はそのまま
73
116
  rk.key(code, mod)
74
117
  end
data/example/tmtms.rb CHANGED
@@ -1,107 +1,69 @@
1
1
  # tmtms 用
2
2
 
3
3
  require 'rkremap'
4
- include Rkremap::KeyCode
5
-
6
- class State
7
- attr_accessor :converted
8
-
9
- def initialize
10
- @press = nil
11
- @converted = false
12
- @thread = nil
13
- end
14
-
15
- def press(thread)
16
- @press = true
17
- @converted = false
18
- @thread = thread
19
- end
20
-
21
- def release
22
- @press = false
23
- @converted = false
24
- @thread.kill
25
- @thread = nil
26
- end
4
+ require 'tmtms_timer'
27
5
 
28
- def pressed?
29
- @press
30
- end
31
- end
6
+ include Rkremap::KeyCode
32
7
 
33
- rk = Rkremap.new
8
+ rk = Rkremap.new(*ARGV, mouse: true, exclude: /touchpad/i)
34
9
  rk.grab = true
35
10
  rk.x11 = true
36
11
 
37
- # 変換/無変換キーを0.5秒以上押してるとALTキーとして扱う。
38
- # 0.5秒以内でも変換/無変換キーを押しながら他のキーを押すとALTキーとして扱う。
12
+ until system "xinput | grep -q rkremap"
13
+ sleep 0.1
14
+ end
15
+ system "xinput set-prop pointer:rkremap 'libinput Scroll Method Enabled' 0 0 1"
39
16
 
40
- state = {
41
- KEY_HENKAN => State.new,
42
- KEY_MUHENKAN => State.new,
17
+ # HENKAN, MUHENKAN を 0.5秒以上押したら SUPER とする
18
+ timer = Tmtms::Timer.new
19
+ jobs = {
20
+ KEY_HENKAN => nil,
21
+ KEY_MUHENKAN => nil,
43
22
  }
44
23
 
45
24
  henkan_map = {
46
- KEY_HENKAN => KEY_RIGHTALT,
47
- KEY_MUHENKAN => KEY_LEFTALT,
25
+ KEY_HENKAN => KEY_RIGHTMETA,
26
+ KEY_MUHENKAN => KEY_RIGHTMETA, # LEFTMETA だとデスクトップ環境のメニューが開いたりするため
48
27
  }
49
28
 
50
- rk.match(code: [KEY_HENKAN, KEY_MUHENKAN], type: :press) do |event|
51
- thr = Thread.new(event.code) do |code|
52
- sleep 0.5
53
- rk.synchronize do
54
- if state[code].pressed?
55
- rk.event(code: henkan_map[code], type: :press)
56
- state[code].converted = true
29
+ rk.match(code: [KEY_HENKAN, KEY_MUHENKAN]) do |event|
30
+ if event.type == :press
31
+ job = timer.set(0.5) do
32
+ rk.synchronize do
33
+ rk.event(code: henkan_map[event.code], type: :press)
57
34
  end
58
35
  end
36
+ jobs[event.code] = job
37
+ elsif event.type == :release
38
+ if jobs[event.code]&.cancel # 0.5秒以内に離された
39
+ rk.key(event.code)
40
+ else
41
+ rk.event(code: henkan_map[event.code], type: :release)
42
+ end
59
43
  end
60
- state[event.code].press(thr)
61
- event.skip
62
- end
63
-
64
- rk.match(code: [KEY_HENKAN, KEY_MUHENKAN], type: :release) do |event|
65
- if state[event.code].converted
66
- rk.event(code: henkan_map[event.code], type: :release)
67
- event.skip
68
- else
69
- rk.event(code: event.code, type: :press)
70
- rk.event(code: event.code, type: :release)
71
- end
72
- state[event.code].release
73
- end
74
-
75
- rk.match(code: [KEY_HENKAN, KEY_MUHENKAN], type: :repeat) do |event|
76
44
  event.skip
77
45
  end
78
46
 
47
+ # 何かキーが押されたときに HENKAN, MUHENKAN が押されてれば SUPER が押されてることにする
79
48
  rk.match(type: :press) do
80
49
  [KEY_HENKAN, KEY_MUHENKAN].each do |code|
81
- if state[code].pressed?
50
+ if jobs[code]&.cancel # 0.5秒以内
82
51
  rk.event(code: henkan_map[code], type: :press)
83
- state[code].converted = true
84
52
  end
85
53
  end
86
54
  end
87
55
 
56
+ # マウスボタンイベントはそのまま
57
+ rk.match(device: :mouse) do |event|
58
+ rk.event(code: event.code, type: event.type)
59
+ event.skip
60
+ end
61
+
88
62
  # CAPSLOCK は CTRL に変換
89
63
  rk.match(code: KEY_CAPSLOCK) do |event|
90
- rk.event(code: KEY_LEFTCTRL, type: event.type)
91
- event.skip
64
+ event.code = KEY_LEFTCTRL
92
65
  end
93
66
 
94
- ctrl_map = {
95
- KEY_A => KEY_HOME,
96
- KEY_E => KEY_END,
97
- KEY_B => KEY_LEFT,
98
- KEY_F => KEY_RIGHT,
99
- KEY_N => KEY_DOWN,
100
- KEY_P => KEY_UP,
101
- KEY_D => KEY_DELETE,
102
- KEY_H => KEY_BACKSPACE,
103
- KEY_I => KEY_TAB,
104
- }
105
67
  mod_disable_ctrl = {
106
68
  KEY_LEFTCTRL => false,
107
69
  KEY_RIGHTCTRL => false,
@@ -120,56 +82,107 @@ mod_disable_meta = {
120
82
  }
121
83
  mod_disable_all = {}.merge(mod_disable_ctrl, mod_disable_shift, mod_disable_alt, mod_disable_meta)
122
84
 
85
+ # JISキーボードを英語配列にしたときに一部キーを変える
123
86
  key_map = {
124
87
  KEY_YEN => KEY_BACKSLASH,
125
88
  KEY_BACKSLASH => KEY_GRAVE,
126
89
  KEY_GRAVE => KEY_ESC,
127
90
  }
91
+ rk.match do |event, mod|
92
+ event.code = key_map[event.code] || event.code
93
+ # RO キーは「\」(SHIFTキーを押してる場合は「_」)
94
+ if event.code == KEY_RO
95
+ event.code = (mod[KEY_LEFTSHIFT] || mod[KEY_RIGHTSHIFT]) ? KEY_MINUS : KEY_BACKSLASH
96
+ end
97
+ end
98
+
99
+ # Emacs や VirtualBox ではそのまま
100
+ rk.match(app: /Emacs|VirtualBox Machine/) do |event|
101
+ rk.event(code: event.code, type: event.type)
102
+ event.skip
103
+ end
128
104
 
129
- rk.start do |code, mod, app|
130
- # JISキーボードを英語配列にしたときに一部キーを変える
131
- code = key_map[code] || code
132
- if code == KEY_RO
133
- code = mod[KEY_LEFTSHIFT] || mod[KEY_RIGHTSHIFT] ? KEY_MINUS : KEY_BACKSLASH
105
+ # 端末
106
+ rk.match(app: /terminal/i) do |event, mod|
107
+ # Super+Ctrl はそのまま
108
+ if (mod[KEY_LEFTMETA] || mod[KEY_RIGHTMETA]) && (mod[KEY_LEFTCTRL] || mod[KEY_RIGHTCTRL])
109
+ rk.event(code: event.code, type: event.type)
110
+ # Super+0/Minus は Ctrl+0/Minus に変換
111
+ elsif (mod[KEY_LEFTMETA] || mod[KEY_RIGHTMETA]) && Rkremap::CODE_KEY[event.code] =~ /\AKEY_(0|MINUS)\z/
112
+ rk.with_modifier(mod_disable_all.merge(KEY_LEFTCTRL => true)) do
113
+ rk.event(code: event.code, type: event.type)
114
+ end
115
+ # Super+KEY は Ctrl+Shift+KEY に変換
116
+ elsif (mod[KEY_LEFTMETA] || mod[KEY_RIGHTMETA]) && Rkremap::CODE_KEY[event.code] =~ /\AKEY_([A-Z]|EQUAL)\z/
117
+ rk.with_modifier(mod_disable_meta.merge(KEY_LEFTCTRL => true, KEY_LEFTSHIFT => true)) do
118
+ rk.event(code: event.code, type: event.type)
119
+ end
120
+ # それ以外はそのまま
121
+ else # rubocop:disable Lint/DuplicateBranch
122
+ rk.event(code: event.code, type: event.type)
134
123
  end
124
+ event.skip
125
+ end
135
126
 
136
- # Emacs や端末等ではそのまま
137
- if app.class_name == 'Emacs' || app.class_name =~ /terminal/i || app.class_name == 'VirtualBox Machine'
127
+ # その他のウィンドウ
128
+ ctrl_map = {
129
+ KEY_A => KEY_HOME,
130
+ KEY_E => KEY_END,
131
+ KEY_B => KEY_LEFT,
132
+ KEY_F => KEY_RIGHT,
133
+ KEY_N => KEY_DOWN,
134
+ KEY_P => KEY_UP,
135
+ KEY_D => KEY_DELETE,
136
+ KEY_H => KEY_BACKSPACE,
137
+ KEY_I => KEY_TAB,
138
+ }
139
+
140
+ rk.start do |code, mod|
141
+ # Super + Ctrl + 何か はそのまま
142
+ if (mod[KEY_LEFTMETA] || mod[KEY_RIGHTMETA]) && (mod[KEY_LEFTCTRL] || mod[KEY_RIGHTCTRL])
138
143
  rk.key(code, mod)
139
144
  next
140
145
  end
141
146
 
142
- # ALT+[A-Z]/Enter を Ctrl+[A-Z]/Enter に変換
143
- if (mod[KEY_LEFTALT] || mod[KEY_RIGHTALT]) && (Rkremap::CODE_KEY[code] =~ /\AKEY_[A-Z]\z/ || code == KEY_ENTER)
144
- mod.merge!(mod_disable_alt, {KEY_LEFTCTRL => true})
145
- mod[KEY_LEFTCTRL] = true
146
- rk.key(code, mod)
147
+ # Super+[A-Z]/Minus/Equal/Enter を Ctrl+[A-Z]/Minus/Equal/Enter に変換
148
+ if (mod[KEY_LEFTMETA] || mod[KEY_RIGHTMETA]) && (Rkremap::CODE_KEY[code] =~ /\AKEY_([0-9A-Z]|MINUS|EQUAL|ENTER)\z/)
149
+ rk.key(code, mod.merge(mod_disable_meta, KEY_LEFTCTRL => true))
150
+ next
151
+ end
152
+
153
+ # Alt + F, B は Ctrl + →, ← に変換
154
+ if (mod[KEY_LEFTALT] || mod[KEY_RIGHTALT]) && (code == KEY_F || code == KEY_B)
155
+ rk.key(code == KEY_F ? KEY_RIGHT : KEY_LEFT, mod.merge(mod_disable_alt, KEY_LEFTCTRL => true))
147
156
  next
148
157
  end
149
158
 
150
159
  # Ctrl は他のキーに変換
151
160
  if mod[KEY_LEFTCTRL] || mod[KEY_RIGHTCTRL]
152
161
  # Ctrl+I/O はそのまま
153
- if code == KEY_I || code ==KEY_O
162
+ if code == KEY_I || code == KEY_O
154
163
  rk.key(code, mod)
155
164
  next
156
165
  end
166
+
157
167
  # Ctrl+K は行末まで削除
158
168
  if code == KEY_K
159
- rk.key(KEY_END, mod_disable_all.merge({KEY_LEFTSHIFT => true}))
160
- rk.key(KEY_X, mod_disable_all.merge({KEY_LEFTCTRL => true}))
169
+ rk.key(KEY_END, mod_disable_all.merge(KEY_LEFTSHIFT => true)) # SHIFT+END
170
+ rk.key(KEY_X, mod_disable_all.merge(KEY_LEFTCTRL => true)) # Ctrl+X
161
171
  next
162
172
  end
173
+
163
174
  # 単純な変換
164
175
  if ctrl_map[code]
165
- rk.key(ctrl_map[code], mod_disable_ctrl)
176
+ rk.key(ctrl_map[code], mod.merge(mod_disable_ctrl))
166
177
  next
167
178
  end
179
+
168
180
  # その他の Ctrl+[A-Z] は無視
169
181
  if Rkremap::CODE_KEY[code] =~ /\AKEY_[A-Z]\z/
170
182
  next
171
183
  end
172
184
  end
173
185
 
186
+ # それ以外はそのまま
174
187
  rk.key(code, mod)
175
188
  end