]> Pileus Git - ~andy/gtk/blobdiff - gdk/quartz/gdkkeys-quartz.c
Change FSF Address
[~andy/gtk] / gdk / quartz / gdkkeys-quartz.c
index c35eccb98ad5925c02347e15d37c1920c89d8a5f..1e8c46b6fdaa2d96dd25414d3216deddf940c727 100644 (file)
@@ -14,9 +14,7 @@
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  */
 /* Some parts of this code come from quartzKeyboard.c,
  * from the Apple X11 Server.
@@ -54,6 +52,8 @@
 #include <Carbon/Carbon.h>
 #include <AppKit/NSEvent.h>
 #include "gdk.h"
+#include "gdkquartzkeys.h"
+#include "gdkkeysprivate.h"
 #include "gdkkeysyms.h"
 
 #define NUM_KEYCODES 128
 
 static GdkKeymap *default_keymap = NULL;
 
-typedef struct _GdkKeymapQuartz GdkKeymapQuartz;
-typedef struct _GdkKeymapQuartzClass GdkKeymapQuartzClass;
+struct _GdkQuartzKeymap
+{
+  GdkKeymap keymap;
+};
 
-G_DEFINE_TYPE (GdkKeyMapQuartz, _gdk_keymap_quartz, GDK_TYPE_KEYMAP)
+struct _GdkQuartzKeymapClass
+{
+  GdkKeymapClass keymap_class;
+};
+
+G_DEFINE_TYPE (GdkQuartzKeymap, gdk_quartz_keymap, GDK_TYPE_KEYMAP)
 
 GdkKeymap *
 _gdk_quartz_display_get_keymap (GdkDisplay *display)
 {
   if (default_keymap == NULL)
-    default_keymap = g_object_new (_gdk_keymap_quartz_get_type (), NULL);
+    default_keymap = g_object_new (gdk_quartz_keymap_get_type (), NULL);
 
   return default_keymap;
 }
@@ -127,7 +134,7 @@ const static struct {
   guint keycode;
   guint keyval;
   unsigned int modmask; /* So we can tell when a mod key is pressed/released */
