Class: Rum::HotkeySet

Inherits:
Object
  • Object
show all
Defined in:
lib/rum/hotkey_core.rb

Overview

TODO: Needs refactoring.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(layout) ⇒ HotkeySet

Returns a new instance of HotkeySet.



182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/rum/hotkey_core.rb', line 182

def initialize layout
  @layout = layout
  # All hotkeys that consist entirely of modifiers
  @modifier_hotkeys = {}
  @modifiers = layout.modifiers.sort_by &:id
  # All modifier combinations of all registered hotkeys
  @modifier_combinations = Hash.new(0)
  @up = {}
  @down = {}
  @up_fuzzy = {}
  @down_fuzzy = {}
end

Instance Attribute Details

#downObject

Returns the value of attribute down.



179
180
181
# File 'lib/rum/hotkey_core.rb', line 179

def down
  @down
end

#down_fuzzyObject

Returns the value of attribute down_fuzzy.



179
180
181
# File 'lib/rum/hotkey_core.rb', line 179

def down_fuzzy
  @down_fuzzy
end

#hotkeysObject

Returns the value of attribute hotkeys.



179
180
181
# File 'lib/rum/hotkey_core.rb', line 179

def hotkeys
  @hotkeys
end

#layoutObject

Returns the value of attribute layout.



179
180
181
# File 'lib/rum/hotkey_core.rb', line 179

def layout
  @layout
end

#modifier_hotkeysObject

Returns the value of attribute modifier_hotkeys.



179
180
181
# File 'lib/rum/hotkey_core.rb', line 179

def modifier_hotkeys
  @modifier_hotkeys
end

#modifiersObject

Returns the value of attribute modifiers.



179
180
181
# File 'lib/rum/hotkey_core.rb', line 179

def modifiers
  @modifiers
end

#upObject

Returns the value of attribute up.



179
180
181
# File 'lib/rum/hotkey_core.rb', line 179

def up
  @up
end

#up_fuzzyObject

Returns the value of attribute up_fuzzy.



179
180
181
# File 'lib/rum/hotkey_core.rb', line 179

def up_fuzzy
  @up_fuzzy
end

Instance Method Details

#add_hotkey(string, action, condition, repeated, location) ⇒ Object



195
196
197
198
199
# File 'lib/rum/hotkey_core.rb', line 195

def add_hotkey(string, action, condition, repeated, location)
  action = Action.new(action, condition, repeated, location)
  action.hotkey = hotkey_from_string(string)
  register(action)
end

#add_translation(string, to, condition, location) ⇒ Object

Implement translations in terms of normal hotkeys. TODO: Extending HotkeyProcessor to natively support translations might be a simpler and more solid approach.



209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/rum/hotkey_core.rb', line 209

def add_translation(string, to, condition, location)
  down_hotkey = hotkey_from_string(string)
  up_hotkey   = hotkey_from_string(string)
  down_hotkey.direction = :down
  up_hotkey.direction   = :up
  to_key = @layout[to]

  catch_modifier_up = proc do
    if down_hotkey.modifiers.include? @key
      send_key_event(to_key, false)
      remove_hook(catch_modifier_up)
    end
  end
  down_action = Action.new( lambda do
                              send_key_event(to_key, true)
                              Rum.hotkey_processor.add_hook(catch_modifier_up)
                            end,
                            condition, true, location)
  up_action   = Action.new( lambda do
                              send_key_event(to_key, false)
                              Rum.hotkey_processor.remove_hook(catch_modifier_up)
                            end,
                            condition, true, location)
  down_action.hotkey = down_hotkey
  up_action.hotkey   = up_hotkey
  register(down_action)
  register(up_action)
end

#fuzzy_lookup(down, key, pressed_modifiers) ⇒ Object



379
380
381
382
383
384
385
386
# File 'lib/rum/hotkey_core.rb', line 379

def fuzzy_lookup(down, key, pressed_modifiers)
  if (hotkeys = (down ? @down_fuzzy : @up_fuzzy)[key])
    hotkeys.each do |modifiers, hotkey|
      return hotkey if modifiers.all? { |mod| pressed_modifiers[mod] }
    end
    nil
  end
end

#get_dict(hotkey) ⇒ Object



288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# File 'lib/rum/hotkey_core.rb', line 288

def get_dict(hotkey)
  if hotkey.fuzzy?
    dict = if hotkey.direction == :up
             @up_fuzzy
           else
             @down_fuzzy
           end
    dict = (dict[hotkey.key] ||= {})
    dict_key = hotkey.modifiers
  else
    dict_key = key_signature(hotkey)
    dict = if (dir = hotkey.direction and dir == :up) or \
              (hotkey.key.modifier? and @modifier_combinations[dict_key] > 0)
             @up
           else
             @down
           end
  end
  [dict, dict_key]
end

#hotkey_from_string(str) ⇒ Object



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
# File 'lib/rum/hotkey_core.rb', line 238

