diff options
author | Matthias Clasen <mclasen@redhat.com> | 2007-06-30 01:43:04 +0000 |
---|---|---|
committer | Matthias Clasen <matthiasc@src.gnome.org> | 2007-06-30 01:43:04 +0000 |
commit | 436a34e31810b11dbe55d0bfb5548bc5cd412fca (patch) | |
tree | 74db219bc055d1a5bb44adfecaa513b4dacc911e /gdk/x11 | |
parent | 5c31ca5c85ee13f9cdf11baa466e7dd77e2df94a (diff) | |
download | gtk+-436a34e31810b11dbe55d0bfb5548bc5cd412fca.tar.gz |
New function to determine if keyboard layouts for both LTR and LTR
2007-06-29 Matthias Clasen <mclasen@redhat.com>
* gdk/gdk.symbols:
* gdk/gdkkeys.h:
* gdk/x11/gdkkeys-x11.c (gdk_keymap_have_bidi_layouts): New
function to determine if keyboard layouts for both LTR and LTR
languages are in use. Refactor the direction caching code to
make this information available. (#451575, Behnam Esfahbod)
svn path=/trunk/; revision=18301
Diffstat (limited to 'gdk/x11')
-rw-r--r-- | gdk/x11/gdkkeys-x11.c | 179 |
1 files changed, 125 insertions, 54 deletions
diff --git a/gdk/x11/gdkkeys-x11.c b/gdk/x11/gdkkeys-x11.c index 779090f04e..f5ca8bc226 100644 --- a/gdk/x11/gdkkeys-x11.c +++ b/gdk/x11/gdkkeys-x11.c @@ -584,73 +584,93 @@ get_direction (XkbDescRec *xkb, return PANGO_DIRECTION_LTR; } -static void -update_direction (GdkKeymapX11 *keymap_x11, - gint group) +static PangoDirection +get_direction_from_cache (GdkKeymapX11 *keymap_x11, + XkbDescPtr xkb, + gint group) { - XkbDescRec *xkb = get_xkb (keymap_x11); - Atom group_atom; + Atom group_atom = xkb->names->groups[group]; - 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; + gboolean cache_hit = FALSE; + DirectionCacheEntry *cache = keymap_x11->group_direction_cache; - PangoDirection direction = PANGO_DIRECTION_NEUTRAL; - gint i; + 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 (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) { - 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; - } + cache_hit = TRUE; + cache[i].serial = keymap_x11->current_cache_serial++; /* freshen */ + direction = cache[i].direction; + group_atom = cache[i].group_atom; + break; } - } - else + } + } + else + { + /* initialize cache */ + for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++) { - /* 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++; + 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; + /* insert in cache */ + if (!cache_hit) + { + gint oldest = 0; - direction = get_direction (xkb, group); + 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++; + /* 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; + return direction; +} + +static 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; +} + +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) + { + 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 +693,7 @@ _gdk_keymap_state_changed (GdkDisplay *display, 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"); @@ -693,6 +713,15 @@ _gdk_keymap_keys_changed (GdkDisplay *display) g_signal_emit_by_name (display_x11->keymap, "keys_changed", 0); } +/** + * gdk_keymap_get_direction: + * @keymap: a #GdkKeymap or %NULL to use the default keymap + * + * Returns the direction of effective layout of the keymap. + * + * @Returns: %PANGO_DIRECTION_LTR or %PANGO_DIRECTION_RTL if determines the + * direction. %PANGO_DIRECTION_NEUTRAL otherwise. + **/ PangoDirection gdk_keymap_get_direction (GdkKeymap *keymap) { @@ -710,7 +739,7 @@ gdk_keymap_get_direction (GdkKeymap *keymap) 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; @@ -720,6 +749,48 @@ gdk_keymap_get_direction (GdkKeymap *keymap) return PANGO_DIRECTION_NEUTRAL; } +/** + * gdk_keymap_have_bidi_layouts: + * @keymap: a #GdkKeymap or %NULL to use the default keymap + * + * Determines if keyboard layouts for both right-to-left and left-to-right + * languages are in use. + * + * @Returns: %TRUE if there are layouts in both directions, %FALSE otherwise + * + * Since: 2.12 + **/ +gboolean +gdk_keymap_have_bidi_layouts (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); + + 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; +} + /** * gdk_keymap_get_entries_for_keyval: * @keymap: a #GdkKeymap, or %NULL to use the default keymap |