-} known_keys[] = {
+} modifier_keys[] = {
   {  54, GDK_KEY_Meta_R,    NSCommandKeyMask },
   {  55, GDK_KEY_Meta_L,    NSCommandKeyMask },
   {  56, GDK_KEY_Shift_L,   NSShiftKeyMask },
@@ -136,23 +143,29 @@ const static struct {
   {  59, GDK_KEY_Control_L, NSControlKeyMask },
   {  60, GDK_KEY_Shift_R,   NSShiftKeyMask },
   {  61, GDK_KEY_Alt_R,     NSAlternateKeyMask },
-  {  62, GDK_KEY_Control_R, NSControlKeyMask },
-  { 122, GDK_KEY_F1, 0 },
-  { 120, GDK_KEY_F2, 0 },
-  {  99, GDK_KEY_F3, 0 },
-  { 118, GDK_KEY_F4, 0 },
-  {  96, GDK_KEY_F5, 0 },
-  {  97, GDK_KEY_F6, 0 },
-  {  98, GDK_KEY_F7, 0 },
-  { 100, GDK_KEY_F8, 0 },
-  { 101, GDK_KEY_F9, 0 },
-  { 109, GDK_KEY_F10, 0 },
-  { 103, GDK_KEY_F11, 0 },
-  { 111, GDK_KEY_F12, 0 },
-  { 105, GDK_KEY_F13, 0 },
-  { 107, GDK_KEY_F14, 0 },
-  { 113, GDK_KEY_F15, 0 },
-  { 106, GDK_KEY_F16, 0 }
+  {  62, GDK_KEY_Control_R, NSControlKeyMask }
+};
+
+const static struct {
+  guint keycode;
+  guint keyval;
+} function_keys[] = {
+  { 122, GDK_KEY_F1 },
+  { 120, GDK_KEY_F2 },
+  {  99, GDK_KEY_F3 },
+  { 118, GDK_KEY_F4 },
+  {  96, GDK_KEY_F5 },
+  {  97, GDK_KEY_F6 },
+  {  98, GDK_KEY_F7 },
+  { 100, GDK_KEY_F8 },
+  { 101, GDK_KEY_F9 },
+  { 109, GDK_KEY_F10 },
+  { 103, GDK_KEY_F11 },
+  { 111, GDK_KEY_F12 },
+  { 105, GDK_KEY_F13 },
+  { 107, GDK_KEY_F14 },
+  { 113, GDK_KEY_F15 },
+  { 106, GDK_KEY_F16 }
 };
 
 const static struct {
@@ -196,7 +209,60 @@ const static struct {
   { 0x001d, GDK_KEY_Right },
   { 0x001e, GDK_KEY_Up },
   { 0x001f, GDK_KEY_Down },
-  { 0x007f, GDK_KEY_Delete }
+  { 0x007f, GDK_KEY_Delete },
+  { 0xf027, GDK_KEY_dead_acute },
+  { 0xf060, GDK_KEY_dead_grave },
+  { 0xf300, GDK_KEY_dead_grave },
+  { 0xf0b4, GDK_KEY_dead_acute },
+  { 0xf301, GDK_KEY_dead_acute },
+  { 0xf385, GDK_KEY_dead_acute },
+  { 0xf05e, GDK_KEY_dead_circumflex },
+  { 0xf2c6, GDK_KEY_dead_circumflex },
+  { 0xf302, GDK_KEY_dead_circumflex },
+  { 0xf07e, GDK_KEY_dead_tilde },
+  { 0xf303, GDK_KEY_dead_tilde },
+  { 0xf342, GDK_KEY_dead_perispomeni },
+  { 0xf0af, GDK_KEY_dead_macron },
+  { 0xf304, GDK_KEY_dead_macron },
+  { 0xf2d8, GDK_KEY_dead_breve },
+  { 0xf306, GDK_KEY_dead_breve },
+  { 0xf2d9, GDK_KEY_dead_abovedot },
+  { 0xf307, GDK_KEY_dead_abovedot },
+  { 0xf0a8, GDK_KEY_dead_diaeresis },
+  { 0xf308, GDK_KEY_dead_diaeresis },
+  { 0xf2da, GDK_KEY_dead_abovering },
+  { 0xf30A, GDK_KEY_dead_abovering },
+  { 0xf022, GDK_KEY_dead_doubleacute },
+  { 0xf2dd, GDK_KEY_dead_doubleacute },
+  { 0xf30B, GDK_KEY_dead_doubleacute },
+  { 0xf2c7, GDK_KEY_dead_caron },
+  { 0xf30C, GDK_KEY_dead_caron },
+  { 0xf0be, GDK_KEY_dead_cedilla },
+  { 0xf327, GDK_KEY_dead_cedilla },
+  { 0xf2db, GDK_KEY_dead_ogonek },
+  { 0xf328, GDK_KEY_dead_ogonek },
+  { 0xfe5d, GDK_KEY_dead_iota },
+  { 0xf323, GDK_KEY_dead_belowdot },
+  { 0xf309, GDK_KEY_dead_hook },
+  { 0xf31B, GDK_KEY_dead_horn },
+  { 0xf02d, GDK_KEY_dead_stroke },
+  { 0xf335, GDK_KEY_dead_stroke },
+  { 0xf336, GDK_KEY_dead_stroke },
+  { 0xf313, GDK_KEY_dead_abovecomma },
+  /*  { 0xf313, GDK_KEY_dead_psili }, */
+  { 0xf314, GDK_KEY_dead_abovereversedcomma },
+  /*  { 0xf314, GDK_KEY_dead_dasia }, */
+  { 0xf30F, GDK_KEY_dead_doublegrave },
+  { 0xf325, GDK_KEY_dead_belowring },
+  { 0xf2cd, GDK_KEY_dead_belowmacron },
+  { 0xf331, GDK_KEY_dead_belowmacron },
+  { 0xf32D, GDK_KEY_dead_belowcircumflex },
+  { 0xf330, GDK_KEY_dead_belowtilde },
+  { 0xf32E, GDK_KEY_dead_belowbreve },
+  { 0xf324, GDK_KEY_dead_belowdiaeresis },
+  { 0xf311, GDK_KEY_dead_invertedbreve },
+  { 0xf02c, GDK_KEY_dead_belowcomma },
+  { 0xf326, GDK_KEY_dead_belowcomma }
 };
 
 static void
@@ -297,18 +363,10 @@ maybe_update_keymap (void)
                        p[j] = GDK_KEY_ISO_Left_Tab;
 
                      if (!found)
-                        {
-                          guint tmp;
-                          
-                          tmp = gdk_unicode_to_keyval (uc);
-                          if (tmp != (uc | 0x01000000))
-                            p[j] = tmp;
-                          else
-                            p[j] = 0;
-                        }
+                        p[j] = gdk_unicode_to_keyval (uc);
                    }
                }
-             
+
              if (p[3] == p[2])
                p[3] = 0;
              if (p[2] == p[1])
@@ -344,13 +402,12 @@ maybe_update_keymap (void)
                  UniChar uc;
                  
                  key_code = modifiers[j] | i;
