Hopefully fix for #268

This commit is contained in:
Dave Davenport 2015-11-20 20:53:27 +01:00
parent 1bd231bc3d
commit 266ee5efb7
5 changed files with 156 additions and 137 deletions

View file

@ -100,7 +100,7 @@ void textbox_draw ( textbox *tb, cairo_t *draw );
* *
* @returns if the key was handled (1), unhandled(0) or handled and return was pressed (-1) * @returns if the key was handled (1), unhandled(0) or handled and return was pressed (-1)
*/ */
int textbox_keypress ( textbox *tb, XIC xic, XEvent *ev ); int textbox_keypress ( textbox *tb, XEvent *ev, char *pad, KeySym key, Status stat );
/** /**
* @param tb Handle to the textbox * @param tb Handle to the textbox

View file

@ -30,6 +30,9 @@ ActionBindingEntry abe[NUM_ABE];
// Use this so we can ignore numlock mask. // Use this so we can ignore numlock mask.
// TODO: maybe use something smarter here.. // TODO: maybe use something smarter here..
extern unsigned int NumlockMask; extern unsigned int NumlockMask;
extern unsigned int AltMask;
extern unsigned int SuperRMask;
extern unsigned int SuperLMask;
/** /**
* LIST OF DEFAULT SETTINGS * LIST OF DEFAULT SETTINGS
@ -142,7 +145,7 @@ int abe_test_action ( KeyBindingAction action, unsigned int mask, KeySym key )
if ( kb->keysym == key ) { if ( kb->keysym == key ) {
// Bits 13 and 14 of the modifiers together are the group number, and // Bits 13 and 14 of the modifiers together are the group number, and
// should be ignored when looking up key bindings // should be ignored when looking up key bindings
if ( ( mask & ~( LockMask | NumlockMask | ( 1 << 13 ) | ( 1 << 14 ) ) ) == kb->modmask ) { if ( ( mask & ( AltMask | ControlMask | SuperRMask | SuperLMask ) ) == kb->modmask ) {
return TRUE; return TRUE;
} }
} }

View file

@ -1468,52 +1468,61 @@ MenuReturn menu ( Switcher *sw, char **input, char *prompt, unsigned int *select
// Key press event. // Key press event.
else if ( ev.type == KeyPress ) { else if ( ev.type == KeyPress ) {
do { do {
KeySym key = XkbKeycodeToKeysym ( display, ev.xkey.keycode, 0, 0 ); // This is needed for letting the Input Method handle combined keys.
// E.g. `e into è
if ( XFilterEvent ( &ev, main_window ) ) {
continue;
}
Status stat;
char pad[32];
KeySym key;// = XkbKeycodeToKeysym ( display, ev.xkey.keycode, 0, 0 );
int len = Xutf8LookupString ( xic, &( ev.xkey ), pad, sizeof ( pad ), &key, &stat );
pad[len] = 0;
// Handling of paste if ( stat == XLookupKeySym || stat == XLookupBoth ) {
if ( abe_test_action ( PASTE_PRIMARY, ev.xkey.state, key ) ) { // Handling of paste
XConvertSelection ( display, XA_PRIMARY, netatoms[UTF8_STRING], netatoms[UTF8_STRING], main_window, CurrentTime ); if ( abe_test_action ( PASTE_PRIMARY, ev.xkey.state, key ) ) {
} XConvertSelection ( display, XA_PRIMARY, netatoms[UTF8_STRING], netatoms[UTF8_STRING], main_window, CurrentTime );
else if ( abe_test_action ( PASTE_SECONDARY, ev.xkey.state, key ) ) {
XConvertSelection ( display, netatoms[CLIPBOARD], netatoms[UTF8_STRING], netatoms[UTF8_STRING], main_window,
CurrentTime );
}
else if ( abe_test_action ( MODE_PREVIOUS, ev.xkey.state, key ) ) {
state.retv = MENU_PREVIOUS;
*( state.selected_line ) = 0;
state.quit = TRUE;
break;
}
// Menu navigation.
else if ( abe_test_action ( MODE_NEXT, ev.xkey.state, key ) ) {
state.retv = MENU_NEXT;
*( state.selected_line ) = 0;
state.quit = TRUE;
break;
}
// Toggle case sensitivity.
else if ( abe_test_action ( TOGGLE_CASE_SENSITIVITY, ev.xkey.state, key ) ) {
config.case_sensitive = !config.case_sensitive;
*( state.selected_line ) = 0;
state.refilter = TRUE;
state.update = TRUE;
if ( config.case_sensitive ) {
textbox_text ( state.case_indicator, "*" );
} }
else { else if ( abe_test_action ( PASTE_SECONDARY, ev.xkey.state, key ) ) {
textbox_text ( state.case_indicator, " " ); XConvertSelection ( display, netatoms[CLIPBOARD], netatoms[UTF8_STRING], netatoms[UTF8_STRING], main_window,
CurrentTime );
} }
} else if ( abe_test_action ( MODE_PREVIOUS, ev.xkey.state, key ) ) {
// Special delete entry command. state.retv = MENU_PREVIOUS;
else if ( abe_test_action ( DELETE_ENTRY, ev.xkey.state, key ) ) { *( state.selected_line ) = 0;
if ( state.selected < state.filtered_lines ) {
*( state.selected_line ) = state.line_map[state.selected];
state.retv = MENU_ENTRY_DELETE;
state.quit = TRUE; state.quit = TRUE;
break; break;
} }
} // Menu navigation.
else{ else if ( abe_test_action ( MODE_NEXT, ev.xkey.state, key ) ) {
state.retv = MENU_NEXT;
*( state.selected_line ) = 0;
state.quit = TRUE;
break;
}
// Toggle case sensitivity.
else if ( abe_test_action ( TOGGLE_CASE_SENSITIVITY, ev.xkey.state, key ) ) {
config.case_sensitive = !config.case_sensitive;
*( state.selected_line ) = 0;
state.refilter = TRUE;
state.update = TRUE;
if ( config.case_sensitive ) {
textbox_text ( state.case_indicator, "*" );
}
else {
textbox_text ( state.case_indicator, " " );
}
}
// Special delete entry command.
else if ( abe_test_action ( DELETE_ENTRY, ev.xkey.state, key ) ) {
if ( state.selected < state.filtered_lines ) {
*( state.selected_line ) = state.line_map[state.selected];
state.retv = MENU_ENTRY_DELETE;
state.quit = TRUE;
break;
}
}
for ( unsigned int a = CUSTOM_1; a <= CUSTOM_19; a++ ) { for ( unsigned int a = CUSTOM_1; a <= CUSTOM_19; a++ ) {
if ( abe_test_action ( a, ev.xkey.state, key ) ) { if ( abe_test_action ( a, ev.xkey.state, key ) ) {
if ( state.selected < state.filtered_lines ) { if ( state.selected < state.filtered_lines ) {
@ -1524,17 +1533,14 @@ MenuReturn menu ( Switcher *sw, char **input, char *prompt, unsigned int *select
break; break;
} }
} }
}
{
// Skip if we detected key before. // Skip if we detected key before.
if ( state.quit ) { if ( state.quit ) {
continue; continue;
} }
// This is needed for letting the Input Method handle combined keys.
// E.g. `e into è
if ( XFilterEvent ( &ev, main_window ) ) {
continue;
}
int rc = textbox_keypress ( state.text, xic, &ev ); int rc = textbox_keypress ( state.text, &ev, pad, key, stat );
// Row is accepted. // Row is accepted.
if ( rc < 0 ) { if ( rc < 0 ) {
shift = ( ( ev.xkey.state & ShiftMask ) == ShiftMask ); shift = ( ( ev.xkey.state & ShiftMask ) == ShiftMask );

View file

@ -45,7 +45,9 @@
// Use this so we can ignore numlock mask. // Use this so we can ignore numlock mask.
// TODO: maybe use something smarter here.. // TODO: maybe use something smarter here..
extern unsigned int NumlockMask; extern unsigned int NumlockMask;
extern unsigned int ModeSwitchMask; extern unsigned int AltMask;
extern unsigned int SuperRMask;
extern unsigned int SuperLMask;
/** /**
* Font + font color cache. * Font + font color cache.
@ -496,90 +498,84 @@ static void textbox_cursor_del_word ( textbox *tb )
// 0 = unhandled // 0 = unhandled
// 1 = handled // 1 = handled
// -1 = handled and return pressed (finished) // -1 = handled and return pressed (finished)
int textbox_keypress ( textbox *tb, XIC xic, XEvent *ev ) int textbox_keypress ( textbox *tb, XEvent *ev, char *pad, KeySym key, Status stat )
{ {
KeySym key;
Status stat;
char pad[32];
int len;
if ( !( tb->flags & TB_EDITABLE ) ) { if ( !( tb->flags & TB_EDITABLE ) ) {
return 0; return 0;
} }
if ( stat == XLookupKeySym || stat == XLookupBoth ) {
// Left or Ctrl-b
if ( abe_test_action ( MOVE_CHAR_BACK, ev->xkey.state, key ) ) {
textbox_cursor_dec ( tb );
return 2;
}
// Right or Ctrl-F
else if ( abe_test_action ( MOVE_CHAR_FORWARD, ev->xkey.state, key ) ) {
textbox_cursor_inc ( tb );
return 2;
}
len = Xutf8LookupString ( xic, &ev->xkey, pad, sizeof ( pad ), &key, &stat ); // Ctrl-U: Kill from the beginning to the end of the line.
pad[len] = 0; else if ( abe_test_action ( CLEAR_LINE, ev->xkey.state, key ) ) {
// Left or Ctrl-b textbox_text ( tb, "" );
if ( abe_test_action ( MOVE_CHAR_BACK, ev->xkey.state, key ) ) { return 1;
textbox_cursor_dec ( tb ); }
return 2; // Ctrl-A
else if ( abe_test_action ( MOVE_FRONT, ev->xkey.state, key ) ) {
textbox_cursor ( tb, 0 );
return 2;
}
// Ctrl-E
else if ( abe_test_action ( MOVE_END, ev->xkey.state, key ) ) {
textbox_cursor_end ( tb );
return 2;
}
// Ctrl-Alt-h
else if ( abe_test_action ( REMOVE_WORD_BACK, ev->xkey.state, key ) ) {
textbox_cursor_bkspc_word ( tb );
return 1;
}
// Ctrl-Alt-d
else if ( abe_test_action ( REMOVE_WORD_FORWARD, ev->xkey.state, key ) ) {
textbox_cursor_del_word ( tb );
return 1;
} // Delete or Ctrl-D
else if ( abe_test_action ( REMOVE_CHAR_FORWARD, ev->xkey.state, key ) ) {
textbox_cursor_del ( tb );
return 1;
}
// Alt-B
else if ( abe_test_action ( MOVE_WORD_BACK, ev->xkey.state, key ) ) {
textbox_cursor_dec_word ( tb );
return 2;
}
// Alt-F
else if ( abe_test_action ( MOVE_WORD_FORWARD, ev->xkey.state, key ) ) {
textbox_cursor_inc_word ( tb );
return 2;
}
// BackSpace, Ctrl-h
else if ( abe_test_action ( REMOVE_CHAR_BACK, ev->xkey.state, key ) ) {
textbox_cursor_bkspc ( tb );
return 1;
}
else if ( abe_test_action ( ACCEPT_CUSTOM, ev->xkey.state, key ) ) {
return -2;
}
else if ( abe_test_action ( ACCEPT_ENTRY_CONTINUE, ev->xkey.state, key ) ) {
return -3;
}
else if ( abe_test_action ( ACCEPT_ENTRY, ev->xkey.state, key ) ) {
return -1;
}
} }
// Right or Ctrl-F if ( *pad != 0 && ( stat == XLookupBoth || stat == XLookupChars ) ) {
else if ( abe_test_action ( MOVE_CHAR_FORWARD, ev->xkey.state, key ) ) { // Filter When alt/ctrl is pressed do not accept the character.
textbox_cursor_inc ( tb ); if ( !g_ascii_iscntrl ( *pad ) && 0 == ( ev->xkey.state & ( ControlMask | AltMask | SuperRMask | SuperLMask ) ) ) {
return 2; textbox_insert ( tb, tb->cursor, pad );
} textbox_cursor_inc ( tb );
return 1;
// Ctrl-U: Kill from the beginning to the end of the line. }
else if ( abe_test_action ( CLEAR_LINE, ev->xkey.state, key ) ) {
textbox_text ( tb, "" );
return 1;
}
// Ctrl-A
else if ( abe_test_action ( MOVE_FRONT, ev->xkey.state, key ) ) {
textbox_cursor ( tb, 0 );
return 2;
}
// Ctrl-E
else if ( abe_test_action ( MOVE_END, ev->xkey.state, key ) ) {
textbox_cursor_end ( tb );
return 2;
}
// Ctrl-Alt-h
else if ( abe_test_action ( REMOVE_WORD_BACK, ev->xkey.state, key ) ) {
textbox_cursor_bkspc_word ( tb );
return 1;
}
// Ctrl-Alt-d
else if ( abe_test_action ( REMOVE_WORD_FORWARD, ev->xkey.state, key ) ) {
textbox_cursor_del_word ( tb );
return 1;
} // Delete or Ctrl-D
else if ( abe_test_action ( REMOVE_CHAR_FORWARD, ev->xkey.state, key ) ) {
textbox_cursor_del ( tb );
return 1;
}
// Alt-B
else if ( abe_test_action ( MOVE_WORD_BACK, ev->xkey.state, key ) ) {
textbox_cursor_dec_word ( tb );
return 2;
}
// Alt-F
else if ( abe_test_action ( MOVE_WORD_FORWARD, ev->xkey.state, key ) ) {
textbox_cursor_inc_word ( tb );
return 2;
}
// BackSpace, Ctrl-h
else if ( abe_test_action ( REMOVE_CHAR_BACK, ev->xkey.state, key ) ) {
textbox_cursor_bkspc ( tb );
return 1;
}
else if ( abe_test_action ( ACCEPT_CUSTOM, ev->xkey.state, key ) ) {
return -2;
}
else if ( abe_test_action ( ACCEPT_ENTRY_CONTINUE, ev->xkey.state, key ) ) {
return -3;
}
else if ( abe_test_action ( ACCEPT_ENTRY, ev->xkey.state, key ) ) {
return -1;
}
// Filter When alt/ctrl/etc is pressed do not accept the character.
// Ignore others (numlock, shift,..).
else if ( !iscntrl ( *pad ) && 0 ==
( ev->xkey.state & ~( ModeSwitchMask | NumlockMask | ( 1 << 12 ) | ( 1 << 13 ) | ShiftMask | LockMask ) ) ) {
textbox_insert ( tb, tb->cursor, pad );
textbox_cursor_inc ( tb );
return 1;
} }
return 0; return 0;

View file

@ -57,8 +57,10 @@
Atom netatoms[NUM_NETATOMS]; Atom netatoms[NUM_NETATOMS];
const char *netatom_names[] = { EWMH_ATOMS ( ATOM_CHAR ) }; const char *netatom_names[] = { EWMH_ATOMS ( ATOM_CHAR ) };
// Mask indicating num-lock. // Mask indicating num-lock.
unsigned int NumlockMask = 0; unsigned int NumlockMask = 0;
unsigned int ModeSwitchMask = 0; unsigned int AltMask = 0;
unsigned int SuperRMask = 0;
unsigned int SuperLMask = 0;
extern Colormap map; extern Colormap map;
@ -368,16 +370,24 @@ void x11_ungrab_key ( Display *display, unsigned int modmask, KeySym key )
*/ */
static void x11_figure_out_numlock_mask ( Display *display ) static void x11_figure_out_numlock_mask ( Display *display )
{ {
XModifierKeymap *modmap = XGetModifierMapping ( display ); XModifierKeymap *modmap = XGetModifierMapping ( display );
KeyCode kc = XKeysymToKeycode ( display, XK_Num_Lock ); KeyCode kc = XKeysymToKeycode ( display, XK_Num_Lock );
KeyCode kc_ms = XKeysymToKeycode ( display, XK_Mode_switch ); KeyCode kc_altl = XKeysymToKeycode ( display, XK_Alt_L );
KeyCode kc_superr = XKeysymToKeycode ( display, XK_Super_R );
KeyCode kc_superl = XKeysymToKeycode ( display, XK_Super_L );
for ( int i = 0; i < 8; i++ ) { for ( int i = 0; i < 8; i++ ) {
for ( int j = 0; j < ( int ) modmap->max_keypermod; j++ ) { for ( int j = 0; j < ( int ) modmap->max_keypermod; j++ ) {
if ( modmap->modifiermap[i * modmap->max_keypermod + j] == kc ) { if ( modmap->modifiermap[i * modmap->max_keypermod + j] == kc ) {
NumlockMask = ( 1 << i ); NumlockMask = ( 1 << i );
} }
if ( modmap->modifiermap[i * modmap->max_keypermod + j] == kc_ms ) { if ( modmap->modifiermap[i * modmap->max_keypermod + j] == kc_altl ) {
ModeSwitchMask = ( 1 << i ); AltMask |= ( 1 << i );
}
if ( modmap->modifiermap[i * modmap->max_keypermod + j] == kc_superr ) {
SuperRMask |= ( 1 << i );
}
if ( modmap->modifiermap[i * modmap->max_keypermod + j] == kc_superl ) {
SuperLMask |= ( 1 << i );
} }
} }
} }
@ -402,9 +412,14 @@ void x11_parse_key ( char *combo, unsigned int *mod, KeySym *key )
} }
if ( strcasestr ( combo, "alt" ) ) { if ( strcasestr ( combo, "alt" ) ) {
modmask |= Mod1Mask; modmask |= AltMask;
}
if ( strcasestr ( combo, "superr" ) ) {
modmask |= SuperRMask;
}
if ( strcasestr ( combo, "superl" ) ) {
modmask |= SuperLMask;
} }
if ( strcasestr ( combo, "mod2" ) ) { if ( strcasestr ( combo, "mod2" ) ) {
modmask |= Mod2Mask; modmask |= Mod2Mask;
} }
@ -436,7 +451,6 @@ void x11_parse_key ( char *combo, unsigned int *mod, KeySym *key )
// TODO popup // TODO popup
fprintf ( stderr, "sorry, cannot understand key combination: %s\n", combo ); fprintf ( stderr, "sorry, cannot understand key combination: %s\n", combo );
} }
*key = sym; *key = sym;
} }