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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d204d310504030119a941b532fec985cae5747c1d1e04958baefbb112327a629
4
- data.tar.gz: c98176cf3e753eb59da16e614159a5516e9bc1701e63806ec02d3e3bd8c4d076
3
+ metadata.gz: 04a75325e18cfa14e1eeb93462af309c6d692083c5ef4a2609e6dfd53747a6c8
4
+ data.tar.gz: 1f86fc05c3098eed25b0d09bbebfc75fdad37122898ee9762376ce5241f21c60
5
5
  SHA512:
6
- metadata.gz: e04feb18bbae681fc1b5bbd2f8a95ea85b58aff976865d857fd044274214eb9f2502c34bb7ff4cb9b620f3658e55f82157b4c6b98dbe4eb5dce8ce8446ff042d
7
- data.tar.gz: 941f5b2893c031a7891151635b8cfb83d5ce410d8c0751da86a2b2699ce440a10221684dba881849bd54f4afa10f3b18cd8defe98b0a7601cfed4f5eb15bd7b6
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-K/I/O は日本語変換時はそのまま
163
- if (code == KEY_K || code == KEY_I || code ==KEY_O) && File.exist?('/tmp/fcitx-enabled')
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.devices
19
- Dir.children("/dev/input").map do |dev|
20
- dev =~ /\Aevent\d+\z/ ? Evdev.new("/dev/input/#{dev}") : nil
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
- h = inputs.map{|ev| [ev.io, ev]}.to_h
28
- r, = IO.select(inputs.map(&:io), nil, nil, nil)
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) &&
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Rkremap
4
- VERSION = "0.2.1"
4
+ VERSION = "0.3.0"
5
5
  end
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
- devices = Array(devices) if devices.is_a? String
24
- @inputs = devices ? devices.map{|d| Evdev.new(d)} : Evdev.devices.select(&:keyboard?)
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
- @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]}
47
54
  @winattr = WinAttr.new if @x11
48
55
  @inputs.each(&:grab) if @grab
49
56
  while true
50
57
  @keys = []
51
- input = Evdev.select(@inputs)
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.2.1
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-29 00:00:00.000000000 Z
11
+ date: 2022-03-05 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: key remapper
14
14
  email: