~canonical-dx-team/ubuntu/maverick/gtk+2.0/menuproxy

« back to all changes in this revision

Viewing changes to gdk/quartz/gdkkeys-quartz.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-05-04 12:24:25 UTC
  • mfrom: (1.1.21 upstream)
  • Revision ID: james.westby@ubuntu.com-20070504122425-0m8midgzrp40y8w2
Tags: 2.10.12-1ubuntu1
* Sync with Debian
* New upstream version:
  Fixed bugs:
  - 379414 file chooser warnings when changing path in the entry
  - 418585 GtkFileChooserDefault sizing code is not DPI independent
  - 419568 Crash in search if start with special letter
  - 435062 build dies with icon cache validation
  - 379399 Segfault to call gtk_print_operation_run twice.
  - 387889 cups backend has problems when there are too many printers
  - 418531 invalid read to gtkicontheme.c gtk_icon_theme_lookup_icon...
  - 423916 crash in color scheme code
  - 424042 Segmentation fault while quickly pressing Alt+arrows
  - 415260 Protect against negative indices when setting values in G...
  - 419171 XGetVisualInfo() may not set nxvisuals
  - 128852 Gdk cursors don't look good on win32
  - 344657 Ctrl-H doesn't toggle "Show Hidden Files" setting
  - 345345 PrintOperation::paginate is not emitted for class handler
  - 347567 GtkPrintOperation::end-print is not emitted if it's cance...
  - 369112 gtk_ui_manager_add_ui should accept unnamed separator
  - 392015 Selected menu item invisible on Windows Vista
  - 399253 MS-Windows Theme Bottom Tab placement rendering glitches
  - 399425 gtk_input_dialog_fill_axes() adds child to gtkscrolledwin...
  - 403251 [patch] little memory leak in GtkPrintJob
  - 403267 [patch] memory leak in GtkPageSetupUnixDialog
  - 403470 MS-Windows Theme tab placement other than on top leaks a ...
  - 404506 Windows system fonts that have multi-byte font names cann...
  - 405089 Incorrect window placement for GtkEventBox private window
  - 405515 Minor leak in gtkfilesystemmodel.c
  - 405539 gdk_pixbuf_save() for PNG saver can return FALSE without ...
  - 415681 gdk_window_clear_area includes an extra line and column o...
  - 418219 GtkRecentChooser should apply filter before sorting and c...
  - 418403 Scroll to printer after selecting it from settings
  - 421985 _gtk_print_operation_platform_backend_launch_preview
  - 421990 gtk_print_job_get_surface
  - 421993 gtk_print_operation_init
  - 423064 Conditional jump or move depends on uninitialised value(s...
  - 423722 Fix printing header in gtk-demo
  - 424168 gtk_print_operation_run on async preview
  - 425655 Don't install gtk+-unix-print-2.0.pc on non-UNIX platforms
  - 425786 GDK segfaults if XineramaQueryScreens fails
  - 428665 Lpr Backend gets stuck in infinite loop during gtk_enumer...
  - 429902 GtkPrintOperation leaks cairo contextes
  - 431997 First delay of GdkPixbufAnimationIter is wrong
  - 433242 Inconsistent scroll arrow position calculations
  - 433972 Placing gtk.Expander inside a gtk.TextView() changes gtk....
  - 434261 _gtk_toolbar_elide_underscores incorrectly handles some s...
  - 383354 ctrl-L should make 'Location' entry disappear
  - 418673 gtk_recent_manager_add_item
  - 429732 gtk_accel_group_finalize accesses invalid memory
  - 435028 WM_CLIENT_LEADER is wrong on the leader_window
  - 431067 Background of the header window is not updated
  - 338843 add recent files support inside the ui manager
  - 148535 add drop shadow to menus, tooltips, etc. under Windows XP
* debian/control.in:
  - Conflicts on ubuntulooks (<= 0.9.11-1)
* debian/patches/15_default-fallback-icon-theme.patch:
  - patch from Debian, fallback on gnome icon theme

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* gdkkeys-quartz.c
 
2
 *
 
3
 * Copyright (C) 2000 Red Hat, Inc.
 
4
 * Copyright (C) 2005 Imendio AB
 
5
 *
 
6
 * This library is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU Lesser General Public
 
8
 * License as published by the Free Software Foundation; either
 
9
 * version 2 of the License, or (at your option) any later version.
 
10
 *
 
11
 * This library is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
 * Lesser General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU Lesser General Public
 
17
 * License along with this library; if not, write to the
 
18
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
19
 * Boston, MA 02111-1307, USA.
 
20
 */
 
21
/* Some parts of this code come from quartzKeyboard.c,
 
22
 * from the Apple X11 Server.
 
23
 *
 
24
 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
 
25
 *
 
26
 *  Permission is hereby granted, free of charge, to any person
 
27
 *  obtaining a copy of this software and associated documentation files
 
28
 *  (the "Software"), to deal in the Software without restriction,
 
29
 *  including without limitation the rights to use, copy, modify, merge,
 
30
 *  publish, distribute, sublicense, and/or sell copies of the Software,
 
31
 *  and to permit persons to whom the Software is furnished to do so,
 
32
 *  subject to the following conditions:
 
33
 *
 
34
 *  The above copyright notice and this permission notice shall be
 
35
 *  included in all copies or substantial portions of the Software.
 
36
 *
 
37
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
38
 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
39
 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 
40
 *  NONINFRINGEMENT.  IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
 
41
 *  HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 
42
 *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
43
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 
44
 *  DEALINGS IN THE SOFTWARE.
 
45
 *
 
46
 *  Except as contained in this notice, the name(s) of the above
 
47
 *  copyright holders shall not be used in advertising or otherwise to
 
48
 *  promote the sale, use or other dealings in this Software without
 
49
 *  prior written authorization.
 
50
 */
 
51
 
 
52
#include <config.h>
 
53
 
 
54
#include <Carbon/Carbon.h>
 
55
#include <AppKit/NSEvent.h>
 
56
#include "gdk.h"
 
57
#include "gdkkeysyms.h"
 
58
 
 
59
#define NUM_KEYCODES 128
 
60
#define KEYVALS_PER_KEYCODE 4
 
61
 
 
62
static GdkKeymap *default_keymap = NULL;
 
63
 
 
64
static KeyboardLayoutRef current_layout = NULL;
 
65
 
 
66
/* This is a table of all keyvals. Each keycode gets KEYVALS_PER_KEYCODE entries.
 
67
 * TThere is 1 keyval per modifier (Nothing, Shift, Alt, Shift+Alt);
 
68
 */
 
69
static guint *keyval_array = NULL;
 
70
 
 
71
static inline UniChar
 
72
macroman2ucs (unsigned char c)
 
73
{
 
74
  /* Precalculated table mapping MacRoman-128 to Unicode. Generated
 
75
     by creating single element CFStringRefs then extracting the
 
76
     first character. */
 
77
  
 
78
  static const unsigned short table[128] = {
 
79
    0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1,
 
80
    0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8,
 
81
    0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3,
 
82
    0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc,
 
83
    0x2020, 0xb0, 0xa2, 0xa3, 0xa7, 0x2022, 0xb6, 0xdf,
 
84
    0xae, 0xa9, 0x2122, 0xb4, 0xa8, 0x2260, 0xc6, 0xd8,
 
85
    0x221e, 0xb1, 0x2264, 0x2265, 0xa5, 0xb5, 0x2202, 0x2211,
 
86
    0x220f, 0x3c0, 0x222b, 0xaa, 0xba, 0x3a9, 0xe6, 0xf8,
 
87
    0xbf, 0xa1, 0xac, 0x221a, 0x192, 0x2248, 0x2206, 0xab,
 
88
    0xbb, 0x2026, 0xa0, 0xc0, 0xc3, 0xd5, 0x152, 0x153,
 
89
    0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xf7, 0x25ca,
 
90
    0xff, 0x178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02,
 
91
    0x2021, 0xb7, 0x201a, 0x201e, 0x2030, 0xc2, 0xca, 0xc1,
 
92
    0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4,
 
93
    0xf8ff, 0xd2, 0xda, 0xdb, 0xd9, 0x131, 0x2c6, 0x2dc,
 
94
    0xaf, 0x2d8, 0x2d9, 0x2da, 0xb8, 0x2dd, 0x2db, 0x2c7
 
95
  };
 
96
 
 
97
  if (c < 128)
 
98
    return c;
 
99
  else
 
100
    return table[c - 128];
 
101
}
 
102
 
 
103
const static struct {
 
104
  guint keycode;
 
105
  guint keyval;
 
106
  unsigned int modmask; /* So we can tell when a mod key is pressed/released */
 
107
} known_keys[] = {
 
108
  {  54, GDK_Meta_R,    NSCommandKeyMask },
 
109
  {  55, GDK_Meta_L,    NSCommandKeyMask },
 
110
  {  56, GDK_Shift_L,   NSShiftKeyMask },
 
111
  {  57, GDK_Caps_Lock, NSAlphaShiftKeyMask },
 
112
  {  58, GDK_Alt_L,     NSAlternateKeyMask },
 
113
  {  59, GDK_Control_L, NSControlKeyMask },
 
114
  {  60, GDK_Shift_R,   NSShiftKeyMask },
 
115
  {  61, GDK_Alt_R,     NSAlternateKeyMask },
 
116
  {  62, GDK_Control_R, NSControlKeyMask },
 
117
  { 122, GDK_F1, 0 },
 
118
  { 120, GDK_F2, 0 },
 
119
  {  99, GDK_F3, 0 },
 
120
  { 118, GDK_F4, 0 },
 
121
  {  96, GDK_F5, 0 },
 
122
  {  97, GDK_F6, 0 },
 
123
  {  98, GDK_F7, 0 },
 
124
  { 100, GDK_F8, 0 },
 
125
  { 101, GDK_F9, 0 },
 
126
  { 109, GDK_F10, 0 },
 
127
  { 103, GDK_F11, 0 },
 
128
  { 111, GDK_F12, 0 },
 
129
  { 105, GDK_F13, 0 },
 
130
  { 107, GDK_F14, 0 },
 
131
  { 113, GDK_F15, 0 }
 
132
};
 
133
 
 
134
const static struct {
 
135
  guint keycode;
 
136
  guint normal_keyval, keypad_keyval;
 
137
} known_numeric_keys[] = {
 
138
  { 65, GDK_period, GDK_KP_Decimal },
 
139
  { 67, GDK_asterisk, GDK_KP_Multiply },
 
140
  { 69, GDK_plus, GDK_KP_Add },
 
141
  { 75, GDK_slash, GDK_KP_Divide },
 
142
  { 76, 0x01000003, GDK_KP_Enter },
 
143
  { 78, GDK_minus, GDK_KP_Subtract },
 
144
  { 81, GDK_equal, GDK_KP_Equal },
 
145
  { 82, GDK_0, GDK_KP_0 },
 
146
  { 83, GDK_1, GDK_KP_1 },
 
147
  { 84, GDK_2, GDK_KP_2 },
 
148
  { 85, GDK_3, GDK_KP_3 },
 
149
  { 86, GDK_4, GDK_KP_4 },
 
150
  { 87, GDK_5, GDK_KP_5 },
 
151
  { 88, GDK_6, GDK_KP_6 },
 
152
  { 89, GDK_7, GDK_KP_7 },
 
153
  { 91, GDK_8, GDK_KP_8 },
 
154
  { 92, GDK_9, GDK_KP_9 }
 
155
};
 
156
 
 
157
/* These values aren't covered by gdk_unicode_to_keyval */
 
158
const static struct {
 
159
  gunichar ucs_value;
 
160
  guint keyval;
 
161
} special_ucs_table [] = {
 
162
  { 0x0001, GDK_Home },
 
163
  { 0x0003, GDK_Return },
 
164
  { 0x0004, GDK_End },
 
165
  { 0x0008, GDK_BackSpace },
 
166
  { 0x0009, GDK_Tab },
 
167
  { 0x000b, GDK_Page_Up },
 
168
  { 0x000c, GDK_Page_Down },
 
169
  { 0x000d, GDK_Return },
 
170
  { 0x001b, GDK_Escape },
 
171
  { 0x001c, GDK_Left },
 
172
  { 0x001d, GDK_Right },
 
173
  { 0x001e, GDK_Up },
 
174
  { 0x001f, GDK_Down },
 
175
  { 0x007f, GDK_Delete }
 
176
};
 
177
 
 
178
static void
 
179
maybe_update_keymap (void)
 
180
{
 
181
  KeyboardLayoutRef new_layout;
 
182
 
 
183
  KLGetCurrentKeyboardLayout (&new_layout);
 
184
 
 
185
  if (new_layout != current_layout)
 
186
    {
 
187
      guint *p;
 
188
      int i;
 
189
 
 
190
      KeyboardLayoutKind layout_kind;
 
191
      
 
192
      g_free (keyval_array);
 
193
      keyval_array = g_new0 (guint, NUM_KEYCODES * KEYVALS_PER_KEYCODE);
 
194
 
 
195
      /* Get the layout kind */
 
196
      KLGetKeyboardLayoutProperty (new_layout, kKLKind, (const void **)&layout_kind);
 
197
 
 
198
      /* 8-bit-only keyabord layout */
 
199
      if (layout_kind == kKLKCHRKind)
 
200
        { 
 
201
          const void *chr_data;
 
202
          
 
203
          /* Get chr data */
 
204
          KLGetKeyboardLayoutProperty (new_layout, kKLKCHRData, (const void **)&chr_data);
 
205
          
 
206
          for (i = 0; i < NUM_KEYCODES; i++) 
 
207
            {
 
208
              int j;
 
209
              UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey|optionKey};
 
210
 
 
211
              p = keyval_array + i * KEYVALS_PER_KEYCODE;
 
212
              
 
213
              for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
 
214
                {
 
215
                  UInt32 c, state = 0;
 
216
                  UInt16 key_code;
 
217
                  UniChar uc;
 
218
                  
 
219
                  key_code = modifiers[j]|i;
 
220
                  c = KeyTranslate (chr_data, key_code, &state);
 
221
 
 
222
                  if (state != 0)
 
223
                    {
 
224
                      UInt32 state2 = 0;
 
225
                      c = KeyTranslate (chr_data, key_code | 128, &state2);
 
226
                    }
 
227
 
 
228
                  if (c != 0 && c != 0x10)
 
229
                    {
 
230
                      int k;
 
231
                      gboolean found = FALSE;
 
232
 
 
233
                      /* FIXME: some keyboard layouts (e.g. Russian) use
 
234
                       * a different 8-bit character set. We should
 
235
                       * check for this. Not a serious problem, because
 
236
                       * most (all?) of these layouts also have a
 
237
                       * uchr version. 
 
238
                       */
 
239
                      uc = macroman2ucs (c);
 
240
 
 
241
                      for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++) 
 
242
                        {
 
243
                          if (special_ucs_table[k].ucs_value == uc)
 
244
                            {
 
245
                              p[j] = special_ucs_table[k].keyval;
 
246
                              found = TRUE;
 
247
                              break;
 
248
                            }
 
249
                        }
 
250
                      
 
251
                      if (!found)
 
252
                        p[j] = gdk_unicode_to_keyval (uc);
 
253
                    }
 
254
                }
 
255
              
 
256
              if (p[3] == p[2])
 
257
                p[3] = 0;
 
258
              if (p[2] == p[1])
 
259
                p[2] = 0;
 
260
              if (p[1] == p[0])
 
261
                p[1] = 0;
 
262
              if (p[0] == p[2] && 
 
263
                  p[1] == p[3])
 
264
                p[2] = p[3] = 0;
 
265
            }
 
266
        }
 
267
      /* unicode keyboard layout */
 
268
      else if (layout_kind == kKLKCHRuchrKind || layout_kind == kKLuchrKind)
 
269
        { 
 
270
          const void *chr_data;
 
271
          
 
272
          /* Get chr data */
 
273
          KLGetKeyboardLayoutProperty (new_layout, kKLuchrData, (const void **)&chr_data);
 
274
          
 
275
          for (i = 0; i < NUM_KEYCODES; i++) 
 
276
            {
 
277
              int j;
 
278
              UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey|optionKey};
 
279
              UniChar chars[4];
 
280
              UniCharCount nChars;
 
281
 
 
282
              p = keyval_array + i * KEYVALS_PER_KEYCODE;
 
283
 
 
284
              for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
 
285
                {
 
286
                  UInt32 state = 0;
 
287
                  OSStatus err;
 
288
                  UInt16 key_code;
 
289
                  UniChar uc;
 
290
                  
 
291
                  key_code = modifiers[j]|i;
 
292
                  err = UCKeyTranslate (chr_data, i, kUCKeyActionDown,
 
293
                                        (modifiers[j] >> 8) & 0xFF,
 
294
                                        LMGetKbdType(),
 
295
                                        kUCKeyTranslateNoDeadKeysMask,
 
296
                                        &state, 4, &nChars, chars);
 
297
 
 
298
 
 
299
                  /* FIXME: Theoretically, we can get multiple UTF-16 values;
 
300
                   * we should convert them to proper unicode and figure
 
301
                   * out whether there are really keyboard layouts that
 
302
                   * give us more than one character for one keypress. */
 
303
                  if (err == noErr && nChars == 1)
 
304
                    {
 
305
                      int k;
 
306
                      gboolean found = FALSE;
 
307
                      
 
308
                      uc = chars[0];
 
309
 
 
310
                      for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++) 
 
311
                        {
 
312
                          if (special_ucs_table[k].ucs_value == uc)
 
313
                            {
 
314
                              p[j] = special_ucs_table[k].keyval;
 
315
                              found = TRUE;
 
316
                              break;
 
317
                            }
 
318
                        }
 
319
                      
 
320
                      if (!found)
 
321
                        p[j] = gdk_unicode_to_keyval (uc);
 
322
                    }
 
323
                }
 
324
              
 
325
              if (p[3] == p[2])
 
326
                p[3] = 0;
 
327
              if (p[2] == p[1])
 
328
                p[2] = 0;
 
329
              if (p[1] == p[0])
 
330
                p[1] = 0;
 
331
              if (p[0] == p[2] && 
 
332
                  p[1] == p[3])
 
333
                p[2] = p[3] = 0;
 
334
            }
 
