Index: x11/gdkkeys-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkkeys-x11.c,v
retrieving revision 1.56.2.1
diff -u -p -d -B -r1.56.2.1 gdkkeys-x11.c
--- x11/gdkkeys-x11.c	20 Sep 2006 18:17:17 -0000	1.56.2.1
+++ x11/gdkkeys-x11.c	26 Sep 2006 15:53:29 -0000
@@ -584,73 +584,82 @@ get_direction (XkbDescRec *xkb, 
     return PANGO_DIRECTION_LTR;
 }
 
+static PangoDirection
+get_direction_from_cache (GdkKeymapX11 *keymap_x11,
+			  XkbDescPtr xkb,
+			  gint group)
+{
+  Atom group_atom = xkb->names->groups[group];
+
+  gboolean cache_hit = FALSE;
+  DirectionCacheEntry *cache = keymap_x11->group_direction_cache;
+
+  PangoDirection direction = PANGO_DIRECTION_NEUTRAL;
+  gint i;
+
+  if (keymap_x11->have_direction)
+    {
+      /* lookup in cache */
+      for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++)
+      {
+	if (cache[i].group_atom == group_atom)
+	  {
+	    cache_hit = TRUE;
+	    cache[i].serial = keymap_x11->current_cache_serial++; /* freshen */
+	    direction = cache[i].direction;
+	    group_atom = cache[i].group_atom;
+	    break;
+	  }
+      }
+    }
+  else
+    {
+      /* initialize cache */
+      for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++)
+	{
+	  cache[i].group_atom = 0;
+	  cache[i].serial = keymap_x11->current_cache_serial;
+	}
+      keymap_x11->current_cache_serial++;
+    }
+
+  /* insert in cache */
+  if (!cache_hit)
+    {
+      gint oldest = 0;
+
+      direction = get_direction (xkb, group);
+
+      /* remove the oldest entry */
+      for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++)
+	{
+	  if (cache[i].serial < cache[oldest].serial)
+	    oldest = i;
+	}
+      
+      cache[oldest].group_atom = group_atom;
+      cache[oldest].direction = direction;
+      cache[oldest].serial = keymap_x11->current_cache_serial++;
+    }
+
+  return direction;
+}
+
 static void
 update_direction (GdkKeymapX11 *keymap_x11,
 		  gint          group)
 {
   XkbDescPtr xkb = get_xkb (keymap_x11);
   Atom group_atom;
 
   group_atom = xkb->names->groups[group];
 
   /* a group change? */
   if (!keymap_x11->have_direction || keymap_x11->current_group_atom != group_atom)
     {
-      gboolean cache_hit = FALSE;
-      DirectionCacheEntry *cache = keymap_x11->group_direction_cache;
-
-      PangoDirection direction = PANGO_DIRECTION_NEUTRAL;
-      gint i;
-
-      if (keymap_x11->have_direction)
-	{
-          /* lookup in cache */
-	  for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++)
-	  {
-	    if (cache[i].group_atom == group_atom)
-	      {
-		cache_hit = TRUE;
-		cache[i].serial = keymap_x11->current_cache_serial++; /* freshen */
-		direction = cache[i].direction;
-		group_atom = cache[i].group_atom;
-		break;
-	      }
-	  }
-	}
-      else
-	{
-          /* initialize cache */
-	  for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++)
-	    {
-	      cache[i].group_atom = 0;
-	      cache[i].serial = keymap_x11->current_cache_serial;
-	    }
-	  keymap_x11->current_cache_serial++;
-	}
-
-      /* insert in cache */
-      if (!cache_hit)
-	{
-	  gint oldest = 0;
-
-	  direction = get_direction (xkb, group);
-
-	  /* remove the oldest entry */
-	  for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++)
-	    {
-	      if (cache[i].serial < cache[oldest].serial)
-	        oldest = i;
-	    }
-	  
-	  cache[oldest].group_atom = group_atom;
-	  cache[oldest].direction = direction;
-	  cache[oldest].serial = keymap_x11->current_cache_serial++;
-	}
-
-      keymap_x11->current_group_atom = group_atom;
-
+      keymap_x11->current_direction = get_direction_from_cache (keymap_x11, xkb, group);
+      keymap_x11->current_group_atom = group_atom;
       keymap_x11->have_direction = TRUE;
