rkremap 0.4.1 → 0.5.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 +4 -4
- data/README.md +38 -0
- data/example/henkan-super.rb +9 -34
- data/example/tmtms.rb +50 -60
- data/lib/rkremap/event.rb +6 -2
- data/lib/rkremap/remap.rb +118 -0
- data/lib/rkremap/version.rb +1 -1
- data/lib/rkremap.rb +21 -2
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 93f0a2d7d2c705b779d942618d4da708ef395386bc9529d06cc4c4f644243bac
|
4
|
+
data.tar.gz: bddb932d29c287b3e00105adac03fc420506253c5f00c309dee22da46678502f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 41fff4f8444a6c585403ac5a3655eb5b4e1d631332594c95e4d3149a973dced926b4a726cf912522e7ac3c0dcbb4ba0e3ea6461dfe6853e04c1a9086162307e2
|
7
|
+
data.tar.gz: 88b6bdb97c04ed2629d1eac337e89f9854f954daf392b4e0a395e6df94699ff1c7e7e66be78ea3adeb3221fff8a6a88d2d8a38699f503575c5376bbdfcf96556
|
data/README.md
CHANGED
@@ -79,6 +79,44 @@ rkremap.exclude = /touchpad/i
|
|
79
79
|
`true` の場合はキーボードデバイスの接続を自動検知する。
|
80
80
|
`new` 時にデバイスファイルが指定されない場合は `true` になる。
|
81
81
|
|
82
|
+
### Rkremap#remap
|
83
|
+
|
84
|
+
引数の Hash で変換するキーを指定する:
|
85
|
+
```ruby
|
86
|
+
rk.remap(KEY_CAPSLOCK => KEY_LEFTCTRL)
|
87
|
+
```
|
88
|
+
|
89
|
+
変換元を配列で修飾キーを書くとその修飾キーとの組み合わせで変換する:
|
90
|
+
```ruby
|
91
|
+
rk.remap([KEY_LEFTCTRL, KEY_A] => KEY_HOME)
|
92
|
+
```
|
93
|
+
|
94
|
+
hold を指定すると指定秒数長押ししたときだけ変換する:
|
95
|
+
```ruby
|
96
|
+
rk.remap(hold: 0.5, map: {
|
97
|
+
KEY_MUHENKAN => KEY_RIGHTMETA,
|
98
|
+
KEY_HENKAN => KEY_RIGHTMETA,
|
99
|
+
})
|
100
|
+
```
|
101
|
+
|
102
|
+
次のように書くと、A も B も C もすべて A になってしまう:
|
103
|
+
```ruby
|
104
|
+
rk.remap(KEY_A => KEY_B)
|
105
|
+
rk.remap(KEY_B => KEY_C)
|
106
|
+
rk.remap(KEY_C => KEY_A)
|
107
|
+
```
|
108
|
+
|
109
|
+
A を B, B を C, C を A と変換したい場合は次のように書く:
|
110
|
+
```ruby
|
111
|
+
rk.remap(
|
112
|
+
KEY_A => KEY_B,
|
113
|
+
KEY_B => KEY_C,
|
114
|
+
KEY_C => KEY_A
|
115
|
+
)
|
116
|
+
```
|
117
|
+
|
118
|
+
`#remap` で実現できないような複雑な処理は、後述の `#match` や `#start` で書くことができるかもしれない。
|
119
|
+
|
82
120
|
### Rkremap#start
|
83
121
|
|
84
122
|
なにかキーを押されたらブロックを実行する。修飾キー単体ではブロックは実行されない。
|
data/example/henkan-super.rb
CHANGED
@@ -2,48 +2,23 @@
|
|
2
2
|
# 0.5秒以内でも変換/無変換キーを押しながら他のキーを押すとSUPERキーとして扱う。
|
3
3
|
|
4
4
|
require 'rkremap'
|
5
|
-
require 'tmtms_timer'
|
6
5
|
|
7
6
|
include Rkremap::KeyCode
|
8
7
|
|
9
|
-
rk = Rkremap.new
|
8
|
+
rk = Rkremap.new(*ARGV, mouse: true)
|
10
9
|
rk.grab = true
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
KEY_HENKAN => nil,
|
15
|
-
KEY_MUHENKAN => nil,
|
16
|
-
}
|
17
|
-
|
18
|
-
henkan_map = {
|
11
|
+
# HENKAN, MUHENKAN を 0.5秒以上押したら SUPER とする
|
12
|
+
rk.remap(hold: 0.5, map: {
|
19
13
|
KEY_HENKAN => KEY_RIGHTMETA,
|
20
14
|
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
|
15
|
+
})
|
40
16
|
|
41
|
-
#
|
42
|
-
rk.match(
|
43
|
-
[
|
44
|
-
|
45
|
-
|
46
|
-
end
|
17
|
+
# マウスボタンイベントはそのまま
|
18
|
+
rk.match(device: :mouse) do |event|
|
19
|
+
unless Rkremap::CODE_KEY[event.code] =~ /^KEY_/
|
20
|
+
rk.event(code: event.code, type: event.type)
|
21
|
+
event.skip
|
47
22
|
end
|
48
23
|
end
|
49
24
|
|
data/example/tmtms.rb
CHANGED
@@ -1,68 +1,43 @@
|
|
1
1
|
# tmtms 用
|
2
2
|
|
3
3
|
require 'rkremap'
|
4
|
-
require 'tmtms_timer'
|
5
4
|
|
6
5
|
include Rkremap::KeyCode
|
7
6
|
|
8
|
-
rk = Rkremap.new(*ARGV, mouse: true, exclude: /
|
7
|
+
rk = Rkremap.new(*ARGV, mouse: true, exclude: /\AELAN0676/i)
|
9
8
|
rk.grab = true
|
10
9
|
rk.x11 = true
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
end
|
11
|
+
# rkremap がシステムに認識されたら中ボタンスクロールを有効にする
|
12
|
+
sleep 0.1 until system "xinput | grep -q rkremap"
|
15
13
|
system "xinput set-prop pointer:rkremap 'libinput Scroll Method Enabled' 0 0 1"
|
16
14
|
|
17
15
|
# HENKAN, MUHENKAN を 0.5秒以上押したら SUPER とする
|
18
|
-
|
19
|
-
jobs = {
|
20
|
-
KEY_HENKAN => nil,
|
21
|
-
KEY_MUHENKAN => nil,
|
22
|
-
}
|
23
|
-
|
24
|
-
henkan_map = {
|
16
|
+
rk.remap(hold: 0.5, map: {
|
25
17
|
KEY_HENKAN => KEY_RIGHTMETA,
|
26
18
|
KEY_MUHENKAN => KEY_RIGHTMETA, # LEFTMETA だとデスクトップ環境のメニューが開いたりするため
|
27
|
-
}
|
28
|
-
|
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)
|
34
|
-
end
|
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
|
43
|
-
end
|
44
|
-
event.skip
|
45
|
-
end
|
46
|
-
|
47
|
-
# 何かキーが押されたときに HENKAN, MUHENKAN が押されてれば SUPER が押されてることにする
|
48
|
-
rk.match(type: :press) do
|
49
|
-
[KEY_HENKAN, KEY_MUHENKAN].each do |code|
|
50
|
-
if jobs[code]&.cancel # 0.5秒以内
|
51
|
-
rk.event(code: henkan_map[code], type: :press)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
19
|
+
})
|
55
20
|
|
56
21
|
# マウスボタンイベントはそのまま
|
57
22
|
rk.match(device: :mouse) do |event|
|
58
|
-
|
59
|
-
|
23
|
+
unless Rkremap::CODE_KEY[event.code] =~ /^KEY_/
|
24
|
+
rk.event(code: event.code, type: event.type)
|
25
|
+
event.skip
|
26
|
+
end
|
60
27
|
end
|
61
28
|
|
62
29
|
# CAPSLOCK は CTRL に変換
|
63
|
-
rk.
|
64
|
-
|
65
|
-
|
30
|
+
rk.remap(KEY_CAPSLOCK => KEY_LEFTCTRL)
|
31
|
+
|
32
|
+
# JISキーボードを英語配列にしたときに一部キーを変える
|
33
|
+
rk.remap(
|
34
|
+
KEY_YEN => KEY_BACKSLASH,
|
35
|
+
KEY_BACKSLASH => KEY_GRAVE,
|
36
|
+
KEY_GRAVE => KEY_ESC,
|
37
|
+
[KEY_LEFTSHIFT, KEY_RO] => [KEY_LEFTSHIFT, KEY_MINUS],
|
38
|
+
[KEY_RIGHTSHIFT, KEY_RO] => [KEY_LEFTSHIFT, KEY_MINUS],
|
39
|
+
KEY_RO => KEY_BACKSLASH,
|
40
|
+
)
|
66
41
|
|
67
42
|
mod_disable_ctrl = {
|
68
43
|
KEY_LEFTCTRL => false,
|
@@ -82,23 +57,23 @@ mod_disable_meta = {
|
|
82
57
|
}
|
83
58
|
mod_disable_all = {}.merge(mod_disable_ctrl, mod_disable_shift, mod_disable_alt, mod_disable_meta)
|
84
59
|
|
85
|
-
#
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
KEY_GRAVE => KEY_ESC,
|
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
|
60
|
+
# VirtualBox
|
61
|
+
rk.match(app: /VirtualBox Machine/) do |event|
|
62
|
+
rk.event(code: event.code, type: event.type)
|
63
|
+
event.skip
|
97
64
|
end
|
98
65
|
|
99
|
-
# Emacs
|
100
|
-
rk.match(app:
|
101
|
-
|
66
|
+
# Emacs
|
67
|
+
rk.match(app: {class_name: 'Emacs'}) do |event, mod|
|
68
|
+
# 修飾キーが Super だけの場合は Alt として扱う。ただしキーが TAB の場合は除く。
|
69
|
+
mod_enabled = mod.select{_2}.keys
|
70
|
+
if !mod_enabled.empty? && mod_enabled.all?{_1 == KEY_LEFTMETA || _1 == KEY_RIGHTMETA} && event.code != KEY_TAB
|
71
|
+
rk.with_modifier(mod_disable_meta.merge(KEY_LEFTALT => true)) do
|
72
|
+
rk.event(code: event.code, type: event.type)
|
73
|
+
end
|
74
|
+
else
|
75
|
+
rk.event(code: event.code, type: event.type)
|
76
|
+
end
|
102
77
|
event.skip
|
103
78
|
end
|
104
79
|
|
@@ -124,6 +99,16 @@ rk.match(app: /terminal/i) do |event, mod|
|
|
124
99
|
event.skip
|
125
100
|
end
|
126
101
|
|
102
|
+
# Firefox で Super+Ctrl+C は Alt+Ctrl+C に変換
|
103
|
+
rk.match(app: {class_name: 'firefox'}) do |event, mod|
|
104
|
+
if (mod[KEY_LEFTMETA] || mod[KEY_RIGHTMETA]) && (mod[KEY_LEFTCTRL] || mod[KEY_RIGHTCTRL]) && event.code == KEY_C
|
105
|
+
rk.with_modifier(mod_disable_meta.merge(KEY_LEFTCTRL => true, KEY_LEFTALT => true)) do
|
106
|
+
rk.event(code: event.code, type: event.type)
|
107
|
+
end
|
108
|
+
event.skip
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
127
112
|
# その他のウィンドウ
|
128
113
|
ctrl_map = {
|
129
114
|
KEY_A => KEY_HOME,
|
@@ -149,6 +134,11 @@ rk.start do |code, mod|
|
|
149
134
|
rk.key(code, mod.merge(mod_disable_meta, KEY_LEFTCTRL => true))
|
150
135
|
next
|
151
136
|
end
|
137
|
+
# Super+[←→] を Alt+[←→] に変換
|
138
|
+
if (mod[KEY_LEFTMETA] || mod[KEY_RIGHTMETA]) && (Rkremap::CODE_KEY[code] =~ /\AKEY_(LEFT|RIGHT)\z/)
|
139
|
+
rk.key(code, mod.merge(mod_disable_meta, KEY_LEFTALT => true))
|
140
|
+
next
|
141
|
+
end
|
152
142
|
|
153
143
|
# Alt + F, B は Ctrl + →, ← に変換
|
154
144
|
if (mod[KEY_LEFTALT] || mod[KEY_RIGHTALT]) && (code == KEY_F || code == KEY_B)
|
data/lib/rkremap/event.rb
CHANGED
@@ -23,11 +23,15 @@ class Rkremap
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def inspect
|
26
|
-
|
26
|
+
if ev_type == EV_KEY
|
27
|
+
"#<Rkremap::Event: #{code}(#{CODE_KEY[code]}) #{value} #{device.inspect}>"
|
28
|
+
else
|
29
|
+
"#<Rkremap::Event: type: #{ev_type}>"
|
30
|
+
end
|
27
31
|
end
|
28
32
|
|
29
33
|
def type
|
30
|
-
|
34
|
+
value == 1 ? :press : value == 0 ? :release : :repeat
|
31
35
|
end
|
32
36
|
|
33
37
|
def match?(device:, code:, type:, app:)
|
@@ -0,0 +1,118 @@
|
|
1
|
+
class Rkremap
|
2
|
+
class Remap
|
3
|
+
# @param map [Hash] from => to
|
4
|
+
# @param hold [Numeric] seconds
|
5
|
+
def initialize(rk, map:, hold:)
|
6
|
+
@rk = rk
|
7
|
+
@pressed = {}
|
8
|
+
|
9
|
+
if hold
|
10
|
+
setup_holding_event(map, hold)
|
11
|
+
else
|
12
|
+
setup_event(map)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# @param map [Hash] {form => to}
|
17
|
+
def setup_event(map)
|
18
|
+
keycodes = map.keys.flatten
|
19
|
+
|
20
|
+
@rk.match(code: keycodes, type: :press) do |event, current_mod|
|
21
|
+
map.each do |from, to|
|
22
|
+
if event_match?(from, event, current_mod)
|
23
|
+
make_press_event(to, event)
|
24
|
+
break
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
@rk.match(code: keycodes, type: :repeat) do |event|
|
30
|
+
event.skip
|
31
|
+
end
|
32
|
+
|
33
|
+
@rk.match(code: keycodes, type: :release) do |event|
|
34
|
+
if @pressed[event.code]
|
35
|
+
@rk.event(code: @pressed[event.code], type: :release)
|
36
|
+
@pressed[event.code] = nil
|
37
|
+
event.skip
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# @param map [Hash] {form => to}
|
43
|
+
# @param hold [Numeric] seconds
|
44
|
+
def setup_holding_event(map, hold)
|
45
|
+
keycodes = map.keys.flatten
|
46
|
+
timer = Tmtms::Timer.new
|
47
|
+
jobs = map.transform_values{nil}
|
48
|
+
|
49
|
+
@rk.match(code: keycodes, type: :press) do |event|
|
50
|
+
map.each do |from, to|
|
51
|
+
if from == event.code
|
52
|
+
jobs[event.code] = timer.set(hold) do
|
53
|
+
@rk.synchronize{ make_press_event(to) }
|
54
|
+
end
|
55
|
+
event.skip
|
56
|
+
break
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
@rk.match(code: keycodes, type: :repeat) do |event|
|
62
|
+
event.skip
|
63
|
+
end
|
64
|
+
|
65
|
+
@rk.match(code: keycodes, type: :release) do |event|
|
66
|
+
code = event.code
|
67
|
+
if jobs[code]
|
68
|
+
if jobs[code].cancel
|
69
|
+
event.value = 1
|
70
|
+
@rk.append_event(Event.new(event.device, event.time, event.ev_type, event.code, 0))
|
71
|
+
elsif map[code]
|
72
|
+
event.code = map[code]
|
73
|
+
@pressed[code] = nil
|
74
|
+
end
|
75
|
+
jobs[code] = nil
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
@rk.match(type: :press) do
|
80
|
+
jobs.each do |code, job|
|
81
|
+
make_press_event(map[code]) if job&.cancel
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# @param keys [Integer, Array<Integer>] KEY_A, [KEY_LEFTCTRL, KEY_A], [:SHIFT, KEY_A], ...
|
87
|
+
# @param event [Rkremap::Event]
|
88
|
+
# @param mod [Hash] current modifiers status
|
89
|
+
def event_match?(keys, event, mod)
|
90
|
+
if keys == event.code
|
91
|
+
return true
|
92
|
+
end
|
93
|
+
keys = Array(keys)
|
94
|
+
return false unless keys.include? event.code
|
95
|
+
(keys - [event.code]).all?{mod[_1]}
|
96
|
+
end
|
97
|
+
|
98
|
+
# @param to [Integer, Array<Integer>]
|
99
|
+
# @param event [Rkremap::Event, nil]
|
100
|
+
def make_press_event(to, event=nil)
|
101
|
+
to = Array(to)
|
102
|
+
f = true
|
103
|
+
to.each do |key|
|
104
|
+
@pressed[event.code] = key if event
|
105
|
+
if @rk.modifiers.include? key
|
106
|
+
@rk.event(code: key, type: :press)
|
107
|
+
elsif event
|
108
|
+
event.code = key
|
109
|
+
f = false
|
110
|
+
else
|
111
|
+
@rk.key(key)
|
112
|
+
f = false
|
113
|
+
end
|
114
|
+
end
|
115
|
+
event&.skip if f
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
data/lib/rkremap/version.rb
CHANGED
data/lib/rkremap.rb
CHANGED
@@ -7,6 +7,7 @@ require_relative 'rkremap/evdev_list'
|
|
7
7
|
require_relative 'rkremap/evdev'
|
8
8
|
require_relative 'rkremap/event'
|
9
9
|
require_relative 'rkremap/uinput'
|
10
|
+
require_relative 'rkremap/remap'
|
10
11
|
|
11
12
|
class Rkremap
|
12
13
|
include KeyCode
|
@@ -57,6 +58,17 @@ class Rkremap
|
|
57
58
|
@mutex = Mutex.new
|
58
59
|
end
|
59
60
|
|
61
|
+
# @overload remap(map)
|
62
|
+
# @param map [Hash] from => to
|
63
|
+
# @overload remap(map:, hold: nil)
|
64
|
+
# @param map [Hash] from => to
|
65
|
+
# @param hold [Numeric] seconds
|
66
|
+
def remap(**opts)
|
67
|
+
map, hold = opts[:map], opts[:hold]
|
68
|
+
map ||= opts
|
69
|
+
Remap.new(self, map: map, hold: hold)
|
70
|
+
end
|
71
|
+
|
60
72
|
# @param device [Symbol, Regexp]
|
61
73
|
# @param code [Integer]
|
62
74
|
# @param type [Symbol] :press / :release / :repeat
|
@@ -71,9 +83,10 @@ class Rkremap
|
|
71
83
|
@evdev_list.detect_loop
|
72
84
|
@mod_state = @modifiers.map.to_h{|m| [m, false]}
|
73
85
|
winattr = WinAttr.new if @x11
|
86
|
+
@events = []
|
74
87
|
while true
|
75
88
|
@keys = []
|
76
|
-
event = @evdev_list.read_event
|
89
|
+
event = @events.shift || @evdev_list.read_event
|
77
90
|
if event.ev_type != EV_KEY
|
78
91
|
if event.device.grab?
|
79
92
|
@uinput.write_event(event.ev_type, event.code, event.value)
|
@@ -126,6 +139,12 @@ class Rkremap
|
|
126
139
|
end
|
127
140
|
end
|
128
141
|
|
142
|
+
# @param event [Rkremap::Event]
|
143
|
+
def append_event(event)
|
144
|
+
@events.push event
|
145
|
+
@events.push Event.new(event.device, event.time, EV_SYN, SYN_REPORT, 0)
|
146
|
+
end
|
147
|
+
|
129
148
|
private
|
130
149
|
|
131
150
|
def update_modifiers(code, value)
|
@@ -178,7 +197,7 @@ class Rkremap
|
|
178
197
|
# @param app [Array, Hash, String, Regexp]
|
179
198
|
# @return [Boolean]
|
180
199
|
def match?(app)
|
181
|
-
|
200
|
+
[app].flatten.each do |a|
|
182
201
|
a = {class_name: a, title: a} unless a.is_a? Hash
|
183
202
|
return true if match_sub(a[:class_name], class_name) || match_sub(a[:title], title)
|
184
203
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rkremap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- TOMITA Masahiro
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-09-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: tmtms_timer
|
@@ -41,6 +41,7 @@ files:
|
|
41
41
|
- lib/rkremap/evdev_list.rb
|
42
42
|
- lib/rkremap/event.rb
|
43
43
|
- lib/rkremap/keycode.rb
|
44
|
+
- lib/rkremap/remap.rb
|
44
45
|
- lib/rkremap/uinput.rb
|
45
46
|
- lib/rkremap/version.rb
|
46
47
|
- lib/rkremap/winattr.rb
|
@@ -67,7 +68,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
67
68
|
- !ruby/object:Gem::Version
|
68
69
|
version: '0'
|
69
70
|
requirements: []
|
70
|
-
rubygems_version: 3.
|
71
|
+
rubygems_version: 3.5.0.dev
|
71
72
|
signing_key:
|
72
73
|
specification_version: 4
|
73
74
|
summary: key remapper
|