335
        }
 
336
      else
 
337
        {
 
338
          g_error ("unknown type of keyboard layout (neither KCHR nor uchr)"
 
339
                   " - not supported right now");
 
340
        }
 
341
 
 
342
      for (i = 0; i < G_N_ELEMENTS (known_keys); i++)
 
343
        {
 
344
          p = keyval_array + known_keys[i].keycode * KEYVALS_PER_KEYCODE;
 
345
 
 
346
          if (p[0] == 0 && p[1] == 0 && 
 
347
              p[2] == 0 && p[3] == 0)
 
348
            p[0] = known_keys[i].keyval;
 
349
        }
 
350
 
 
351
      for (i = 0; i < G_N_ELEMENTS (known_numeric_keys); i++)
 
352
        {
 
353
          p = keyval_array + known_numeric_keys[i].keycode * KEYVALS_PER_KEYCODE;
 
354
 
 
355
          if (p[0] == known_numeric_keys[i].normal_keyval);
 
356
              p[0] = known_numeric_keys[i].keypad_keyval;
 
357
        }
 
358
      
 
359
      if (current_layout)
 
360
        g_signal_emit_by_name (default_keymap, "keys_changed");
 
361
 
 
362
      current_layout = new_layout;
 
363
    }
 
364
}
 
365
 
 
366
GdkKeymap *
 