-                 err = UCKeyTranslate (chr_data, i, kUCKeyActionDown,
+                 err = UCKeyTranslate (chr_data, i, kUCKeyActionDisplay,
                                        (modifiers[j] >> 8) & 0xFF,
                                        LMGetKbdType(),
-                                       kUCKeyTranslateNoDeadKeysMask,
+                                       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
@@ -359,8 +416,22 @@ maybe_update_keymap (void)
                    {
                      int k;
                      gboolean found = FALSE;
-                     
-                     uc = chars[0];
+
+                     /* 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++) 
                        {
@@ -377,20 +448,12 @@ maybe_update_keymap (void)
                       */
                      if (found && p[j] == GDK_KEY_Tab && modifiers[j] == shiftKey)
                        p[j] = GDK_KEY_ISO_Left_Tab;
-                     
+
                      if (!found)
-                        {
-                          guint tmp;
-                          
-                          tmp = gdk_unicode_to_keyval (uc);
-                          if (tmp != (uc | 0x01000000))
-                            p[j] = tmp;
-                          else
-                            p[j] = 0;
-                        }
+                        p[j] = gdk_unicode_to_keyval (uc);
                    }
                }
-             
+
              if (p[3] == p[2])
                p[3] = 0;
              if (p[2] == p[1])
@@ -410,13 +473,21 @@ maybe_update_keymap (void)
        }
 #endif
 
-      for (i = 0; i < G_N_ELEMENTS (known_keys); i++)
+      for (i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
        {
-         p = keyval_array + known_keys[i].keycode * KEYVALS_PER_KEYCODE;
+         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] = known_keys[i].keyval;
+           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++)
@@ -434,17 +505,6 @@ maybe_update_keymap (void)
     }
 }
 
