rkremap 0.1.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 945483dcd11240d5c54b359a15055219532f2f311275633503e7d485aa68917b
4
- data.tar.gz: d594c9b549696f964cde750094169ba7198c0ac9ab5f5dfc59a7936d9610a09d
3
+ metadata.gz: 04a75325e18cfa14e1eeb93462af309c6d692083c5ef4a2609e6dfd53747a6c8
4
+ data.tar.gz: 1f86fc05c3098eed25b0d09bbebfc75fdad37122898ee9762376ce5241f21c60
5
5
  SHA512:
6
- metadata.gz: a1412a373a0673172a9eba0449613ab9a76debf400b622977887031c294f8381a58a7c060ef6451e6264703690974aeddb305ce35619c07958a2b5a1239ecf12
7
- data.tar.gz: 619ee1de0814c2542c2a4f347dca7c48e640590a01ff58f2b7362ed80ef447acaf1576df2a2a659eaac95c9a7ec0a8f52d732d8024356613fbef43f055b16dd2
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
- 引数に `/dev/input/event*` を指定する。キーボードデバイス以外を指定してもたぶん無意味。
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)
@@ -4,7 +4,7 @@
4
4
  require 'rkremap'
5
5
  include Rkremap::KeyCode
6
6
 
7
- rk = Rkremap.new('/dev/input/event3')
7
+ rk = Rkremap.new
8
8
  rk.grab = true
9
9
 
10
10
  class State
data/example/keylogger.rb CHANGED
@@ -6,7 +6,7 @@ def code2key(code)
6
6
  Rkremap::CODE_KEY[code].to_s.sub(/\AKEY_/, '')
7
7
  end
8
8
 
9
- rk = Rkremap.new('/dev/input/event3')
9
+ rk = Rkremap.new
10
10
  rk.grab = false
11
11
  rk.x11 = true
12
12
  rk.start do |code, mod, app|
@@ -33,7 +33,7 @@ mod_disable_meta = {
33
33
  }
34
34
  mod_disable_all = {}.merge(mod_disable_ctrl, mod_disable_shift, mod_disable_alt, mod_disable_meta)
35
35
 
36
- rk = Rkremap.new("/dev/input/event3")
36
+ rk = Rkremap.new
37
37
  rk.grab = true
38
38
  rk.x11 = true
39
39
  rk.start do |code, mod, app|
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("/dev/input/event3")
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+K は行末まで削除 (日本語変換時はそのまま)
163
- if code == KEY_K && !File.exist?('/tmp/fcitx-enabled')
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Rkremap
4
- VERSION = "0.1.0"
4
+ VERSION = "0.3.0"
5
5
  end
@@ -1,12 +1,4 @@
1
- require 'ffi'
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 = FFI::MemoryPointer.new(:Window)
21
- revert_to = FFI::MemoryPointer.new(:int)
22
- X11.XGetInputFocus(@display, win, revert_to)
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.new
30
- root = FFI::MemoryPointer.new(:Window)
31
- parent = FFI::MemoryPointer.new(:Window)
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, root, parent, children, nchildren)
38
- X11.XFree(children.read_pointer)
39
- break unless class_hint[:name].null? && class_hint[:class].null?
40
- win = parent.read(:Window)
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[:name].null?
43
- win_name = class_hint[:name].read_string
44
- X11.XFree(class_hint[:name])
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[:class].null?
47
- win_class = class_hint[:class].read_string
48
- X11.XFree(class_hint[:class])
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.new
57
- text_list = FFI::MemoryPointer.new(:pointer)
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, count)
61
- title = text_list.read(:pointer).read(:string)&.force_encoding('utf-8')
62
- X11.XFreeStringList(text_list.read(:pointer))
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 FFI::Library
85
- ffi_lib 'X11'
86
- attach_function :XOpenDisplay, [:string], :Display
87
- attach_function :XGetInputFocus, [:Display, :pointer, :pointer], :int
88
- attach_function :XGetClassHint, [:Display, :Window, XClassHint.by_ref], :int
89
- attach_function :XQueryTree, [:Display, :Window, :pointer, :pointer, :pointer, :pointer], :Status
90
- attach_function :XGetWMName, [:Display, :Window, XTextProperty.by_ref], :void
91
- attach_function :Xutf8TextPropertyToTextList, [:Display, XTextProperty.by_ref, :pointer, :pointer], :int
92
- attach_function :XFree, [:pointer], :int
93
- attach_function :XFreeStringList, [:pointer], :void
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
- # @param device [String]
31
- def initialize(device)
32
- @input = File.open(device)
33
- @uinput = File.open('/dev/uinput', 'w')
34
- setup_uinput
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
- @mod_state = @modifiers.map{|m| [m, false]}.to_h
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
- @input.ioctl(EVIOCGRAB, 1) if @grab
55
+ @inputs.each(&:grab) if @grab
57
56
  while true
58
57
  @keys = []
59
- raw = @input.sysread(24)
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.syswrite(['', EV_KEY, code, value].pack('a16SSl'))
134
- @uinput.syswrite(['', EV_SYN, SYN_REPORT, 0].pack('a16SSl'))
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.1.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-01-10 00:00:00.000000000 Z
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