Handle Shift+Tab (ISO_Left_Tab) in x0vncserver
diff --git a/unix/x0vncserver/XDesktop.cxx b/unix/x0vncserver/XDesktop.cxx
index 59e2532..0273a6d 100644
--- a/unix/x0vncserver/XDesktop.cxx
+++ b/unix/x0vncserver/XDesktop.cxx
@@ -289,6 +289,7 @@
 KeyCode XDesktop::XkbKeysymToKeycode(Display* dpy, KeySym keysym) {
   XkbDescPtr xkb;
   XkbStateRec state;
+  unsigned int mods;
   unsigned keycode;
 
   xkb = XkbGetMap(dpy, XkbAllComponentsMask, XkbUseCoreKbd);
@@ -296,15 +297,15 @@
     return 0;
 
   XkbGetState(dpy, XkbUseCoreKbd, &state);
+  // XkbStateFieldFromRec() doesn't work properly because
+  // state.lookup_mods isn't properly updated, so we do this manually
+  mods = XkbBuildCoreState(XkbStateMods(&state), state.group);
 
   for (keycode = xkb->min_key_code;
        keycode <= xkb->max_key_code;
        keycode++) {
     KeySym cursym;
-    unsigned int mods, out_mods;
-    // XkbStateFieldFromRec() doesn't work properly because
-    // state.lookup_mods isn't properly updated, so we do this manually
-    mods = XkbBuildCoreState(XkbStateMods(&state), state.group);
+    unsigned int out_mods;
     XkbTranslateKeyCode(xkb, keycode, mods, &out_mods, &cursym);
     if (cursym == keysym)
       break;
@@ -315,6 +316,11 @@
 
   XkbFreeKeyboard(xkb, XkbAllComponentsMask, True);
 
+  // Shift+Tab is usually ISO_Left_Tab, but RFB hides this fact. Do
+  // another attempt if we failed the initial lookup
+  if ((keycode == 0) && (keysym == XK_Tab) && (mods & ShiftMask))
+    return XkbKeysymToKeycode(dpy, XK_ISO_Left_Tab);
+
   return keycode;
 }
 #endif