[Anthy-dev 1724] Re: uim-pref上でのキー表現

Back to archive index

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);
}



Anthy-dev メーリングリストの案内
Back to archive index