From: Ian Jackson Date: Wed, 18 Nov 2009 21:10:07 +0000 (+0000) Subject: make shifted keys work - untested, but compiles X-Git-Tag: 5.7~3 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~yarrgweb/git?p=ypp-sc-tools.web-live.git;a=commitdiff_plain;h=ff0e8636a801c474095205c7a00111166e542ca0 make shifted keys work - untested, but compiles --- diff --git a/yarrg/pages.c b/yarrg/pages.c index 28364a0..955add9 100644 --- a/yarrg/pages.c +++ b/yarrg/pages.c @@ -61,17 +61,132 @@ DEBUG_DEFINE_DEBUGF(pages) fatal("X11 operation unexpectedly failed." \ " %s:%d: %s\n", __FILE__,__LINE__,#what)) -static KeyCode keycode(KeySym sym) { - return XKeysymToKeycode(disp,sym); + +/*---------- keyboard map ----------*/ + +#define KEYS(EACH_KEY) \ + EACH_KEY(XK_slash) \ + EACH_KEY(XK_w) \ + EACH_KEY(XK_Return) \ + EACH_KEY(XK_Prior) \ + EACH_KEY(XK_Next) + +#define MAXMAPCOL 6 +typedef struct { + int len; + int kc[3]; +} MappedKey; + +#define KEY_MAP_DEF(xk) \ +static MappedKey mk_##xk; +KEYS(KEY_MAP_DEF) + +typedef struct { + int isdef; /* 'y' if defined; otherwise char indicating why not */ + int kc; +} MappedModifier; + +static int kc_min, kc_max; +static MappedModifier mm_shift, mm_modeswitch, mm_isol3shift; +static KeySym *mapping; +static int mapwidth; + +static void keymap_lookup_modifier(MappedModifier *mm, KeySym sym, + char ifnot) { + int kc; + + mm->isdef= ifnot; + for (kc=kc_min; kc <= kc_max; kc++) { + if (mapping[(kc-kc_min)*mapwidth] == sym) { + mm->isdef= 'y'; + mm->kc= kc; + return; + } + } } -void screenshot_startup(void) { - progress("starting..."); - disp= XOpenDisplay(0); - if (!disp) fatal("Unable to open X11 display."); - sysassert(! gettimeofday(&tv_startup,0) ); +static void keymap_lookup_key(MappedKey *mk, KeySym sym, const char *what) { + const MappedModifier *shift, *xshift; + int col, kc; + char cols[MAXMAPCOL+1]; + + memset(cols,'.',MAXMAPCOL); + cols[MAXMAPCOL]= 0; + + for (col=0; colisdef!='y') { \ + cols[col]= (sh)->isdef; \ + continue; \ + } \ + }while(0) + + shift= col & 1 ? &mm_shift : 0; + CHECK_SHIFT(shift); + + xshift= col >= 4 ? &mm_isol3shift : + col >= 2 ? &mm_modeswitch : + 0; + CHECK_SHIFT(xshift); + + for (kc=kc_min; kc <= kc_max; kc++) { + if (mapping[(kc-kc_min)*mapwidth + col] == sym) + goto found; + } + cols[col]= '_'; + } + fprintf(stderr,"\n" + "Unable to find a key to press to generate %s.\n" + "(Technical details: cols:%s sh:%c:%d modesw:%c:%d isol3:%c:%d)\n", + what, cols, +#define SH_DETAILS(sh) mm_##sh.isdef, mm_##sh.kc + SH_DETAILS(shift), SH_DETAILS(modeswitch), SH_DETAILS(isol3shift)); + fatal("Keymap is unsuitable!"); + + found:; + int *fill= mk->kc; + + if (xshift) *fill++ = xshift->kc; + if (shift) *fill++ = shift->kc; + *fill += kc; + mk->len= fill - mk->kc; +} + +static void keymap_startup(void) { + xassert( XDisplayKeycodes(disp,&kc_min,&kc_max) ); + xassert( mapping= XGetKeyboardMapping(disp, kc_min, kc_max-kc_min+1, + &mapwidth) ); + + XModifierKeymap *modmap; + xassert( modmap= XGetModifierMapping(disp) ); + + /* find a shift keycode */ + mm_shift.isdef= 'x'; + int modent; + for (modent=0; modentmax_keypermod; modent++) { + KeySym shiftsym= modmap->modifiermap[modent]; + if (shiftsym==NoSymbol) continue; + keymap_lookup_modifier(&mm_shift, shiftsym, 's'); + if (mm_shift.isdef!='y') break; + } + + /* find keycodes for mode_switch (column+=2) and ISO L3 shift (column+=4) */ + keymap_lookup_modifier(&mm_modeswitch, XK_Mode_switch, 0); + keymap_lookup_modifier(&mm_isol3shift, XK_ISO_Level3_Shift, 0); + + XFreeModifiermap(modmap); + +#define KEY_MAP_LOOKUP(xk) \ + keymap_lookup_key(&mk_##xk, xk, #xk); + KEYS(KEY_MAP_LOOKUP) + + XFree(mapping); + mapping= 0; } +#define SEND_KEY(xk) (send_key(&mk_##xk)) + /*---------- pager ----------*/ typedef RgbImage Snapshot; @@ -176,10 +291,11 @@ static void check_pointer_not_disturbed(void) { } } -static void send_key(KeySym sym) { +static void send_key(MappedKey *mk) { + int i; check_not_disturbed(); - XTestFakeKeyEvent(disp, keycode(sym),1, 0); - XTestFakeKeyEvent(disp, keycode(sym),0, 0); + for (i=0; ilen; i++) XTestFakeKeyEvent(disp, mk->kc[i], 1, 0); + for (i=mk->len; --i>=0; ) XTestFakeKeyEvent(disp, mk->kc[i], 0, 0); } static void send_mouse_1_updown_here(void) { check_not_disturbed(); @@ -207,7 +323,7 @@ static int pgupdown; static void send_pgup_many(void) { int i; for (i=0; i<25; i++) { - send_key(XK_Prior); + SEND_KEY(XK_Prior); pgupdown--; } debugf("PAGING PageUp x %d\n",i); @@ -216,7 +332,7 @@ static void send_pgup_many(void) { static void send_pgdown_torestore(void) { debugf("PAGING PageDown x %d\n", -pgupdown); while (pgupdown < 0) { - send_key(XK_Next); + SEND_KEY(XK_Next); pgupdown++; } sync_after_input(); @@ -589,9 +705,9 @@ static void prepare_ypp_client(void) { send_mouse_1_updown_here(); sync_after_input(); check_not_disturbed(); - send_key(XK_slash); - send_key(XK_w); - send_key(XK_Return); + SEND_KEY(XK_slash); + SEND_KEY(XK_w); + SEND_KEY(XK_Return); sync_after_input(); Snapshot *status=0; @@ -793,3 +909,12 @@ void find_yppclient_window(void) { " Use --window-id and/or report this as a fault.\n", o_ocean || o_pirate ? "matching ": ""); } + +void screenshot_startup(void) { + progress("starting..."); + disp= XOpenDisplay(0); + if (!disp) fatal("Unable to open X11 display."); + sysassert(! gettimeofday(&tv_startup,0) ); + + keymap_startup(); +}