No error on xcb_grab_key but event loop not catching (Global Hotkey)
Asked Answered
S

1

4

I am trying to set up a global hotkey on Linux.

I had initially used x11 (libX11.so) however I had to do this from a thread. I tried it but the XPendingEvent and XNextEvent would eventually crash the app.

So I switched to xcb (libxcb.so.1). There is no errors, I even check with xcb_request_check however the event loop is not picking anything up. As soon as I start the loop, I get only one event which looks like this:

{
    response_type: 0,
    pad0: 10,
    sequence: 2,
    pad: [620, 2162688, 0, 0, 0, 0, 0],
    full_sequence: 2
}

Here is my code, I actually do this in js-ctypes, but I cut down all the stuff to just show simple agnostic as possible code:

conn = xcb_connect(null, null);

keysyms = xcb_key_symbols_alloc(conn);

keycodesPtr = xcb_key_symbols_get_keycode(keysyms, XK_Space);

setup = xcb_get_setup(conn);

screens = xcb_setup_roots_iterator(setup);
screensCnt = screens.rem;

for (var i=0; i<screensCnt; i++) {
    rez_grab = xcb_grab_key(conn, 1, screens.data.root, XCB_MOD_MASK_ANY, keycodesPtr[0], XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);

    rez_err = xcb_request_check(conn, rez_grab);
    // rez_err is null

    xcb_screen_next(&screens);
}

xcb_flush(conn);

// start event loop
while (true) {
    ev = xcb_poll_for_event(conn);

    console.log(ev);

    if (ev != null) {
        free(ev);
    }

    Sleep(50);
}

console.log(ev) gives me what I posted above earlier, response_type of 0 and then forever after that ev is just null.

Does anyone know what's up? rez_grab as a raw string is xcb_void_cookie_t(2)

Thanks much