367
gdk_keymap_get_for_display (GdkDisplay *display)
 
368
{
 
369
  g_return_val_if_fail (display == gdk_display_get_default (), NULL);
 
370
 
 
371
  if (default_keymap == NULL)
 
372
    default_keymap = g_object_new (gdk_keymap_get_type (), NULL);
 
373
 
 
374
  return default_keymap;
 
375
}
 
376
 
 
377
PangoDirection
 
378
gdk_keymap_get_direction (GdkKeymap *keymap)
 
379
{
 
380
  return PANGO_DIRECTION_NEUTRAL;
 
381
}
 
382
 
 
383
gboolean
 
384
gdk_keymap_get_entries_for_keyval (GdkKeymap     *keymap,
 
385
                                   guint          keyval,
 
386
                                   GdkKeymapKey **keys,
 
387
                                   gint          *n_keys)
 
388
{
 
389
  GArray *keys_array;
 
390
  int i;
 
391
 
 
392
  g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
 
393
  g_return_val_if_fail (keys != NULL, FALSE);
 
394
  g_return_val_if_fail (n_keys != NULL, FALSE);
 
395
  g_return_val_if_fail (keyval != 0, FALSE);
 
396
 
 
397
  maybe_update_keymap ();
 
398
 
 
399
  *n_keys = 0;
 
400
  keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
 
401
 
 
402
  for (i = 0; i < NUM_KEYCODES * KEYVALS_PER_KEYCODE; i++)
 
403
    {
 
404
      GdkKeymapKey key;
 
405
 
 
406
      if (keyval_array[i] != keyval)
 
407
        continue;
 
408
 
 
409
      (*n_keys)++;
 
410
 
 
411
      key.keycode = i / KEYVALS_PER_KEYCODE;
 
412
      key.group = 0;
 
413
      key.level = i % KEYVALS_PER_KEYCODE;
 
414
 
 
415
      g_array_append_val (keys_array, key);
 
416
    }
 
417
 
 
418
  *keys = (GdkKeymapKey *)g_array_free (keys_array, FALSE);
 
419
  
 
420
  return *n_keys > 0;;
 
421
}
 