-GdkKeymap *
-gdk_keymap_get_for_display (GdkDisplay *display)
-{
-  g_return_val_if_fail (display == gdk_display_get_default (), NULL);
-
-  if (default_keymap == NULL)
-    default_keymap = g_object_new (gdk_keymap_get_type (), NULL);
-
-  return default_keymap;
-}
-
 static PangoDirection
 gdk_quartz_keymap_get_direction (GdkKeymap *keymap)
 {
@@ -496,8 +556,8 @@ gdk_quartz_keymap_get_entries_for_keyval (GdkKeymap     *keymap,
       (*n_keys)++;
 
       key.keycode = i / KEYVALS_PER_KEYCODE;
-      key.group = 0;
-      key.level = i % KEYVALS_PER_KEYCODE;
+      key.group = (i % KEYVALS_PER_KEYCODE) >= 2;
+      key.level = i % 2;
 
       g_array_append_val (keys_array, key);
     }
@@ -552,7 +612,7 @@ gdk_quartz_keymap_get_entries_for_keycode (GdkKeymap     *keymap,
          GdkKeymapKey key;
 
          key.keycode = hardware_keycode;
-         key.group = i / 2;
+         key.group = i >= 2;
          key.level = i % 2;
 
          g_array_append_val (keys_array, key);
@@ -608,6 +668,11 @@ translate_keysym (guint           hardware_keycode,
         tmp_keyval = upper;
     }
 
+  if (effective_group)
+    *effective_group = group;
+  if (effective_level)
+    *effective_level = level;
+
   return tmp_keyval;
 }
 
@@ -638,12 +703,18 @@ gdk_quartz_keymap_translate_keyboard_state (GdkKeymap       *keymap,
 
   if (hardware_keycode < 0 || hardware_keycode >= NUM_KEYCODES)
     return FALSE;
-  
-  /* Check if shift or capslock modify the keyval */
-  for (bit = GDK_SHIFT_MASK; bit < GDK_CONTROL_MASK; bit <<= 1)
+
+  /* Check if modifiers modify the keyval */
+  for (bit = GDK_SHIFT_MASK; bit < GDK_BUTTON1_MASK; bit <<= 1)
     {
-      if (translate_keysym (hardware_keycode, group, state & ~bit, NULL, NULL) !=
-         translate_keysym (hardware_keycode, group, state | bit, NULL, NULL))
+      if (translate_keysym (hardware_keycode,
+                            (bit == GDK_MOD1_MASK) ? 0 : group,
+                            state & ~bit,
+                            NULL, NULL) !=
+         translate_keysym (hardware_keycode,
+                            (bit == GDK_MOD1_MASK) ? 1 : group,
+                            state | bit,
+                            NULL, NULL))
        tmp_modifiers |= bit;
     }
 
@@ -662,17 +733,49 @@ static void
 gdk_quartz_keymap_add_virtual_modifiers (GdkKeymap       *keymap,
                                          GdkModifierType *state)
 {
-  /* FIXME: For now, we've mimiced the Windows backend. */
+  if (*state & GDK_MOD2_MASK)
+    *state |= GDK_META_MASK;
 }
 
 static gboolean
 gdk_quartz_keymap_map_virtual_modifiers (GdkKeymap       *keymap,
                                          GdkModifierType *state)
 {
-  /* FIXME: For now, we've mimiced the Windows backend. */
+  if (*state & GDK_META_MASK)
+    *state |= GDK_MOD2_MASK;
+
   return TRUE;
 }
 
+static GdkModifierType
+gdk_quartz_keymap_get_modifier_mask (GdkKeymap         *keymap,
+                                     GdkModifierIntent  intent)
+{
+  switch (intent)
+    {
+    case GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR:
+      return GDK_MOD2_MASK;
+
+    case GDK_MODIFIER_INTENT_CONTEXT_MENU:
+      return GDK_CONTROL_MASK;
+
+    case GDK_MODIFIER_INTENT_EXTEND_SELECTION:
+      return GDK_SHIFT_MASK;
+
+    case GDK_MODIFIER_INTENT_MODIFY_SELECTION:
+      return GDK_MOD2_MASK;
+
+    case GDK_MODIFIER_INTENT_NO_TEXT_INPUT:
+      return GDK_MOD2_MASK | GDK_CONTROL_MASK;
+
+    case GDK_MODIFIER_INTENT_SHIFT_GROUP:
+      return GDK_MOD1_MASK;
+
+    default:
+      g_return_val_if_reached (0);
+    }
+}
+
 /* What sort of key event is this? Returns one of
  * GDK_KEY_PRESS, GDK_KEY_RELEASE, GDK_NOTHING (should be ignored)
  */
@@ -700,11 +803,11 @@ _gdk_quartz_keys_event_type (NSEvent *event)
   keycode = [event keyCode];
   flags = [event modifierFlags];
   
-  for (i = 0; i < G_N_ELEMENTS (known_keys); i++)
+  for (i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
     {
-      if (known_keys[i].keycode == keycode)
+      if (modifier_keys[i].keycode == keycode)
        {
-         if (flags & known_keys[i].modmask)
+         if (flags & modifier_keys[i].modmask)
            return GDK_KEY_PRESS;
          else
            return GDK_KEY_RELEASE;
@@ -721,12 +824,12 @@ _gdk_quartz_keys_is_modifier (guint keycode)
 {
   gint i;
   
-  for (i = 0; i < G_N_ELEMENTS (known_keys); i++)
+  for (i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
     {
-      if (known_keys[i].modmask == 0)
+      if (modifier_keys[i].modmask == 0)
        break;
 
-      if (known_keys[i].keycode == keycode)
+      if (modifier_keys[i].keycode == keycode)
        return TRUE;
     }
 
@@ -734,23 +837,23 @@ _gdk_quartz_keys_is_modifier (guint keycode)
 }
 
 static void
-_gdk_keymap_quartz_init (GdkKeymapQuartz *keymap)
+gdk_quartz_keymap_init (GdkQuartzKeymap *keymap)
 {
 }
 
 static void
-_gdk_keymap_quartz_finalize (GObject *object)
+gdk_quartz_keymap_finalize (GObject *object)
 {
-  G_OBJECT_CLASS (_gdk_keymap_quartz_parent_class)->finalize (object);
+  G_OBJECT_CLASS (gdk_quartz_keymap_parent_class)->finalize (object);
 }
 
 static void
-_gdk_keymap_quartz_class_init (GdkKeymapQuartzClass *klass)
+gdk_quartz_keymap_class_init (GdkQuartzKeymapClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GdkKeymapClass *keymap_class = GDK_KEYMAP_CLASS (klass);
 
-  object_class->finalize = gdk_keymap_quartz_finalize;
+  object_class->finalize = gdk_quartz_keymap_finalize;
 
   keymap_class->get_direction = gdk_quartz_keymap_get_direction;
   keymap_class->have_bidi_layouts = gdk_quartz_keymap_have_bidi_layouts;
@@ -762,4 +865,5 @@ _gdk_keymap_quartz_class_init (GdkKeymapQuartzClass *klass)
   keymap_class->translate_keyboard_state = gdk_quartz_keymap_translate_keyboard_state;
   keymap_class->add_virtual_modifiers = gdk_quartz_keymap_add_virtual_modifiers;
   keymap_class->map_virtual_modifiers = gdk_quartz_keymap_map_virtual_modifiers;
+  keymap_class->get_modifier_mask = gdk_quartz_keymap_get_modifier_mask;
 }