summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/keyb.c4
-rw-r--r--source/rofi.c82
-rw-r--r--source/scrollbar.c1
-rw-r--r--source/textbox.c6
-rw-r--r--source/view.c106
-rw-r--r--source/x11-helper.c6
6 files changed, 145 insertions, 60 deletions
diff --git a/source/keyb.c b/source/keyb.c
index 7c6e7046..4ed04a67 100644
--- a/source/keyb.c
+++ b/source/keyb.c
@@ -8,7 +8,7 @@
typedef struct _KeyBinding
{
unsigned int modmask;
- KeySym keysym;
+ xkb_keysym_t keysym;
} KeyBinding;
typedef struct _ActionBindingEntry
@@ -133,7 +133,7 @@ void cleanup_abe ( void )
}
}
-int abe_test_action ( KeyBindingAction action, unsigned int mask, KeySym key )
+int abe_test_action ( KeyBindingAction action, unsigned int mask, xkb_keysym_t key )
{
ActionBindingEntry *akb = &( abe[action] );
diff --git a/source/rofi.c b/source/rofi.c
index f3e2557e..18b9c76f 100644
--- a/source/rofi.c
+++ b/source/rofi.c
@@ -36,7 +36,9 @@
#include <locale.h>
#include <xcb/xcb.h>
#include <xcb/xcb_aux.h>
+#include <xcb/xkb.h>
#include <xkbcommon/xkbcommon.h>
+#include <xkbcommon/xkbcommon-x11.h>
#include <X11/X.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
@@ -66,6 +68,7 @@
#include "view.h"
#include "view-internal.h"
+#include "xkb-internal.h"
gboolean daemon_mode = FALSE;
// Pidfile.
@@ -75,9 +78,10 @@ SnDisplay *sndisplay = NULL;
SnLauncheeContext *sncontext = NULL;
xcb_connection_t *xcb_connection = NULL;
xcb_screen_t *xcb_screen = NULL;
-Display *display = NULL;
-char *display_str = NULL;
-char *config_path = NULL;
+struct xkb_stuff xkb = { NULL };
+Display *display = NULL;
+char *display_str = NULL;
+char *config_path = NULL;
// Array of modi.
Mode **modi = NULL;
unsigned int num_modi = 0;
@@ -128,7 +132,7 @@ static int switcher_get ( const char *name )
}
extern unsigned int NumlockMask;
-int locate_switcher ( KeySym key, unsigned int modstate )
+int locate_switcher ( xkb_keysym_t key, unsigned int modstate )
{
// ignore annoying modifiers
unsigned int modstate_filtered = modstate & ~( LockMask | NumlockMask );
@@ -285,10 +289,10 @@ int show_error_message ( const char *msg, int markup )
* Function that listens for global key-presses.
* This is only used when in daemon mode.
*/
-static void handle_keypress ( xcb_key_press_event_t *ev )
+static void handle_keypress ( xcb_key_press_event_t *ev, struct xkb_stuff *xkb )
{
- int index;
- KeySym key = XkbKeycodeToKeysym ( display, ev->detail, 0, 0 );
+ xkb_keysym_t key = xkb_state_key_get_one_sym ( xkb->state, ev->detail );
+ int index;
index = locate_switcher ( key, ev->state );
if ( index >= 0 ) {
run_switcher ( index );
@@ -557,7 +561,7 @@ static gboolean main_loop_x11_event_handler ( xcb_generic_event_t *ev, G_GNUC_UN
sn_xcb_display_process_event ( sndisplay, ev );
}
if ( state != NULL ) {
- rofi_view_itterrate ( state, ev );
+ rofi_view_itterrate ( state, ev, &xkb );
if ( rofi_view_get_completed ( state ) ) {
// This menu is done.
rofi_view_finalize ( state );
@@ -576,7 +580,7 @@ static gboolean main_loop_x11_event_handler ( xcb_generic_event_t *ev, G_GNUC_UN
// Ignore it.
// If keypress, handle it.
if ( ( ev->response_type & ~0x80 ) == XCB_KEY_PRESS ) {
- handle_keypress ( (xcb_key_press_event_t *) ev );
+ handle_keypress ( (xcb_key_press_event_t *) ev, &xkb );
}
}
return G_SOURCE_CONTINUE;
@@ -600,6 +604,7 @@ static gboolean main_loop_signal_handler_hup ( G_GNUC_UNUSED gpointer data )
grab_global_keybindings ();
// We need to flush, otherwise the first key presses are not caught.
xcb_flush ( xcb_connection );
+ XFlush ( display );
return G_SOURCE_CONTINUE;
}
@@ -804,6 +809,65 @@ int main ( int argc, char *argv[] )
xcb_connection = XGetXCBConnection ( display );
xcb_screen = xcb_aux_get_screen ( xcb_connection, DefaultScreen ( display ) );
+ 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 */
+ 0, /* 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 );
+ xkb.state = xkb_x11_state_new_from_device ( xkb.keymap, xcb_connection, xkb.device_id );
+
main_loop = g_main_loop_new ( NULL, FALSE );
TICK_N ( "Setup mainloop" );
diff --git a/source/scrollbar.c b/source/scrollbar.c
index 35b3d3d3..2f3eee63 100644
--- a/source/scrollbar.c
+++ b/source/scrollbar.c
@@ -23,6 +23,7 @@
*/
#include <config.h>
+#include <xkbcommon/xkbcommon.h>
#include <X11/X.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
diff --git a/source/textbox.c b/source/textbox.c
index bb784eb8..d9225fb3 100644
--- a/source/textbox.c
+++ b/source/textbox.c
@@ -533,14 +533,14 @@ static void textbox_cursor_del_word ( textbox *tb )
// 0 = unhandled
// 1 = handled
// -1 = handled and return pressed (finished)
-int textbox_keypress ( textbox *tb, xcb_key_press_event_t *ev, char *pad, int pad_len, KeySym key, Status stat )
+int textbox_keypress ( textbox *tb, xcb_key_press_event_t *ev, char *pad, int pad_len, xkb_keysym_t key )
{
if ( !( tb->flags & TB_EDITABLE ) ) {
return 0;
}
int old_blink = tb->blink;
tb->blink = 2;
- if ( stat == XLookupKeySym || stat == XLookupBoth ) {
+ if ( key != XKB_KEY_NoSymbol ) {
// Left or Ctrl-b
if ( abe_test_action ( MOVE_CHAR_BACK, ev->state, key ) ) {
textbox_cursor_dec ( tb );
@@ -606,7 +606,7 @@ int textbox_keypress ( textbox *tb, xcb_key_press_event_t *ev, char *pad, int pa
return -1;
}
}
- if ( pad_len > 0 && ( stat == XLookupBoth || stat == XLookupChars ) ) {
+ if ( pad_len > 0 ) {
// Filter When alt/ctrl is pressed do not accept the character.
if ( !g_ascii_iscntrl ( *pad ) ) {
textbox_insert ( tb, tb->cursor, pad, pad_len );
diff --git a/source/view.c b/source/view.c
index c5ef9b84..ffde0a32 100644
--- a/source/view.c
+++ b/source/view.c
@@ -34,6 +34,8 @@
#include <errno.h>
#include <time.h>
#include <locale.h>
+#include <xkbcommon/xkbcommon-x11.h>
+#include <xcb/xkb.h>
#include <X11/X.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
@@ -54,7 +56,7 @@
#include "rofi.h"
#include "mode.h"
-#include "rofi.h"
+#include "xkb-internal.h"
#include "helper.h"
#include "textbox.h"
#include "scrollbar.h"
@@ -367,34 +369,58 @@ static void rofi_view_resize ( RofiViewState *state )
state->update = TRUE;
}
-void rofi_view_itterrate ( RofiViewState *state, xcb_generic_event_t *event )
+void rofi_view_itterrate ( RofiViewState *state, xcb_generic_event_t *event, xkb_stuff *xkb )
{
uint8_t type = event->response_type & ~0x80;
- switch ( type )
- {
- case XCB_EXPOSE:
- state->update = TRUE;
- break;
- case XCB_CONFIGURE_NOTIFY:
- {
- xcb_configure_notify_event_t *xce = (xcb_configure_notify_event_t *) event;
- if ( xce->window == main_window ) {
- if ( state->x != xce->x || state->y != xce->y ) {
- state->x = xce->x;
- state->y = xce->y;
- state->update = TRUE;
- }
- if ( state->w != xce->width || state->h != xce->height ) {
- state->w = xce->width;
- state->h = xce->height;
- cairo_xlib_surface_set_size ( surface, state->w, state->h );
- rofi_view_resize ( state );
- }
+ if ( type == xkb->first_event ) {
+ switch ( event->pad0 )
+ {
+ case XCB_XKB_MAP_NOTIFY:
+ xkb_state_unref ( xkb->state );
+ xkb_keymap_unref ( xkb->keymap );
+ xkb->keymap = xkb_x11_keymap_new_from_device ( xkb->context, xkb->xcb_connection, xkb->device_id, 0 );
+ xkb->state = xkb_x11_state_new_from_device ( xkb->keymap, xkb->xcb_connection, xkb->device_id );
+ break;
+ case XCB_XKB_STATE_NOTIFY:
+ {
+ xcb_xkb_state_notify_event_t *ksne = (xcb_xkb_state_notify_event_t *) event;
+ xkb_state_update_mask ( xkb->state,
+ ksne->baseMods,
+ ksne->latchedMods,
+ ksne->lockedMods,
+ ksne->baseGroup,
+ ksne->latchedGroup,
+ ksne->lockedGroup );
+ break;
+ }
}
}
- break;
- default:
- state->x11_event_loop ( state, event, xkb );
+ else{ switch ( type )
+ {
+ case XCB_EXPOSE:
+ state->update = TRUE;
+ break;
+ case XCB_CONFIGURE_NOTIFY:
+ {
+ xcb_configure_notify_event_t *xce = (xcb_configure_notify_event_t *) event;
+ if ( xce->window == main_window ) {
+ if ( state->x != xce->x || state->y != xce->y ) {
+ state->x = xce->x;
+ state->y = xce->y;
+ state->update = TRUE;
+ }
+ if ( state->w != xce->width || state->h != xce->height ) {
+ state->w = xce->width;
+ state->h = xce->height;
+ cairo_xlib_surface_set_size ( surface, state->w, state->h );
+ rofi_view_resize ( state );
+ }
+ }
+ break;
+ }
+ default:
+ state->x11_event_loop ( state, event, xkb );
+ }
}
rofi_view_update ( state );
}
@@ -996,7 +1022,7 @@ static void rofi_view_paste ( RofiViewState *state, xcb_selection_notify_event_t
*
* Keyboard navigation through the elements.
*/
-static int rofi_view_keyboard_navigation ( RofiViewState *state, KeySym key, unsigned int modstate )
+static int rofi_view_keyboard_navigation ( RofiViewState *state, xkb_keysym_t key, unsigned int modstate )
{
// pressing one of the global key bindings closes the switcher. This allows fast closing of the
// menu if an item is not selected
@@ -1246,7 +1272,7 @@ void rofi_view_setup_fake_transparency ( Display *display, RofiViewState *state
}
}
-static void rofi_view_mainloop_iter ( RofiViewState *state, xcb_generic_event_t *ev )
+static void rofi_view_mainloop_iter ( RofiViewState *state, xcb_generic_event_t *ev, xkb_stuff *xkb )
{
switch ( ev->response_type & ~0x80 )
{
@@ -1279,20 +1305,14 @@ static void rofi_view_mainloop_iter ( RofiViewState *state, xcb_generic_event_t
case XCB_KEY_PRESS:
{
xcb_key_press_event_t *xkpe = (xcb_key_press_event_t *) ev;
- XEvent fake_event;
- fake_event.type = KeyPress;
- fake_event.xany.display = display;
- fake_event.xany.window = xkpe->event;
- fake_event.xkey.state = xkpe->state;
- fake_event.xkey.keycode = xkpe->detail;
- // This is needed for letting the Input Method handle combined keys.
- // E.g. `e into รจ
- Status stat;
- char pad[32];
- KeySym key; // = XkbKeycodeToKeysym ( display, ev->xkey.keycode, 0, 0 );
- int len = Xutf8LookupString ( xic, &( fake_event.xkey ), pad, sizeof ( pad ), &key, &stat );
- pad[len] = 0;
- if ( stat == XLookupKeySym || stat == XLookupBoth ) {
+ xcb_keysym_t key;
+ char pad[32];
+ int len = 0;
+
+ key = xkb_state_key_get_one_sym ( xkb->state, xkpe->detail );
+ len = xkb_state_key_get_utf8 ( xkb->state, xkpe->detail, pad, sizeof ( pad ) );
+
+ if ( key != XKB_KEY_NoSymbol ) {
// Handling of paste
if ( abe_test_action ( PASTE_PRIMARY, xkpe->state, key ) ) {
XConvertSelection ( display, XA_PRIMARY, netatoms[UTF8_STRING], netatoms[UTF8_STRING], main_window, CurrentTime );
@@ -1364,7 +1384,7 @@ static void rofi_view_mainloop_iter ( RofiViewState *state, xcb_generic_event_t
break;
}
- int rc = textbox_keypress ( state->text, xkpe, pad, len, key, stat );
+ int rc = textbox_keypress ( state->text, xkpe, pad, len, key );
// Row is accepted.
if ( rc < 0 ) {
int shift = ( ( xkpe->state & ShiftMask ) == ShiftMask );
@@ -1625,7 +1645,7 @@ RofiViewState *rofi_view_create ( Mode *sw,
}
return state;
}
-static void __error_dialog_event_loop ( RofiViewState *state, xcb_generic_event_t *ev )
+static void __error_dialog_event_loop ( RofiViewState *state, xcb_generic_event_t *ev, G_GNUC_UNUSED xkb_stuff *xkb )
{
// Handle event.
switch ( ev->response_type & ~0x80 )
diff --git a/source/x11-helper.c b/source/x11-helper.c
index 6e18c802..576ec72c 100644
--- a/source/x11-helper.c
+++ b/source/x11-helper.c
@@ -433,7 +433,7 @@ static void x11_figure_out_numlock_mask ( Display *display )
}
// convert a Mod+key arg to mod mask and keysym
-void x11_parse_key ( char *combo, unsigned int *mod, KeySym *key )
+void x11_parse_key ( char *combo, unsigned int *mod, xkb_keysym_t *key )
{
GString *str = g_string_new ( "" );
unsigned int modmask = 0;
@@ -506,9 +506,9 @@ void x11_parse_key ( char *combo, unsigned int *mod, KeySym *key )
i--;
}
- KeySym sym = XStringToKeysym ( combo + i );
+ xkb_keysym_t sym = xkb_keysym_from_name ( combo + i, XKB_KEYSYM_CASE_INSENSITIVE );
- if ( sym == NoSymbol || ( !modmask && ( strchr ( combo, '-' ) || strchr ( combo, '+' ) ) ) ) {
+ if ( sym == XKB_KEY_NoSymbol || ( !modmask && ( strchr ( combo, '-' ) || strchr ( combo, '+' ) ) ) ) {
g_string_append_printf ( str, "Sorry, rofi cannot understand the key combination: <i>%s</i>\n", combo );
g_string_append ( str, "\nRofi supports the following modifiers:\n\t" );
g_string_append ( str, "<i>Shift,Control,Alt,AltGR,SuperL,SuperR," );