-      keymap_x11->current_direction = direction;
     }
 }
 
@@ -673,7 +682,7 @@ _gdk_keymap_state_changed (GdkDisplay *d
       had_direction = keymap_x11->have_direction;
       direction = keymap_x11->current_direction;
       
-      update_direction (keymap_x11, xkb_event->state.locked_group);
+      update_direction (keymap_x11, XkbStateGroup (&xkb_event->state));
       
       if (!had_direction || direction != keymap_x11->current_direction)
 	g_signal_emit_by_name (keymap_x11, "direction_changed");      
@@ -710,7 +719,7 @@ gdk_keymap_get_direction (GdkKeymap *key
 
 	  XkbGetState (GDK_DISPLAY_XDISPLAY (display), XkbUseCoreKbd, 
 		       &state_rec);
-	  update_direction (keymap_x11, XkbGroupLock (&state_rec));
+	  update_direction (keymap_x11, XkbStateGroup (&state_rec));
 	}
   
       return keymap_x11->current_direction;
@@ -718,6 +727,47 @@ gdk_keymap_get_direction (GdkKeymap *key
   else
 #endif /* HAVE_XKB */
     return PANGO_DIRECTION_NEUTRAL;
+}
+
+int
+get_num_groups (GdkKeymap *keymap, XkbDescPtr xkb)
+{
+      Display *display = KEYMAP_XDISPLAY (keymap);
+      XkbGetControls(display, XkbSlowKeysMask, xkb);
+      XkbGetUpdatedMap (display, XkbKeySymsMask | XkbKeyTypesMask |
+			XkbModifierMapMask | XkbVirtualModsMask, xkb);
+      return xkb->ctrls->num_groups;
+}
+
+gboolean
+gdk_keymap_have_bidi_directions (GdkKeymap *keymap)
+{
+  keymap = GET_EFFECTIVE_KEYMAP (keymap);
+
+#if HAVE_XKB
+  if (KEYMAP_USE_XKB (keymap))
+    {
+      GdkKeymapX11 *keymap_x11 = GDK_KEYMAP_X11 (keymap);
+      XkbDescPtr xkb = get_xkb (keymap_x11);
+      int num_groups = get_num_groups (keymap, xkb);
+
+      register int i;
+      gboolean have_ltr_keyboard = FALSE;
+      gboolean have_rtl_keyboard = FALSE;
+
+      for (i = 0; i < num_groups; i++)
+      {
+	if (get_direction_from_cache (keymap_x11, xkb, i) == PANGO_DIRECTION_RTL)
+	  have_rtl_keyboard = TRUE;
+	else
+	  have_ltr_keyboard = TRUE;
+      }
+
+      return have_ltr_keyboard && have_rtl_keyboard;
+    }
+  else
+#endif /* HAVE_XKB */
+    return FALSE;
 }
 
 /**
Index: gdkkeys.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkkeys.h,v
retrieving revision 1.7
diff -u -p -d -B -r1.7 gdkkeys.h
--- gdkkeys.h	12 Jun 2005 05:32:24 -0000	1.7
+++ gdkkeys.h	26 Sep 2006 15:53:29 -0000
@@ -101,6 +101,7 @@ gboolean       gdk_keymap_get_entries_fo
 						    guint              **keyvals,
 						    gint                *n_entries);
 PangoDirection gdk_keymap_get_direction            (GdkKeymap           *keymap);
+gboolean       gdk_keymap_have_bidi_directions     (GdkKeymap           *keymap);
 
 /* Key values
  */
