1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 #include <gdk/gdkinternals.h>
22 #include "gdkkeysyms.h"
23 #include "gdkprivate-fb.h"
28 #include <sys/ioctl.h>
32 typedef struct _GdkFBKeyboard GdkFBKeyboard;
33 typedef struct _GdkFBKeyboardDevice GdkFBKeyboardDevice;
35 struct _GdkFBKeyboard {
41 gboolean caps_lock : 1;
46 GdkFBKeyboardDevice *dev;
49 struct _GdkFBKeyboardDevice {
51 gboolean (*open)(GdkFBKeyboard *kb);
52 void (*close)(GdkFBKeyboard *kb);
54 guint (*lookup_key) (GdkFBKeyboard *kb,
55 const GdkKeymapKey *key);
56 gboolean (*translate_keyboard_state) (GdkFBKeyboard *kb,
57 guint hardware_keycode,
58 GdkModifierType state,
61 gint *effective_group,
63 GdkModifierType *unused_modifiers);
64 gboolean (*get_entries_for_keyval) (GdkFBKeyboard *kb,
68 gboolean (*get_entries_for_keycode) (GdkFBKeyboard *kb,
69 guint hardware_keycode,
77 static GdkFBKeyboard *gdk_fb_keyboard = NULL;
78 static GdkKeymap *default_keymap = NULL;
80 static gboolean xlate_open (GdkFBKeyboard *kb);
81 static void xlate_close (GdkFBKeyboard *kb);
82 static guint xlate_lookup (GdkFBKeyboard *kb,
83 const GdkKeymapKey *key);
84 static gboolean xlate_translate (GdkFBKeyboard *kb,
85 guint hardware_keycode,
86 GdkModifierType state,
89 gint *effective_group,
91 GdkModifierType *unused_modifiers);
92 static gboolean xlate_get_for_keyval (GdkFBKeyboard *kb,
96 static gboolean xlate_get_for_keycode (GdkFBKeyboard *kb,
97 guint hardware_keycode,
102 static gboolean raw_open (GdkFBKeyboard *kb);
103 static void raw_close (GdkFBKeyboard *kb);
104 static guint raw_lookup (GdkFBKeyboard *kb,
105 const GdkKeymapKey *key);
106 static gboolean raw_translate (GdkFBKeyboard *kb,
107 guint hardware_keycode,
108 GdkModifierType state,
111 gint *effective_group,
113 GdkModifierType *unused_modifiers);
114 static gboolean raw_get_for_keyval (GdkFBKeyboard *kb,
118 static gboolean raw_get_for_keycode (GdkFBKeyboard *kb,
119 guint hardware_keycode,
125 static GdkFBKeyboardDevice keyb_devs[] =
133 xlate_get_for_keyval,
134 xlate_get_for_keycode
148 gdk_keymap_get_default (void)
150 if (default_keymap == NULL)
151 default_keymap = g_object_new (gdk_keymap_get_type (), NULL);
153 return default_keymap;
157 gdk_keymap_get_direction (GdkKeymap *keymap)
159 /* FIXME: Only supports LTR keymaps at the moment */
160 return PANGO_DIRECTION_LTR;
164 gdk_fb_keyboard_modifiers ()
166 return gdk_fb_keyboard->modifier_state;
170 gdk_fb_keyboard_open (void)
173 GdkFBKeyboardDevice *device;
177 keyb = g_new0 (GdkFBKeyboard, 1);
180 keyb_type = getenv ("GDK_KEYBOARD_TYPE");
184 for (i = 0; i < G_N_ELEMENTS(keyb_devs); i++)
186 if (g_strcasecmp(keyb_type, keyb_devs[i].name)==0)
190 if (i == G_N_ELEMENTS(keyb_devs))
192 g_warning ("No keyboard driver of type %s found", keyb_type);
196 device = &keyb_devs[i];
200 if (!device->open(keyb))
202 g_warning ("Keyboard driver open failed");
207 gdk_fb_keyboard = keyb;
213 gdk_fb_keyboard_close (void)
215 gdk_fb_keyboard->dev->close(gdk_fb_keyboard);
216 g_free (gdk_fb_keyboard);
221 * gdk_keymap_get_entries_for_keyval:
222 * @keymap: a #GdkKeymap, or %NULL to use the default keymap
223 * @keyval: a keyval, such as %GDK_a, %GDK_Up, %GDK_Return, etc.
224 * @keys: return location for an array of #GdkKeymapKey
225 * @n_keys: return location for number of elements in returned array
227 * Obtains a list of keycode/group/level combinations that will
228 * generate @keyval. Groups and levels are two kinds of keyboard mode;
229 * in general, the level determines whether the top or bottom symbol
230 * on a key is used, and the group determines whether the left or
231 * right symbol is used. On US keyboards, the shift key changes the
232 * keyboard level, and there are no groups. A group switch key might
233 * convert a keyboard between Hebrew to English modes, for example.
234 * #GdkEventKey contains a %group field that indicates the active
235 * keyboard group. The level is computed from the modifier mask.
236 * The returned array should be freed
239 * Return value: %TRUE if keys were found and returned
242 gdk_keymap_get_entries_for_keyval (GdkKeymap *keymap,
247 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
248 g_return_val_if_fail (keys != NULL, FALSE);
249 g_return_val_if_fail (n_keys != NULL, FALSE);
250 g_return_val_if_fail (keyval != 0, FALSE);
252 return gdk_fb_keyboard->dev->get_entries_for_keyval (gdk_fb_keyboard,
259 * gdk_keymap_get_entries_for_keycode:
260 * @keymap: a #GdkKeymap or %NULL to use the default keymap
261 * @hardware_keycode: a keycode
262 * @keys: return location for array of #GdkKeymapKey, or NULL
263 * @keyvals: return location for array of keyvals, or NULL
264 * @n_entries: length of @keys and @keyvals
266 * Returns the keyvals bound to @hardware_keycode.
267 * The Nth #GdkKeymapKey in @keys is bound to the Nth
268 * keyval in @keyvals. Free the returned arrays with g_free().
269 * When a keycode is pressed by the user, the keyval from
270 * this list of entries is selected by considering the effective
271 * keyboard group and level. See gdk_keymap_translate_keyboard_state().
273 * Returns: %TRUE if there were any entries
276 gdk_keymap_get_entries_for_keycode (GdkKeymap *keymap,
277 guint hardware_keycode,
282 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
283 g_return_val_if_fail (n_entries != NULL, FALSE);
285 return gdk_fb_keyboard->dev->get_entries_for_keycode (gdk_fb_keyboard,
294 * gdk_keymap_lookup_key:
295 * @keymap: a #GdkKeymap or %NULL to use the default keymap
296 * @key: a #GdkKeymapKey with keycode, group, and level initialized
298 * Looks up the keyval mapped to a keycode/group/level triplet.
299 * If no keyval is bound to @key, returns 0. For normal user input,
300 * you want to use gdk_keymap_translate_keyboard_state() instead of
301 * this function, since the effective group/level may not be
302 * the same as the current keyboard state.
304 * Return value: a keyval, or 0 if none was mapped to the given @key
307 gdk_keymap_lookup_key (GdkKeymap *keymap,
308 const GdkKeymapKey *key)
310 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), 0);
311 g_return_val_if_fail (key != NULL, 0);
312 g_return_val_if_fail (key->group < 4, 0);
314 return gdk_fb_keyboard->dev->lookup_key (gdk_fb_keyboard, key);
319 * gdk_keymap_translate_keyboard_state:
320 * @keymap: a #GdkKeymap, or %NULL to use the default
321 * @hardware_keycode: a keycode
322 * @state: a modifier state
323 * @group: active keyboard group
324 * @keyval: return location for keyval
325 * @effective_group: return location for effective group
326 * @level: return location for level
327 * @unused_modifiers: return location for modifiers that didn't affect the group or level
330 * Translates the contents of a #GdkEventKey into a keyval, effective
331 * group, and level. Modifiers that didn't affect the translation and
332 * are thus available for application use are returned in
333 * @unused_modifiers. See gdk_keyval_get_keys() for an explanation of
334 * groups and levels. The @effective_group is the group that was
335 * actually used for the translation; some keys such as Enter are not
336 * affected by the active keyboard group. The @level is derived from
337 * @state. For convenience, #GdkEventKey already contains the translated
338 * keyval, so this function isn't as useful as you might think.
340 * Return value: %TRUE if there was a keyval bound to the keycode/state/group
343 gdk_keymap_translate_keyboard_state (GdkKeymap *keymap,
344 guint hardware_keycode,
345 GdkModifierType state,
348 gint *effective_group,
350 GdkModifierType *unused_modifiers)
352 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
353 g_return_val_if_fail (group < 4, FALSE);
355 return gdk_fb_keyboard->dev->translate_keyboard_state (gdk_fb_keyboard,
366 gdk_fb_handle_key (guint hw_keycode,
368 guint modifier_state,
377 /* handle some magic keys */
379 (modifier_state & (GDK_CONTROL_MASK|GDK_MOD1_MASK)))
381 if (keyval == GDK_BackSpace)
383 ioctl (gdk_display->tty_fd, KDSKBMODE, K_XLATE);
387 if (keyval == GDK_Return)
388 gdk_fb_redraw_all ();
391 win = gdk_fb_keyboard_event_window (gdk_fb_window_find_focus (),
392 key_up ? GDK_KEY_RELEASE : GDK_KEY_PRESS);
395 event = gdk_event_make (win,
396 key_up ? GDK_KEY_RELEASE : GDK_KEY_PRESS,
399 event->key.state = modifier_state;
400 event->key.keyval = keyval;
401 event->key.string = string;
402 event->key.length = string_length;
403 event->key.hardware_keycode = hw_keycode;
404 event->key.group = group;
410 /******************************************************
411 ********* Device specific keyboard code **************
412 ******************************************************/
415 /* XLATE keyboard driver */
423 {"\x5b\x41", GDK_F1},
424 {"\x5b\x42", GDK_F2},
425 {"\x5b\x43", GDK_F3},
426 {"\x5b\x44", GDK_F4},
427 {"\x5b\x45", GDK_F5},
428 {"\x31\x37\x7e", GDK_F6},
429 {"\x31\x38\x7e", GDK_F7},
430 {"\x31\x39\x7e", GDK_F8},
431 {"\x32\x30\x7e", GDK_F9},
432 {"\x32\x31\x7e", GDK_F10},
433 {"\x32\x33\x7e", GDK_F11},
434 {"\x32\x34\x7e", GDK_F12},
436 {"\x32\x35\x7e", GDK_F1, GDK_SHIFT_MASK},
437 {"\x32\x36\x7e", GDK_F2, GDK_SHIFT_MASK},
438 {"\x32\x38\x7e", GDK_F3, GDK_SHIFT_MASK},
439 {"\x32\x39\x7e", GDK_F4, GDK_SHIFT_MASK},
440 {"\x33\x31\x7e", GDK_F5, GDK_SHIFT_MASK},
441 {"\x33\x32\x7e", GDK_F6, GDK_SHIFT_MASK},
442 {"\x33\x33\x7e", GDK_F7, GDK_SHIFT_MASK},
443 {"\x33\x34\x7e", GDK_F8, GDK_SHIFT_MASK},
445 {"\x31\x7e", GDK_Home},
446 {"\x35\x7e", GDK_Page_Up},
447 {"\x34\x7e", GDK_End},
448 {"\x36\x7e", GDK_Page_Down},
449 {"\x32\x7e", GDK_Insert},
450 {"\x33\x7e", GDK_Delete},
465 {'@', GDK_CONTROL_MASK},
466 {'a', GDK_CONTROL_MASK},
467 {'b', GDK_CONTROL_MASK},
468 {'c', GDK_CONTROL_MASK},
469 {'d', GDK_CONTROL_MASK},
470 {'e', GDK_CONTROL_MASK},
471 {'f', GDK_CONTROL_MASK},
472 {'g', GDK_CONTROL_MASK},
473 {'h', GDK_CONTROL_MASK},
475 {'j', GDK_CONTROL_MASK},
476 {'k', GDK_CONTROL_MASK},
477 {'l', GDK_CONTROL_MASK},
479 {'n', GDK_CONTROL_MASK},
480 {'o', GDK_CONTROL_MASK},
482 {'p', GDK_CONTROL_MASK},
483 {'q', GDK_CONTROL_MASK},
484 {'r', GDK_CONTROL_MASK},
485 {'s', GDK_CONTROL_MASK},
486 {'t', GDK_CONTROL_MASK},
487 {'u', GDK_CONTROL_MASK},
488 {'v', GDK_CONTROL_MASK},
489 {'w', GDK_CONTROL_MASK},
490 {'x', GDK_CONTROL_MASK},
491 {'y', GDK_CONTROL_MASK},
492 {'z', GDK_CONTROL_MASK},
494 {'\\', GDK_CONTROL_MASK},
495 {']', GDK_CONTROL_MASK},
496 {'^', GDK_CONTROL_MASK},
497 {'_', GDK_CONTROL_MASK},
739 iscode (char *code, char *str, int str_max)
743 for (i = 0; code[i] && (i < str_max); i++)
745 if (code[i] != str[i])
748 return (code[i] == 0);
752 xlate_io (GIOChannel *gioc,
756 GdkFBKeyboard *keyb = (GdkFBKeyboard *)data;
764 n = read (keyb->fd, buf, sizeof(buf));
766 g_error ("Nothing from keyboard!");
768 for (i = 0; i < n; i++)
772 if ((buf[i] == 27) && (i+1 != n)) /* Escape */
774 /* Esc is not the last char in buffer, interpret as code sequence */
782 for (j=0;j<G_N_ELEMENTS (xlate_codes);j++)
784 if (iscode (xlate_codes[j].str, &buf[i], left))
786 /* Ctrl-Alt Return can't be pressed in the XLATE driver,
787 * use Shift F1 instead */
788 if ((xlate_codes[j].code == GDK_F1) &&
789 (xlate_codes[j].modifier & GDK_SHIFT_MASK))
790 gdk_fb_redraw_all ();
792 if ((xlate_codes[j].code == GDK_F2) &&
793 (xlate_codes[j].modifier & GDK_SHIFT_MASK))
798 gdk_fb_set_rotation (deg);
802 gdk_fb_handle_key (xlate_codes[j].code,
804 xlate_codes[j].modifier,
809 gdk_fb_handle_key (xlate_codes[j].code,
811 xlate_codes[j].modifier,
816 i += strlen (xlate_codes[j].str);
825 modifier |= GDK_MOD1_MASK;
834 keycode = xlate_chars[buf[i]].code;
837 modifier |= xlate_chars[buf[i]].modifier;
842 len = ((keycode < 255) && isprint (keycode)) ? 1 : 0;
843 gdk_fb_handle_key (keycode,
847 (len)?g_strdup(dummy) : NULL,
850 gdk_fb_handle_key (keycode,
854 (len)?g_strdup(dummy) : NULL,
864 xlate_open (GdkFBKeyboard *kb)
866 const char cursoroff_str[] = "\033[?1;0;0c";
869 tcgetattr (gdk_display->tty_fd, &ts);
872 ts.c_lflag &= ~(ICANON|ECHO|ISIG);
874 tcsetattr (gdk_display->tty_fd, TCSAFLUSH, &ts);
876 tcsetpgrp (gdk_display->tty_fd, getpgrp());
878 write (gdk_display->tty_fd, cursoroff_str, strlen (cursoroff_str));
880 ioctl (gdk_display->tty_fd, KDSKBMODE, K_XLATE);
882 kb->fd = gdk_display->tty_fd;
883 kb->io = g_io_channel_unix_new (kb->fd);
884 kb->io_tag = g_io_add_watch (kb->io,
885 G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
893 xlate_close (GdkFBKeyboard *kb)
896 const char cursoron_str[] = "\033c";
898 write (gdk_display->tty_fd, cursoron_str, strlen (cursoron_str));
900 tcgetattr (gdk_display->tty_fd, &ts);
901 ts.c_lflag |= (ICANON|ECHO|ISIG);
902 tcsetattr (gdk_display->tty_fd, TCSAFLUSH, &ts);
904 g_source_remove (kb->io_tag);
905 g_io_channel_unref (kb->io);
906 /* don't close kb->fd, it is the tty from gdk_display */
910 xlate_lookup (GdkFBKeyboard *kb,
911 const GdkKeymapKey *key)
913 g_warning ("xlate_lookup() NIY");
918 xlate_translate (GdkFBKeyboard *kb,
919 guint hardware_keycode,
920 GdkModifierType state,
923 gint *effective_group,
925 GdkModifierType *unused_modifiers)
927 g_warning ("xlate_translate() NIY");
932 xlate_get_for_keyval (GdkFBKeyboard *kb,
937 g_warning ("xlate_get_for_keyval() NIY");
942 xlate_get_for_keycode (GdkFBKeyboard *kb,
943 guint hardware_keycode,
948 g_warning ("xlate_get_for_keycode() NIY");
952 /* Raw keyboard support */
954 static const guint trans_table[256][3] = {
970 {GDK_BackSpace, 0, 0},
987 {GDK_Control_L, 0, 0}, /* mod */
1002 {GDK_Shift_L, 0, 0}, /* mod */
1017 {GDK_Shift_R, 0, 0}, /* mod */
1018 {GDK_KP_Multiply, 0, 0},
1246 raw_io (GIOChannel *gioc,
1250 GdkFBKeyboard *k = data;
1254 n = read (k->fd, buf, sizeof(buf));
1256 g_error("Nothing from keyboard!");
1258 for (i = 0; i < n; i++)
1267 keycode = buf[i] & 0x7F;
1268 key_up = buf[i] & 0x80;
1270 if (keycode > G_N_ELEMENTS (trans_table))
1272 g_warning ("Unknown keycode");
1276 if ( (keycode == 0x1D) /* left Ctrl */
1277 || (keycode == 0x9D) /* right Ctrl */
1278 || (keycode == 0x38) /* left Alt */
1279 || (keycode == 0xB8) /* right Alt */
1280 || (keycode == 0x2A) /* left Shift */
1281 || (keycode == 0x36) /* right Shift */)
1285 case 0x1D: /* Left Ctrl */
1286 case 0x9D: /* Right Ctrl */
1288 k->modifier_state &= ~GDK_CONTROL_MASK;
1290 k->modifier_state |= GDK_CONTROL_MASK;
1292 case 0x38: /* Left Alt */
1293 case 0xB8: /* Right Alt */
1295 k->modifier_state &= ~GDK_MOD1_MASK;
1297 k->modifier_state |= GDK_MOD1_MASK;
1299 case 0x2A: /* Left Shift */
1300 case 0x36: /* Right Shift */
1302 k->modifier_state &= ~GDK_SHIFT_MASK;
1304 k->modifier_state |= GDK_SHIFT_MASK;
1307 continue; /* Don't generate events for modifiers */
1310 if (keycode == 0x3A /* Caps lock */)
1313 k->caps_lock = !k->caps_lock;
1315 ioctl (k->fd, KDSETLED, k->caps_lock ? LED_CAP : 0);
1319 if (trans_table[keycode][0] >= GDK_F1 &&
1320 trans_table[keycode][0] <= GDK_F35 &&
1321 (k->modifier_state & GDK_MOD1_MASK))
1323 if (key_up) /* Only switch on release */
1325 gint vtnum = trans_table[keycode][0] - GDK_F1 + 1;
1327 /* Do the whole funky VT switch thing */
1328 ioctl (gdk_display->console_fd, VT_ACTIVATE, vtnum);
1329 ioctl (gdk_display->console_fd, VT_WAITACTIVE, gdk_display->vt);
1330 gdk_fb_redraw_all ();
1338 if (k->modifier_state & GDK_CONTROL_MASK)
1340 else if (k->modifier_state & GDK_SHIFT_MASK)
1343 keyval = trans_table[keycode][mod--];
1344 } while (!keyval && (mod >= 0));
1346 if (k->caps_lock && (keyval >= 'a') && (keyval <= 'z'))
1347 keyval = toupper (keyval);
1352 len = isprint (keyval) ? 1 : 0;
1356 gdk_fb_handle_key (keycode,
1360 (len)?g_strdup(dummy):NULL,
1369 raw_open (GdkFBKeyboard *kb)
1371 const char cursoroff_str[] = "\033[?1;0;0c";
1374 tcgetattr (gdk_display->tty_fd, &ts);
1377 ts.c_lflag &= ~(ICANON|ECHO|ISIG);
1379 tcsetattr (gdk_display->tty_fd, TCSAFLUSH, &ts);
1381 tcsetpgrp (gdk_display->tty_fd, getpgrp());
1383 write (gdk_display->tty_fd, cursoroff_str, strlen (cursoroff_str));
1385 if (ioctl (gdk_display->tty_fd, KDSKBMODE, K_MEDIUMRAW) < 0)
1387 g_warning ("setting tty to K_MEDIUMRAW failed");
1391 kb->fd = gdk_display->tty_fd;
1392 kb->io = g_io_channel_unix_new (kb->fd);
1393 kb->io_tag = g_io_add_watch (kb->io,
1394 G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
1402 raw_close (GdkFBKeyboard *kb)
1405 const char cursoron_str[] = "\033c";
1407 write (gdk_display->tty_fd, cursoron_str, strlen (cursoron_str));
1409 tcgetattr (gdk_display->tty_fd, &ts);
1410 ts.c_lflag |= (ICANON|ECHO|ISIG);
1411 tcsetattr (gdk_display->tty_fd, TCSAFLUSH, &ts);
1413 ioctl (gdk_display->tty_fd, KDSKBMODE, K_XLATE);
1415 g_source_remove (kb->io_tag);
1416 g_io_channel_unref (kb->io);
1417 /* don't close kb->fd, it is the tty from gdk_display */
1421 raw_lookup (GdkFBKeyboard *kb,
1422 const GdkKeymapKey *key)
1424 g_warning ("raw_lookup() NIY");
1429 raw_translate (GdkFBKeyboard *kb,
1430 guint hardware_keycode,
1431 GdkModifierType state,
1434 gint *effective_group,
1436 GdkModifierType *unused_modifiers)
1438 g_warning ("raw_translate() NIY");
1443 raw_get_for_keyval (GdkFBKeyboard *kb,
1445 GdkKeymapKey **keys,
1448 g_warning ("raw_get_for_keyval() NIY");
1453 raw_get_for_keycode (GdkFBKeyboard *kb,
1454 guint hardware_keycode,
1455 GdkKeymapKey **keys,
1459 g_warning ("raw_get_for_keycode() NIY");