forked from AuroraMiddleware/gtk
quartz: remove check for keymap changes from update_keymap()
The function is now only called when the keymap has actually changed. bug #698183.
This commit is contained in:
parent
c2919a6e91
commit
e62709da2e
@ -61,17 +61,6 @@
|
||||
|
||||
static GdkKeymap *default_keymap = NULL;
|
||||
|
||||
/* Note: we could check only if building against the 10.5 SDK instead, but
|
||||
* that would make non-xml layouts not work in 32-bit which would be a quite
|
||||
* bad regression. This way, old unsupported layouts will just not work in
|
||||
* 64-bit.
|
||||
*/
|
||||
#ifdef __LP64__
|
||||
static TISInputSourceRef current_layout = NULL;
|
||||
#else
|
||||
static KeyboardLayoutRef current_layout = NULL;
|
||||
#endif
|
||||
|
||||
/* This is a table of all keyvals. Each keycode gets KEYVALS_PER_KEYCODE entries.
|
||||
* TThere is 1 keyval per modifier (Nothing, Shift, Alt, Shift+Alt);
|
||||
*/
|
||||
@ -249,7 +238,14 @@ static void
|
||||
update_keymap (void)
|
||||
{
|
||||
const void *chr_data = NULL;
|
||||
guint *p;
|
||||
int i;
|
||||
|
||||
/* Note: we could check only if building against the 10.5 SDK instead, but
|
||||
* that would make non-xml layouts not work in 32-bit which would be a quite
|
||||
* bad regression. This way, old unsupported layouts will just not work in
|
||||
* 64-bit.
|
||||
*/
|
||||
#ifdef __LP64__
|
||||
TISInputSourceRef new_layout = TISCopyCurrentKeyboardLayoutInputSource ();
|
||||
CFDataRef layout_data_ref;
|
||||
@ -261,228 +257,220 @@ update_keymap (void)
|
||||
KLGetCurrentKeyboardLayout (&new_layout);
|
||||
#endif
|
||||
|
||||
if (new_layout != current_layout)
|
||||
{
|
||||
guint *p;
|
||||
int i;
|
||||
|
||||
g_free (keyval_array);
|
||||
keyval_array = g_new0 (guint, NUM_KEYCODES * KEYVALS_PER_KEYCODE);
|
||||
g_free (keyval_array);
|
||||
keyval_array = g_new0 (guint, NUM_KEYCODES * KEYVALS_PER_KEYCODE);
|
||||
|
||||
#ifdef __LP64__
|
||||
layout_data_ref = (CFDataRef) TISGetInputSourceProperty
|
||||
(new_layout, kTISPropertyUnicodeKeyLayoutData);
|
||||
layout_data_ref = (CFDataRef) TISGetInputSourceProperty
|
||||
(new_layout, kTISPropertyUnicodeKeyLayoutData);
|
||||
|
||||
if (layout_data_ref)
|
||||
chr_data = CFDataGetBytePtr (layout_data_ref);
|
||||
if (layout_data_ref)
|
||||
chr_data = CFDataGetBytePtr (layout_data_ref);
|
||||
|
||||
if (chr_data == NULL)
|
||||
{
|
||||
g_error ("cannot get keyboard layout data");
|
||||
return;
|
||||
}
|
||||
#else
|
||||
/* Get the layout kind */
|
||||
KLGetKeyboardLayoutProperty (new_layout, kKLKind, (const void **)&layout_kind);
|
||||
|
||||
/* 8-bit-only keyabord layout */
|
||||
if (layout_kind == kKLKCHRKind)
|
||||
{
|
||||
/* Get chr data */
|
||||
KLGetKeyboardLayoutProperty (new_layout, kKLKCHRData, (const void **)&chr_data);
|
||||
|
||||
for (i = 0; i < NUM_KEYCODES; i++)
|
||||
{
|
||||
int j;
|
||||
UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey | optionKey};
|
||||
|
||||
p = keyval_array + i * KEYVALS_PER_KEYCODE;
|
||||
|
||||
for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
|
||||
{
|
||||
UInt32 c, state = 0;
|
||||
UInt16 key_code;
|
||||
UniChar uc;
|
||||
|
||||
key_code = modifiers[j] | i;
|
||||
c = KeyTranslate (chr_data, key_code, &state);
|
||||
|
||||
if (state != 0)
|
||||
{
|
||||
UInt32 state2 = 0;
|
||||
c = KeyTranslate (chr_data, key_code | 128, &state2);
|
||||
}
|
||||
|
||||
if (c != 0 && c != 0x10)
|
||||
{
|
||||
int k;
|
||||
gboolean found = FALSE;
|
||||
|
||||
/* FIXME: some keyboard layouts (e.g. Russian) use
|
||||
* a different 8-bit character set. We should
|
||||
* check for this. Not a serious problem, because
|
||||
* most (all?) of these layouts also have a
|
||||
* uchr version.
|
||||
*/
|
||||
uc = macroman2ucs (c);
|
||||
|
||||
for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++)
|
||||
{
|
||||
if (special_ucs_table[k].ucs_value == uc)
|
||||
{
|
||||
p[j] = special_ucs_table[k].keyval;
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Special-case shift-tab since GTK+ expects
|
||||
* GDK_ISO_Left_Tab for that.
|
||||
*/
|
||||
if (found && p[j] == GDK_Tab && modifiers[j] == shiftKey)
|
||||
p[j] = GDK_ISO_Left_Tab;
|
||||
|
||||
if (!found)
|
||||
p[j] = gdk_unicode_to_keyval (uc);
|
||||
}
|
||||
}
|
||||
|
||||
if (p[3] == p[2])
|
||||
p[3] = 0;
|
||||
if (p[2] == p[1])
|
||||
p[2] = 0;
|
||||
if (p[1] == p[0])
|
||||
p[1] = 0;
|
||||
if (p[0] == p[2] &&
|
||||
p[1] == p[3])
|
||||
p[2] = p[3] = 0;
|
||||
}
|
||||
}
|
||||
/* unicode keyboard layout */
|
||||
else if (layout_kind == kKLKCHRuchrKind || layout_kind == kKLuchrKind)
|
||||
{
|
||||
/* Get chr data */
|
||||
KLGetKeyboardLayoutProperty (new_layout, kKLuchrData, (const void **)&chr_data);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < NUM_KEYCODES; i++)
|
||||
{
|
||||
int j;
|
||||
UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey | optionKey};
|
||||
UniChar chars[4];
|
||||
UniCharCount nChars;
|
||||
|
||||
p = keyval_array + i * KEYVALS_PER_KEYCODE;
|
||||
|
||||
for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
|
||||
{
|
||||
UInt32 state = 0;
|
||||
OSStatus err;
|
||||
UInt16 key_code;
|
||||
UniChar uc;
|
||||
|
||||
key_code = modifiers[j] | i;
|
||||
err = UCKeyTranslate (chr_data, i, kUCKeyActionDisplay,
|
||||
(modifiers[j] >> 8) & 0xFF,
|
||||
LMGetKbdType(),
|
||||
0,
|
||||
&state, 4, &nChars, chars);
|
||||
|
||||
/* FIXME: Theoretically, we can get multiple UTF-16 values;
|
||||
* we should convert them to proper unicode and figure
|
||||
* out whether there are really keyboard layouts that
|
||||
* give us more than one character for one keypress. */
|
||||
if (err == noErr && nChars == 1)
|
||||
{
|
||||
int k;
|
||||
gboolean found = FALSE;
|
||||
|
||||
/* A few <Shift><Option>keys return two
|
||||
* characters, the first of which is U+00a0,
|
||||
* which isn't interesting; so we return the
|
||||
* second. More sophisticated handling is the
|
||||
* job of a GtkIMContext.
|
||||
*
|
||||
* If state isn't zero, it means that it's a
|
||||
* dead key of some sort. Some of those are
|
||||
* enumerated in the special_ucs_table with the
|
||||
* high nibble set to f to push it into the
|
||||
* private use range. Here we do the same.
|
||||
*/
|
||||
if (state != 0)
|
||||
chars[nChars - 1] |= 0xf000;
|
||||
uc = chars[nChars - 1];
|
||||
|
||||
for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++)
|
||||
{
|
||||
if (special_ucs_table[k].ucs_value == uc)
|
||||
{
|
||||
p[j] = special_ucs_table[k].keyval;
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Special-case shift-tab since GTK+ expects
|
||||
* GDK_ISO_Left_Tab for that.
|
||||
*/
|
||||
if (found && p[j] == GDK_Tab && modifiers[j] == shiftKey)
|
||||
p[j] = GDK_ISO_Left_Tab;
|
||||
|
||||
if (!found)
|
||||
p[j] = gdk_unicode_to_keyval (uc);
|
||||
}
|
||||
}
|
||||
|
||||
if (p[3] == p[2])
|
||||
p[3] = 0;
|
||||
if (p[2] == p[1])
|
||||
p[2] = 0;
|
||||
if (p[1] == p[0])
|
||||
p[1] = 0;
|
||||
if (p[0] == p[2] &&
|
||||
p[1] == p[3])
|
||||
p[2] = p[3] = 0;
|
||||
}
|
||||
#ifndef __LP64__
|
||||
}
|
||||
else
|
||||
{
|
||||
g_error ("unknown type of keyboard layout (neither KCHR nor uchr)"
|
||||
" - not supported right now");
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
|
||||
{
|
||||
p = keyval_array + modifier_keys[i].keycode * KEYVALS_PER_KEYCODE;
|
||||
|
||||
if (p[0] == 0 && p[1] == 0 &&
|
||||
p[2] == 0 && p[3] == 0)
|
||||
p[0] = modifier_keys[i].keyval;
|
||||
}
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (function_keys); i++)
|
||||
{
|
||||
p = keyval_array + function_keys[i].keycode * KEYVALS_PER_KEYCODE;
|
||||
|
||||
p[0] = function_keys[i].keyval;
|
||||
p[1] = p[2] = p[3] = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (known_numeric_keys); i++)
|
||||
{
|
||||
p = keyval_array + known_numeric_keys[i].keycode * KEYVALS_PER_KEYCODE;
|
||||
|
||||
if (p[0] == known_numeric_keys[i].normal_keyval)
|
||||
p[0] = known_numeric_keys[i].keypad_keyval;
|
||||
}
|
||||
|
||||
if (current_layout)
|
||||
g_signal_emit_by_name (default_keymap, "keys_changed");
|
||||
|
||||
current_layout = new_layout;
|
||||
if (chr_data == NULL)
|
||||
{
|
||||
g_error ("cannot get keyboard layout data");
|
||||
return;
|
||||
}
|
||||
#else
|
||||
/* Get the layout kind */
|
||||
KLGetKeyboardLayoutProperty (new_layout, kKLKind, (const void **)&layout_kind);
|
||||
|
||||
/* 8-bit-only keyabord layout */
|
||||
if (layout_kind == kKLKCHRKind)
|
||||
{
|
||||
/* Get chr data */
|
||||
KLGetKeyboardLayoutProperty (new_layout, kKLKCHRData, (const void **)&chr_data);
|
||||
|
||||
for (i = 0; i < NUM_KEYCODES; i++)
|
||||
{
|
||||
int j;
|
||||
UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey | optionKey};
|
||||
|
||||
p = keyval_array + i * KEYVALS_PER_KEYCODE;
|
||||
|
||||
for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
|
||||
{
|
||||
UInt32 c, state = 0;
|
||||
UInt16 key_code;
|
||||
UniChar uc;
|
||||
|
||||
key_code = modifiers[j] | i;
|
||||
c = KeyTranslate (chr_data, key_code, &state);
|
||||
|
||||
if (state != 0)
|
||||
{
|
||||
UInt32 state2 = 0;
|
||||
c = KeyTranslate (chr_data, key_code | 128, &state2);
|
||||
}
|
||||
|
||||
if (c != 0 && c != 0x10)
|
||||
{
|
||||
int k;
|
||||
gboolean found = FALSE;
|
||||
|
||||
/* FIXME: some keyboard layouts (e.g. Russian) use a
|
||||
* different 8-bit character set. We should check
|
||||
* for this. Not a serious problem, because most
|
||||
* (all?) of these layouts also have a uchr version.
|
||||
*/
|
||||
uc = macroman2ucs (c);
|
||||
|
||||
for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++)
|
||||
{
|
||||
if (special_ucs_table[k].ucs_value == uc)
|
||||
{
|
||||
p[j] = special_ucs_table[k].keyval;
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Special-case shift-tab since GTK+ expects
|
||||
* GDK_ISO_Left_Tab for that.
|
||||
*/
|
||||
if (found && p[j] == GDK_Tab && modifiers[j] == shiftKey)
|
||||
p[j] = GDK_ISO_Left_Tab;
|
||||
|
||||
if (!found)
|
||||
p[j] = gdk_unicode_to_keyval (uc);
|
||||
}
|
||||
}
|
||||
|
||||
if (p[3] == p[2])
|
||||
p[3] = 0;
|
||||
if (p[2] == p[1])
|
||||
p[2] = 0;
|
||||
if (p[1] == p[0])
|
||||
p[1] = 0;
|
||||
if (p[0] == p[2] &&
|
||||
p[1] == p[3])
|
||||
p[2] = p[3] = 0;
|
||||
}
|
||||
}
|
||||
/* unicode keyboard layout */
|
||||
else if (layout_kind == kKLKCHRuchrKind || layout_kind == kKLuchrKind)
|
||||
{
|
||||
/* Get chr data */
|
||||
KLGetKeyboardLayoutProperty (new_layout, kKLuchrData, (const void **)&chr_data);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < NUM_KEYCODES; i++)
|
||||
{
|
||||
int j;
|
||||
UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey | optionKey};
|
||||
UniChar chars[4];
|
||||
UniCharCount nChars;
|
||||
|
||||
p = keyval_array + i * KEYVALS_PER_KEYCODE;
|
||||
|
||||
for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
|
||||
{
|
||||
UInt32 state = 0;
|
||||
OSStatus err;
|
||||
UInt16 key_code;
|
||||
UniChar uc;
|
||||
|
||||
key_code = modifiers[j] | i;
|
||||
err = UCKeyTranslate (chr_data, i, kUCKeyActionDisplay,
|
||||
(modifiers[j] >> 8) & 0xFF,
|
||||
LMGetKbdType(),
|
||||
0,
|
||||
&state, 4, &nChars, chars);
|
||||
|
||||
/* FIXME: Theoretically, we can get multiple UTF-16
|
||||
* values; we should convert them to proper unicode and
|
||||
* figure out whether there are really keyboard layouts
|
||||
* that give us more than one character for one
|
||||
* keypress.
|
||||
*/
|
||||
if (err == noErr && nChars == 1)
|
||||
{
|
||||
int k;
|
||||
gboolean found = FALSE;
|
||||
|
||||
/* A few <Shift><Option>keys return two characters,
|
||||
* the first of which is U+00a0, which isn't
|
||||
* interesting; so we return the second. More
|
||||
* sophisticated handling is the job of a
|
||||
* GtkIMContext.
|
||||
*
|
||||
* If state isn't zero, it means that it's a dead
|
||||
* key of some sort. Some of those are enumerated in
|
||||
* the special_ucs_table with the high nibble set to
|
||||
* f to push it into the private use range. Here we
|
||||
* do the same.
|
||||
*/
|
||||
if (state != 0)
|
||||
chars[nChars - 1] |= 0xf000;
|
||||
uc = chars[nChars - 1];
|
||||
|
||||
for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++)
|
||||
{
|
||||
if (special_ucs_table[k].ucs_value == uc)
|
||||
{
|
||||
p[j] = special_ucs_table[k].keyval;
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Special-case shift-tab since GTK+ expects
|
||||
* GDK_ISO_Left_Tab for that.
|
||||
*/
|
||||
if (found && p[j] == GDK_Tab && modifiers[j] == shiftKey)
|
||||
p[j] = GDK_ISO_Left_Tab;
|
||||
|
||||
if (!found)
|
||||
p[j] = gdk_unicode_to_keyval (uc);
|
||||
}
|
||||
}
|
||||
|
||||
if (p[3] == p[2])
|
||||
p[3] = 0;
|
||||
if (p[2] == p[1])
|
||||
p[2] = 0;
|
||||
if (p[1] == p[0])
|
||||
p[1] = 0;
|
||||
if (p[0] == p[2] &&
|
||||
p[1] == p[3])
|
||||
p[2] = p[3] = 0;
|
||||
}
|
||||
#ifndef __LP64__
|
||||
}
|
||||
else
|
||||
{
|
||||
g_error ("unknown type of keyboard layout (neither KCHR nor uchr)"
|
||||
" - not supported right now");
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
|
||||
{
|
||||
p = keyval_array + modifier_keys[i].keycode * KEYVALS_PER_KEYCODE;
|
||||
|
||||
if (p[0] == 0 && p[1] == 0 &&
|
||||
p[2] == 0 && p[3] == 0)
|
||||
p[0] = modifier_keys[i].keyval;
|
||||
}
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (function_keys); i++)
|
||||
{
|
||||
p = keyval_array + function_keys[i].keycode * KEYVALS_PER_KEYCODE;
|
||||
|
||||
p[0] = function_keys[i].keyval;
|
||||
p[1] = p[2] = p[3] = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (known_numeric_keys); i++)
|
||||
{
|
||||
p = keyval_array + known_numeric_keys[i].keycode * KEYVALS_PER_KEYCODE;
|
||||
|
||||
if (p[0] == known_numeric_keys[i].normal_keyval)
|
||||
p[0] = known_numeric_keys[i].keypad_keyval;
|
||||
}
|
||||
|
||||
g_signal_emit_by_name (default_keymap, "keys-changed");
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
Reference in New Issue
Block a user