422
 
 
423
gboolean
 
424
gdk_keymap_get_entries_for_keycode (GdkKeymap     *keymap,
 
425
                                    guint          hardware_keycode,
 
426
                                    GdkKeymapKey **keys,
 
427
                                    guint        **keyvals,
 
428
                                    gint          *n_entries)
 
429
{
 
430
  GArray *keys_array, *keyvals_array;
 
431
  int i;
 
432
  guint *p;
 
433
 
 
434
  g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
 
435
  g_return_val_if_fail (n_entries != NULL, FALSE);
 
436
 
 
437
  maybe_update_keymap ();
 
438
 
 
439
  *n_entries = 0;
 
440
 
 
441
  if (hardware_keycode > NUM_KEYCODES)
 
442
    return FALSE;
 
443
 
 
444
  if (keys)
 
445
    keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
 
446
  else
 
447
    keys_array = NULL;
 
448
 
 
449
  if (keyvals)
 
450
    keyvals_array = g_array_new (FALSE, FALSE, sizeof (guint));
 
451
  else
 
452
    keyvals_array = NULL;
 
453
 
 
454
  p = keyval_array + hardware_keycode * KEYVALS_PER_KEYCODE;
 
455
  
 
456
  for (i = 0; i < KEYVALS_PER_KEYCODE; i++)
 
457
    {
 
458
      if (!p[i])
 
459
        continue;
 
460
 
 
461
      (*n_entries)++;
 
462
      
 
463
      if (keyvals_array)
 
464
        g_array_append_val (keyvals_array, p[i]);
 
465
 
 
466
      if (keys_array)
 
467
        {
 
468
          GdkKeymapKey key;
 
469
 
 
470
          key.keycode = hardware_keycode;
 
471
          key.group = i / 2;
 
472
          key.level = i % 2;
 
473
 
 
474
          g_array_append_val (keys_array, key);
 
475
        }
 
476
    }
 
477
  
 
478
  if (keys)
 
479
    *keys = (GdkKeymapKey *)g_array_free (keys_array, FALSE);
 
480
 
 
481
  if (keyvals)
 
482
    *keyvals = (guint *)g_array_free (keyvals_array, FALSE);
 
483
 
 
484
  return *n_entries > 0;
 
485
}
 
