rkremap 0.1.0 → 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 +13 -1
- data/example/henkan-alt.rb +1 -1
- data/example/keylogger.rb +1 -1
- data/example/mac-shortcut.rb +1 -1
- data/example/tmtms.rb +8 -13
- data/lib/rkremap/evdev.rb +154 -0
- data/lib/rkremap/version.rb +1 -1
- data/lib/rkremap/winattr.rb +45 -60
- data/lib/rkremap.rb +46 -37
- metadata +4 -17
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
@@ -25,7 +25,9 @@ KERNEL=="uinput", GROUP="input"
|
|
25
25
|
|
26
26
|
### `Rkremap.new`
|
27
27
|
|
28
|
-
|
28
|
+
引数を指定しなければ自動的にキーボードデバイスの検出を試みる。
|
29
|
+
|
30
|
+
引数を指定する場合は `/dev/input/event*` を指定する。キーボードデバイス以外を指定してもたぶん無意味。
|
29
31
|
キーボードのデバイスファイル名を調べるには
|
30
32
|
```
|
31
33
|
cat /proc/bus/input/devices
|
@@ -46,6 +48,15 @@ ThinkPad 本体のキーボードは `/dev/input/event3` だった。
|
|
46
48
|
|
47
49
|
`true` に設定すると X のアプリ名等を取得できる。X 環境下でないなら `false` を設定する。
|
48
50
|
|
51
|
+
### Rkremap#modifers
|
52
|
+
|
53
|
+
修飾キーの一覧。これらのキーは単体で押されただけでは `start` ブロックを実行しない。
|
54
|
+
|
55
|
+
### auto_detect
|
56
|
+
|
57
|
+
`true` の場合はキーボードデバイスの接続を自動検知する。
|
58
|
+
`new` 時にデバイスファイルが指定されない場合は `true` になる。
|
59
|
+
|
49
60
|
### Rkremap#start
|
50
61
|
|
51
62
|
なにかキーを押されたらブロックを実行する。修飾キー単体ではブロックは実行されない。
|
@@ -79,6 +90,7 @@ ThinkPad 本体のキーボードは `/dev/input/event3` だった。
|
|
79
90
|
* [xkeysnail - もうひとつの Linux 向けキーリマッパ - Qiita](https://qiita.com/mooz@github/items/c5f25f27847333dd0b37)
|
80
91
|
* [k0kubun/xremap: Dynamic key remapper for X11 and Wayland](https://github.com/k0kubun/xremap)
|
81
92
|
* [Linux向けの最強のキーリマッパーを作った - k0kubun's blog](https://k0kubun.hatenablog.com/entry/xkremap)
|
93
|
+
* [Linux用キーリマッパーxremapをRustで書き直した - k0kubun's blog](https://k0kubun.hatenablog.com/entry/xremap)
|
82
94
|
* [kui/rbindkeys: key remap with ruby](https://github.com/kui/rbindkeys)
|
83
95
|
* [Ruby で設定できる Linux 環境向けキーリマッパー作った — 電卓片手に](http://k-ui.jp/blog/2012/06/06/rbindkeys-configurable-key-remapper-in-ruby/)
|
84
96
|
* [Linux の入力デバイスをカスタマイズ - Qiita](https://qiita.com/propella/items/a73fc333c95d14d06835)
|
data/example/henkan-alt.rb
CHANGED
data/example/keylogger.rb
CHANGED
data/example/mac-shortcut.rb
CHANGED
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
|
@@ -40,7 +30,7 @@ class State
|
|
40
30
|
end
|
41
31
|
end
|
42
32
|
|
43
|
-
rk = Rkremap.new
|
33
|
+
rk = Rkremap.new
|
44
34
|
rk.grab = true
|
45
35
|
rk.x11 = true
|
46
36
|
|
@@ -159,8 +149,13 @@ rk.start do |code, mod, app|
|
|
159
149
|
|
160
150
|
# Ctrl は他のキーに変換
|
161
151
|
if mod[KEY_LEFTCTRL] || mod[KEY_RIGHTCTRL]
|
162
|
-
# Ctrl+
|
163
|
-
if code ==
|
152
|
+
# Ctrl+I/O はそのまま
|
153
|
+
if code == KEY_I || code ==KEY_O
|
154
|
+
rk.key(code, mod)
|
155
|
+
next
|
156
|
+
end
|
157
|
+
# Ctrl+K は行末まで削除
|
158
|
+
if code == KEY_K
|
164
159
|
rk.key(KEY_END, mod_disable_all.merge({KEY_LEFTSHIFT => true}))
|
165
160
|
rk.key(KEY_X, mod_disable_all.merge({KEY_LEFTCTRL => true}))
|
166
161
|
next
|
@@ -0,0 +1,154 @@
|
|
1
|
+
class Rkremap
|
2
|
+
EV_KEY = 1
|
3
|
+
EV_SYN = 0
|
4
|
+
SYN_REPORT = 0
|
5
|
+
|
6
|
+
# https://www.kernel.org/doc/html/v4.12/input/input_uapi.html
|
7
|
+
class Evdev
|
8
|
+
EVIOCGBIT_ANY = 2147566880 # EVIOCGBIT(0, 1)
|
9
|
+
EVIOCGBIT_EV_KEY = 2153792801 # EVIOCGBIT(EV_KEY, (KEY_MAX-1)/8+1)
|
10
|
+
EVIOCGRAB = 1074021776
|
11
|
+
EVIOCGNAME = 2164278534 # EVIOCGNAME(256)
|
12
|
+
|
13
|
+
@io2evdev = {}
|
14
|
+
def self.io2evdev
|
15
|
+
@io2evdev
|
16
|
+
end
|
17
|
+
|
18
|
+
@device_list = {}
|
19
|
+
|
20
|
+
# @return [Array<Evdev>]
|
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
|
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
|
41
|
+
end
|
42
|
+
|
43
|
+
# @param inputs [Array<Evdev>]
|
44
|
+
# @param timeout [Numeric]
|
45
|
+
# @return [Evdev]
|
46
|
+
def self.select(inputs, timeout)
|
47
|
+
r, = IO.select(inputs.map(&:io), nil, nil, timeout)
|
48
|
+
r && @io2evdev[r[0]]
|
49
|
+
end
|
50
|
+
|
51
|
+
# @return [String]
|
52
|
+
attr_reader :path
|
53
|
+
|
54
|
+
# @param path [String]
|
55
|
+
def initialize(path)
|
56
|
+
@path = path
|
57
|
+
@io = nil
|
58
|
+
@capa = nil
|
59
|
+
@uinput = nil
|
60
|
+
end
|
61
|
+
|
62
|
+
def eql?(other)
|
63
|
+
other.is_a?(Evdev) && self.path == other.path
|
64
|
+
end
|
65
|
+
|
66
|
+
# @return [IO]
|
67
|
+
def io
|
68
|
+
return @io if @io
|
69
|
+
@io = File.open(@path)
|
70
|
+
self.class.io2evdev[@io] = self
|
71
|
+
@io
|
72
|
+
end
|
73
|
+
|
74
|
+
def close
|
75
|
+
@io&.close
|
76
|
+
self.class.remove_device(self)
|
77
|
+
end
|
78
|
+
|
79
|
+
# @param key [Integer]
|
80
|
+
# @return [Boolean]
|
81
|
+
def capable?(key)
|
82
|
+
unless @capa
|
83
|
+
buf = ' ' * ((KeyCode::KEY_MAX-1)/8+1)
|
84
|
+
io.ioctl(EVIOCGBIT_EV_KEY, buf)
|
85
|
+
@capa = buf.unpack('C*')
|
86
|
+
end
|
87
|
+
@capa[key/8][key%8] != 0
|
88
|
+
end
|
89
|
+
|
90
|
+
# @return [Boolean]
|
91
|
+
def keyboard?
|
92
|
+
buf = ' '
|
93
|
+
io.ioctl(EVIOCGNAME, buf)
|
94
|
+
return false if buf =~ /\Arkremap\0*\z/
|
95
|
+
|
96
|
+
io.ioctl(EVIOCGBIT_ANY, buf)
|
97
|
+
return false if buf.unpack1('C')[EV_KEY] == 0
|
98
|
+
capable?(KeyCode::KEY_0) && capable?(KeyCode::KEY_9) &&
|
99
|
+
capable?(KeyCode::KEY_A) && capable?(KeyCode::KEY_Z) && capable?(KeyCode::KEY_SPACE)
|
100
|
+
end
|
101
|
+
|
102
|
+
def grab
|
103
|
+
io.ioctl(EVIOCGRAB, 1)
|
104
|
+
end
|
105
|
+
|
106
|
+
# struct input_event {
|
107
|
+
# struct timeval time;
|
108
|
+
# unsigned short type;
|
109
|
+
# unsigned short code;
|
110
|
+
# unsigned int value;
|
111
|
+
# };
|
112
|
+
# @return [Array<Time, Integer, Integer, Integer>]
|
113
|
+
def read_event
|
114
|
+
raw = io.sysread(24) # sizeof(struct input_event)
|
115
|
+
sec, usec, type, code, value = raw.unpack('Q!Q!SSl')
|
116
|
+
time = Time.at(sec, usec)
|
117
|
+
return time, type, code, value
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# https://www.kernel.org/doc/html/v4.12/input/uinput.html
|
122
|
+
class Uinput
|
123
|
+
UI_SET_EVBIT = 1074025828
|
124
|
+
UI_SET_KEYBIT = 1074025829
|
125
|
+
UI_DEV_SETUP = 1079792899
|
126
|
+
UI_DEV_CREATE = 21761
|
127
|
+
|
128
|
+
def initialize
|
129
|
+
@dev = File.open('/dev/uinput', 'w')
|
130
|
+
setup
|
131
|
+
end
|
132
|
+
|
133
|
+
def setup
|
134
|
+
@dev.ioctl(UI_SET_EVBIT, EV_KEY)
|
135
|
+
KeyCode::KEY_CNT.times{|k| @dev.ioctl(UI_SET_KEYBIT, k)}
|
136
|
+
bustype = 0x03 # BUS_USB
|
137
|
+
vendor = 0x1234 # てきとー
|
138
|
+
product = 0x5678 # てきとー
|
139
|
+
version = 1 # てきとー
|
140
|
+
name = 'rkremap'
|
141
|
+
ff_efects_max = 0
|
142
|
+
setup = [bustype, vendor, product, version, name, ff_efects_max].pack("SSSSZ80L") # struct uinput_setup
|
143
|
+
@dev.ioctl(UI_DEV_SETUP, setup)
|
144
|
+
@dev.ioctl(UI_DEV_CREATE)
|
145
|
+
end
|
146
|
+
|
147
|
+
# @param type [Integer] EV_KEY/ EV_SYN
|
148
|
+
# @param code [Integer] キーコード / SYN_REPORT
|
149
|
+
# @param value [Integer] 0:release / 1:press / 2:repeat
|
150
|
+
def write_event(type, code, value)
|
151
|
+
@dev.syswrite(['', type, code, value].pack('a16SSl'))
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
data/lib/rkremap/version.rb
CHANGED
data/lib/rkremap/winattr.rb
CHANGED
@@ -1,12 +1,4 @@
|
|
1
|
-
require '
|
2
|
-
|
3
|
-
module FFI
|
4
|
-
typedef :pointer, :Display
|
5
|
-
typedef :ulong, :XID
|
6
|
-
typedef :XID, :Window
|
7
|
-
typedef :int, :Status
|
8
|
-
typedef :ulong, :Atom
|
9
|
-
end
|
1
|
+
require 'fiddle/import'
|
10
2
|
|
11
3
|
class Rkremap
|
12
4
|
# アプリの name, class, title を取得する
|
@@ -14,38 +6,39 @@ class Rkremap
|
|
14
6
|
def initialize
|
15
7
|
@app_win = {}
|
16
8
|
@display = X11.XOpenDisplay(nil) or raise "Cannot open display: #{ENV['DISPLAY']}"
|
9
|
+
@buf = ' '*8
|
17
10
|
end
|
18
11
|
|
12
|
+
# @return [Integer] Window
|
19
13
|
def focus_win
|
20
|
-
win =
|
21
|
-
|
22
|
-
|
23
|
-
win.read(:Window)
|
14
|
+
win = X11::Window.malloc(Fiddle::RUBY_FREE)
|
15
|
+
X11.XGetInputFocus(@display, win, @buf)
|
16
|
+
win.window
|
24
17
|
end
|
25
18
|
|
26
19
|
# @return [Array<window, name, class>]
|
27
20
|
def app_win(window)
|
28
21
|
return @app_win[window] if @app_win[window]
|
29
|
-
class_hint = XClassHint.
|
30
|
-
|
31
|
-
|
32
|
-
children = FFI::MemoryPointer.new(:pointer)
|
33
|
-
nchildren = FFI::MemoryPointer.new(:int)
|
22
|
+
class_hint = X11::XClassHint.malloc(Fiddle::RUBY_FREE)
|
23
|
+
parent = X11::Window.malloc(Fiddle::RUBY_FREE)
|
24
|
+
children = X11::Pointer.malloc(Fiddle::RUBY_FREE)
|
34
25
|
win = window
|
35
26
|
while win > 0
|
27
|
+
class_hint.name = nil
|
28
|
+
class_hint.class_name = nil
|
36
29
|
X11.XGetClassHint(@display, win, class_hint)
|
37
|
-
X11.XQueryTree(@display, win,
|
38
|
-
X11.XFree(children.
|
39
|
-
break unless class_hint
|
40
|
-
win = parent.
|
30
|
+
X11.XQueryTree(@display, win, @buf, parent, children, @buf)
|
31
|
+
X11.XFree(children.ptr)
|
32
|
+
break unless class_hint.name.null? && class_hint.class_name.null?
|
33
|
+
win = parent.window
|
41
34
|
end
|
42
|
-
unless class_hint
|
43
|
-
win_name = class_hint
|
44
|
-
X11.XFree(class_hint
|
35
|
+
unless class_hint.name.null?
|
36
|
+
win_name = class_hint.name.to_s
|
37
|
+
X11.XFree(class_hint.name)
|
45
38
|
end
|
46
|
-
unless class_hint
|
47
|
-
win_class = class_hint
|
48
|
-
X11.XFree(class_hint
|
39
|
+
unless class_hint.class_name.null?
|
40
|
+
win_class = class_hint.class_name.to_s
|
41
|
+
X11.XFree(class_hint.class_name)
|
49
42
|
end
|
50
43
|
@app_win[window] = [win, win_name, win_class]
|
51
44
|
end
|
@@ -53,43 +46,35 @@ class Rkremap
|
|
53
46
|
# @return [String]
|
54
47
|
def app_title(window)
|
55
48
|
win = app_win(window)[0]
|
56
|
-
prop = XTextProperty.
|
57
|
-
text_list =
|
58
|
-
count = FFI::MemoryPointer.new(:int)
|
49
|
+
prop = X11::XTextProperty.malloc(Fiddle::RUBY_FREE)
|
50
|
+
text_list = X11::Pointer.malloc(Fiddle::RUBY_FREE)
|
59
51
|
X11.XGetWMName(@display, win, prop)
|
60
|
-
X11.Xutf8TextPropertyToTextList(@display, prop, text_list,
|
61
|
-
title = text_list.
|
62
|
-
X11.XFreeStringList(text_list.
|
52
|
+
X11.Xutf8TextPropertyToTextList(@display, prop, text_list, @buf)
|
53
|
+
title = text_list.ptr.ptr.to_s.force_encoding('utf-8')
|
54
|
+
X11.XFreeStringList(text_list.ptr)
|
63
55
|
title
|
64
56
|
end
|
65
57
|
end
|
66
58
|
|
67
|
-
class XClassHint < FFI::Struct
|
68
|
-
layout(
|
69
|
-
:name, :pointer,
|
70
|
-
:class, :pointer,
|
71
|
-
)
|
72
|
-
end
|
73
|
-
|
74
|
-
class XTextProperty < FFI::Struct
|
75
|
-
layout(
|
76
|
-
:value, :pointer,
|
77
|
-
:encoding, :Atom,
|
78
|
-
:format, :int,
|
79
|
-
:nitems, :ulong,
|
80
|
-
)
|
81
|
-
end
|
82
|
-
|
83
59
|
module X11
|
84
|
-
extend
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
60
|
+
extend Fiddle::Importer
|
61
|
+
dlload 'libX11.so.6'
|
62
|
+
typealias 'XID', 'unsigned long'
|
63
|
+
typealias 'Window', 'XID'
|
64
|
+
typealias 'Status', 'int'
|
65
|
+
typealias 'Atom', 'unsigned long'
|
66
|
+
Window = struct ['Window window']
|
67
|
+
Pointer = struct ['void *ptr']
|
68
|
+
XClassHint = struct ['char *name', 'char *class_name']
|
69
|
+
XTextProperty = struct ['unsigned char *value', 'Atom encoding', 'int format', 'unsigned long nitems']
|
70
|
+
|
71
|
+
extern 'Display* XOpenDisplay(char*)'
|
72
|
+
extern 'int XGetInputFocus(Display*, Window*, int*)'
|
73
|
+
extern 'int XGetClassHint(Display*, Window, XClassHint*)'
|
74
|
+
extern 'Status XQueryTree(Display*, Window, Window*, Window*, Window**, unsigned int*)'
|
75
|
+
extern 'Status XGetWMName(Display*, Window, XTextProperty*)'
|
76
|
+
extern 'int Xutf8TextPropertyToTextList(Display*, XTextProperty*, char***, int*)'
|
77
|
+
extern 'int XFree(void*)'
|
78
|
+
extern 'void XFreeStringList(char**)'
|
94
79
|
end
|
95
80
|
end
|
data/lib/rkremap.rb
CHANGED
@@ -3,20 +3,11 @@
|
|
3
3
|
require_relative "rkremap/version"
|
4
4
|
require_relative 'rkremap/keycode'
|
5
5
|
require_relative 'rkremap/winattr'
|
6
|
+
require_relative 'rkremap/evdev'
|
6
7
|
|
7
8
|
class Rkremap
|
8
9
|
include KeyCode
|
9
10
|
|
10
|
-
# ioctl constants
|
11
|
-
EVIOCGRAB = 1074021776
|
12
|
-
UI_SET_EVBIT = 1074025828
|
13
|
-
UI_SET_KEYBIT = 1074025829
|
14
|
-
UI_DEV_SETUP = 1079792899
|
15
|
-
UI_DEV_CREATE = 21761
|
16
|
-
EV_KEY = 1
|
17
|
-
EV_SYN = 0
|
18
|
-
SYN_REPORT = 0
|
19
|
-
|
20
11
|
EVENT_TYPE_VALUE = {
|
21
12
|
release: 0,
|
22
13
|
press: 1,
|
@@ -26,12 +17,19 @@ class Rkremap
|
|
26
17
|
attr_accessor :grab
|
27
18
|
attr_accessor :modifiers
|
28
19
|
attr_accessor :x11
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
20
|
+
attr_accessor :auto_detect
|
21
|
+
|
22
|
+
# @param devices [Array<String>, String]
|
23
|
+
def initialize(devices=nil)
|
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
|
31
|
+
raise 'Unable to detect keyboard device' if @inputs.empty?
|
32
|
+
@uinput = Uinput.new
|
35
33
|
@grab = false
|
36
34
|
@x11 = false
|
37
35
|
@modifiers = [
|
@@ -51,15 +49,14 @@ class Rkremap
|
|
51
49
|
end
|
52
50
|
|
53
51
|
def start(&block)
|
54
|
-
|
52
|
+
detect_device_loop if @auto_detect
|
53
|
+
@mod_state = @modifiers.map.to_h{|m| [m, false]}
|
55
54
|
@winattr = WinAttr.new if @x11
|
56
|
-
@
|
55
|
+
@inputs.each(&:grab) if @grab
|
57
56
|
while true
|
58
57
|
@keys = []
|
59
|
-
|
60
|
-
sec, usec, type, code, value = raw.unpack('Q!Q!SSl')
|
58
|
+
time, type, code, value = read_event
|
61
59
|
next if type != EV_KEY
|
62
|
-
time = Time.at(sec, usec)
|
63
60
|
event = Event.new(time, code, value, @winattr)
|
64
61
|
@events.each do |cond, b|
|
65
62
|
synchronize{ b.call event } if event.match?(**cond)
|
@@ -73,6 +70,32 @@ class Rkremap
|
|
73
70
|
end
|
74
71
|
end
|
75
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
|
+
|
76
99
|
def synchronize(&block)
|
77
100
|
@mutex.synchronize(&block)
|
78
101
|
end
|
@@ -100,20 +123,6 @@ class Rkremap
|
|
100
123
|
|
101
124
|
private
|
102
125
|
|
103
|
-
def setup_uinput
|
104
|
-
@uinput.ioctl(UI_SET_EVBIT, EV_KEY)
|
105
|
-
KEY_CNT.times{|k| @uinput.ioctl(UI_SET_KEYBIT, k)}
|
106
|
-
bustype = 0x03 # BUS_USB
|
107
|
-
vendor = 0x1234 # てきとー
|
108
|
-
product = 0x5678 # てきとー
|
109
|
-
version = 1 # てきとー
|
110
|
-
name = 'rkremap'
|
111
|
-
ff_efects_max = 0
|
112
|
-
setup = [bustype, vendor, product, version, name, ff_efects_max].pack("SSSSZ80L") # struct uinput_setup
|
113
|
-
@uinput.ioctl(UI_DEV_SETUP, setup)
|
114
|
-
@uinput.ioctl(UI_DEV_CREATE)
|
115
|
-
end
|
116
|
-
|
117
126
|
def proc_event(code, value, event)
|
118
127
|
if @mod_state.include?(code)
|
119
128
|
@mod_state[code] = value != 0
|
@@ -130,8 +139,8 @@ class Rkremap
|
|
130
139
|
# @param code [Integer]
|
131
140
|
# @param value [Integer] 0:release / 1:press / 2:repeat
|
132
141
|
def write_event(code, value)
|
133
|
-
@uinput.
|
134
|
-
@uinput.
|
142
|
+
@uinput.write_event(EV_KEY, code, value)
|
143
|
+
@uinput.write_event(EV_SYN, SYN_REPORT, 0)
|
135
144
|
end
|
136
145
|
|
137
146
|
class Event
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
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-
|
12
|
-
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: ffi
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '1.0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '1.0'
|
11
|
+
date: 2022-03-05 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
27
13
|
description: key remapper
|
28
14
|
email:
|
29
15
|
- tommy@tmtm.org
|
@@ -37,6 +23,7 @@ files:
|
|
37
23
|
- example/mac-shortcut.rb
|
38
24
|
- example/tmtms.rb
|
39
25
|
- lib/rkremap.rb
|
26
|
+
- lib/rkremap/evdev.rb
|
40
27
|
- lib/rkremap/keycode.rb
|
41
28
|
- lib/rkremap/version.rb
|
42
29
|
- lib/rkremap/winattr.rb
|