Skip to content

Instantly share code, notes, and snippets.

@Noitidart
Last active September 22, 2017 17:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Noitidart/3870a1e5ab341fe8604cf516ff7c93cb to your computer and use it in GitHub Desktop.
Save Noitidart/3870a1e5ab341fe8604cf516ff7c93cb to your computer and use it in GitHub Desktop.
_ff-addon-snippet-xcbGrabKey - Trying to create a global hotkey with XCB. [jsctypes] [xcb] [unix] [linux] [*nix]
Cu.import('resource://gre/modules/ctypes.jsm');
var libxcb;
try {
libxcb = ctypes.open('libxcb.so');
} catch(ignore) {
libxcb = ctypes.open('libxcb.so.1');
}
var libkey;
try {
libkey = ctypes.open('libxcb-keysyms.so');
} catch(ignore) {
libkey = ctypes.open('libxcb-keysyms.so.1');
}
var libutil;
try {
libutil = ctypes.open('libxcb-util.so');
} catch(ignore) {
libutil = ctypes.open('libxcb-util.so.1');
}
var xcb_setup_t = ctypes.StructType('xcb_setup_t', [ // https://github.com/netzbasis/openbsd-xenocara/blob/e6500f41b55e38013ac9b489f66fe49df6b8b68c/lib/libxcb/src/xproto.h#L453
{ status: ctypes.uint8_t },
{ pad0: ctypes.uint8_t },
{ protocol_major_version: ctypes.uint16_t },
{ protocol_minor_version: ctypes.uint16_t },
{ length: ctypes.uint16_t },
{ release_number: ctypes.uint32_t },
{ resource_id_base: ctypes.uint32_t },
{ resource_id_mask: ctypes.uint32_t },
{ motion_buffer_size: ctypes.uint32_t },
{ vendor_len: ctypes.uint16_t },
{ maximum_request_length: ctypes.uint16_t },
{ roots_len: ctypes.uint8_t },
{ pixmap_formats_len: ctypes.uint8_t },
{ image_byte_order: ctypes.uint8_t },
{ bitmap_format_bit_order: ctypes.uint8_t },
{ bitmap_format_scanline_unit: ctypes.uint8_t },
{ bitmap_format_scanline_pad: ctypes.uint8_t },
{ min_keycode: ctypes.uint8_t },
{ max_keycode: ctypes.uint8_t },
{ pad1: ctypes.uint8_t.array(4) }
]);
// var xcb_setup_t = ctypes.voidptr_t;
var xcb_screen_t = ctypes.StructType('xcb_screen_t', [
{ root: ctypes.uint32_t },
{ default_colormap: ctypes.uint32_t },
{ white_pixel: ctypes.uint32_t },
{ black_pixel: ctypes.uint32_t },
{ current_input_masks: ctypes.uint32_t },
{ width_in_pixels: ctypes.uint16_t },
{ height_in_pixels: ctypes.uint16_t },
{ width_in_millimeters: ctypes.uint16_t },
{ height_in_millimeters: ctypes.uint16_t },
{ min_installed_maps: ctypes.uint16_t },
{ max_installed_maps: ctypes.uint16_t },
{ root_visual: ctypes.uint32_t },
{ backing_stores: ctypes.uint8_t },
{ save_unders: ctypes.uint8_t },
{ root_depth: ctypes.uint8_t },
{ allowed_depths_len: ctypes.uint8_t }
]);
var xcb_screen_iterator_t = ctypes.StructType('xcb_screen_iterator_t', [
{ data: xcb_screen_t.ptr },
{ rem: ctypes.int },
{ index: ctypes.int }
]);
var xcb_void_cookie_t = ctypes.StructType('xcb_void_cookie_t', [
{ sequence: ctypes.unsigned_int }
]);
var xcb_generic_event_t = ctypes.StructType('xcb_generic_event_t', [
{ response_type: ctypes.uint8_t },
{ pad0: ctypes.uint8_t },
{ sequence: ctypes.uint16_t },
{ pad: ctypes.uint32_t.array(7) },
{ full_sequence: ctypes.uint32_t }
]);
var xcb_connect = libxcb.declare('xcb_connect', ctypes.default_abi, ctypes.voidptr_t, ctypes.char.ptr, ctypes.int.ptr); // http://xcb.freedesktop.org/PublicApi/#index2h2
var xcb_connection_has_error = libxcb.declare('xcb_connection_has_error', ctypes.default_abi, ctypes.int, ctypes.voidptr_t); // https://xcb.freedesktop.org/manual/group__XCB__Core__API.html#ga70a6bade94bd2824db552abcf5fbdbe3
var xcb_key_symbols_alloc = libkey.declare('xcb_key_symbols_alloc', ctypes.default_abi, ctypes.voidptr_t, ctypes.voidptr_t); // http://www.opensource.apple.com/source/X11libs/X11libs-60/xcb-util/xcb-util-0.3.6/keysyms/xcb_keysyms.h
var xcb_key_symbols_get_keycode = libkey.declare('xcb_key_symbols_get_keycode', ctypes.default_abi, ctypes.uint8_t.ptr, ctypes.voidptr_t, ctypes.uint32_t); // http://www.opensource.apple.com/source/X11libs/X11libs-60/xcb-util/xcb-util-0.3.6/keysyms/xcb_keysyms.h
var free = libxcb.declare('free', ctypes.default_abi, ctypes.void_t, ctypes.voidptr_t); // i guessed on this one
var xcb_allow_events = libxcb.declare('xcb_allow_events', ctypes.default_abi, xcb_void_cookie_t, ctypes.voidptr_t, ctypes.uint8_t, ctypes.uint32_t); // http://www.x.org/releases/X11R7.7/doc/man/man3/xcb_allow_events.3.xhtml
var xcb_aux_sync = libutil.declare('xcb_aux_sync', ctypes.default_abi, ctypes.int, ctypes.voidptr_t); // http://www.x.org/archive/X11R7.5/doc/libxcb/tutorial/index.html
var xcb_change_window_attributes = libxcb.declare('xcb_change_window_attributes', ctypes.default_abi, xcb_void_cookie_t, ctypes.voidptr_t, ctypes.uint32_t, ctypes.uint32_t, ctypes.uint32_t.ptr); // https://xcb.freedesktop.org/manual/group__XCB____API.html#ga3724f4ccfdfa063439258831b75f6224
var xcb_disconnect = libxcb.declare('xcb_disconnect', ctypes.default_abi, ctypes.void_t, ctypes.voidptr_t); // http://xcb.freedesktop.org/PublicApi/#index5h2
var xcb_flush = libxcb.declare('xcb_flush', ctypes.default_abi, ctypes.int, ctypes.voidptr_t); // http://xcb.freedesktop.org/PublicApi/#index13h2
var xcb_generate_id = libxcb.declare('xcb_generate_id', ctypes.default_abi, ctypes.uint32_t, ctypes.voidptr_t); // http://xcb.freedesktop.org/PublicApi/#index16h2
var xcb_get_setup = libxcb.declare('xcb_get_setup', ctypes.default_abi, xcb_setup_t.ptr, ctypes.voidptr_t); // http://xcb.freedesktop.org/PublicApi/#index7h2
var xcb_grab_key = libxcb.declare('xcb_grab_key', ctypes.default_abi, xcb_void_cookie_t, ctypes.voidptr_t, ctypes.uint8_t, ctypes.uint32_t, ctypes.uint16_t, ctypes.uint8_t, ctypes.uint8_t, ctypes.uint8_t); // http://www.x.org/releases/X11R7.7/doc/man/man3/xcb_grab_key.3.xhtml
var xcb_key_symbols_free = libkey.declare('xcb_key_symbols_free', ctypes.default_abi, ctypes.void_t, ctypes.voidptr_t); // http://www.opensource.apple.com/source/X11libs/X11libs-60/xcb-util/xcb-util-0.3.6/keysyms/xcb_keysyms.h
var xcb_poll_for_event = libxcb.declare('xcb_poll_for_event', ctypes.default_abi, xcb_generic_event_t.ptr, ctypes.voidptr_t); // https://xcb.freedesktop.org/PublicApi/#index11h2
var xcb_screen_next = libxcb.declare('xcb_screen_next', ctypes.default_abi, ctypes.void_t, ctypes.voidptr_t); // https://github.com/emmanueldenloye/firefox-pentadactyl/blob/52bcaf3a49f81350110210a90552690b2db332a0/unused_plugins/fix-focus.js#L244
var xcb_setup_roots_iterator = libxcb.declare('xcb_setup_roots_iterator', ctypes.default_abi, xcb_screen_iterator_t, xcb_setup_t.ptr); // https://github.com/netzbasis/openbsd-xenocara/blob/e6500f41b55e38013ac9b489f66fe49df6b8b68c/lib/libxcb/src/xproto.h#L5409
var xcb_ungrab_key = libxcb.declare('xcb_ungrab_key', ctypes.default_abi, xcb_void_cookie_t, ctypes.voidptr_t, ctypes.uint32_t, ctypes.uint32_t, ctypes.uint16_t); // http://www.x.org/archive/current/doc/man/man3/xcb_ungrab_key.3.xhtml
var xcb_wait_for_event = libxcb.declare('xcb_wait_for_event', ctypes.default_abi, xcb_generic_event_t.ptr, ctypes.voidptr_t); // http://xcb.freedesktop.org/PublicApi/#index10h2
// var xcb_grab_key_checked = libxcb.declare('xcb_grab_key_checked ', ctypes.default_abi, xcb_void_cookie_t, ctypes.voidptr_t, ctypes.uint8_t, ctypes.uint32_t, ctypes.uint16_t, ctypes.uint32_t, ctypes.uint8_t, ctypes.uint8_t); // http://libxcb.sourcearchive.com/documentation/1.1/group__XCB____API_gc0b5bb243475091e33be64bd2db95f14.html#gc0b5bb243475091e33be64bd2db95f14
var conn = xcb_connect(null, null);
console.log('conn:', conn.toString());
var keysyms = xcb_key_symbols_alloc(conn);
console.log('keysyms:', keysyms.toString());
var XK_A = 0x0041; // lower case "a" // https://github.com/semonalbertyeah/noVNC_custom/blob/60daa01208a7e25712d17f67282497626de5704d/include/keysym.js#L216
var XK_Print = 0xff61;
var XK_Space = 0x0020;
var XCB_EVENT_MASK_KEY_PRESS = 1;
var XCB_EVENT_MASK_BUTTON_PRESS = 4;
var XCB_EVENT_MASK_EXPOSURE = 32768;
var XCB_CW_EVENT_MASK = 2048;
var XCB_NO_SYMBOL = 0;
var keycodesPtr = xcb_key_symbols_get_keycode(keysyms, XK_A);
console.log('keycodesPtr:', keycodesPtr.toString());
var keycodesArr = [];
var keycodesArrC = ctypes.cast(keycodesPtr, ctypes.uint8_t.array(10).ptr).contents;
console.log('keycodesArrC:', keycodesArrC.toString());
for (var i=0; i<keycodesArrC.length; i++) {
if (keycodesArrC[i] == XCB_NO_SYMBOL) {
break;
}
keycodesArr.push(keycodesArrC[i]);
}
console.log('keycodesArr:', keycodesArr);
if (!keycodesArr.length) {
throw new Error('no keycodes!! so nothing to grab!');
}
free(keycodesPtr);
xcb_key_symbols_free(keysyms);
var setup = xcb_get_setup(conn);
console.log('setup:', setup.contents);
var screens = xcb_setup_roots_iterator(setup);
var grabWins = []; // so iterate through these and ungrab on remove of hotkey
var screensCnt = screens.rem;
console.log('screensCnt:', screensCnt);
for (var i=0; i<screensCnt; i++) {
console.log('screen[' + i + ']:', screens);
console.log('screen[' + i + '].data:', screens.data.contents);
for (var j=0; j<keycodesArr.length; j++) {
var rez_grab = xcb_grab_key(conn, 1, screens.data.contents.root, 32768 /*XCB_MOD_MASK_ANY*/, keycodesArr[j], 1 /*XCB_GRAB_MODE_ASYNC*/, 1 /*XCB_GRAB_MODE_ASYNC*/);
console.log('rez_grab:', rez_grab);
}
var chgValueList = ctypes.uint32_t.array()([
XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_KEY_PRESS
]);
var rez_chg = xcb_change_window_attributes(conn, screens.data.contents.root, XCB_CW_EVENT_MASK, chgValueList);
console.log('rez_chg:', rez_chg);
grabWins.push(screens.data.contents.root);
xcb_screen_next(screens.address());
}
var rez_flush = xcb_flush(conn);
console.log('rez_flush:', rez_flush);
var xcbpoll = setInterval(function() {
var evt = xcb_poll_for_event(conn);
console.log('evt:', evt.toString());
if (!evt.isNull()) {
console.error('evt.contents:', evt.contents, 'evt.pad:', evt.contents.pad.toString());
free(evt);
}
}, 1000);
@Noitidart
Copy link
Author

README

Rev1

  • Doesn't seem to work

Rev2

  • Improved logging

Rev3

  • Some more logging improvment

Rev4

  • More improved logging

Rev5

  • Added links to the API docs of the functions (some of them are to another github repo, i have need to fix that)

Rev6

  • Added commented out xcb_grab_key_checked as it seems to not be found in libxcb nor libkey

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment