Class: Rbindkeys::KeyEventHandler
- Inherits:
-
Object
- Object
- Rbindkeys::KeyEventHandler
- Includes:
- Revdev
- Defined in:
- lib/rbindkeys/key_event_handler.rb,
lib/rbindkeys.rb,
lib/rbindkeys/key_event_handler/configurer.rb
Overview
retrive key binds with key event
Constant Summary collapse
- LOG =
LogUtils.get_logger name
Instance Attribute Summary collapse
-
#active_bind_set ⇒ Object
readonly
pressed key binds.
-
#bind_resolver ⇒ Object
readonly
current key bind set which retrive key binds with a key event.
-
#default_bind_resolver ⇒ Object
readonly
defaulut key bind set which retrive key binds with a key event.
-
#operator ⇒ Object
readonly
device operator.
-
#pre_bind_resolver ⇒ Object
readonly
proccessed resolver before bind_resolver.
-
#pressed_key_set ⇒ Object
readonly
code set of pressed key on the event device.
-
#window_bind_resolver_map ⇒ Object
readonly
a hash (key:WindowMatcher, val:BindResolver) to switch BindResolver by the title or app_name of active window.
Class Method Summary collapse
- .get_state_by_value(ev) ⇒ Object
-
.parse_code(code, depth = 0) ⇒ Object
parse and normalize to Fixnum/Array.
-
.parse_symbol(sym) ⇒ Object
TODO convert :j -> KEY_J, :ctrl -> KEY_LEFTCTRL.
Instance Method Summary collapse
- #active_window_changed(window) ⇒ Object
-
#bind_key(input, output = nil, resolver = @bind_resolver, &block) ⇒ Object
define a new key binding.
-
#bind_prefix_key(input, resolver = @bind_resolver, &block) ⇒ Object
- setting for 2stroke key binding input
-
prefix key.
- #fill_gap_pressed_state(event) ⇒ Object
- #handle(event) ⇒ Object
- #handle_press_event(event) ⇒ Object
- #handle_pressed_keys(event) ⇒ Object
- #handle_pressing_event(event) ⇒ Object
- #handle_release_event(event) ⇒ Object
-
#initialize(device_operator) ⇒ KeyEventHandler
constructor
A new instance of KeyEventHandler.
- #load_config(file) ⇒ Object
- #new_bind_resolver(upper_resolver = @bind_resolver, &block) ⇒ Object
-
#pre_bind_key(input, output) ⇒ Object
pre-prosessed key codes replacement for all inputs.
- #set_bind_resolver(resolver) ⇒ Object
-
#window(upper_resolver, arg) ⇒ Object
switch bind_resolver if the active window match arg.
Constructor Details
#initialize(device_operator) ⇒ KeyEventHandler
Returns a new instance of KeyEventHandler.
36 37 38 39 40 41 42 43 44 45 |
# File 'lib/rbindkeys/key_event_handler.rb', line 36 def initialize device_operator @operator = device_operator @default_bind_resolver = BindResolver.new @window_bind_resolver = nil @bind_resolver = @default_bind_resolver @window_bind_resolver_map = [] @pre_bind_resolver = {} @pressed_key_set = [] @active_bind_set = [] end |
Instance Attribute Details
#active_bind_set ⇒ Object (readonly)
pressed key binds
34 35 36 |
# File 'lib/rbindkeys/key_event_handler.rb', line 34 def active_bind_set @active_bind_set end |
#bind_resolver ⇒ Object (readonly)
current key bind set which retrive key binds with a key event
21 22 23 |
# File 'lib/rbindkeys/key_event_handler.rb', line 21 def bind_resolver @bind_resolver end |
#default_bind_resolver ⇒ Object (readonly)
defaulut key bind set which retrive key binds with a key event
18 19 20 |
# File 'lib/rbindkeys/key_event_handler.rb', line 18 def default_bind_resolver @default_bind_resolver end |
#operator ⇒ Object (readonly)
device operator
15 16 17 |
# File 'lib/rbindkeys/key_event_handler.rb', line 15 def operator @operator end |
#pre_bind_resolver ⇒ Object (readonly)
proccessed resolver before bind_resolver
28 29 30 |
# File 'lib/rbindkeys/key_event_handler.rb', line 28 def pre_bind_resolver @pre_bind_resolver end |
#pressed_key_set ⇒ Object (readonly)
code set of pressed key on the event device
31 32 33 |
# File 'lib/rbindkeys/key_event_handler.rb', line 31 def pressed_key_set @pressed_key_set end |
#window_bind_resolver_map ⇒ Object (readonly)
a hash (key:WindowMatcher, val:BindResolver) to switch BindResolver by the title or app_name of active window
25 26 27 |
# File 'lib/rbindkeys/key_event_handler.rb', line 25 def window_bind_resolver_map @window_bind_resolver_map end |
Class Method Details
.get_state_by_value(ev) ⇒ Object
232 233 234 235 236 237 238 |
# File 'lib/rbindkeys/key_event_handler.rb', line 232 def get_state_by_value ev case ev.value when 0 then 'released ' when 1 then 'pressed ' when 2 then 'pressing ' end end |
.parse_code(code, depth = 0) ⇒ Object
parse and normalize to Fixnum/Array
210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/rbindkeys/key_event_handler.rb', line 210 def parse_code code, depth = 0 if code.kind_of? Symbol code = parse_symbol code elsif code.kind_of? Array raise ArgumentError, "expect Array is the depth less than 1" if depth >= 1 code.map!{|c| parse_code c, (depth+1)} elsif code.kind_of? Fixnum and depth == 0 code = [code] elsif not code.kind_of? Fixnum raise ArgumentError, "expect Symbol / Fixnum / Array" end code end |
.parse_symbol(sym) ⇒ Object
TODO convert :j -> KEY_J, :ctrl -> KEY_LEFTCTRL
225 226 227 228 229 230 |
# File 'lib/rbindkeys/key_event_handler.rb', line 225 def parse_symbol sym if not sym.kind_of? Symbol raise ArgumentError, "expect Symbol / Fixnum / Array" end Revdev.const_get sym end |
Instance Method Details
#active_window_changed(window) ⇒ Object
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/rbindkeys/key_event_handler.rb', line 175 def active_window_changed window if not window.nil? title = window.title app_name = window.app_name if LOG.info? LOG.info "" unless LOG.debug? LOG.info "change active_window: :class => \"#{app_name}\", :title => \"#{title}\"" end @window_bind_resolver_map.each do |matcher, bind_resolver| if matcher.match? app_name, title if LOG.info? LOG.info "=> matcher #{matcher.app_name.inspect}, #{matcher.title.inspect}" LOG.info " bind_resolver #{bind_resolver.inspect}" end set_bind_resolver bind_resolver @window_bind_resolver = bind_resolver return end end else if LOG.info? LOG.info "" unless LOG.debug? LOG.info "change active_window: nil" end end LOG.info "=> no matcher" if LOG.info? set_bind_resolver @default_bind_resolver @window_bind_resolver = nil return end |
#bind_key(input, output = nil, resolver = @bind_resolver, &block) ⇒ Object
define a new key binding
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/rbindkeys/key_event_handler/configurer.rb', line 26 def bind_key input, output=nil, resolver=@bind_resolver, &block if input.kind_of?(Array) or input.kind_of?(Fixnum) input = KeyEventHandler.parse_code input else raise ArgumentError, '1st arg expect Array / Fixnum' end if block_given? output = block elsif output.nil? raise ArgumentError, 'expect 1 arg with a block / 2 args' elsif output.kind_of? BindResolver elsif output.kind_of?(Array) or output.kind_of?(Fixnum) output = KeyEventHandler::parse_code output elsif output == :through or output == :ignore else raise ArgumentError, '2nd arg expect Array / Fixnum / BindResolver / '+ 'Symbol(:through/:ignore)' end LOG.info "bind_key #{input.inspect},\t#{output.inspect}\t#{resolver}" if LOG.info? resolver.bind input, output end |
#bind_prefix_key(input, resolver = @bind_resolver, &block) ⇒ Object
setting for 2stroke key binding
- input
-
prefix key. (e.g. [KEY_LEFTCTRL, KEY_X] (C-x)
- resolver
-
upper bind_resolver for fall throught
- block
-
to define sub-binds on this prefix key bind
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/rbindkeys/key_event_handler/configurer.rb', line 55 def bind_prefix_key input, resolver=@bind_resolver, &block if not block_given? raise ArgumentError, "expect a block" end input = KeyEventHandler::parse_code input LOG.info "bind_prefix_key #{input.inspect}\t#{resolver}" if LOG.info? tmp = input.clone tail_input = tmp.pop binded_resolver = resolver.just_resolve tail_input, tmp if binded_resolver == nil binded_resolver = BindResolver.new :ignore, true resolver.bind input, binded_resolver elsif not binded_resolver.kind_of? BindResolver raise DuplicateNodeError, "the codes (#{input.inspect}) was already binded" end @bind_resolver = binded_resolver yield @bind_resolver = resolver binded_resolver end |
#fill_gap_pressed_state(event) ⇒ Object
155 156 157 158 159 160 161 162 |
# File 'lib/rbindkeys/key_event_handler.rb', line 155 def fill_gap_pressed_state event return if @operator.pressed_key_set == @pressed_key_set sub = @pressed_key_set - @operator.pressed_key_set if event.value == 0 sub.delete event.code end sub.each {|code| @operator.press_key code} end |
#handle(event) ⇒ Object
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/rbindkeys/key_event_handler.rb', line 52 def handle event if LOG.info? LOG.info "" unless LOG.debug? LOG.info "read\t#{KeyEventHandler.get_state_by_value event} "+ "#{event.hr_code}(#{event.code})" end # handle pre_key_bind_set event.code = (@pre_bind_resolver[event.code] or event.code) # swich to handle event with event.value result = case event.value when 0 then handle_release_event event when 1 then handle_press_event event when 2 then handle_pressing_event event else raise UnknownKeyValue, "expect 0, 1 or 2 as event.value(#{event.value})" end case result when :through fill_gap_pressed_state event if event.value == 1 @operator.send_event event when :ignore # ignore the original event end handle_pressed_keys event LOG.info "pressed_keys real:#{@pressed_key_set.inspect} "+ "virtual:#{@operator.pressed_key_set.inspect}" if LOG.info? end |
#handle_press_event(event) ⇒ Object
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/rbindkeys/key_event_handler.rb', line 117 def handle_press_event event r = @bind_resolver.resolve event.code, @pressed_key_set LOG.debug "resolve result: #{r.inspect}" if LOG.debug? if r.kind_of? KeyBind if @bind_resolver.two_stroke? set_bind_resolver (@window_bind_resolver or @default_bind_resolver) end if r.output.kind_of? Array r.input.clone.delete_if{|c|c==event.code}.each {|c| @operator.release_key c} r.output.each {|c| @operator.press_key c} @active_bind_set << r :ignore elsif r.output.kind_of? BindResolver set_bind_resolver r.output :ignore elsif r.output.kind_of? Proc r.output.call event, @operator elsif r.output.kind_of? Symbol r end else r end end |
#handle_pressed_keys(event) ⇒ Object
164 165 166 167 168 169 170 171 172 173 |
# File 'lib/rbindkeys/key_event_handler.rb', line 164 def handle_pressed_keys event if event.value == 1 @pressed_key_set << event.code @pressed_key_set.sort! # TODO do not sort. implement an bubble insertion elsif event.value == 0 if @pressed_key_set.delete(event.code).nil? LOG.warn "#{event.code} does not exists on @pressed_keys" if LOG.warn? end end end |
#handle_pressing_event(event) ⇒ Object
146 147 148 149 150 151 152 153 |
# File 'lib/rbindkeys/key_event_handler.rb', line 146 def handle_pressing_event event if @active_bind_set.empty? :through else @active_bind_set.each {|kb| kb.output.each {|c| @operator.pressing_key c}} :ignore end end |
#handle_release_event(event) ⇒ Object
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/rbindkeys/key_event_handler.rb', line 85 def handle_release_event event release_bind_set = [] @active_bind_set.reject! do |key_bind| if key_bind.input.include? event.code release_bind_set << key_bind true else false end end if release_bind_set.empty? :through else release_bind_set.each do |kb| kb.output.each {|c|@operator.release_key c} if kb.input_recovery kb.input.clone.delete_if {|c|c==event.code}.each {|c|@operator.press_key c} end end :ignore end end |
#load_config(file) ⇒ Object
47 48 49 50 |
# File 'lib/rbindkeys/key_event_handler.rb', line 47 def load_config file code = File.read file instance_eval code, file end |
#new_bind_resolver(upper_resolver = @bind_resolver, &block) ⇒ Object
79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/rbindkeys/key_event_handler/configurer.rb', line 79 def new_bind_resolver upper_resolver=@bind_resolver, &block if not block_given? raise ArgumentError, "expect a block" end new_resolver = BindResolver.new upper_resolver old_resolver = @bind_resolver @bind_resolver = new_resolver yield @bind_resolver = old_resolver new_resolver end |
#pre_bind_key(input, output) ⇒ Object
pre-prosessed key codes replacement for all inputs
10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/rbindkeys/key_event_handler/configurer.rb', line 10 def pre_bind_key input, output if not (input.kind_of? Fixnum and output.kind_of? Fixnum) raise ArgumentError, 'expect Fixnum for input and output' end if @pre_bind_resolver.has_key? input raise DuplicateNodeError, "1st arg (#{input}) was already entried" end LOG.info "pre_bind_key #{input.inspect},\t#{output.inspect}" if LOG.info? @pre_bind_resolver[input] = output [input, output] end |
#set_bind_resolver(resolver) ⇒ Object
109 110 111 112 113 114 115 |
# File 'lib/rbindkeys/key_event_handler.rb', line 109 def set_bind_resolver resolver old_resolver = @bind_resolver if LOG.info? @bind_resolver = resolver LOG.info "switch bind_resolver: #{old_resolver} => "+ "#{@bind_resolver}" if LOG.info? @bind_resolver end |
#window(upper_resolver, arg) ⇒ Object
switch bind_resolver if the active window match arg
- upperresolver_
-
a upper bind_resolver, :through, :ignore
- arg
-
a hash or a regexp
arg
if a hash, which have entries :title => Regexp and/or :class => Regexp, was given, this bind is active when the window title match with :title’s Regexp AND the window class match with :class’s Regexp. if a regexp was given, this bind is active when the window title match with the given regexp
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/rbindkeys/key_event_handler/configurer.rb', line 105 def window upper_resolver, arg if upper_resolver.nil? upper_resolver = @bind_resolver elsif upper_resolver.kind_of? Symbol upper_resolver = FixResolver.instance upper_resolver elsif not upper_resolver.kind_of? BindResolver raise ArgumentError, "1nd argument is expected to be a BindResolver or"+ " a Symbol : #{ upper_resolver.to_s}" end if arg.kind_of? Regexp arg = { :title => arg } elsif arg.kind_of? Hash arg.each do |k, v| if not (k.kind_of?(Symbol) and v.kind_of?(Regexp)) raise ArgumentError, 'the 2nd argument Hash must only have'+ " Symbol keys and Regexp values : #{arg.inspect}" end end else raise ArgumentError, "2nd argument is expected to be a Hash or a Regexp : #{arg}" end resolver = BindResolver.new(upper_resolver) @window_bind_resolver_map.push [WindowMatcher.new(arg), resolver] if block_given? old_resolver = @bind_resolver @bind_resolver = resolver yield @bind_resolver = old_resolver end resolver end |