486
 
 
487
guint
 
488
gdk_keymap_lookup_key (GdkKeymap          *keymap,
 
489
                       const GdkKeymapKey *key)
 
490
{
 
491
  g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), 0);
 
492
  g_return_val_if_fail (key != NULL, 0);
 
493
  g_return_val_if_fail (key->group < 4, 0);
 
494
 
 
495
  /* FIXME: Implement */
 
496
 
 
497
  return 0;
 
498
}
 
499
 
 
500
#define GET_KEYVAL(keycode, group, level) (keyval_array[(keycode * KEYVALS_PER_KEYCODE + group * 2 + level)])
 
501
 
 
502
static guint
 
503
translate_keysym (guint           hardware_keycode,
 
504
                  gint            group,
 
505
                  GdkModifierType state,
 
506
                  gint           *effective_group,
 
507
                  gint           *effective_level)
 
508
{
 
509
  gint level;
 
510
  guint tmp_keyval;
 
511
 
 
512
  level = (state & GDK_SHIFT_MASK) ? 1 : 0;
 
513
 
 
514
  if (!(GET_KEYVAL (hardware_keycode, group, 0) || GET_KEYVAL (hardware_keycode, group, 1)) &&
 
515
      (GET_KEYVAL (hardware_keycode, 0, 0) || GET_KEYVAL (hardware_keycode, 0, 1)))
 
516
    group = 0;
 
517
 
 
518
  if (!GET_KEYVAL (hardware_keycode, group, level) &&
 
519
      GET_KEYVAL (hardware_keycode, group, 0))
 
520
    level = 0;
 
521
 
 
522
  tmp_keyval = GET_KEYVAL (hardware_keycode, group, level);
 
523
 
 
524
  if (state & GDK_LOCK_MASK)
 
525
    {
 
526
      guint upper = gdk_keyval_to_upper (tmp_keyval);
 
527
        if (upper != tmp_keyval)
 
528
          tmp_keyval = upper;
 
529
    }
 
530
 
 
531
  return tmp_keyval;
 
532
}
 
