From ad455c43f54f1ec259d9aea48cc16e7c4485b584 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 14 Jan 2012 14:09:44 +0100 Subject: x11: allow unicode input This change allows using non-ASCII keys with X11. These keys were ingored before. Technically, this creates an invisible, non-interactive input method context. If creation fails, the code falls back to the old method, which allows a subset of ASCII only. --- libvo/x11_common.c | 74 +++++++++++++++++++++++++++++++++--------------------- libvo/x11_common.h | 3 +++ 2 files changed, 48 insertions(+), 29 deletions(-) diff --git a/libvo/x11_common.c b/libvo/x11_common.c index cdbbc213b5..3f55fa2f93 100644 --- a/libvo/x11_common.c +++ b/libvo/x11_common.c @@ -23,6 +23,7 @@ #include #include "config.h" +#include "bstr.h" #include "options.h" #include "mp_msg.h" #include "mp_fifo.h" @@ -422,6 +423,8 @@ int vo_init(struct vo *vo) x11->screen = DefaultScreen(x11->display); // screen ID x11->rootwin = RootWindow(x11->display, x11->screen); // root window ID + x11->xim = XOpenIM(x11->display, NULL, NULL, NULL); + init_atoms(vo->x11); #ifdef CONFIG_XF86VM @@ -523,6 +526,8 @@ void vo_uninit(struct vo_x11_state *x11) "vo: x11 uninit called but X11 not initialized..\n"); } else { mp_msg(MSGT_VO, MSGL_V, "vo: uninit ...\n"); + if (x11->xim) + XCloseIM(x11->xim); XSetErrorHandler(NULL); XCloseDisplay(x11->display); x11->depthonscreen = 0; @@ -533,24 +538,6 @@ void vo_uninit(struct vo_x11_state *x11) #include "wskeys.h" -#ifdef XF86XK_AudioPause -static const struct mp_keymap keysym_map[] = { - {XF86XK_MenuKB, KEY_MENU}, - {XF86XK_AudioPlay, KEY_PLAY}, {XF86XK_AudioPause, KEY_PAUSE}, {XF86XK_AudioStop, KEY_STOP}, - {XF86XK_AudioPrev, KEY_PREV}, {XF86XK_AudioNext, KEY_NEXT}, - {XF86XK_AudioMute, KEY_MUTE}, {XF86XK_AudioLowerVolume, KEY_VOLUME_DOWN}, {XF86XK_AudioRaiseVolume, KEY_VOLUME_UP}, - {0, 0} -}; - -static void vo_x11_putkey_ext(struct vo *vo, int keysym, int modifiers) -{ - struct mp_fifo *f = vo->key_fifo; - int mpkey = lookup_keymap_table(keysym_map, keysym); - if (mpkey) - mplayer_put_key(f, mpkey + modifiers); -} -#endif - static const struct mp_keymap keymap[] = { // special keys {wsPause, KEY_PAUSE}, {wsEscape, KEY_ESC}, {wsBackSpace, KEY_BS}, @@ -584,10 +571,17 @@ static const struct mp_keymap keymap[] = { {wsGrayRight, KEY_KP6}, {wsGrayHome, KEY_KP7}, {wsGrayUp, KEY_KP8}, {wsGrayPgUp, KEY_KP9}, {wsGrayDelete, KEY_KPDEL}, +#ifdef XF86XK_AudioPause + {XF86XK_MenuKB, KEY_MENU}, + {XF86XK_AudioPlay, KEY_PLAY}, {XF86XK_AudioPause, KEY_PAUSE}, {XF86XK_AudioStop, KEY_STOP}, + {XF86XK_AudioPrev, KEY_PREV}, {XF86XK_AudioNext, KEY_NEXT}, + {XF86XK_AudioMute, KEY_MUTE}, {XF86XK_AudioLowerVolume, KEY_VOLUME_DOWN}, {XF86XK_AudioRaiseVolume, KEY_VOLUME_UP}, +#endif + {0, 0} }; -static void vo_x11_putkey(struct vo *vo, int key, int modifiers) +static int vo_x11_lookupkey(int key) { static const char *passthrough_keys = " -+*/<>`~!@#$%^&()_{}:;\"\',.?\\|=[]"; int mpkey = 0; @@ -600,8 +594,7 @@ static void vo_x11_putkey(struct vo *vo, int key, int modifiers) if (!mpkey) mpkey = lookup_keymap_table(keymap, key); - if (mpkey) - mplayer_put_key(vo->key_fifo, mpkey + modifiers); + return mpkey; } @@ -746,6 +739,9 @@ void vo_x11_uninit(struct vo *vo) { XEvent xev; + if (x11->xic) + XDestroyIC(x11->xic); + XUnmapWindow(x11->display, x11->window); XSelectInput(x11->display, x11->window, StructureNotifyMask); XDestroyWindow(x11->display, x11->window); @@ -785,8 +781,6 @@ int vo_x11_check_events(struct vo *vo) Display *display = vo->x11->display; int ret = 0; XEvent Event; - char buf[100]; - KeySym keySym; if (x11->vo_mouse_autohide && x11->mouse_waiting_hide && (GetTimerMS() - x11->mouse_timer >= 1000)) { @@ -812,8 +806,8 @@ int vo_x11_check_events(struct vo *vo) break; case KeyPress: { - XLookupString(&Event.xkey, buf, sizeof(buf), &keySym, - &x11->compose_status); + char buf[100]; + KeySym keySym = 0; int modifiers = 0; if (Event.xkey.state & ShiftMask) modifiers |= KEY_MODIFIER_SHIFT; @@ -823,10 +817,27 @@ int vo_x11_check_events(struct vo *vo) modifiers |= KEY_MODIFIER_ALT; if (Event.xkey.state & Mod4Mask) modifiers |= KEY_MODIFIER_META; -#ifdef XF86XK_AudioPause - vo_x11_putkey_ext(vo, keySym, modifiers); -#endif - vo_x11_putkey(vo, keySym, modifiers); + if (x11->xic) { + Status status; + int len = Xutf8LookupString(x11->xic, &Event.xkey, buf, + sizeof(buf), &keySym, + &status); + int mpkey = vo_x11_lookupkey(keySym); + if (mpkey) { + mplayer_put_key(vo->key_fifo, mpkey | modifiers); + } else if (status == XLookupChars + || status == XLookupBoth) + { + struct bstr t = { buf, len }; + mplayer_put_key_utf8(vo->key_fifo, modifiers, t); + } + } else { + XLookupString(&Event.xkey, buf, sizeof(buf), &keySym, + &x11->compose_status); + int mpkey = vo_x11_lookupkey(keySym); + if (mpkey) + mplayer_put_key(vo->key_fifo, mpkey | modifiers); + } ret |= VO_EVENT_KEYPRESS; } break; @@ -1144,6 +1155,11 @@ void vo_x11_create_vo_window(struct vo *vo, XVisualInfo *vis, int x, int y, XSetWMNormalHints(mDisplay, x11->window, &hint); if (!vo_border) vo_x11_decoration(vo, 0); // map window + x11->xic = XCreateIC(x11->xim, + XNInputStyle, XIMPreeditNone | XIMStatusNone, + XNClientWindow, x11->window, + XNFocusWindow, x11->window, + NULL); XSelectInput(mDisplay, x11->window, NoEventMask); vo_x11_selectinput_witherr(mDisplay, x11->window, StructureNotifyMask | KeyPressMask | PointerMotionMask | diff --git a/libvo/x11_common.h b/libvo/x11_common.h index a8b13cc690..6ba2780747 100644 --- a/libvo/x11_common.h +++ b/libvo/x11_common.h @@ -36,6 +36,9 @@ struct vo_x11_state { int display_is_local; int depthonscreen; + XIM xim; + XIC xic; + GC vo_gc; struct xv_ck_info_s { -- cgit v1.2.3