Kenichi Handa
handa****@m17n*****
2005年 2月 3日 (木) 11:49:13 JST
In article <20050****@mbox0*****>, YamaKen <yamak****@bp*****> writes: > ヤマケンです。ちょっと考えてみました。 > At Wed, 2 Feb 2005 14:04:10 +0900, > ekato****@ees***** wrote: >> On 2005/01/30, at 5:41, YamaKen wrote: >> >> > Caps Lockなしの場合で言うと、加藤さん案では<Shift>jというユーザ >> > 入力が"J"、<Control><Shift>jが"<Control><Shift>j"としてユーザに >> > 見える事になり、<Shift>jの表現が<Control>のあるなしで変化する事 >> > になります。これを指して一貫性が無いと表現しました。 >> >> そうですね。一貫性はありません。 >> ただし、たぶん、これはぼくの独特の感じ方だと思いますが、modifier として >> Shift key だけを押す場合は、そのままでは出せない ascii char >> (大文字や、! とか #とか) を出すための手段だと思っているので、 >> 他の modifier とは違うように認識していて違和感は無いです。このため >> 逆に大文字のキーなのに、表記に <Shift> が付いていると違和感を感じて >> しまいます。 > 私も個人的には"<Shift>j"よりは"J"の方がわかりやすいです。あくま > でもCaps Lock on/offに関係なく1つの表現にマッチさせるための妥協 > 案なので、別の解決策さえあればこれにはこだわりません。 僕もここんところ m17n-lib の次のバージョンでの input key の表 現について考えていたんですが、基本的には上記に賛成です。 ただ modifier を key の表現に付加するかどうかについては、もっ とシステマティックに、「その modifier の有無が KeySym に影響 を与える場合は modifier を付加しない」という方法を使おうと思っ ています(X Window ベースの話ですが)。 つまり 'a' '[' などはshift-modifier の有無で KeySym が変わる ので shift-modifier なしで表現、 Delete とか Return は shift-modifier が有ろうが無かろうが KeySym は変わらないので shift-modifier が有る時には S-Delete, S-Return になる。他の modifier についても同様。 具体的には最後に付けたプログラムが生成するようなキー表現を使 おうと思っています。100x100 のウィンドウ内でキー入力すると、 それがどういう表現で認識されるかが stdout に出力されます。 例えばあるユーザが a も <Shift>a も KeySym a にマップしている 場合は <Shift>a は S-a が入力されたと認識され、大抵の入力メソッ ドはそんなキーは知らないので application に戻されることになり ます。 −− 半田@AIST handa****@m17n***** #include <stdio.h> #include <X11/Xlib.h> #include <X11/keysym.h> int meta_mask; int alt_mask; int super_mask; int hyper_mask; static void find_modifier_bits (Display *display) { KeyCode meta_l = XKeysymToKeycode (display, XK_Meta_L); KeyCode meta_r = XKeysymToKeycode (display, XK_Meta_R); KeyCode alt_l = XKeysymToKeycode (display, XK_Alt_L); KeyCode alt_r = XKeysymToKeycode (display, XK_Alt_R); KeyCode super_l = XKeysymToKeycode (display, XK_Super_L); KeyCode super_r = XKeysymToKeycode (display, XK_Super_R); KeyCode hyper_l = XKeysymToKeycode (display, XK_Hyper_L); KeyCode hyper_r = XKeysymToKeycode (display, XK_Hyper_R); XModifierKeymap *mods = XGetModifierMapping (display); int i, j; /* We skip the first three sets for Shift, Lock, and Control. The remaining sets are for Mod1, Mod2, Mod3, Mod4, and Mod5. */ for (i = 3; i < 8; i++) for (j = 0; j < mods->max_keypermod; j++) { KeyCode code = mods->modifiermap[i * mods->max_keypermod + j]; if (! code) continue; if (code == meta_l || code == meta_r) meta_mask |= (1 << i); else if (code == alt_l || code == alt_r) alt_mask |= (1 << i); else if (code == super_l || code == super_r) super_mask |= (1 << i); else if (code == hyper_l || code == hyper_r) hyper_mask |= (1 << i); } /* If meta keys are not in any modifier, use alt keys as meta keys. */ if (! meta_mask) { meta_mask = alt_mask; alt_mask = 0; } /* If both meta and alt are assigned to the same modifier, give meta keys priority. */ if (meta_mask & alt_mask) alt_mask &= ~meta_mask; XFreeModifiermap (mods); } static int parse_event (Display *display, XKeyEvent *event, char *buf1) { KeySym keysym, k; unsigned int state = event->state, save = state; char buf2[256]; int len; len = XLookupString (event, buf2, 256, &keysym, NULL); if (len > 1 || (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)) return -1; /* Reset each modifier mask if the resetting produces different keysym. */ if (state & ShiftMask) { event->state = save & ~ShiftMask; if (XLookupString (event, buf1, 256, &k, NULL) != len || k != keysym) state = event->state; } if (state & ControlMask) { event->state = save & ~ControlMask; if (XLookupString (event, buf1, 256, &k, NULL) != len || k != keysym) state = event->state; } if (state & meta_mask) { event->state = save & ~meta_mask; if (XLookupString (event, buf1, 256, &k, NULL) != len || k != keysym) state = event->state; } if (state & alt_mask) { event->state = save & ~alt_mask; if (XLookupString (event, buf1, 256, &k, NULL) != len || k != keysym) state = event->state; } if (state & super_mask) { event->state = save & ~super_mask; if (XLookupString (event, buf1, 256, &k, NULL) != len || k != keysym) state = event->state; } if (state & hyper_mask) { event->state = save & ~hyper_mask; if (XLookupString (event, buf1, 256, &k, NULL) != len || k != keysym) state = event->state; } if (keysym >= XK_space && keysym <= XK_asciitilde) { /* Short key name for ASCII. */ buf2[0] = keysym; buf2[1] = '\0'; } else { char *str = XKeysymToString (keysym); if (! str) return -1; strcpy (buf2, str); } /* Accumulate mnemonics for modifiers in buf1. */ buf1[0] = '\0'; if (state & hyper_mask) strcat (buf1, "H-"); if (state & super_mask) strcat (buf1, "s-"); if (state & alt_mask) strcat (buf1, "A-"); if (state & ControlMask) strcat (buf1, "C-"); if (state & meta_mask) strcat (buf1, "M-"); if (state & ShiftMask) strcat (buf1, "S-"); /* At last, append a key name. */ strcat (buf1, buf2); return 0; } int main () { Display *display = XOpenDisplay (NULL); int screen = DefaultScreen (display); Window window; XEvent event; char buf[256]; find_modifier_bits (display); window = XCreateSimpleWindow (display, DefaultRootWindow (display), 0, 0, 100, 100, 1, BlackPixel (display, screen), WhitePixel (display, screen)); XSelectInput (display, window, ExposureMask | KeyPressMask); XMapWindow (display, window); while (1) { XNextEvent (display, &event); if (event.xany.type == Expose) XClearWindow (display, window); else if (event.xany.type == KeyPress && parse_event (display, (XKeyEvent *) &event, buf) >= 0) printf ("%s\n", buf); } exit (0); }