示例#1
0
文件: pointer.c 项目: gyroninja/bspwm
int16_t modfield_from_keysym(xcb_keysym_t keysym)
{
	uint16_t modfield = 0;
	xcb_keycode_t *keycodes = NULL, *mod_keycodes = NULL;
	xcb_get_modifier_mapping_reply_t *reply = NULL;
	xcb_key_symbols_t *symbols = xcb_key_symbols_alloc(dpy);

	if ((keycodes = xcb_key_symbols_get_keycode(symbols, keysym)) == NULL ||
	    (reply = xcb_get_modifier_mapping_reply(dpy, xcb_get_modifier_mapping(dpy), NULL)) == NULL ||
	    reply->keycodes_per_modifier < 1 ||
	    (mod_keycodes = xcb_get_modifier_mapping_keycodes(reply)) == NULL) {
		goto end;
	}

	unsigned int num_mod = xcb_get_modifier_mapping_keycodes_length(reply) / reply->keycodes_per_modifier;
	for (unsigned int i = 0; i < num_mod; i++) {
		for (unsigned int j = 0; j < reply->keycodes_per_modifier; j++) {
			xcb_keycode_t mk = mod_keycodes[i * reply->keycodes_per_modifier + j];
			if (mk == XCB_NO_SYMBOL) {
				continue;
			}
			for (xcb_keycode_t *k = keycodes; *k != XCB_NO_SYMBOL; k++) {
				if (*k == mk) {
					modfield |= (1 << i);
				}
			}
		}
	}

end:
	xcb_key_symbols_free(symbols);
	free(keycodes);
	free(reply);
	return modfield;
}
XRecordKeyboardMonitor::XRecordKeyboardMonitor(Display *display)
    : m_connection(xcb_connect(XDisplayString(display), 0)),
      m_modifiersPressed(0), m_keysPressed(0)
{
    if (!m_connection) {
        return;
    }

    xcb_get_modifier_mapping_cookie_t modmapCookie =
        xcb_get_modifier_mapping(m_connection);

    m_context = xcb_generate_id(m_connection);
    xcb_record_range_t range;
    memset(&range, 0, sizeof(range));
    range.device_events.first = XCB_KEY_PRESS;
    range.device_events.last = XCB_KEY_RELEASE;
    xcb_record_client_spec_t cs = XCB_RECORD_CS_ALL_CLIENTS;
    xcb_record_create_context(m_connection, m_context, 0, 1, 1, &cs, &range);
    xcb_flush(m_connection);

    QScopedPointer<xcb_get_modifier_mapping_reply_t, QScopedPointerPodDeleter>
    modmap(xcb_get_modifier_mapping_reply(m_connection, modmapCookie, 0));
    if (!modmap) {
        return;
    }

    int nModifiers = xcb_get_modifier_mapping_keycodes_length(modmap.data());
    xcb_keycode_t *modifiers = xcb_get_modifier_mapping_keycodes(modmap.data());
    m_modifier.fill(false, std::numeric_limits<xcb_keycode_t>::max() + 1);
    for (xcb_keycode_t *i = modifiers; i < modifiers + nModifiers; i++) {
        m_modifier[*i] = true;
    }
    m_ignore.fill(false, std::numeric_limits<xcb_keycode_t>::max() + 1);
    for (xcb_keycode_t *i = modifiers;
            i < modifiers + modmap->keycodes_per_modifier; i++)
    {
        m_ignore[*i] = true;
    }
    m_pressed.fill(false, std::numeric_limits<xcb_keycode_t>::max() + 1);

    m_cookie = xcb_record_enable_context(m_connection, m_context);
    xcb_flush(m_connection);

    m_notifier = new QSocketNotifier(xcb_get_file_descriptor(m_connection),
                                     QSocketNotifier::Read, this);
    connect(m_notifier, SIGNAL(activated(int)), SLOT(processNextReply()));
    m_notifier->setEnabled(true);
}