Seedbed answered 10/3, 2016 at 2:0 Comment(13)
I don't understant the "while (true)" what is the true value ? . Could you create a more simple working code that reproduce your problem. Sometimes just doing this guide you to the solution.Alessandraalessandria
Thanks @Alessandraalessandria very much for the attention. I was just modifying the code to make it simple my real code is here - github.com/Noitidart/NativeShot/blob/master/modules/hotkey/… - it is basically an endless event loop I'm trying to create, so I know when a hotkey I specified was pressed. And I know grab_key so that key has no affect anywhere, except for my hotkey. Its not working though :( I based it on https://mcmap.net/q/429401/-global-alt-space-hotkey-grabbing-weird-keyboard-focus-behaviour/1828637 - but I am in a thread so it might be different.Seedbed
Have you set up the attributes for the root window? This C program works.Oogenesis
Thanks @n.m. very much will try in just a couple hours, I hadn't tried setting attr on root window. Thanks very much for your attention! I'll report back how it goes. :)Seedbed
Drats @n.m. its not working for me, did you try that code from a thread?Seedbed
Nope, I'm not sure why this should matter.Oogenesis
Thanks I'm not sure why my thing won't work :( I do exactly the same just from a thread :( Does the grab succesfully grab your space bar?Seedbed
@n.m. can you please share how I can compile your C program I tried gcc -o grab grab.c -L/usr/X11/lib -lX11 -lstdc++ however it fails for me :(Seedbed
I use gcc -o grab grab.c -std=gnu99 -lxcb -lxcb-keysyms, you may have to add -I and/or -L flags but no other flags.Oogenesis
Hey @n.m. I made a very readable version of this here - gist.github.com/Noitidart/3870a1e5ab341fe8604cf516ff7c93cb - do you use firefox by any chance? You can copy paste my code into scratchpad in "browser" environment and run - youtube.com/watch?v=oo4STWceGTM if you could take a look at this i would suuuuper greatful I need another set of eyes on this :(Seedbed
Oh before running, you can open Browser Console with Ctrl + Shift + J and you can see all the stuff being logged. :) This screenshot is what it looks like for me right now- i.imgur.com/L1C8q2a.pngSeedbed
Hey @n.m. my friend compiled grab.c and it didnt work for him on debinan or ubuntu. BUT we found this other example and compiled it and it worked for him on debian, but not on Ubuntu 15.01, 14.04 or on xubuntu - gist.github.com/Noitidart/ab95289bc45a125b2d37bd7e3572122f - we compiled it with gcc mpkey.c -std=gnu99 -lxcb -lxcb-keysyms after installing sudo apt-get install x11proto-core-dev and apt-get install libxcb-keysyms1-dev. Isnt xcb cross flavor? Do you know why its not working on ubuntu? Thanks so muchSeedbed
@n.m. figured it out at long last!! I was using XCB_MOD_MASK_ANY and this constant works on Debian but not on Ubuntu, which is what I was using to test. I swithced that up to use num lock, caps lock etc and now it works! :) github.com/Noitidart/NativeShot/blob/master/modules/hotkey/… that was very very crazy i had no idea the XCB_MOD_MASK_ANY constant didnt work on Ubuntu - github.com/Noitidart/System-Hotkey/blob/master/modules/hotkey/… your exact code i tried on ubuntu it didnt work, but worked on debianSeedbed
S
5

Figured it out at long last!! Ah figured this one out! I was using XCB_MOD_MASK_ANY and this constant works on Debian but not on Ubuntu, which is what I was using to test. I switched that up to use num lock, caps lock etc and now it works! :)

ostypes.API('xcb_grab_key')(conn, 1, screens.data.contents.root, ostypes.CONST.XCB_MOD_MASK_LOCK, keycodesArr[j], ostypes.CONST.XCB_GRAB_MODE_ASYNC, ostypes.CONST.XCB_GRAB_MODE_ASYNC); // caps lock
ostypes.API('xcb_grab_key')(conn, 1, screens.data.contents.root, ostypes.CONST.XCB_MOD_MASK_2, keycodesArr[j], ostypes.CONST.XCB_GRAB_MODE_ASYNC, ostypes.CONST.XCB_GRAB_MODE_ASYNC); // num lock
ostypes.API('xcb_grab_key')(conn, 1, screens.data.contents.root, ostypes.CONST.XCB_MOD_MASK_LOCK | ostypes.CONST.XCB_MOD_MASK_2, keycodesArr[j], ostypes.CONST.XCB_GRAB_MODE_ASYNC, ostypes.CONST.XCB_GRAB_MODE_ASYNC); // caps lock AND num lock

that was very very crazy i had no idea the XCB_MOD_MASK_ANY constant didnt work on Ubuntu -

var rez_grab = ostypes.API('xcb_grab_key')(conn, 1, screens.data.contents.root, ostypes.CONST.XCB_MOD_MASK_ANY, keycodesArr[j], ostypes.CONST.XCB_GRAB_MODE_ASYNC, ostypes.CONST.XCB_GRAB_MODE_ASYNC);

I also tried @n.m's code. On ubuntu it didnt work, but worked on debian -

#include <xcb/xcb.h>
#define XK_LATIN1
#include <xcb/xcb_keysyms.h>
#include <X11/keysymdef.h>
#include <stdio.h>
#include <stdlib.h>

int
main ()
{
  xcb_connection_t *conn;

  conn = xcb_connect (NULL, NULL);

  xcb_key_symbols_t * keysyms = xcb_key_symbols_alloc(conn);

  xcb_keycode_t * keycodesPtr = xcb_key_symbols_get_keycode(keysyms, XK_space);

  const xcb_setup_t* setup = xcb_get_setup(conn);

  xcb_screen_iterator_t screens = xcb_setup_roots_iterator(setup);
  int screensCnt = screens.rem;

  for (int i=0; i<screensCnt; i++) {

      xcb_void_cookie_t rez_grab = xcb_grab_key(conn, 1, screens.data->root, XCB_MOD_MASK_ANY, keycodesPtr[0], XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);

      const static uint32_t values[] = { XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS };

      xcb_change_window_attributes (conn, screens.data->root, XCB_CW_EVENT_MASK, values);

      xcb_screen_next(&screens);
  }

  xcb_flush(conn);

  // start event loop
  while (1) {
      xcb_generic_event_t *ev = xcb_wait_for_event(conn);

      if (ev && ((ev->response_type & ~0x80) == XCB_KEY_PRESS))
      {
          xcb_key_press_event_t *kp = (xcb_key_press_event_t *)ev;
          printf ("Got key press %d\n", (int)kp->event);
      }

      if (ev != NULL) {
          free(ev);
      }
  }

  return 0;
}
Seedbed answered 6/5, 2016 at 0:44 Comment(6)
So did you manage to generate events from keys without any modifier? Because I'm on Ubuntu and I'm having the same problem of XCB_MOD_MASK_ANY not working... (But all the other mod masks, like XCB_MOD_MASK_SHIFT, XCB_MOD_MASK_1 do seem to work)Selfsuggestion
@étale-cohomology Yep, I registered listeners like this - github.com/Noitidart/jscSystemHotkey/blob/master/… - for no mods just pass in XCB_NONE which is 0. Here are the codes I used for the various mods - github.com/Noitidart/jscSystemHotkey/blob/master/… - If it works for you, please post up another question I would love to supply answer and get some points for accepted answer. :) This is a great topic on mods - #19376838Seedbed
@étale-cohomology the key thing to note is that caps lock and num lock are counted as modifiers. so you have to xcb_grab_key for XCB_NONE, then xcb_grab_key again for num lock XCB_MOD_MASK_LOCK, then xcb_grab_key again for caps lock XCB_MOD_MASK_2, and finally again for if both numlock and capslock are on XCB_MOD_MASK_2 | XCB_MOD_MASK_LOCKSeedbed
Any update for why XCB_MOD_MASK_ANY doesn't work?Callisto
Found the answer - the reason why XCB_MOD_MASK_ANY didn't work for you is probably because that key was already grabbed somewhere: gitlab.freedesktop.org/xorg/lib/libxcb/-/issues/57Callisto
Thanks for sharing that bam!Seedbed

© 2022 - 2024 — McMap. All rights reserved.