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.
This commit is contained in:
wm4 2012-01-14 14:09:44 +01:00
parent a63e880400
commit ad455c43f5
2 changed files with 48 additions and 29 deletions

View File

@ -23,6 +23,7 @@
#include <limits.h>
#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 |

View File

@ -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 {