533
 
 
534
gboolean
 
535
gdk_keymap_translate_keyboard_state (GdkKeymap       *keymap,
 
536
                                     guint            hardware_keycode,
 
537
                                     GdkModifierType  state,
 
538
                                     gint             group,
 
539
                                     guint           *keyval,
 
540
                                     gint            *effective_group,
 
541
                                     gint            *level,
 
542
                                     GdkModifierType *consumed_modifiers)
 
543
{
 
544
  guint tmp_keyval;
 
545
  GdkModifierType bit;
 
546
  guint tmp_modifiers = 0;
 
547
 
 
548
  g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
 
549
  g_return_val_if_fail (group >= 0 && group <= 1, FALSE);
 
550
  
 
551
  maybe_update_keymap ();
 
552
 
 
553
  if (keyval)
 
554
    *keyval = 0;
 
555
  if (effective_group)
 
556
    *effective_group = 0;
 
557
  if (level)
 
558
    *level = 0;
 
559
  if (consumed_modifiers)
 
560
    *consumed_modifiers = 0;
 
561
 
 
562
  if (hardware_keycode < 0 || hardware_keycode >= NUM_KEYCODES)
 
563
    return FALSE;
 
564
  
 
565
  /* Check if shift or capslock modify the keyval */
 
566
  for (bit = GDK_SHIFT_MASK; bit < GDK_CONTROL_MASK; bit <<= 1)
 
567
    {
 
568
      if (translate_keysym (hardware_keycode, group, state & ~bit, NULL, NULL) !=
 
569
          translate_keysym (hardware_keycode, group, state | bit, NULL, NULL))
 
570
        tmp_modifiers |= bit;
 
571
    }
 
572
 
 
573
  tmp_keyval = translate_keysym (hardware_keycode, group, state, level, effective_group);
 
574
 
 
575
  if (consumed_modifiers)
 
576
    *consumed_modifiers = tmp_modifiers;
 
577
 
 
578
  if (keyval)
 
579
    *keyval = tmp_keyval; 
 
580
 
 
581
  return TRUE;
 
582
}
 
