# Patch to Xvnc 3.3.3r1 by Vlad Harchev # # Патч к vncserver'у для Х, улучшающий ввод не-latin1 (т.е. русских в # частности). Этот патч не обязателен. Без него нажатие русских букв при # нажатой capslock будет выдавать буквы нижнего регистра (а должны по-идее # выдаваться буквы верхнего регистра), при наложенном патче эта проблема # устаряется. # # # This patch in theory can be applied to any version of Xvnc since file it # modifies wasn't changed for a long time. # # This patch makes Xvnc to correctly position new keysyms (that are not yet # registered) according to their case in kbdptr.c:KeySyms, thus allowing # properly emit keyboard events when Capslock is active and keys corresponding # to those new keysyms are pressed. Example: before this patch, activating # capslock and pressing key that emits XK_Cyrillic_a, resulted in emission # of XKeyEvent without surrounding XKeyEvent for pressing and releasing # shift key, thus client's XLookupString returned string corresponding to # XK_Cyrillic_a (though correct value should be string corresponding to # XK_Cyrillic_A since CapsLock was active). # So, this patch only improves input of non-latin letters when capslock is # active. IMO it's more ideologically correct than the approach used before. # This patch was sent to VNC team. # diff -ru vnc_unixsrc-was/Xvnc/programs/Xserver/hw/vnc/kbdptr.c vnc_unixsrc/Xvnc/programs/Xserver/hw/vnc/kbdptr.c --- vnc_unixsrc-was/Xvnc/programs/Xserver/hw/vnc/kbdptr.c Thu Apr 29 16:10:54 1999 +++ vnc_unixsrc/Xvnc/programs/Xserver/hw/vnc/kbdptr.c Tue Sep 12 13:48:43 2000 @@ -29,6 +29,8 @@ #define NEED_EVENTS #include "X11/Xproto.h" #include "inputstr.h" + +#define XK_CYRILLIC #include #include #include "rfb.h" @@ -258,6 +260,111 @@ } } +/* this is an exact copy of XLib's XConvertCase. */ +static void +XConvertCase(sym, lower, upper) + register KeySym sym; + KeySym *lower; + KeySym *upper; +{ + *lower = sym; + *upper = sym; + switch(sym >> 8) { + case 0: /* Latin 1 */ + if ((sym >= XK_A) && (sym <= XK_Z)) + *lower += (XK_a - XK_A); + else if ((sym >= XK_a) && (sym <= XK_z)) + *upper -= (XK_a - XK_A); + else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis)) + *lower += (XK_agrave - XK_Agrave); + else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis)) + *upper -= (XK_agrave - XK_Agrave); + else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn)) + *lower += (XK_oslash - XK_Ooblique); + else if ((sym >= XK_oslash) && (sym <= XK_thorn)) + *upper -= (XK_oslash - XK_Ooblique); + break; + case 1: /* Latin 2 */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym == XK_Aogonek) + *lower = XK_aogonek; + else if (sym >= XK_Lstroke && sym <= XK_Sacute) + *lower += (XK_lstroke - XK_Lstroke); + else if (sym >= XK_Scaron && sym <= XK_Zacute) + *lower += (XK_scaron - XK_Scaron); + else if (sym >= XK_Zcaron && sym <= XK_Zabovedot) + *lower += (XK_zcaron - XK_Zcaron); + else if (sym == XK_aogonek) + *upper = XK_Aogonek; + else if (sym >= XK_lstroke && sym <= XK_sacute) + *upper -= (XK_lstroke - XK_Lstroke); + else if (sym >= XK_scaron && sym <= XK_zacute) + *upper -= (XK_scaron - XK_Scaron); + else if (sym >= XK_zcaron && sym <= XK_zabovedot) + *upper -= (XK_zcaron - XK_Zcaron); + else if (sym >= XK_Racute && sym <= XK_Tcedilla) + *lower += (XK_racute - XK_Racute); + else if (sym >= XK_racute && sym <= XK_tcedilla) + *upper -= (XK_racute - XK_Racute); + break; + case 2: /* Latin 3 */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym >= XK_Hstroke && sym <= XK_Hcircumflex) + *lower += (XK_hstroke - XK_Hstroke); + else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex) + *lower += (XK_gbreve - XK_Gbreve); + else if (sym >= XK_hstroke && sym <= XK_hcircumflex) + *upper -= (XK_hstroke - XK_Hstroke); + else if (sym >= XK_gbreve && sym <= XK_jcircumflex) + *upper -= (XK_gbreve - XK_Gbreve); + else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex) + *lower += (XK_cabovedot - XK_Cabovedot); + else if (sym >= XK_cabovedot && sym <= XK_scircumflex) + *upper -= (XK_cabovedot - XK_Cabovedot); + break; + case 3: /* Latin 4 */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym >= XK_Rcedilla && sym <= XK_Tslash) + *lower += (XK_rcedilla - XK_Rcedilla); + else if (sym >= XK_rcedilla && sym <= XK_tslash) + *upper -= (XK_rcedilla - XK_Rcedilla); + else if (sym == XK_ENG) + *lower = XK_eng; + else if (sym == XK_eng) + *upper = XK_ENG; + else if (sym >= XK_Amacron && sym <= XK_Umacron) + *lower += (XK_amacron - XK_Amacron); + else if (sym >= XK_amacron && sym <= XK_umacron) + *upper -= (XK_amacron - XK_Amacron); + break; + case 6: /* Cyrillic */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE) + *lower -= (XK_Serbian_DJE - XK_Serbian_dje); + else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze) + *upper += (XK_Serbian_DJE - XK_Serbian_dje); + else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN) + *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu); + else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign) + *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu); + break; + case 7: /* Greek */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent) + *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); + else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent && + sym != XK_Greek_iotaaccentdieresis && + sym != XK_Greek_upsilonaccentdieresis) + *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); + else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA) + *lower += (XK_Greek_alpha - XK_Greek_ALPHA); + else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega && + sym != XK_Greek_finalsmallsigma) + *upper -= (XK_Greek_alpha - XK_Greek_ALPHA); + break; + } +} + void KbdAddEvent(down, keySym, cl) @@ -275,7 +382,8 @@ Bool fakeShiftLRelease = FALSE; Bool fakeShiftRRelease = FALSE; Bool shiftedKey; - + KeySym low,hi; + #ifdef CORBA if (cl) { CARD32 clientId = cl->sock; @@ -284,6 +392,7 @@ } #endif + XConvertCase(keySym,&low,&hi); if (down) { ev.u.u.type = KeyPress; } else { @@ -319,20 +428,28 @@ } i = freeKey; - keySyms->map[i] = keySym; + if (low==hi) { + keySyms->map[i] = keySym; + } else { + keySyms->map[i] = low; + keySyms->map[i+1] = hi; + } SendMappingNotify(MappingKeyboard, MIN_KEY_CODE + (i / keySyms->mapWidth), 1, serverClient); rfbLog("KbdAddEvent: unknown KeySym 0x%x - allocating KeyCode %d\n", keySym, MIN_KEY_CODE + (i / keySyms->mapWidth)); + + if (hi!=low && keySym == hi) + ++i; } time = GetTimeInMillis(); shiftedKey = ((i % keySyms->mapWidth) == 1); - if (down && (keySym > 32) && (keySym < 127)) { + if (down && hi!=low) { if (shiftedKey && !(kbdDevice->key->state & ShiftMask)) { fakeShiftPress = TRUE; fake.u.u.type = KeyPress;