[patch at end]
[Sorry for replying so late, I have been in culinary heaven, i.e.
Japan. Since XEmacs 21.0 is not out of the door yet I believe it can
and should be fixed]
Martin Buchholz <martin(a)xemacs.org> writes 3 weeks ago:
> J>  2. XEmacs Considers a key a modifier if ANY of its Keysyms is a
> J>     modifier.
> 
> J> [this] is wrong (or at the very least
> J> inconsistent with the rest of the X world).
> I'm not convinced that XEmacs is acting incorrectly.
Personally is I do not really think it is relevant whether or not
XEmacs is incorrect. XEmacs is behaving differently from
xterm/XIM/other apps which is what matters. They all accept keysyms
even if another keysym on the generating key is a modifier.
>     113         0xff7e (Mode_switch)    0xff20 (Multi_key)
> 
> What is Shift-AltGr supposed to give with the above combination?
Dunno, isn't that something for X to worry about, not XEmacs?
Basically. I think we should do it something like this (I moved the
behavior to the x_to_emacs_keysym function since it doesn't require 
duplication of the XlookupString calls).
1998-07-16  Jan Vroonhof  <vroonhof(a)math.ethz.ch>
	* event-Xt.c (x_to_emacs_keysym): Return nil for modifier keysyms.
	(x_event_to_emacs_event): Let x_to_emacs_keysym check for modifier 
	keys thus no longer considering all keysyms on a key.
Index: event-Xt.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs-20/src/event-Xt.c,v
retrieving revision 1.41
diff -u -u -r1.41 event-Xt.c
--- event-Xt.c	1998/06/20 00:58:46	1.41
+++ event-Xt.c	1998/07/17 03:09:56
@@ -769,7 +769,7 @@
      /* simple_p means don't try too hard (ASCII only) */
 {
   KeySym keysym = 0;
-
+  
 #ifdef HAVE_XIM
   int len;
   char buffer[64];
@@ -794,7 +794,8 @@
          than passing in 0) to avoid crashes on German IRIX */
       char dummy[256];
       XLookupString (event, dummy, 200, &keysym, 0);
-      return x_keysym_to_emacs_keysym (keysym, simple_p);
+      return (IsModifierKey (keysym) || keysym == XK_Mode_switch )
+	? Qnil : x_keysym_to_emacs_keysym (keysym, simple_p);
     }
 #endif /* ! XIM_MOTIF */
 
@@ -843,7 +844,8 @@
     {
     case XLookupKeySym:
     case XLookupBoth:
-      return x_keysym_to_emacs_keysym (keysym, simple_p);
+      return (IsModifierKey (keysym) || keysym == XK_Mode_switch )
+	? Qnil : x_keysym_to_emacs_keysym (keysym, simple_p);
 
     case XLookupChars:
       {
@@ -983,20 +985,16 @@
 	  {
 	    Lisp_Object keysym;
 	    XKeyEvent *ev = &x_event->xkey;
-	    KeyCode keycode = ev->keycode;
-
-	    if (x_key_is_modifier_p (keycode, d)) /* it's a modifier key */
-	      return 0;
-
 	    /* This used to compute the frame from the given X window and
 	       store it here, but we really don't care about the frame. */
 	    emacs_event->channel = DEVICE_CONSOLE (d);
 	    keysym = x_to_emacs_keysym (&x_event->xkey, 0);
 
-	    /* If the emacs keysym is nil, then that means that the
-	       X keysym was NoSymbol, which probably means that
-	       we're in the midst of reading a Multi_key sequence,
-	       or a "dead" key prefix, or XIM input.  Ignore it. */
+	    /* If the emacs keysym is nil, then that means that the X
+	       keysym was either a Modifier or NoSymbol, which
+	       probably means that we're in the midst of reading a
+	       Multi_key sequence, or a "dead" key prefix, or XIM
+	       input. Ignore it. */
 	    if (NILP (keysym))
 	      return 0;