class Xkeyrap::Cli

Public Class Methods

get_parent_window_name(display, top_level_windows, focused_window) click to toggle source
# File lib/xkeyrap.rb, line 54
def self.get_parent_window_name(display, top_level_windows, focused_window)
  root     = FFI::MemoryPointer.new :Window
  parent   = FFI::MemoryPointer.new :Window
  number   = FFI::MemoryPointer.new :uint
  children = FFI::MemoryPointer.new :pointer
  begin
    q = Xlib.XQueryTree(display.to_native, focused_window.to_native, root, parent, children, number)
    parent_window_id = parent.read(:int)
    parent_window = top_level_windows.select {|tlw| tlw.id == parent_window_id }.first
    parent_window.property("WM_CLASS")[1]
  rescue
    "global"
  end
end
run(keyboard_device) click to toggle source
# File lib/xkeyrap.rb, line 12
def self.run(keyboard_device)
  display = XlibObj::Display.new(':0')
  virtual_device = Uinput::Device.new do
    self.name = "Xkeyrap virtual device"
    self.type = LinuxInput::BUS_VIRTUAL

    Xkeyrap::Key::ALL_KEYS.each do |k|
      self.add_key(k)
    end

    self.add_event(:EV_KEY)
    self.add_event(:EV_SYN)
  end

  keyboard = Evdev.new(keyboard_device)
  keyboard.grab

  command = Command.new(virtual_device, nil)

  keyboard.on(*Xkeyrap::Key::ALL_KEYS) do |state, key|
    root_window = display.screens.first.root_window
    top_level_windows = root_window.property(:_NET_CLIENT_LIST_STACKING)
    focused_window = display.focused_window
    wm_class_name = if focused_window.property("WM_CLASS")
                      focused_window.property("WM_CLASS")[1]
                    else
                      get_parent_window_name(display, top_level_windows, focused_window)
                    end

    command.receive(state, key, wm_class_name)
  end

  loop do
    begin
      keyboard.handle_event
    rescue Evdev::AwaitEvent
      Kernel.select([keyboard.event_channel])
      retry
    end
  end
end