make control keys work in menus/dialogs/etc with the new obt code, using XLookup stuff

This commit is contained in:
Dana Jansens 2010-02-11 15:05:16 -05:00
parent 6c760c5a63
commit 096dad0c6c
11 changed files with 101 additions and 143 deletions

View file

@ -281,7 +281,7 @@ KeyCode* obt_keyboard_keysym_to_keycode(KeySym sym)
return ret;
}
gunichar obt_keyboard_keypress_to_unichar(ObtIC *ic, XKeyPressedEvent *ev)
gunichar obt_keyboard_keypress_to_unichar(ObtIC *ic, XEvent *ev)
{
gunichar unikey = 0;
KeySym sym;
@ -290,6 +290,8 @@ gunichar obt_keyboard_keypress_to_unichar(ObtIC *ic, XKeyPressedEvent *ev)
gint len, bufsz;
gboolean got_string = FALSE;
g_return_val_if_fail(ev->type == KeyPress, 0);
if (!ic)
g_warning("Using obt_keyboard_keypress_to_unichar() without an "
"Input Context. No i18n support!");
@ -299,9 +301,9 @@ gunichar obt_keyboard_keypress_to_unichar(ObtIC *ic, XKeyPressedEvent *ev)
bufsz = sizeof(fixbuf);
#ifdef X_HAVE_UTF8_STRING
len = Xutf8LookupString(ic->xic, ev, buf, bufsz, &sym, &status);
len = Xutf8LookupString(ic->xic, &ev->xkey, buf, bufsz, &sym, &status);
#else
len = XmbLookupString(ic->xic, ev, buf, bufsz, &sym, &status);
len = XmbLookupString(ic->xic, &ev->xkey, buf, bufsz, &sym, &status);
#endif
if (status == XBufferOverflow) {
@ -309,9 +311,11 @@ gunichar obt_keyboard_keypress_to_unichar(ObtIC *ic, XKeyPressedEvent *ev)
bufsz = len;
#ifdef X_HAVE_UTF8_STRING
len = Xutf8LookupString(ic->xic, ev, buf, bufsz, &sym, &status);
len = Xutf8LookupString(ic->xic, &ev->xkey, buf, bufsz, &sym,
&status);
#else
len = XmbLookupString(ic->xic, ev, buf, bufsz, &sym, &status);
len = XmbLookupString(ic->xic, &ev->xkey, buf, bufsz, &sym,
&status);
#endif
}
@ -338,7 +342,7 @@ gunichar obt_keyboard_keypress_to_unichar(ObtIC *ic, XKeyPressedEvent *ev)
else {
buf = fixbuf;
bufsz = sizeof(fixbuf);
len = XLookupString(ev, buf, bufsz, &sym, NULL);
len = XLookupString(&ev->xkey, buf, bufsz, &sym, NULL);
if ((guchar)buf[0] >= 32) /* not an ascii control character */
got_string = TRUE;
}
@ -354,6 +358,18 @@ gunichar obt_keyboard_keypress_to_unichar(ObtIC *ic, XKeyPressedEvent *ev)
return unikey;
}
KeySym obt_keyboard_keypress_to_keysym(XEvent *ev)
{
KeySym sym;
gint r;
g_return_val_if_fail(ev->type == KeyPress, None);
sym = None;
r = XLookupString(&ev->xkey, NULL, 0, &sym, NULL);
return sym;
}
void obt_keyboard_context_renew(ObtIC *ic)
{
if (ic->xic) {

View file

@ -21,6 +21,7 @@
#include <glib.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
G_BEGIN_DECLS
@ -60,7 +61,11 @@ guint obt_keyboard_modkey_to_modmask(ObtModkeysKey key);
KeyCode* obt_keyboard_keysym_to_keycode(KeySym sym);
/*! Translate a KeyPress event to the unicode character it represents */
gunichar obt_keyboard_keypress_to_unichar(ObtIC *ic, XKeyPressedEvent *ev);
gunichar obt_keyboard_keypress_to_unichar(ObtIC *ic, XEvent *ev);
/*! Translate a KeyPress event to the KeySym that it represents. Use this
for control keys, not for getting text input! */
KeySym obt_keyboard_keypress_to_keysym(XEvent *ev);
/*! Create an input context for a window.
@client The top-level client window for the input context.

View file

@ -185,17 +185,17 @@ static gboolean i_input_func(guint initial_state,
}
if (e->type == KeyPress) {
KeySym sym = obt_keyboard_keypress_to_keysym(e);
/* Escape cancels no matter what */
if (ob_keycode_match(e->xkey.keycode, OB_KEY_ESCAPE)) {
if (sym == XK_Escape) {
o->cancel = TRUE;
o->state = e->xkey.state;
return FALSE;
}
/* There were no modifiers and they pressed enter */
else if (ob_keycode_match(e->xkey.keycode, OB_KEY_RETURN) &&
!initial_state)
{
else if (sym == XK_Return && !initial_state) {
o->cancel = FALSE;
o->state = e->xkey.state;
return FALSE;

View file

@ -312,17 +312,15 @@ static gboolean i_input_func(guint initial_state,
}
if (e->type == KeyPress) {
KeySym sym = obt_keyboard_keypress_to_keysym(e);
/* Escape cancels no matter what */
if (ob_keycode_match(e->xkey.keycode, OB_KEY_ESCAPE)) {
if (sym == XK_Escape)
return FALSE;
}
/* There were no modifiers and they pressed enter */
else if (ob_keycode_match(e->xkey.keycode, OB_KEY_RETURN) &&
!initial_state)
{
else if (sym == XK_Return && !initial_state)
return FALSE;
}
}
/* They released the modifiers */
else if (e->type == KeyRelease && initial_state && !(mods & initial_state))

View file

@ -269,16 +269,16 @@ static gboolean i_input_func(guint initial_state,
}
if (e->type == KeyPress) {
KeySym sym = obt_keyboard_keypress_to_keysym(e);
/* Escape cancels no matter what */
if (ob_keycode_match(e->xkey.keycode, OB_KEY_ESCAPE)) {
if (sym == XK_Escape) {
end_cycle(TRUE, e->xkey.state, options);
return FALSE;
}
/* There were no modifiers and they pressed enter */
else if (ob_keycode_match(e->xkey.keycode, OB_KEY_RETURN) &&
!initial_state)
{
else if (sym == XK_Return && !initial_state) {
end_cycle(FALSE, e->xkey.state, options);
return FALSE;
}

View file

@ -1777,20 +1777,20 @@ static gboolean event_handle_menu_input(XEvent *ev)
/* Allow control while going thru the menu */
else if (ev->type == KeyPress && (mods & ~ControlMask) == 0) {
gunichar unikey;
KeySym sym;
frame->got_press = TRUE;
frame->press_keycode = ev->xkey.keycode;
frame->press_doexec = FALSE;
unikey = obt_keyboard_keypress_to_unichar(menu_frame_ic(frame),
&ev->xkey);
sym = obt_keyboard_keypress_to_keysym(ev);
if (ob_keycode_match(ev->xkey.keycode, OB_KEY_ESCAPE)) {
if (sym == XK_Escape) {
menu_frame_hide_all();
ret = TRUE;
}
else if (ob_keycode_match(ev->xkey.keycode, OB_KEY_LEFT)) {
else if (sym == XK_Left) {
/* Left goes to the parent menu */
if (frame->parent) {
/* remove focus from the child */
@ -1802,7 +1802,7 @@ static gboolean event_handle_menu_input(XEvent *ev)
ret = TRUE;
}
else if (ob_keycode_match(ev->xkey.keycode, OB_KEY_RIGHT)) {
else if (sym == XK_Right) {
/* Right goes to the selected submenu */
if (frame->selected->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU)
{
@ -1813,28 +1813,37 @@ static gboolean event_handle_menu_input(XEvent *ev)
ret = TRUE;
}
else if (ob_keycode_match(ev->xkey.keycode, OB_KEY_UP)) {
else if (sym == XK_Up) {
menu_frame_select_previous(frame);
ret = TRUE;
}
else if (ob_keycode_match(ev->xkey.keycode, OB_KEY_DOWN)) {
else if (sym == XK_Down) {
menu_frame_select_next(frame);
ret = TRUE;
}
else if (ob_keycode_match(ev->xkey.keycode, OB_KEY_HOME)) {
else if (sym == XK_Home) {
menu_frame_select_first(frame);
ret = TRUE;
}
else if (ob_keycode_match(ev->xkey.keycode, OB_KEY_END)) {
else if (sym == XK_End) {
menu_frame_select_last(frame);
ret = TRUE;
}
else if (sym == XK_Return) {
frame->press_doexec = TRUE;
ret = TRUE;
}
/* keyboard accelerator shortcuts. (if it was a valid key) */
else if (unikey) {
else if (frame->entries &&
(unikey =
obt_keyboard_keypress_to_unichar(menu_frame_ic(frame),
ev)))
{
GList *start;
GList *it;
ObMenuEntryFrame *found = NULL;
@ -1885,27 +1894,15 @@ static gboolean event_handle_menu_input(XEvent *ev)
doesn't get sent to the focused application.
Allow ControlMask only, and don't bother if the menu is empty */
else if (ev->type == KeyRelease && (mods & ~ControlMask) == 0 &&
frame->entries && frame->got_press)
{
if (ob_keycode_match(ev->xkey.keycode, OB_KEY_RETURN)) {
/* Enter runs the active item or goes into the submenu.
Control-Enter runs it without closing the menu. */
else if (ev->type == KeyRelease && (mods & ~ControlMask) == 0) {
if (frame->press_keycode == ev->xkey.keycode &&
frame->got_press &&
frame->press_doexec)
{
if (frame->child)
menu_frame_select_next(frame->child);
else if (frame->selected)
menu_entry_frame_execute(frame->selected, ev->xkey.state);
ret = TRUE;
}
if (frame->press_keycode == ev->xkey.keycode &&
frame->press_doexec)
{
if (frame->selected->entry->type == OB_MENU_ENTRY_TYPE_NORMAL)
menu_entry_frame_execute(frame->selected, ev->xkey.state);
else
menu_frame_select_next(frame->child);
}
}
}

View file

@ -43,21 +43,6 @@ typedef enum
OB_NUM_CURSORS
} ObCursor;
typedef enum
{
OB_KEY_RETURN,
OB_KEY_ESCAPE,
OB_KEY_LEFT,
OB_KEY_RIGHT,
OB_KEY_UP,
OB_KEY_DOWN,
OB_KEY_TAB,
OB_KEY_SPACE,
OB_KEY_HOME,
OB_KEY_END,
OB_NUM_KEYS
} ObKey;
typedef enum
{
OB_STATE_STARTING,

View file

@ -594,24 +594,25 @@ static void cancel_edge_warp(void)
obt_main_loop_timeout_remove(ob_main_loop, edge_warp_delay_func);
}
static void move_with_keys(gint keycode, gint state)
static void move_with_keys(KeySym sym, guint state)
{
gint dx = 0, dy = 0, ox = cur_x, oy = cur_y;
gint opx, px, opy, py;
gint dist = 0;
/* shift means jump to edge */
if (state & obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_SHIFT)) {
if (state & obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_SHIFT))
{
gint x, y;
ObDirection dir;
if (ob_keycode_match(keycode, OB_KEY_RIGHT))
if (sym == XK_Right)
dir = OB_DIRECTION_EAST;
else if (ob_keycode_match(keycode, OB_KEY_LEFT))
else if (sym == XK_Left)
dir = OB_DIRECTION_WEST;
else if (ob_keycode_match(keycode, OB_KEY_DOWN))
else if (sym == XK_Down)
dir = OB_DIRECTION_SOUTH;
else /* if (ob_keycode_match(keycode, OB_KEY_UP)) */
else /* sym == XK_Up */
dir = OB_DIRECTION_NORTH;
client_find_move_directional(moveresize_client, dir, &x, &y);
@ -627,13 +628,13 @@ static void move_with_keys(gint keycode, gint state)
else
dist = KEY_DIST;
if (ob_keycode_match(keycode, OB_KEY_RIGHT))
if (sym == XK_Right)
dx = dist;
else if (ob_keycode_match(keycode, OB_KEY_LEFT))
else if (sym == XK_Left)
dx = -dist;
else if (ob_keycode_match(keycode, OB_KEY_DOWN))
else if (sym == XK_Down)
dy = dist;
else /* if (ob_keycode_match(keycode, OB_KEY_UP)) */
else /* if (sym == XK_Up) */
dy = -dist;
}
@ -659,14 +660,14 @@ static void move_with_keys(gint keycode, gint state)
start_y += (py - opy) - (cur_y - oy);
}
static void resize_with_keys(gint keycode, gint state)
static void resize_with_keys(KeySym sym, guint state)
{
gint dw = 0, dh = 0, pdx = 0, pdy = 0, opx, opy, px, py;
gint resist = 0;
ObDirection dir;
/* pick the edge if it needs to move */
if (ob_keycode_match(keycode, OB_KEY_RIGHT)) {
if (sym == XK_Right) {
dir = OB_DIRECTION_EAST;
if (key_resize_edge != OB_DIRECTION_WEST &&
key_resize_edge != OB_DIRECTION_EAST)
@ -674,7 +675,7 @@ static void resize_with_keys(gint keycode, gint state)
key_resize_edge = OB_DIRECTION_EAST;
return;
}
} else if (ob_keycode_match(keycode, OB_KEY_LEFT)) {
} else if (sym == XK_Left) {
dir = OB_DIRECTION_WEST;
if (key_resize_edge != OB_DIRECTION_WEST &&
key_resize_edge != OB_DIRECTION_EAST)
@ -682,7 +683,7 @@ static void resize_with_keys(gint keycode, gint state)
key_resize_edge = OB_DIRECTION_WEST;
return;
}
} else if (ob_keycode_match(keycode, OB_KEY_UP)) {
} else if (sym == XK_Up) {
dir = OB_DIRECTION_NORTH;
if (key_resize_edge != OB_DIRECTION_NORTH &&
key_resize_edge != OB_DIRECTION_SOUTH)
@ -690,7 +691,7 @@ static void resize_with_keys(gint keycode, gint state)
key_resize_edge = OB_DIRECTION_NORTH;
return;
}
} else /* if (ob_keycode_match(keycode, OB_KEY_DOWN)) */ {
} else /* if (sym == XK_Down) */ {
dir = OB_DIRECTION_SOUTH;
if (key_resize_edge != OB_DIRECTION_NORTH &&
key_resize_edge != OB_DIRECTION_SOUTH)
@ -701,16 +702,17 @@ static void resize_with_keys(gint keycode, gint state)
}
/* shift means jump to edge */
if (state & obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_SHIFT)) {
if (state & obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_SHIFT))
{
gint x, y, w, h;
if (ob_keycode_match(keycode, OB_KEY_RIGHT))
if (sym == XK_Right)
dir = OB_DIRECTION_EAST;
else if (ob_keycode_match(keycode, OB_KEY_LEFT))
else if (sym == XK_Left)
dir = OB_DIRECTION_WEST;
else if (ob_keycode_match(keycode, OB_KEY_DOWN))
else if (sym == XK_Down)
dir = OB_DIRECTION_SOUTH;
else /* if (ob_keycode_match(keycode, OB_KEY_UP)) */
else /* if (sym == XK_Up)) */
dir = OB_DIRECTION_NORTH;
client_find_resize_directional(moveresize_client, key_resize_edge,
@ -912,24 +914,24 @@ gboolean moveresize_event(XEvent *e)
}
used = TRUE;
} else if (e->type == KeyPress) {
if (ob_keycode_match(e->xkey.keycode, OB_KEY_ESCAPE)) {
KeySym sym = obt_keyboard_keypress_to_keysym(e);
if (sym == XK_Escape) {
moveresize_end(TRUE);
used = TRUE;
} else if (ob_keycode_match(e->xkey.keycode, OB_KEY_RETURN)) {
} else if (sym == XK_Return) {
moveresize_end(FALSE);
used = TRUE;
} else if (ob_keycode_match(e->xkey.keycode, OB_KEY_RIGHT) ||
ob_keycode_match(e->xkey.keycode, OB_KEY_LEFT) ||
ob_keycode_match(e->xkey.keycode, OB_KEY_DOWN) ||
ob_keycode_match(e->xkey.keycode, OB_KEY_UP))
} else if (sym == XK_Right || sym == XK_Left ||
sym == XK_Up || sym == XK_Down)
{
if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD)) {
resize_with_keys(e->xkey.keycode, e->xkey.state);
resize_with_keys(sym, e->xkey.state);
used = TRUE;
} else if (corner ==
OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE_KEYBOARD))
{
move_with_keys(e->xkey.keycode, e->xkey.state);
move_with_keys(sym, e->xkey.state);
used = TRUE;
}
}

View file

@ -80,9 +80,6 @@
#include <X11/Xcursor/Xcursor.h>
#endif
#include <X11/Xlib.h>
#include <X11/keysym.h>
RrInstance *ob_rr_inst;
RrImageCache *ob_rr_icons;
RrTheme *ob_rr_theme;
@ -101,7 +98,6 @@ static gboolean reconfigure = FALSE;
static gboolean restart = FALSE;
static gchar *restart_path = NULL;
static Cursor cursors[OB_NUM_CURSORS];
static KeyCode *keys[OB_NUM_KEYS];
static gint exitcode = 0;
static guint remote_control = 0;
static gboolean being_replaced = FALSE;
@ -217,18 +213,6 @@ gint main(gint argc, gchar **argv)
if (reconfigure) obt_keyboard_reload();
/* get the keycodes for keys we use */
keys[OB_KEY_RETURN] = obt_keyboard_keysym_to_keycode(XK_Return);
keys[OB_KEY_ESCAPE] = obt_keyboard_keysym_to_keycode(XK_Escape);
keys[OB_KEY_LEFT] = obt_keyboard_keysym_to_keycode(XK_Left);
keys[OB_KEY_RIGHT] = obt_keyboard_keysym_to_keycode(XK_Right);
keys[OB_KEY_UP] = obt_keyboard_keysym_to_keycode(XK_Up);
keys[OB_KEY_DOWN] = obt_keyboard_keysym_to_keycode(XK_Down);
keys[OB_KEY_TAB] = obt_keyboard_keysym_to_keycode(XK_Tab);
keys[OB_KEY_SPACE] = obt_keyboard_keysym_to_keycode(XK_space);
keys[OB_KEY_HOME] = obt_keyboard_keysym_to_keycode(XK_Home);
keys[OB_KEY_END] = obt_keyboard_keysym_to_keycode(XK_End);
{
ObtXmlInst *i;
@ -405,18 +389,6 @@ gint main(gint argc, gchar **argv)
event_shutdown(reconfigure);
config_shutdown();
actions_shutdown(reconfigure);
/* Free the key codes for built in keys */
g_free(keys[OB_KEY_RETURN]);
g_free(keys[OB_KEY_ESCAPE]);
g_free(keys[OB_KEY_LEFT]);
g_free(keys[OB_KEY_RIGHT]);
g_free(keys[OB_KEY_UP]);
g_free(keys[OB_KEY_DOWN]);
g_free(keys[OB_KEY_TAB]);
g_free(keys[OB_KEY_SPACE]);
g_free(keys[OB_KEY_HOME]);
g_free(keys[OB_KEY_END]);
} while (reconfigure);
}
@ -737,16 +709,6 @@ Cursor ob_cursor(ObCursor cursor)
return cursors[cursor];
}
gboolean ob_keycode_match(KeyCode code, ObKey key)
{
KeyCode *k;
g_assert(key < OB_NUM_KEYS);
for (k = keys[key]; *k; ++k)
if (*k == code) return TRUE;
return FALSE;
}
ObState ob_state(void)
{
return state;

View file

@ -27,7 +27,6 @@
#include "obt/display.h"
#include <glib.h>
#include <X11/Xlib.h>
extern RrInstance *ob_rr_inst;
extern RrImageCache *ob_rr_icons;
@ -62,6 +61,4 @@ void ob_exit_with_error(const gchar *msg) G_GNUC_NORETURN;
Cursor ob_cursor(ObCursor cursor);
gboolean ob_keycode_match(KeyCode code, ObKey key);
#endif

View file

@ -525,6 +525,7 @@ gboolean prompt_key_event(ObPrompt *self, XEvent *e)
{
gboolean shift;
guint shift_mask, mods;
KeySym sym;
if (e->type != KeyPress) return FALSE;
@ -536,23 +537,18 @@ gboolean prompt_key_event(ObPrompt *self, XEvent *e)
if (mods != 0 && mods != shift_mask)
return FALSE;
if (ob_keycode_match(e->xkey.keycode, OB_KEY_ESCAPE))
sym = obt_keyboard_keypress_to_keysym(e);
if (sym == XK_Escape)
prompt_cancel(self);
else if (ob_keycode_match(e->xkey.keycode, OB_KEY_RETURN) ||
ob_keycode_match(e->xkey.keycode, OB_KEY_SPACE))
{
else if (sym == XK_Return || sym == XK_space)
prompt_run_callback(self, self->focus->result);
}
else if (ob_keycode_match(e->xkey.keycode, OB_KEY_TAB) ||
ob_keycode_match(e->xkey.keycode, OB_KEY_LEFT) ||
ob_keycode_match(e->xkey.keycode, OB_KEY_RIGHT))
{
else if (sym == XK_Tab || sym == XK_Left || sym == XK_Right) {
gint i;
gboolean left;
ObPromptElement *oldfocus;
left = ob_keycode_match(e->xkey.keycode, OB_KEY_LEFT) ||
(ob_keycode_match(e->xkey.keycode, OB_KEY_TAB) && shift);
left = (sym == XK_Left) || ((sym == XK_Tab) && shift);
oldfocus = self->focus;
for (i = 0; i < self->n_buttons; ++i)