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.
22 #include <gdk/gdkinternals.h>
23 #include "gdkkeysyms.h"
24 #include "gdkprivate-fb.h"
31 #include <sys/ioctl.h>
35 typedef struct _GdkFBKeyboard GdkFBKeyboard;
36 typedef struct _GdkFBKeyboardDevice GdkFBKeyboardDevice;
38 struct _GdkFBKeyboard {
49 GdkFBKeyboardDevice *dev;
52 struct _GdkFBKeyboardDevice {
54 gboolean (*open)(GdkFBKeyboard *kb);
55 void (*close)(GdkFBKeyboard *kb);
57 guint (*lookup_key) (GdkFBKeyboard *kb,
58 const GdkKeymapKey *key);
59 gboolean (*translate_keyboard_state) (GdkFBKeyboard *kb,
60 guint hardware_keycode,
61 GdkModifierType state,
64 gint *effective_group,
66 GdkModifierType *consumed_modifiers);
67 gboolean (*get_entries_for_keyval) (GdkFBKeyboard *kb,
71 gboolean (*get_entries_for_keycode) (GdkFBKeyboard *kb,
72 guint hardware_keycode,
80 static GdkFBKeyboard *gdk_fb_keyboard = NULL;
81 static GdkKeymap *default_keymap = NULL;
83 static gboolean xlate_open (GdkFBKeyboard *kb);
84 static void xlate_close (GdkFBKeyboard *kb);
85 static guint xlate_lookup (GdkFBKeyboard *kb,
86 const GdkKeymapKey *key);
87 static gboolean xlate_translate (GdkFBKeyboard *kb,
88 guint hardware_keycode,
89 GdkModifierType state,
92 gint *effective_group,
94 GdkModifierType *consumed_modifiers);
95 static gboolean xlate_get_for_keyval (GdkFBKeyboard *kb,
99 static gboolean xlate_get_for_keycode (GdkFBKeyboard *kb,
100 guint hardware_keycode,
105 static gboolean raw_open (GdkFBKeyboard *kb);
106 static void raw_close (GdkFBKeyboard *kb);
107 static guint raw_lookup (GdkFBKeyboard *kb,
108 const GdkKeymapKey *key);
109 static gboolean raw_translate (GdkFBKeyboard *kb,
110 guint hardware_keycode,
111 GdkModifierType state,
114 gint *effective_group,
116 GdkModifierType *consumed_modifiers);
117 static gboolean raw_get_for_keyval (GdkFBKeyboard *kb,
121 static gboolean raw_get_for_keycode (GdkFBKeyboard *kb,
122 guint hardware_keycode,
128 static GdkFBKeyboardDevice keyb_devs[] =
136 xlate_get_for_keyval,
137 xlate_get_for_keycode
151 gdk_keymap_get_default_for_display (GdkDisplay *display)
153 if (default_keymap == NULL)
154 default_keymap = g_object_new (gdk_keymap_get_type (), NULL);
156 return default_keymap;
160 gdk_keymap_get_for_display (GdkDisplay *display)
162 return gdk_keymap_get_default_for_display (display);
166 gdk_keymap_get_direction (GdkKeymap *keymap)
168 /* FIXME: Only supports LTR keymaps at the moment */
169 return PANGO_DIRECTION_LTR;
173 gdk_fb_keyboard_modifiers (void)
175 return gdk_fb_keyboard->modifier_state;
179 gdk_fb_keyboard_init (gboolean open_dev)
185 gdk_fb_keyboard = g_new0 (GdkFBKeyboard, 1);
186 keyb = gdk_fb_keyboard;
189 keyb_type = getenv ("GDK_KEYBOARD_TYPE");
194 for (i = 0; i < G_N_ELEMENTS(keyb_devs); i++)
196 if (g_ascii_strcasecmp(keyb_type, keyb_devs[i].name)==0)
200 if (i == G_N_ELEMENTS(keyb_devs))
202 g_warning ("No keyboard driver of type %s found", keyb_type);
206 keyb->dev = &keyb_devs[i];
209 return gdk_fb_keyboard_open ();
215 gdk_fb_keyboard_open (void)
218 GdkFBKeyboardDevice *device;
220 keyb = gdk_fb_keyboard;
223 if (!device->open(keyb))
225 g_warning ("Keyboard driver open failed");
233 gdk_fb_keyboard_close (void)
235 gdk_fb_keyboard->dev->close(gdk_fb_keyboard);
240 gdk_keymap_get_entries_for_keyval (GdkKeymap *keymap,
245 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
246 g_return_val_if_fail (keys != NULL, FALSE);
247 g_return_val_if_fail (n_keys != NULL, FALSE);
248 g_return_val_if_fail (keyval != 0, FALSE);
250 return gdk_fb_keyboard->dev->get_entries_for_keyval (gdk_fb_keyboard,
257 gdk_keymap_get_entries_for_keycode (GdkKeymap *keymap,
258 guint hardware_keycode,
263 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
264 g_return_val_if_fail (n_entries != NULL, FALSE);
266 return gdk_fb_keyboard->dev->get_entries_for_keycode (gdk_fb_keyboard,
275 gdk_keymap_lookup_key (GdkKeymap *keymap,
276 const GdkKeymapKey *key)
278 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), 0);
279 g_return_val_if_fail (key != NULL, 0);
280 g_return_val_if_fail (key->group < 4, 0);
282 return gdk_fb_keyboard->dev->lookup_key (gdk_fb_keyboard, key);
287 gdk_keymap_translate_keyboard_state (GdkKeymap *keymap,
288 guint hardware_keycode,
289 GdkModifierType state,
292 gint *effective_group,
294 GdkModifierType *consumed_modifiers)
296 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
297 g_return_val_if_fail (group < 4, FALSE);
299 return gdk_fb_keyboard->dev->translate_keyboard_state (gdk_fb_keyboard,
310 gdk_fb_handle_key (guint hw_keycode,
312 guint modifier_state,
321 /* handle some magic keys */
323 (modifier_state & GDK_CONTROL_MASK) &&
324 (modifier_state & GDK_MOD1_MASK))
326 if (keyval == GDK_BackSpace)
328 ioctl (gdk_display->tty_fd, KDSKBMODE, K_XLATE);
332 if (keyval == GDK_Return)
333 gdk_fb_redraw_all ();
336 win = gdk_fb_keyboard_event_window (gdk_fb_window_find_focus (),
337 key_up ? GDK_KEY_RELEASE : GDK_KEY_PRESS);
340 event = gdk_event_make (win,
341 key_up ? GDK_KEY_RELEASE : GDK_KEY_PRESS,
344 event->key.state = modifier_state;
345 event->key.keyval = keyval;
346 event->key.string = string;
347 event->key.length = string_length;
348 event->key.hardware_keycode = hw_keycode;
349 event->key.group = group;
355 /******************************************************
356 ********* Device specific keyboard code **************
357 ******************************************************/
360 /* XLATE keyboard driver */
368 {"\x5b\x41", GDK_F1},
369 {"\x5b\x42", GDK_F2},
370 {"\x5b\x43", GDK_F3},
371 {"\x5b\x44", GDK_F4},
372 {"\x5b\x45", GDK_F5},
373 {"\x31\x37\x7e", GDK_F6},
374 {"\x31\x38\x7e", GDK_F7},
375 {"\x31\x39\x7e", GDK_F8},
376 {"\x32\x30\x7e", GDK_F9},
377 {"\x32\x31\x7e", GDK_F10},
378 {"\x32\x33\x7e", GDK_F11},
379 {"\x32\x34\x7e", GDK_F12},
381 {"\x32\x35\x7e", GDK_F1, GDK_SHIFT_MASK},
382 {"\x32\x36\x7e", GDK_F2, GDK_SHIFT_MASK},
383 {"\x32\x38\x7e", GDK_F3, GDK_SHIFT_MASK},
384 {"\x32\x39\x7e", GDK_F4, GDK_SHIFT_MASK},
385 {"\x33\x31\x7e", GDK_F5, GDK_SHIFT_MASK},
386 {"\x33\x32\x7e", GDK_F6, GDK_SHIFT_MASK},
387 {"\x33\x33\x7e", GDK_F7, GDK_SHIFT_MASK},
388 {"\x33\x34\x7e", GDK_F8, GDK_SHIFT_MASK},
390 {"\x31\x7e", GDK_Home},
391 {"\x35\x7e", GDK_Page_Up},
392 {"\x34\x7e", GDK_End},
393 {"\x36\x7e", GDK_Page_Down},
394 {"\x32\x7e", GDK_Insert},
395 {"\x33\x7e", GDK_Delete},
410 {'@', GDK_CONTROL_MASK},
411 {'a', GDK_CONTROL_MASK},
412 {'b', GDK_CONTROL_MASK},
413 {'c', GDK_CONTROL_MASK},
414 {'d', GDK_CONTROL_MASK},
415 {'e', GDK_CONTROL_MASK},
416 {'f', GDK_CONTROL_MASK},
417 {'g', GDK_CONTROL_MASK},
418 {'h', GDK_CONTROL_MASK},
420 {'j', GDK_CONTROL_MASK},
421 {'k', GDK_CONTROL_MASK},
422 {'l', GDK_CONTROL_MASK},
424 {'n', GDK_CONTROL_MASK},
425 {'o', GDK_CONTROL_MASK},
427 {'p', GDK_CONTROL_MASK},
428 {'q', GDK_CONTROL_MASK},
429 {'r', GDK_CONTROL_MASK},
430 {'s', GDK_CONTROL_MASK},
431 {'t', GDK_CONTROL_MASK},
432 {'u', GDK_CONTROL_MASK},
433 {'v', GDK_CONTROL_MASK},
434 {'w', GDK_CONTROL_MASK},
435 {'x', GDK_CONTROL_MASK},
436 {'y', GDK_CONTROL_MASK},
437 {'z', GDK_CONTROL_MASK},
439 {'\\', GDK_CONTROL_MASK},
440 {']', GDK_CONTROL_MASK},
441 {'^', GDK_CONTROL_MASK},
442 {'_', GDK_CONTROL_MASK},
684 iscode (char *code, char *str, int str_max)
688 for (i = 0; code[i] && (i < str_max); i++)
690 if (code[i] != str[i])
693 return (code[i] == 0);
697 xlate_io (GIOChannel *gioc,
701 GdkFBKeyboard *keyb = (GdkFBKeyboard *)data;
709 n = read (keyb->fd, buf, sizeof(buf));
711 g_error ("Nothing from keyboard!");
717 if ((buf[i] == 27) && (i+1 != n)) /* Escape */
719 /* Esc is not the last char in buffer, interpret as code sequence */
727 for (j=0;j<G_N_ELEMENTS (xlate_codes);j++)
729 if (iscode (xlate_codes[j].str, &buf[i], left))
731 /* Ctrl-Alt Return can't be pressed in the XLATE driver,
732 * use Shift F1 instead */
733 if ((xlate_codes[j].code == GDK_F1) &&
734 (xlate_codes[j].modifier & GDK_SHIFT_MASK))
735 gdk_fb_redraw_all ();
737 if ((xlate_codes[j].code == GDK_F2) &&
738 (xlate_codes[j].modifier & GDK_SHIFT_MASK))
743 gdk_fb_set_rotation (deg);
746 if ((xlate_codes[j].code == GDK_F8) &&
747 (xlate_codes[j].modifier & GDK_SHIFT_MASK))
751 gdk_fb_handle_key (xlate_codes[j].code,
753 xlate_codes[j].modifier,
758 gdk_fb_handle_key (xlate_codes[j].code,
760 xlate_codes[j].modifier,
765 i += strlen (xlate_codes[j].str);
774 modifier |= GDK_MOD1_MASK;
783 keycode = xlate_chars[buf[i]].code;
786 modifier |= xlate_chars[buf[i]].modifier;
791 len = ((keycode < 255) && isprint (keycode)) ? 1 : 0;
792 gdk_fb_handle_key (keycode,
796 (len)?g_strdup(dummy) : NULL,
799 gdk_fb_handle_key (keycode,
803 (len)?g_strdup(dummy) : NULL,
813 write_string (gint fd,
816 gsize to_write = strlen (str);
820 gssize count = write (fd, str, to_write);
837 xlate_open (GdkFBKeyboard *kb)
839 const char cursoroff_str[] = "\033[?1;0;0c";
842 tcgetattr (gdk_display->tty_fd, &ts);
845 ts.c_lflag &= ~(ICANON|ECHO|ISIG);
847 tcsetattr (gdk_display->tty_fd, TCSAFLUSH, &ts);
849 tcsetpgrp (gdk_display->tty_fd, getpgrp());
851 write_string (gdk_display->tty_fd, cursoroff_str);
853 ioctl (gdk_display->tty_fd, KDSKBMODE, K_XLATE);
855 kb->fd = gdk_display->tty_fd;
856 kb->io = g_io_channel_unix_new (kb->fd);
857 kb->io_tag = g_io_add_watch (kb->io,
858 G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
866 xlate_close (GdkFBKeyboard *kb)
869 const char cursoron_str[] = "\033c\033[3g\033]R";
871 write_string (gdk_display->tty_fd, cursoron_str);
873 tcgetattr (gdk_display->tty_fd, &ts);
874 ts.c_lflag |= (ICANON|ECHO|ISIG);
875 tcsetattr (gdk_display->tty_fd, TCSAFLUSH, &ts);
877 g_source_remove (kb->io_tag);
878 g_io_channel_unref (kb->io);
880 /* don't close kb->fd, it is the tty from gdk_display */
884 xlate_lookup (GdkFBKeyboard *kb,
885 const GdkKeymapKey *key)
895 xlate_translate (GdkFBKeyboard *kb,
896 guint hardware_keycode,
897 GdkModifierType state,
900 gint *effective_group,
902 GdkModifierType *consumed_modifiers)
905 *keyval = hardware_keycode;
907 *effective_group = 0;
910 if (consumed_modifiers)
911 *consumed_modifiers = 0;
916 xlate_get_for_keyval (GdkFBKeyboard *kb,
922 *keys = g_new (GdkKeymapKey, 1);
923 (*keys)->keycode = keyval;
930 xlate_get_for_keycode (GdkFBKeyboard *kb,
931 guint hardware_keycode,
938 *keys = g_new (GdkKeymapKey, 1);
939 (*keys)->keycode = hardware_keycode;
945 *keyvals = g_new (guint, 1);
946 **keyvals = hardware_keycode;
954 /* Raw keyboard support */
956 static const guint trans_table[256][3] = {
972 {GDK_BackSpace, 0, 0},
989 {GDK_Control_L, 0, 0}, /* mod */
1004 {GDK_Shift_L, 0, 0}, /* mod */
1019 {GDK_Shift_R, 0, 0}, /* mod */
1020 {GDK_KP_Multiply, 0, 0},
1075 {GDK_Page_Up, 0, 0},
1080 {GDK_Page_Down, 0, 0},
1248 raw_io (GIOChannel *gioc,
1252 GdkFBKeyboard *k = data;
1256 n = read (k->fd, buf, sizeof(buf));
1258 g_error("Nothing from keyboard!");
1260 for (i = 0; i < n; i++)
1269 keycode = buf[i] & 0x7F;
1270 key_up = buf[i] & 0x80;
1272 if (keycode > G_N_ELEMENTS (trans_table))
1274 g_warning ("Unknown keycode");
1278 if ( (keycode == 0x1D) /* left Ctrl */
1279 || (keycode == 0x9D) /* right Ctrl */
1280 || (keycode == 0x38) /* left Alt */
1281 || (keycode == 0xB8) /* right Alt */
1282 || (keycode == 0x2A) /* left Shift */
1283 || (keycode == 0x36) /* right Shift */)
1287 case 0x1D: /* Left Ctrl */
1288 case 0x9D: /* Right Ctrl */
1290 k->modifier_state &= ~GDK_CONTROL_MASK;
1292 k->modifier_state |= GDK_CONTROL_MASK;
1294 case 0x38: /* Left Alt */
1295 case 0xB8: /* Right Alt */
1297 k->modifier_state &= ~GDK_MOD1_MASK;
1299 k->modifier_state |= GDK_MOD1_MASK;
1301 case 0x2A: /* Left Shift */
1302 case 0x36: /* Right Shift */
1304 k->modifier_state &= ~GDK_SHIFT_MASK;
1306 k->modifier_state |= GDK_SHIFT_MASK;
1309 continue; /* Don't generate events for modifiers */
1312 if (keycode == 0x3A /* Caps lock */)
1315 k->caps_lock = !k->caps_lock;
1317 ioctl (k->fd, KDSETLED, k->caps_lock ? LED_CAP : 0);
1321 if (trans_table[keycode][0] >= GDK_F1 &&
1322 trans_table[keycode][0] <= GDK_F35 &&
1323 (k->modifier_state & GDK_MOD1_MASK))
1325 if (key_up) /* Only switch on release */
1327 gint vtnum = trans_table[keycode][0] - GDK_F1 + 1;
1329 /* Do the whole funky VT switch thing */
1330 ioctl (gdk_display->console_fd, VT_ACTIVATE, vtnum);
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_string (gdk_display->tty_fd, cursoroff_str);
1385 if (ioctl (gdk_display->tty_fd, KDSKBMODE, K_MEDIUMRAW) < 0)
1387 g_warning ("setting tty to K_MEDIUMRAW failed (are you root?)");
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_string (gdk_display->tty_fd, 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 if (key->group != 0)
1426 if ((key->keycode < 0) || (key->keycode >= 256))
1428 if ((key->level < 0) || (key->level >= 3))
1430 return trans_table[key->keycode][key->level];
1434 raw_translate (GdkFBKeyboard *kb,
1435 guint hardware_keycode,
1436 GdkModifierType state,
1439 gint *effective_group,
1441 GdkModifierType *consumed_modifiers)
1448 if (effective_group)
1449 *effective_group = 0;
1452 if (consumed_modifiers)
1453 *consumed_modifiers = 0;
1455 if ((hardware_keycode < 0) || (hardware_keycode >= 256))
1461 if (state & GDK_CONTROL_MASK)
1463 else if (state & GDK_SHIFT_MASK)
1469 tmp_keyval = trans_table[hardware_keycode][tmp_level --];
1470 } while (!tmp_keyval && (tmp_level >= 0));
1473 *keyval = tmp_keyval;
1481 raw_get_for_keyval (GdkFBKeyboard *kb,
1483 GdkKeymapKey **keys,
1489 retval = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
1491 for (i = 0; i < 256; i++)
1492 for (j = 0; j < 3; j++)
1493 if (trans_table[i][j] == keyval)
1501 g_array_append_val (retval, key);
1504 if (retval->len > 0)
1506 *keys = (GdkKeymapKey*) retval->data;
1507 *n_keys = retval->len;
1515 g_array_free (retval, retval->len > 0 ? FALSE : TRUE);
1521 raw_get_for_keycode (GdkFBKeyboard *kb,
1522 guint hardware_keycode,
1523 GdkKeymapKey **keys,
1528 GArray *keyval_array;
1531 if (hardware_keycode <= 0 ||
1532 hardware_keycode >= 256)
1544 key_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
1549 keyval_array = g_array_new (FALSE, FALSE, sizeof (guint));
1551 keyval_array = NULL;
1553 for (i = 0; i < 3; i++)
1559 key.keycode = hardware_keycode;
1563 g_array_append_val (key_array, key);
1568 g_array_append_val (keyval_array, trans_table[hardware_keycode][i]);
1572 if ((key_array && key_array->len > 0) ||
1573 (keyval_array && keyval_array->len > 0))
1576 *keys = (GdkKeymapKey*) key_array->data;
1579 *keyvals = (guint*) keyval_array->data;
1582 *n_entries = key_array->len;
1584 *n_entries = keyval_array->len;
1598 g_array_free (key_array, key_array->len > 0 ? FALSE : TRUE);
1600 g_array_free (keyval_array, keyval_array->len > 0 ? FALSE : TRUE);
1602 return *n_entries > 0;