def hotkey_from_string str
  *modifier_aliases, key_alias = str.split(' ')
  fuzzy = !!modifier_aliases.delete('*')

  # Lookup modifiers
  modifiers = []
  modifier_aliases.each do |modifier_alias|
    if key = @layout.modifier_lookup(modifier_alias)
      modifiers << key
    else
      raise "Invalid modifier: #{modifier_alias}"
    end
  end
  modifiers = modifiers.sort_by &:id

  # Lookup key
  key = @layout[key_alias]
  raise "#{key_alias} is no valid key." unless key

  Hotkey.new(key, modifiers, fuzzy)
end

#key_signature(hotkey) ⇒ Object



309
310
311
# File 'lib/rum/hotkey_core.rb', line 309

def key_signature hotkey
  hotkey.modifiers.dup << hotkey.key
end

#lookup(down, signature) ⇒ Object



375
376
377
# File 'lib/rum/hotkey_core.rb', line 375

def lookup(down, signature)
  (down ? @down : @up)[signature]
end

#lookup_hotkey(hotkey) ⇒ Object



313
314
315
316
# File 'lib/rum/hotkey_core.rb', line 313

def lookup_hotkey hotkey
  dict, dict_key = get_dict(hotkey)
  dict[dict_key]
end

#maybe_reregister_mod_hotkey(modifiers, change_count, threshold) ⇒ Object

Example:

  1. The modifier hotkey ‘ctrl shift’ is the only registered hotkey.

  2. The hotkey ‘ctrl shift a’ gets registered.

Now the ‘ctrl shift’ hotkey needs to be re-registered to avoid getting triggered while ‘ctrl shift a’ is pressed.

Vice versa: When all conflicting modifier combinations have been unregistered, a modifier hotkey can be re-registered to trigger instantly.

This function keeps track of active modifier_combinations when hotkeys ar added or removed. It re-registers corresponding modifier hotkeys accordingly.



364
365
366
367
368
369
370
371
372
373
# File 'lib/rum/hotkey_core.rb', line 364

def maybe_reregister_mod_hotkey(modifiers, change_count, threshold)
  count = @modifier_combinations[modifiers]
  if count == threshold and (mod_hotkey = @modifier_hotkeys[modifiers])
    unregister_hotkey(mod_hotkey)
    @modifier_combinations[modifiers] = count + change_count
    register_hotkey(mod_hotkey)
  else
    @modifier_combinations[modifiers] = count + change_count
  end
end

#register(action) ⇒ Object



260
261
262
263
264
265
266
267
268
269
270
271
272
# File 'lib/rum/hotkey_core.rb', line 260

def register action
  hotkey = register_hotkey(action.hotkey)
  if action.condition
    hotkey.actions.unshift action # put actions with conditions first
  else
    # Only one conditionless action per hotkey
    unless last_action = hotkey.actions.last and last_action.condition
      hotkey.actions.pop
    end
    hotkey.actions << action
  end
  action
end

#register_hotkey(hotkey) ⇒ Object



318
319
320
321
322
323
324
325
326
327
328
329
# File 'lib/rum/hotkey_core.rb', line 318

def register_hotkey hotkey
  dict, dict_key = get_dict(hotkey)
  existing_hotkey = dict[dict_key] and return existing_hotkey

  dict[dict_key] = hotkey
  if hotkey.key.modifier? # Modifier hotkeys aren't allowed to be fuzzy.
    @modifier_hotkeys[dict_key] = hotkey
  else
    register_modifier_combination(hotkey.modifiers)
  end
  hotkey
end

#register_modifier_combination(modifiers) ⇒ Object



342
343
344
# File 'lib/rum/hotkey_core.rb', line 342

def register_modifier_combination(modifiers)
  maybe_reregister_mod_hotkey(modifiers, 1, 0)
end

#remove_hotkey(string) ⇒ Object



201
202
203
204
# File 'lib/rum/hotkey_core.rb', line 201

def remove_hotkey string
  hotkey = hotkey_from_string(string)
  Rum.hotkey_set.unregister_conditionless_action(hotkey)
end

#unregister(action) ⇒ Object



274
275
276
277
278
279
280
# File 'lib/rum/hotkey_core.rb', line 274

def unregister action
  if hotkey = action.hotkey
    hotkey.actions.delete(action)
    unregister_hotkey(hotkey) if hotkey.actions.empty?
    action
  end
end

#unregister_conditionless_action(hotkey) ⇒ Object



282
283
284
285
286
# File 'lib/rum/hotkey_core.rb', line 282

def unregister_conditionless_action hotkey
  if hotkey = lookup_hotkey(hotkey) and action = hotkey.actions.last
    unregister action unless action.condition
  end
end

#unregister_hotkey(hotkey) ⇒ Object



331
332
333
334
335
336
337
338
339
340
# File 'lib/rum/hotkey_core.rb', line 331

def unregister_hotkey hotkey
  dict, dict_key = get_dict(hotkey)
  if dict.delete(dict_key)
    if hotkey.key.modifier?
      @modifier_hotkeys.delete(hotkey)
    else
      unregister_modifier_combination(hotkey.modifiers)
    end
  end
end

#unregister_modifier_combination(modifiers) ⇒ Object



346
347
348
# File 'lib/rum/hotkey_core.rb', line 346

def unregister_modifier_combination(modifiers)
  maybe_reregister_mod_hotkey(modifiers, -1, 1)
end