583
 
 
584
/* What sort of key event is this? Returns one of
 
585
 * GDK_KEY_PRESS, GDK_KEY_RELEASE, GDK_NOTHING (should be ignored)
 
586
 */
 
587
GdkEventType
 
588
_gdk_quartz_key_event_type (NSEvent *event)
 
589
{
 
590
  unsigned short keycode;
 
591
  unsigned int flags;
 
592
  int i;
 
593
  
 
594
  switch ([event type])
 
595
    {
 
596
    case NSKeyDown:
 
597
      return GDK_KEY_PRESS;
 
598
    case NSKeyUp:
 
599
      return GDK_KEY_RELEASE;
 
600
    case NSFlagsChanged:
 
601
      break;
 
602
    default:
 
603
      g_assert_not_reached ();
 
604
    }
 
605
  
 
606
  /* For flags-changed events, we have to find the special key that caused the
 
607
   * event, and see if it's in the modifier mask. */
 
608
  keycode = [event keyCode];
 
609
  flags = [event modifierFlags];
 
610
  
 
611
  for (i = 0; i < G_N_ELEMENTS (known_keys); i++)
 
612
    {
 
613
      if (known_keys[i].keycode == keycode)
 
614
        {
 
615
          if (flags & known_keys[i].modmask)
 
616
            return GDK_KEY_PRESS;
 
617
          else
 
618
            return GDK_KEY_RELEASE;
 
619
        }
 
620
    }
 
621
  
 
622
  /* Some keypresses (eg: Expose' activations) seem to trigger flags-changed
 
623
   * events for no good reason. Ignore them! */
 
624
  return GDK_NOTHING;
 
625
}
 
626
 
 
627
gboolean
 
628
_gdk_quartz_key_is_modifier (guint keycode)
 
629
{
 
630
  gint i;
 
631
  
 
632
  for (i = 0; i < G_N_ELEMENTS (known_keys); i++)
 
633
    {
 
634
      if (known_keys[i].modmask == 0)
 
635
        break;
 
636
 
 
637
      if (known_keys[i].keycode == keycode)
 
638
        return TRUE;
 
639
    }
 
640
 
 
641
  return FALSE;
 
642
}