rkremap 0.3.0.1 → 0.5.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 +107 -5
- data/example/henkan-super.rb +9 -41
- data/example/keylogger.rb +2 -2
- data/example/mac-shortcut.rb +49 -12
- data/example/tmtms.rb +74 -68
- data/lib/rkremap/evdev.rb +47 -85
- data/lib/rkremap/evdev_list.rb +90 -0
- data/lib/rkremap/event.rb +48 -0
- data/lib/rkremap/keycode.rb +81 -1
- data/lib/rkremap/remap.rb +105 -0
- data/lib/rkremap/uinput.rb +40 -0
- data/lib/rkremap/version.rb +1 -1
- data/lib/rkremap/winattr.rb +4 -1
- data/lib/rkremap.rb +113 -85
- metadata +21 -3
data/lib/rkremap.rb
CHANGED
@@ -1,13 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
3
|
+
require_relative 'rkremap/version'
|
4
4
|
require_relative 'rkremap/keycode'
|
5
5
|
require_relative 'rkremap/winattr'
|
6
|
+
require_relative 'rkremap/evdev_list'
|
6
7
|
require_relative 'rkremap/evdev'
|
8
|
+
require_relative 'rkremap/event'
|
9
|
+
require_relative 'rkremap/uinput'
|
10
|
+
require_relative 'rkremap/remap'
|
7
11
|
|
8
12
|
class Rkremap
|
9
13
|
include KeyCode
|
10
14
|
|
15
|
+
# /usr/include/linux/input-event-codes.h
|
16
|
+
EV_SYN = 0
|
17
|
+
EV_KEY = 1
|
18
|
+
EV_REL = 2
|
19
|
+
EV_ABS = 3
|
20
|
+
EV_MSC = 4
|
21
|
+
SYN_REPORT = 0
|
22
|
+
|
11
23
|
EVENT_TYPE_VALUE = {
|
12
24
|
release: 0,
|
13
25
|
press: 1,
|
@@ -18,17 +30,21 @@ class Rkremap
|
|
18
30
|
attr_accessor :modifiers
|
19
31
|
attr_accessor :x11
|
20
32
|
attr_accessor :auto_detect
|
33
|
+
attr_accessor :exclude
|
34
|
+
attr_accessor :mouse
|
21
35
|
|
22
36
|
# @param devices [Array<String>, String]
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
else
|
37
|
+
# @param exclude [Regexp]
|
38
|
+
# @param mouse [Boolean]
|
39
|
+
def initialize(devices=[], exclude: nil, mouse: false)
|
40
|
+
if devices.empty?
|
28
41
|
@auto_detect = true
|
29
|
-
|
42
|
+
else
|
43
|
+
devices = Array(devices)
|
30
44
|
end
|
31
|
-
|
45
|
+
@devices = devices
|
46
|
+
@exclude = exclude
|
47
|
+
@mouse = mouse
|
32
48
|
@uinput = Uinput.new
|
33
49
|
@grab = false
|
34
50
|
@x11 = false
|
@@ -38,60 +54,54 @@ class Rkremap
|
|
38
54
|
KEY_LEFTALT, KEY_RIGHTALT,
|
39
55
|
KEY_LEFTMETA, KEY_RIGHTMETA,
|
40
56
|
]
|
41
|
-
@
|
57
|
+
@event_procs = []
|
42
58
|
@mutex = Mutex.new
|
43
59
|
end
|
44
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
|
+
|
72
|
+
# @param device [Symbol, Regexp]
|
45
73
|
# @param code [Integer]
|
46
74
|
# @param type [Symbol] :press / :release / :repeat
|
47
|
-
|
48
|
-
|
75
|
+
# @param app [Regexp, String]
|
76
|
+
def match(device: nil, code: nil, type: nil, app: nil, &block)
|
77
|
+
@event_procs.push [{device: device, code: code, type: type, app: app}, block]
|
49
78
|
end
|
50
79
|
|
51
80
|
def start(&block)
|
52
|
-
|
81
|
+
@evdev_list = EvdevList.new(@devices, auto_detect: @auto_detect, exclude: @exclude, detect_mouse: @mouse)
|
82
|
+
@evdev_list.grab = @grab
|
83
|
+
@evdev_list.detect_loop
|
53
84
|
@mod_state = @modifiers.map.to_h{|m| [m, false]}
|
54
|
-
|
55
|
-
@inputs.each(&:grab) if @grab
|
85
|
+
winattr = WinAttr.new if @x11
|
56
86
|
while true
|
57
87
|
@keys = []
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
synchronize{ b.call event } if event.match?(**cond)
|
63
|
-
break if event.skipped
|
64
|
-
end
|
65
|
-
next if event.skipped
|
66
|
-
synchronize{ proc_event(code, value, event) }
|
67
|
-
@keys.each do |c, mod, app|
|
68
|
-
synchronize{ block.call(c, mod, app) } if block
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
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
|
88
|
+
event = @evdev_list.read_event
|
89
|
+
if event.ev_type != EV_KEY
|
90
|
+
if event.device.grab?
|
91
|
+
@uinput.write_event(event.ev_type, event.code, event.value)
|
81
92
|
end
|
93
|
+
next
|
82
94
|
end
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
input.close rescue nil
|
94
|
-
@inputs.delete input
|
95
|
+
app = App.new(winattr) if winattr
|
96
|
+
event.app = app
|
97
|
+
@event_procs.each do |cond, b|
|
98
|
+
synchronize{ b.call(event, @mod_state.dup, app) } if event.match?(**cond)
|
99
|
+
break if event.skipped?
|
100
|
+
end
|
101
|
+
next if event.skipped?
|
102
|
+
synchronize{ proc_event(event, app) }
|
103
|
+
@keys.each do |c, mod, app_|
|
104
|
+
synchronize{ block.call(c, mod, app_) } if block
|
95
105
|
end
|
96
106
|
end
|
97
107
|
end
|
@@ -102,20 +112,27 @@ class Rkremap
|
|
102
112
|
|
103
113
|
# @param code [Integer]
|
104
114
|
# @param type [Symbol] :press / :release / :repeat
|
105
|
-
|
106
|
-
def event(code: nil, type: nil, event: nil)
|
115
|
+
def event(code: nil, type: nil)
|
107
116
|
value = EVENT_TYPE_VALUE[type] or raise "invalid type: #{type.inspect}"
|
108
|
-
|
117
|
+
update_modifiers(code, value)
|
118
|
+
write_event(code, value)
|
109
119
|
end
|
110
120
|
|
111
121
|
# @param code [Integer]
|
112
122
|
# @param mod [Hash] {MOD_KEY => true, ...}
|
113
123
|
def key(code, mod={})
|
124
|
+
with_modifier(mod) do
|
125
|
+
write_event(code, 1)
|
126
|
+
write_event(code, 0)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# @param mod [Hash] {MOD_KEY => true, ...}
|
131
|
+
def with_modifier(mod, &block)
|
114
132
|
mod_diff(mod).each do |mcode, state|
|
115
133
|
write_event(mcode, state ? 1 : 0)
|
116
134
|
end
|
117
|
-
|
118
|
-
write_event(code, 0)
|
135
|
+
block.call
|
119
136
|
mod_diff(mod).each do |mcode, _|
|
120
137
|
write_event(mcode, @mod_state[mcode] ? 1 : 0)
|
121
138
|
end
|
@@ -123,12 +140,23 @@ class Rkremap
|
|
123
140
|
|
124
141
|
private
|
125
142
|
|
126
|
-
def
|
143
|
+
def update_modifiers(code, value)
|
127
144
|
if @mod_state.include?(code)
|
128
145
|
@mod_state[code] = value != 0
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# @param event [Rkremap::Event]
|
150
|
+
# @param app [Rkremap::App]
|
151
|
+
def proc_event(event, app)
|
152
|
+
code, value = event.code, event.value
|
153
|
+
if @mod_state.include?(code)
|
129
154
|
write_event(code, value)
|
130
|
-
|
131
|
-
|
155
|
+
update_modifiers(code, value)
|
156
|
+
elsif value == 0
|
157
|
+
write_event(code, value)
|
158
|
+
else
|
159
|
+
@keys.push [code, @mod_state.dup, app]
|
132
160
|
end
|
133
161
|
end
|
134
162
|
|
@@ -140,46 +168,46 @@ class Rkremap
|
|
140
168
|
# @param value [Integer] 0:release / 1:press / 2:repeat
|
141
169
|
def write_event(code, value)
|
142
170
|
@uinput.write_event(EV_KEY, code, value)
|
143
|
-
@uinput.write_event(EV_SYN, SYN_REPORT, 0)
|
144
|
-
end
|
145
|
-
|
146
|
-
class Event
|
147
|
-
attr_reader :time
|
148
|
-
attr_reader :code
|
149
|
-
attr_reader :type
|
150
|
-
attr_reader :win
|
151
|
-
attr_reader :skipped
|
152
|
-
|
153
|
-
def initialize(time, code, value, winattr)
|
154
|
-
@time = time
|
155
|
-
@code = code
|
156
|
-
@value = value
|
157
|
-
@type = value == 1 ? :press : value == 0 ? :release : :repeat
|
158
|
-
@win = winattr&.focus_win
|
159
|
-
@skipped = false
|
160
|
-
end
|
161
|
-
|
162
|
-
def match?(code: nil, type: nil)
|
163
|
-
(code.nil? || Array(code).include?(@code)) && (type.nil? || Array(type).include?(@type))
|
164
|
-
end
|
165
|
-
|
166
|
-
def skip
|
167
|
-
@skipped = true
|
168
|
-
end
|
169
171
|
end
|
170
172
|
|
171
173
|
class App
|
172
|
-
|
173
|
-
|
174
|
+
# @param winattr [Rkremap::WinAttr]
|
175
|
+
def initialize(winattr)
|
174
176
|
@winattr = winattr
|
177
|
+
@win = winattr.focus_win
|
175
178
|
end
|
176
179
|
|
180
|
+
# @return [String, nil]
|
177
181
|
def class_name
|
178
182
|
@winattr.app_win(@win)[2] if @winattr && @win
|
179
183
|
end
|
180
184
|
|
185
|
+
# @return [String, nil]
|
181
186
|
def title
|
182
187
|
@winattr.app_title(@win) if @winattr && @win
|
183
188
|
end
|
189
|
+
|
190
|
+
# @param app [Array, Hash, String, Regexp]
|
191
|
+
# @return [Boolean]
|
192
|
+
def match?(app)
|
193
|
+
Array(app).each do |a|
|
194
|
+
a = {class_name: a, title: a} unless a.is_a? Hash
|
195
|
+
return true if match_sub(a[:class_name], class_name) || match_sub(a[:title], title)
|
196
|
+
end
|
197
|
+
false
|
198
|
+
end
|
199
|
+
|
200
|
+
# @param a [String, Regexp]
|
201
|
+
# @param b [String]
|
202
|
+
def match_sub(a, b)
|
203
|
+
case a
|
204
|
+
when String
|
205
|
+
a == b
|
206
|
+
when Regexp
|
207
|
+
a =~ b
|
208
|
+
else
|
209
|
+
false
|
210
|
+
end
|
211
|
+
end
|
184
212
|
end
|
185
213
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rkremap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.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:
|
11
|
+
date: 2022-09-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: tmtms_timer
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.3'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.3'
|
13
27
|
description: key remapper
|
14
28
|
email:
|
15
29
|
- tommy@tmtm.org
|
@@ -24,7 +38,11 @@ files:
|
|
24
38
|
- example/tmtms.rb
|
25
39
|
- lib/rkremap.rb
|
26
40
|
- lib/rkremap/evdev.rb
|
41
|
+
- lib/rkremap/evdev_list.rb
|
42
|
+
- lib/rkremap/event.rb
|
27
43
|
- lib/rkremap/keycode.rb
|
44
|
+
- lib/rkremap/remap.rb
|
45
|
+
- lib/rkremap/uinput.rb
|
28
46
|
- lib/rkremap/version.rb
|
29
47
|
- lib/rkremap/winattr.rb
|
30
48
|
homepage: https://gitlab.com/tmtms/rkremap
|