rkremap 0.2.1 → 0.3.0
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 +9 -0
- data/example/tmtms.rb +2 -12
- data/lib/rkremap/evdev.rb +37 -7
- data/lib/rkremap/version.rb +1 -1
- data/lib/rkremap.rb +37 -5
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 04a75325e18cfa14e1eeb93462af309c6d692083c5ef4a2609e6dfd53747a6c8
|
4
|
+
data.tar.gz: 1f86fc05c3098eed25b0d09bbebfc75fdad37122898ee9762376ce5241f21c60
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3874c3c1a1c9b78a82faf4c3ceb40f28e1d9d5f1380a8ac3f604ffc904f2dcb4099db5b84f2f9542ae4d104ac8f242f4edd8060c8da0aa4f65e8ddc472a4cab2
|
7
|
+
data.tar.gz: f9700cd0991fb27fa03de2a402dd1bfebe0f23cc35d128b5b35ca9115608988ce2f1aeea55cd8525a3c645e1b4a465b0aa0995703e4cb0b58f73bdb7e2efda3f
|
data/README.md
CHANGED
@@ -48,6 +48,15 @@ ThinkPad 本体のキーボードは `/dev/input/event3` だった。
|
|
48
48
|
|
49
49
|
`true` に設定すると X のアプリ名等を取得できる。X 環境下でないなら `false` を設定する。
|
50
50
|
|
51
|
+
### Rkremap#modifers
|
52
|
+
|
53
|
+
修飾キーの一覧。これらのキーは単体で押されただけでは `start` ブロックを実行しない。
|
54
|
+
|
55
|
+
### auto_detect
|
56
|
+
|
57
|
+
`true` の場合はキーボードデバイスの接続を自動検知する。
|
58
|
+
`new` 時にデバイスファイルが指定されない場合は `true` になる。
|
59
|
+
|
51
60
|
### Rkremap#start
|
52
61
|
|
53
62
|
なにかキーを押されたらブロックを実行する。修飾キー単体ではブロックは実行されない。
|
data/example/tmtms.rb
CHANGED
@@ -1,14 +1,4 @@
|
|
1
1
|
# tmtms 用
|
2
|
-
#
|
3
|
-
# fcitx が有効な場合に /tmp/fcitx-enabled ファイルを作るスクリプトを動かしておく:
|
4
|
-
# while :; do
|
5
|
-
# if [ $(fcitx-remote) -eq 2 ]; then
|
6
|
-
# touch /tmp/fcitx-enabled
|
7
|
-
# else
|
8
|
-
# rm -f /tmp/fcitx-enabled
|
9
|
-
# fi
|
10
|
-
# sleep 0.1
|
11
|
-
# done
|
12
2
|
|
13
3
|
require 'rkremap'
|
14
4
|
include Rkremap::KeyCode
|
@@ -159,8 +149,8 @@ rk.start do |code, mod, app|
|
|
159
149
|
|
160
150
|
# Ctrl は他のキーに変換
|
161
151
|
if mod[KEY_LEFTCTRL] || mod[KEY_RIGHTCTRL]
|
162
|
-
# Ctrl
|
163
|
-
if
|
152
|
+
# Ctrl+I/O はそのまま
|
153
|
+
if code == KEY_I || code ==KEY_O
|
164
154
|
rk.key(code, mod)
|
165
155
|
next
|
166
156
|
end
|
data/lib/rkremap/evdev.rb
CHANGED
@@ -8,27 +8,49 @@ class Rkremap
|
|
8
8
|
EVIOCGBIT_ANY = 2147566880 # EVIOCGBIT(0, 1)
|
9
9
|
EVIOCGBIT_EV_KEY = 2153792801 # EVIOCGBIT(EV_KEY, (KEY_MAX-1)/8+1)
|
10
10
|
EVIOCGRAB = 1074021776
|
11
|
+
EVIOCGNAME = 2164278534 # EVIOCGNAME(256)
|
11
12
|
|
12
13
|
@io2evdev = {}
|
13
14
|
def self.io2evdev
|
14
15
|
@io2evdev
|
15
16
|
end
|
16
17
|
|
18
|
+
@device_list = {}
|
19
|
+
|
17
20
|
# @return [Array<Evdev>]
|
18
|
-
def self.
|
19
|
-
|
20
|
-
|
21
|
+
def self.detect
|
22
|
+
devs = []
|
23
|
+
new_devs = Dir.children("/dev/input").map do |dev|
|
24
|
+
if dev =~ /\Aevent\d+\z/
|
25
|
+
path = "/dev/input/#{dev}"
|
26
|
+
devs.push path
|
27
|
+
next if @device_list[path]
|
28
|
+
@device_list[path] = true
|
29
|
+
Evdev.new(path)
|
30
|
+
end
|
21
31
|
end.compact
|
32
|
+
(@device_list.keys - devs).each do |path|
|
33
|
+
@device_list.delete path
|
34
|
+
end
|
35
|
+
new_devs
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.remove_device(evdev)
|
39
|
+
@io2evdev.delete evdev.io
|
40
|
+
@device_list.delete evdev.path
|
22
41
|
end
|
23
42
|
|
24
43
|
# @param inputs [Array<Evdev>]
|
44
|
+
# @param timeout [Numeric]
|
25
45
|
# @return [Evdev]
|
26
|
-
def self.select(inputs)
|
27
|
-
|
28
|
-
r
|
29
|
-
@io2evdev[r[0]]
|
46
|
+
def self.select(inputs, timeout)
|
47
|
+
r, = IO.select(inputs.map(&:io), nil, nil, timeout)
|
48
|
+
r && @io2evdev[r[0]]
|
30
49
|
end
|
31
50
|
|
51
|
+
# @return [String]
|
52
|
+
attr_reader :path
|
53
|
+
|
32
54
|
# @param path [String]
|
33
55
|
def initialize(path)
|
34
56
|
@path = path
|
@@ -37,6 +59,10 @@ class Rkremap
|
|
37
59
|
@uinput = nil
|
38
60
|
end
|
39
61
|
|
62
|
+
def eql?(other)
|
63
|
+
other.is_a?(Evdev) && self.path == other.path
|
64
|
+
end
|
65
|
+
|
40
66
|
# @return [IO]
|
41
67
|
def io
|
42
68
|
return @io if @io
|
@@ -47,6 +73,7 @@ class Rkremap
|
|
47
73
|
|
48
74
|
def close
|
49
75
|
@io&.close
|
76
|
+
self.class.remove_device(self)
|
50
77
|
end
|
51
78
|
|
52
79
|
# @param key [Integer]
|
@@ -63,6 +90,9 @@ class Rkremap
|
|
63
90
|
# @return [Boolean]
|
64
91
|
def keyboard?
|
65
92
|
buf = ' '
|
93
|
+
io.ioctl(EVIOCGNAME, buf)
|
94
|
+
return false if buf =~ /\Arkremap\0*\z/
|
95
|
+
|
66
96
|
io.ioctl(EVIOCGBIT_ANY, buf)
|
67
97
|
return false if buf.unpack1('C')[EV_KEY] == 0
|
68
98
|
capable?(KeyCode::KEY_0) && capable?(KeyCode::KEY_9) &&
|
data/lib/rkremap/version.rb
CHANGED
data/lib/rkremap.rb
CHANGED
@@ -17,11 +17,17 @@ class Rkremap
|
|
17
17
|
attr_accessor :grab
|
18
18
|
attr_accessor :modifiers
|
19
19
|
attr_accessor :x11
|
20
|
+
attr_accessor :auto_detect
|
20
21
|
|
21
22
|
# @param devices [Array<String>, String]
|
22
23
|
def initialize(devices=nil)
|
23
|
-
|
24
|
-
|
24
|
+
if devices
|
25
|
+
devices = Array(devices)
|
26
|
+
@inputs = devices.map{|d| Evdev.new(d)}
|
27
|
+
else
|
28
|
+
@auto_detect = true
|
29
|
+
@inputs = Evdev.detect.select(&:keyboard?)
|
30
|
+
end
|
25
31
|
raise 'Unable to detect keyboard device' if @inputs.empty?
|
26
32
|
@uinput = Uinput.new
|
27
33
|
@grab = false
|
@@ -43,13 +49,13 @@ class Rkremap
|
|
43
49
|
end
|
44
50
|
|
45
51
|
def start(&block)
|
46
|
-
|
52
|
+
detect_device_loop if @auto_detect
|
53
|
+
@mod_state = @modifiers.map.to_h{|m| [m, false]}
|
47
54
|
@winattr = WinAttr.new if @x11
|
48
55
|
@inputs.each(&:grab) if @grab
|
49
56
|
while true
|
50
57
|
@keys = []
|
51
|
-
|
52
|
-
time, type, code, value = input.read_event
|
58
|
+
time, type, code, value = read_event
|
53
59
|
next if type != EV_KEY
|
54
60
|
event = Event.new(time, code, value, @winattr)
|
55
61
|
@events.each do |cond, b|
|
@@ -64,6 +70,32 @@ class Rkremap
|
|
64
70
|
end
|
65
71
|
end
|
66
72
|
|
73
|
+
def detect_device_loop
|
74
|
+
Thread.new do
|
75
|
+
while true
|
76
|
+
sleep 3
|
77
|
+
new_devs = Evdev.detect.select(&:keyboard?)
|
78
|
+
unless new_devs.empty?
|
79
|
+
new_devs.each(&:grab) if @grab
|
80
|
+
@inputs += new_devs
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def read_event
|
87
|
+
while true
|
88
|
+
begin
|
89
|
+
input = Evdev.select(@inputs, 3)
|
90
|
+
next unless input
|
91
|
+
return input.read_event
|
92
|
+
rescue Errno::ENODEV
|
93
|
+
input.close rescue nil
|
94
|
+
@inputs.delete input
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
67
99
|
def synchronize(&block)
|
68
100
|
@mutex.synchronize(&block)
|
69
101
|
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.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- TOMITA Masahiro
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-03-05 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: key remapper
|
14
14
|
email:
|