/** * Query for the XKB extension */ void query_extension(connection& conn) { conn.xkb().use_extension(XCB_XKB_MAJOR_VERSION, XCB_XKB_MINOR_VERSION); if (!conn.extension<xpp::xkb::extension>()->present) { throw application_error("Missing X extension: XKb"); } }
/** * Get keyboard indicators */ map<keyboard::indicator::type, keyboard::indicator> get_indicators(connection& conn, xcb_xkb_device_spec_t device) { map<keyboard::indicator::type, keyboard::indicator> results; unsigned int mask{XCB_XKB_NAME_DETAIL_INDICATOR_NAMES}; auto reply = xcb_xkb_get_names_reply(conn, xcb_xkb_get_names(conn, device, mask), nullptr); if (reply == nullptr) { return results; } xcb_xkb_get_names_value_list_t values{}; void* buffer = xcb_xkb_get_names_value_list(reply); xcb_xkb_get_names_value_list_unpack(buffer, reply->nTypes, reply->indicators, reply->virtualMods, reply->groupNames, reply->nKeys, reply->nKeyAliases, reply->nRadioGroups, reply->which, &values); using get_atom_name_reply = xpp::x::reply::checked::get_atom_name<connection&>; map<xcb_atom_t, get_atom_name_reply> entries; for (int i = 0; i < xcb_xkb_get_names_value_list_indicator_names_length(reply, &values); i++) { entries.emplace(values.indicatorNames[i], xpp::x::get_atom_name(conn, values.indicatorNames[i])); } for (const auto& entry : entries) { auto name = static_cast<get_atom_name_reply>(entry.second).name(); auto type = keyboard::indicator::type::NONE; if (string_util::compare(name, "caps lock")) { type = keyboard::indicator::type::CAPS_LOCK; } else if (string_util::compare(name, "num lock")) { type = keyboard::indicator::type::NUM_LOCK; } else { continue; } auto data = conn.xkb().get_named_indicator(device, 0, 0, entry.first); auto mask = (*conn.xkb().get_indicator_map(device, 1 << data->ndx).maps().begin()).mods; auto enabled = static_cast<bool>(data->on); results.emplace(type, keyboard::indicator{entry.first, mask, name, enabled}); } free(reply); return results; }