static int keyboard_update_kbdtbl(idev_keyboard *k) { idev_device *d = &k->device; struct xkb_compose_state *compose = NULL; kbdtbl *kt; int r; assert(k); kt = k->kbdctx->kbdtbl; if (kt == k->kbdtbl) return 0; if (kt) { errno = 0; compose = xkb_compose_state_new(kt->xkb_compose_table, XKB_COMPOSE_STATE_NO_FLAGS); if (!compose) { r = errno > 0 ? -errno : -EFAULT; goto error; } } kbdtbl_unref(k->kbdtbl); k->kbdtbl = kbdtbl_ref(kt); xkb_compose_state_unref(k->xkb_compose); k->xkb_compose = compose; return 0; error: return log_debug_errno(r, "idev-keyboard: %s/%s: cannot adopt new compose table: %m", d->session->name, d->name); }
WaylandDisplay::WaylandDisplay() { m_display = wl_display_connect(nullptr); m_registry = wl_display_get_registry(m_display); wl_registry_add_listener(m_registry, &g_registryListener, &m_interfaces); wl_display_roundtrip(m_display); m_eventSource = g_source_new(&EventSource::sourceFuncs, sizeof(EventSource)); auto* source = reinterpret_cast<EventSource*>(m_eventSource); source->display = m_display; source->pfd.fd = wl_display_get_fd(m_display); source->pfd.events = G_IO_IN | G_IO_ERR | G_IO_HUP; source->pfd.revents = 0; g_source_add_poll(m_eventSource, &source->pfd); g_source_set_name(m_eventSource, "[WPE] WaylandDisplay"); g_source_set_priority(m_eventSource, G_PRIORITY_HIGH + 30); g_source_set_can_recurse(m_eventSource, TRUE); g_source_attach(m_eventSource, g_main_context_get_thread_default()); if (m_interfaces.xdg) { xdg_shell_add_listener(m_interfaces.xdg, &g_xdgShellListener, nullptr); xdg_shell_use_unstable_version(m_interfaces.xdg, 5); } wl_seat_add_listener(m_interfaces.seat, &g_seatListener, &m_seatData); m_seatData.xkb.context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); m_seatData.xkb.composeTable = xkb_compose_table_new_from_locale(m_seatData.xkb.context, setlocale(LC_CTYPE, nullptr), XKB_COMPOSE_COMPILE_NO_FLAGS); if (m_seatData.xkb.composeTable) m_seatData.xkb.composeState = xkb_compose_state_new(m_seatData.xkb.composeTable, XKB_COMPOSE_STATE_NO_FLAGS); }
static void init_keyboard(Keyboard *keyboard) { int ret = xkb_x11_setup_xkb_extension(keyboard->conn, XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION, XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, NULL, NULL, &keyboard->first_xkb_event, NULL); if (!ret) { fprintf(stderr, "Failed to setup XKB extension.\n"); exit(EXIT_FAILURE); } keyboard->ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!keyboard->ctx) { fprintf(stderr, "Failed to create XKB context.\n"); exit(EXIT_FAILURE); } keyboard->device_id = xkb_x11_get_core_keyboard_device_id(keyboard->conn); if (keyboard->device_id == -1) { fprintf(stderr, "Failed to create keyboard device.\n"); exit(EXIT_FAILURE); } static const xcb_xkb_map_part_t required_map_parts = ( XCB_XKB_MAP_PART_KEY_TYPES | XCB_XKB_MAP_PART_KEY_SYMS | XCB_XKB_MAP_PART_MODIFIER_MAP | XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS | XCB_XKB_MAP_PART_KEY_ACTIONS | XCB_XKB_MAP_PART_VIRTUAL_MODS | XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP); static const xcb_xkb_event_type_t required_events = ( XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY | XCB_XKB_EVENT_TYPE_MAP_NOTIFY | XCB_XKB_EVENT_TYPE_STATE_NOTIFY); xcb_xkb_select_events( keyboard->conn, keyboard->device_id, required_events, 0, required_events, required_map_parts, required_map_parts, NULL); keyboard->compose_table = xkb_compose_table_new_from_locale(keyboard->ctx, get_locale(), XKB_COMPOSE_COMPILE_NO_FLAGS); if (!keyboard->compose_table) { fprintf(stderr, "Failed create compose table.\n"); exit(EXIT_FAILURE); } keyboard->compose_state = xkb_compose_state_new(keyboard->compose_table, XKB_COMPOSE_STATE_NO_FLAGS); if (!keyboard->compose_state) { fprintf(stderr, "Failed create compose state.\n"); exit(EXIT_FAILURE); } update_keymap(keyboard); }
KeyboardEngine::KeyboardEngine(Instance *instance) : m_instance(instance), m_xkbContext(nullptr, &xkb_context_unref), m_xkbComposeTable(nullptr, &xkb_compose_table_unref), m_xkbComposeState(nullptr, &xkb_compose_state_unref) { m_isoCodes.read(ISOCODES_ISO639_XML, ISOCODES_ISO3166_XML); auto xcb = m_instance->addonManager().addon("xcb"); std::string rule; const char *locale = getenv("LC_ALL"); if (!locale) { locale = getenv("LC_CTYPE"); } if (!locale) { locale = getenv("LANG"); } if (!locale) { locale = "C"; } if (xcb) { auto rules = xcb->call<IXCBModule::xkbRulesNames>(""); if (!rules[0].empty()) { rule = rules[0]; if (rule[0] == '/') { rule += ".xml"; } else { rule = XKEYBOARDCONFIG_XKBBASE "/rules/" + rule + ".xml"; } m_ruleName = rule; } } if (rule.empty() || !m_xkbRules.read(rule)) { rule = XKEYBOARDCONFIG_XKBBASE "/rules/" DEFAULT_XKB_RULES ".xml"; m_xkbRules.read(rule); m_ruleName = DEFAULT_XKB_RULES; } m_xkbContext.reset(xkb_context_new(XKB_CONTEXT_NO_FLAGS)); if (m_xkbContext) { xkb_context_set_log_level(m_xkbContext.get(), XKB_LOG_LEVEL_CRITICAL); m_xkbComposeTable.reset( xkb_compose_table_new_from_locale(m_xkbContext.get(), locale, XKB_COMPOSE_COMPILE_NO_FLAGS)); if (m_xkbComposeTable) { m_xkbComposeState.reset(xkb_compose_state_new(m_xkbComposeTable.get(), XKB_COMPOSE_STATE_NO_FLAGS)); } } }
/* * Loads the XKB compose table from the given locale. * */ static bool load_compose_table(const char *locale) { xkb_compose_table_unref(xkb_compose_table); if ((xkb_compose_table = xkb_compose_table_new_from_locale(xkb_context, locale, 0)) == NULL) { fprintf(stderr, "[i3lock] xkb_compose_table_new_from_locale failed\n"); return false; } struct xkb_compose_state *new_compose_state = xkb_compose_state_new(xkb_compose_table, 0); if (new_compose_state == NULL) { fprintf(stderr, "[i3lock] xkb_compose_state_new failed\n"); return false; } xkb_compose_state_unref(xkb_compose_state); xkb_compose_state = new_compose_state; return true; }
int main ( int argc, char *argv[] ) { TIMINGS_START (); cmd_set_arguments ( argc, argv ); // Version if ( find_arg ( "-v" ) >= 0 || find_arg ( "-version" ) >= 0 ) { #ifdef GIT_VERSION fprintf ( stdout, "Version: "GIT_VERSION "\n" ); #else fprintf ( stdout, "Version: "VERSION "\n" ); #endif exit ( EXIT_SUCCESS ); } // Detect if we are in dmenu mode. // This has two possible causes. // 1 the user specifies it on the command-line. if ( find_arg ( "-dmenu" ) >= 0 ) { dmenu_mode = TRUE; } // 2 the binary that executed is called dmenu (e.g. symlink to rofi) else{ // Get the base name of the executable called. char *base_name = g_path_get_basename ( argv[0] ); const char * const dmenu_str = "dmenu"; dmenu_mode = ( strcmp ( base_name, dmenu_str ) == 0 ); // Free the basename for dmenu detection. g_free ( base_name ); } TICK (); // Get the path to the cache dir. cache_dir = g_get_user_cache_dir (); // Create pid file path. const char *path = g_get_user_runtime_dir (); if ( path ) { pidfile = g_build_filename ( path, "rofi.pid", NULL ); } config_parser_add_option ( xrm_String, "pid", (void * *) &pidfile, "Pidfile location" ); if ( find_arg ( "-config" ) < 0 ) { const char *cpath = g_get_user_config_dir (); if ( cpath ) { config_path = g_build_filename ( cpath, "rofi", "config", NULL ); } } else { char *c = NULL; find_arg_str ( "-config", &c ); config_path = rofi_expand_path ( c ); } TICK (); // Register cleanup function. atexit ( cleanup ); TICK (); // Get DISPLAY, first env, then argument. char *display_str = getenv ( "DISPLAY" ); find_arg_str ( "-display", &display_str ); if ( setlocale ( LC_ALL, "" ) == NULL ) { fprintf ( stderr, "Failed to set locale.\n" ); return EXIT_FAILURE; } xcb->connection = xcb_connect ( display_str, &xcb->screen_nbr ); if ( xcb_connection_has_error ( xcb->connection ) ) { fprintf ( stderr, "Failed to open display: %s", display_str ); return EXIT_FAILURE; } TICK_N ( "Open Display" ); xcb->screen = xcb_aux_get_screen ( xcb->connection, xcb->screen_nbr ); xcb_intern_atom_cookie_t *ac = xcb_ewmh_init_atoms ( xcb->connection, &xcb->ewmh ); xcb_generic_error_t *errors = NULL; xcb_ewmh_init_atoms_replies ( &xcb->ewmh, ac, &errors ); if ( errors ) { fprintf ( stderr, "Failed to create EWMH atoms\n" ); free ( errors ); } if ( xkb_x11_setup_xkb_extension ( xcb->connection, XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION, XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, NULL, NULL, &xkb.first_event, NULL ) < 0 ) { fprintf ( stderr, "cannot setup XKB extension!\n" ); return EXIT_FAILURE; } xkb.context = xkb_context_new ( XKB_CONTEXT_NO_FLAGS ); if ( xkb.context == NULL ) { fprintf ( stderr, "cannot create XKB context!\n" ); return EXIT_FAILURE; } xkb.xcb_connection = xcb->connection; xkb.device_id = xkb_x11_get_core_keyboard_device_id ( xcb->connection ); enum { required_events = ( XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY | XCB_XKB_EVENT_TYPE_MAP_NOTIFY | XCB_XKB_EVENT_TYPE_STATE_NOTIFY ), required_nkn_details = ( XCB_XKB_NKN_DETAIL_KEYCODES ), required_map_parts = ( XCB_XKB_MAP_PART_KEY_TYPES | XCB_XKB_MAP_PART_KEY_SYMS | XCB_XKB_MAP_PART_MODIFIER_MAP | XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS | XCB_XKB_MAP_PART_KEY_ACTIONS | XCB_XKB_MAP_PART_VIRTUAL_MODS | XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP ), required_state_details = ( XCB_XKB_STATE_PART_MODIFIER_BASE | XCB_XKB_STATE_PART_MODIFIER_LATCH | XCB_XKB_STATE_PART_MODIFIER_LOCK | XCB_XKB_STATE_PART_GROUP_BASE | XCB_XKB_STATE_PART_GROUP_LATCH | XCB_XKB_STATE_PART_GROUP_LOCK ), }; static const xcb_xkb_select_events_details_t details = { .affectNewKeyboard = required_nkn_details, .newKeyboardDetails = required_nkn_details, .affectState = required_state_details, .stateDetails = required_state_details, }; xcb_xkb_select_events ( xcb->connection, xkb.device_id, required_events, /* affectWhich */ 0, /* clear */ required_events, /* selectAll */ required_map_parts, /* affectMap */ required_map_parts, /* map */ &details ); xkb.keymap = xkb_x11_keymap_new_from_device ( xkb.context, xcb->connection, xkb.device_id, XKB_KEYMAP_COMPILE_NO_FLAGS ); if ( xkb.keymap == NULL ) { fprintf ( stderr, "Failed to get Keymap for current keyboard device.\n" ); return EXIT_FAILURE; } xkb.state = xkb_x11_state_new_from_device ( xkb.keymap, xcb->connection, xkb.device_id ); if ( xkb.state == NULL ) { fprintf ( stderr, "Failed to get state object for current keyboard device.\n" ); return EXIT_FAILURE; } xkb.compose.table = xkb_compose_table_new_from_locale ( xkb.context, setlocale ( LC_CTYPE, NULL ), 0 ); if ( xkb.compose.table != NULL ) { xkb.compose.state = xkb_compose_state_new ( xkb.compose.table, 0 ); } else { fprintf ( stderr, "Failed to get keyboard compose table. Trying to limp on.\n" ); } if ( xcb_connection_has_error ( xcb->connection ) ) { fprintf ( stderr, "Connection has error\n" ); exit ( EXIT_FAILURE ); } x11_setup ( &xkb ); if ( xcb_connection_has_error ( xcb->connection ) ) { fprintf ( stderr, "Connection has error\n" ); exit ( EXIT_FAILURE ); } const xcb_query_extension_reply_t *er = xcb_get_extension_data ( xcb->connection, &xcb_xinerama_id ); if ( er ) { if ( er->present ) { xcb_xinerama_is_active_cookie_t is_active_req = xcb_xinerama_is_active ( xcb->connection ); xcb_xinerama_is_active_reply_t *is_active = xcb_xinerama_is_active_reply ( xcb->connection, is_active_req, NULL ); xcb->has_xinerama = is_active->state; free ( is_active ); } } main_loop = g_main_loop_new ( NULL, FALSE ); TICK_N ( "Setup mainloop" ); // startup not. xcb->sndisplay = sn_xcb_display_new ( xcb->connection, error_trap_push, error_trap_pop ); if ( xcb_connection_has_error ( xcb->connection ) ) { fprintf ( stderr, "Connection has error\n" ); exit ( EXIT_FAILURE ); } if ( xcb->sndisplay != NULL ) { xcb->sncontext = sn_launchee_context_new_from_environment ( xcb->sndisplay, xcb->screen_nbr ); } if ( xcb_connection_has_error ( xcb->connection ) ) { fprintf ( stderr, "Connection has error\n" ); exit ( EXIT_FAILURE ); } TICK_N ( "Startup Notification" ); // Initialize Xresources subsystem. config_parse_xresource_init (); TICK_N ( "Initialize Xresources system" ); // Setup keybinding setup_abe (); TICK_N ( "Setup abe" ); if ( find_arg ( "-no-config" ) < 0 ) { load_configuration ( ); } if ( !dmenu_mode ) { // setup_modi setup_modi (); } if ( find_arg ( "-no-config" ) < 0 ) { // Reload for dynamic part. load_configuration_dynamic ( ); } // Dump. // catch help request if ( find_arg ( "-h" ) >= 0 || find_arg ( "-help" ) >= 0 || find_arg ( "--help" ) >= 0 ) { help ( argc, argv ); exit ( EXIT_SUCCESS ); } if ( find_arg ( "-dump-xresources" ) >= 0 ) { config_parse_xresource_dump (); exit ( EXIT_SUCCESS ); } if ( find_arg ( "-dump-xresources-theme" ) >= 0 ) { config_parse_xresources_theme_dump (); exit ( EXIT_SUCCESS ); } main_loop_source = g_water_xcb_source_new_for_connection ( NULL, xcb->connection, main_loop_x11_event_handler, NULL, NULL ); TICK_N ( "X11 Setup " ); rofi_view_workers_initialize (); // Setup signal handling sources. // SIGINT g_unix_signal_add ( SIGINT, main_loop_signal_handler_int, NULL ); g_idle_add ( startup, NULL ); // Start mainloop. g_main_loop_run ( main_loop ); return return_code; }
static void keyboardHandleKeymap(void* data, struct wl_keyboard* keyboard, uint32_t format, int fd, uint32_t size) { struct xkb_keymap* keymap; struct xkb_state* state; #ifdef HAVE_XKBCOMMON_COMPOSE_H struct xkb_compose_table* composeTable; struct xkb_compose_state* composeState; #endif char* mapStr; const char* locale; if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { close(fd); return; } mapStr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); if (mapStr == MAP_FAILED) { close(fd); return; } keymap = xkb_keymap_new_from_string(_glfw.wl.xkb.context, mapStr, XKB_KEYMAP_FORMAT_TEXT_V1, 0); munmap(mapStr, size); close(fd); if (!keymap) { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Failed to compile keymap"); return; } state = xkb_state_new(keymap); if (!state) { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Failed to create XKB state"); xkb_keymap_unref(keymap); return; } // Look up the preferred locale, falling back to "C" as default. locale = getenv("LC_ALL"); if (!locale) locale = getenv("LC_CTYPE"); if (!locale) locale = getenv("LANG"); if (!locale) locale = "C"; #ifdef HAVE_XKBCOMMON_COMPOSE_H composeTable = xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale, XKB_COMPOSE_COMPILE_NO_FLAGS); if (composeTable) { composeState = xkb_compose_state_new(composeTable, XKB_COMPOSE_STATE_NO_FLAGS); xkb_compose_table_unref(composeTable); if (composeState) _glfw.wl.xkb.composeState = composeState; else _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Failed to create XKB compose state"); } else { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Failed to create XKB compose table"); } #endif xkb_keymap_unref(_glfw.wl.xkb.keymap); xkb_state_unref(_glfw.wl.xkb.state); _glfw.wl.xkb.keymap = keymap; _glfw.wl.xkb.state = state; _glfw.wl.xkb.controlMask = 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Control"); _glfw.wl.xkb.altMask = 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod1"); _glfw.wl.xkb.shiftMask = 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Shift"); _glfw.wl.xkb.superMask = 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod4"); _glfw.wl.xkb.capsLockMask = 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Lock"); _glfw.wl.xkb.numLockMask = 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod2"); }