Forked from Noitidart/_ff-addon-snippet-xcbGrabKey.js
Created
September 22, 2017 17:40
-
-
Save Happy-Ferret/3c0688abe11d0d75568fd500e0a437eb 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]
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment