x11-cr icon indicating copy to clipboard operation
x11-cr copied to clipboard

How to use X11::Display#grab_button properly?

Open acoolstraw opened this issue 3 years ago • 2 comments

I'm using x11-cr to write a window manager and I'm trying to grab left click but #grab_button doesn't seem to work, it seems to be accepting different types from what it's given but I can't figure out how to give it the correct types. dpy.default_root_window and dpy.root_window scr return a UInt64 instead of an X11::C::Window for some reason

dpy = Display.new
scr = dpy.default_screen_number
root = dpy.root_window scr

dpy.grab_button(1, Mod4Mask, root, true, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None)

loop do
  ev = dpy.next_event
  case ev
  when ButtonEvent
    File.write("~/test.txt", "works")
    break
  end
end

dpy.destroy_window root
dpy.close
0
In src/sled/wm.cr:12:11

 12 | dpy.grab_button(1, Mod4Mask, root, true, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None)
          ^----------
Error: no overload matches 'X11::Display#grab_button' with types Int32, Int32, UInt64, Bool, Int64, Int32, Int32, Int64, Int64

Overloads are:
 - X11::Display#grab_button(button : UInt32, modifiers : UInt32, grab_window : X11::C::Window, owner_events : Bool, event_mask : UInt32, pointer_mode : Int32, keyboard_mode : Int32, confine_to : X11::C::Window, cursor : X11::C::Cursor)

acoolstraw avatar Feb 05 '22 07:02 acoolstraw

it should work, perhaps your keycode is wrong or your numlock/capslock was active?

# ...
modifiers = (ControlMask | ShiftMask).to_u32
keycode = display.keysym_to_keycode(XK_A.to_u64)
display.grab_key(keycode, modifiers, grab_window: root, owner_events: true, pointer_mode: GrabModeAsync, keyboard_mode: GrabModeAsync)
display.select_input(root, KeyPressMask)
loop do
    event = display.next_event
    case event
    when KeyEvent
        if event.release?
            puts "you pressed CTRL SHIFT A"
        end
    end
end

X11::C::Window and such are also just integers afaik, but yes, you need some casting then and again because the types don't match like above, but I don't think it's problematic. This example uses keypresses, not buttons, but it's the same principle I guess?

Note that I have no idea of X11, this is just some googled C code snippets glued together, but it works on my machine

phil294 avatar Jul 15 '22 22:07 phil294

However, display.next_event is a blocking action that does also never Fiber.yield, which prevents any kind of concurrency code... Any idea on how to solve that? :/

Edit: The solution is to either poll check_mask_event every few ms instead, or put the display.next_event into a separate thread (preferrable, much less cpu intensive).

phil294 avatar Jul 15 '22 22:07 phil294

Ok so I needed grab_button too today, and here's how you can do it: Firstly, there is a type error in the source, see PR #19. Once Tamás has merged it, you can achieve it for example like this:

root_win = display.root_window display.default_screen_number
display.grab_button(Button1.to_u32, Mod4Mask.to_u32, grab_window: root_win, owner_events: true, event_mask: ButtonPressMask.to_u32, pointer_mode: GrabModeAsync, keyboard_mode: GrabModeAsync, confine_to: None.to_u64, cursor: None.to_u64)

phil294 avatar Oct 27 '22 21:10 phil294