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"
30 #include <sys/ioctl.h>
34 typedef struct _GdkFBKeyboard GdkFBKeyboard;
35 typedef struct _GdkFBKeyboardDevice GdkFBKeyboardDevice;
37 struct _GdkFBKeyboard {
43 gboolean caps_lock : 1;
48 GdkFBKeyboardDevice *dev;
51 struct _GdkFBKeyboardDevice {
53 gboolean (*open)(GdkFBKeyboard *kb);
54 void (*close)(GdkFBKeyboard *kb);
56 guint (*lookup_key) (GdkFBKeyboard *kb,
57 const GdkKeymapKey *key);
58 gboolean (*translate_keyboard_state) (GdkFBKeyboard *kb,
59 guint hardware_keycode,
60 GdkModifierType state,
63 gint *effective_group,
65 GdkModifierType *consumed_modifiers);
66 gboolean (*get_entries_for_keyval) (GdkFBKeyboard *kb,
70 gboolean (*get_entries_for_keycode) (GdkFBKeyboard *kb,
71 guint hardware_keycode,
79 static GdkFBKeyboard *gdk_fb_keyboard = NULL;
80 static GdkKeymap *default_keymap = NULL;
82 static gboolean xlate_open (GdkFBKeyboard *kb);
83 static void xlate_close (GdkFBKeyboard *kb);
84 static guint xlate_lookup (GdkFBKeyboard *kb,
85 const GdkKeymapKey *key);
86 static gboolean xlate_translate (GdkFBKeyboard *kb,
87 guint hardware_keycode,
88 GdkModifierType state,
91 gint *effective_group,
93 GdkModifierType *consumed_modifiers);
94 static gboolean xlate_get_for_keyval (GdkFBKeyboard *kb,
98 static gboolean xlate_get_for_keycode (GdkFBKeyboard *kb,
99 guint hardware_keycode,
104 static gboolean raw_open (GdkFBKeyboard *kb);
105 static void raw_close (GdkFBKeyboard *kb);
106 static guint raw_lookup (GdkFBKeyboard *kb,
107 const GdkKeymapKey *key);
108 static gboolean raw_translate (GdkFBKeyboard *kb,
109 guint hardware_keycode,
110 GdkModifierType state,
113 gint *effective_group,
115 GdkModifierType *consumed_modifiers);
116 static gboolean raw_get_for_keyval (GdkFBKeyboard *kb,
120 static gboolean raw_get_for_keycode (GdkFBKeyboard *kb,
121 guint hardware_keycode,
127 static GdkFBKeyboardDevice keyb_devs[] =
135 xlate_get_for_keyval,
136 xlate_get_for_keycode
150 gdk_keymap_get_default_for_display (GdkDisplay *display)
152 if (default_keymap == NULL)
153 default_keymap = g_object_new (gdk_keymap_get_type (), NULL);
155 return default_keymap;
159 gdk_keymap_get_for_display (GdkDisplay *display)
161 return gdk_keymap_get_default_for_display (display);
165 gdk_keymap_get_direction (GdkKeymap *keymap)
167 /* FIXME: Only supports LTR keymaps at the moment */
168 return PANGO_DIRECTION_LTR;
172 gdk_fb_keyboard_modifiers ()
174 return gdk_fb_keyboard->modifier_state;
178 gdk_fb_keyboard_init (gboolean open_dev)
184 gdk_fb_keyboard = g_new0 (GdkFBKeyboard, 1);
185 keyb = gdk_fb_keyboard;
188 keyb_type = getenv ("GDK_KEYBOARD_TYPE");
193 for (i = 0; i < G_N_ELEMENTS(keyb_devs); i++)
195 if (g_ascii_strcasecmp(keyb_type, keyb_devs[i].name)==0)
199 if (i == G_N_ELEMENTS(keyb_devs))
201 g_warning ("No keyboard driver of type %s found", keyb_type);
205 keyb->dev = &keyb_devs[i];
208 return gdk_fb_keyboard_open ();
214 gdk_fb_keyboard_open (void)
217 GdkFBKeyboardDevice *device;
219 keyb = gdk_fb_keyboard;
222 if (!device->open(keyb))
224 g_warning ("Keyboard driver open failed");
232 gdk_fb_keyboard_close (void)
234 gdk_fb_keyboard->dev->close(gdk_fb_keyboard);
239 gdk_keymap_get_entries_for_keyval (GdkKeymap *keymap,
244 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
245 g_return_val_if_fail (keys != NULL, FALSE);
246 g_return_val_if_fail (n_keys != NULL, FALSE);
247 g_return_val_if_fail (keyval != 0, FALSE);
249 return gdk_fb_keyboard->dev->get_entries_for_keyval (gdk_fb_keyboard,
256 gdk_keymap_get_entries_for_keycode (GdkKeymap *keymap,
257 guint hardware_keycode,
262 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
263 g_return_val_if_fail (n_entries != NULL, FALSE);
265 return gdk_fb_keyboard->dev->get_entries_for_keycode (gdk_fb_keyboard,
274 gdk_keymap_lookup_key (GdkKeymap *keymap,
275 const GdkKeymapKey *key)
277 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), 0);
278 g_return_val_if_fail (key != NULL, 0);
279 g_return_val_if_fail (key->group < 4, 0);
281 return gdk_fb_keyboard->dev->lookup_key (gdk_fb_keyboard, key);
286 gdk_keymap_translate_keyboard_state (GdkKeymap *keymap,
287 guint hardware_keycode,
288 GdkModifierType state,
291 gint *effective_group,
293 GdkModifierType *consumed_modifiers)
295 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
296 g_return_val_if_fail (group < 4, FALSE);
298 return gdk_fb_keyboard->dev->translate_keyboard_state (gdk_fb_keyboard,
309 gdk_fb_handle_key (guint hw_keycode,
311 guint modifier_state,
320 /* handle some magic keys */
322 (modifier_state & GDK_CONTROL_MASK) &&
323 (modifier_state & GDK_MOD1_MASK))
325 if (keyval == GDK_BackSpace)
327 ioctl (gdk_display->tty_fd, KDSKBMODE, K_XLATE);
331 if (keyval == GDK_Return)
332 gdk_fb_redraw_all ();
335 win = gdk_fb_keyboard_event_window (gdk_fb_window_find_focus (),
336 key_up ? GDK_KEY_RELEASE : GDK_KEY_PRESS);
339 event = gdk_event_make (win,
340 key_up ? GDK_KEY_RELEASE : GDK_KEY_PRESS,
343 event->key.state = modifier_state;
344 event->key.keyval = keyval;
345 event->key.string = string;
346 event->key.length = string_length;
347 event->key.hardware_keycode = hw_keycode;
348 event->key.group = group;
354 /******************************************************
355 ********* Device specific keyboard code **************
356 ******************************************************/
359 /* XLATE keyboard driver */
367 {"\x5b\x41", GDK_F1},
368 {"\x5b\x42", GDK_F2},
369 {"\x5b\x43", GDK_F3},
370 {"\x5b\x44", GDK_F4},
371 {"\x5b\x45", GDK_F5},
372 {"\x31\x37\x7e", GDK_F6},
373 {"\x31\x38\x7e", GDK_F7},
374 {"\x31\x39\x7e", GDK_F8},
375 {"\x32\x30\x7e", GDK_F9},
376 {"\x32\x31\x7e", GDK_F10},
377 {"\x32\x33\x7e", GDK_F11},
378 {"\x32\x34\x7e", GDK_F12},
380 {"\x32\x35\x7e", GDK_F1, GDK_SHIFT_MASK},
381 {"\x32\x36\x7e", GDK_F2, GDK_SHIFT_MASK},
382 {"\x32\x38\x7e", GDK_F3, GDK_SHIFT_MASK},
383 {"\x32\x39\x7e", GDK_F4, GDK_SHIFT_MASK},
384 {"\x33\x31\x7e", GDK_F5, GDK_SHIFT_MASK},
385 {"\x33\x32\x7e", GDK_F6, GDK_SHIFT_MASK},
386 {"\x33\x33\x7e", GDK_F7, GDK_SHIFT_MASK},
387 {"\x33\x34\x7e", GDK_F8, GDK_SHIFT_MASK},
389 {"\x31\x7e", GDK_Home},
390 {"\x35\x7e", GDK_Page_Up},
391 {"\x34\x7e", GDK_End},
392 {"\x36\x7e", GDK_Page_Down},
393 {"\x32\x7e", GDK_Insert},
394 {"\x33\x7e", GDK_Delete},
409 {'@', GDK_CONTROL_MASK},
410 {'a', GDK_CONTROL_MASK},
411 {'b', GDK_CONTROL_MASK},
412 {'c', GDK_CONTROL_MASK},
413 {'d', GDK_CONTROL_MASK},
414 {'e', GDK_CONTROL_MASK},
415 {'f', GDK_CONTROL_MASK},
416 {'g', GDK_CONTROL_MASK},
417 {'h', GDK_CONTROL_MASK},
419 {'j', GDK_CONTROL_MASK},
420 {'k', GDK_CONTROL_MASK},
421 {'l', GDK_CONTROL_MASK},
423 {'n', GDK_CONTROL_MASK},
424 {'o', GDK_CONTROL_MASK},
426 {'p', GDK_CONTROL_MASK},
427 {'q', GDK_CONTROL_MASK},
428 {'r', GDK_CONTROL_MASK},
429 {'s', GDK_CONTROL_MASK},
430 {'t', GDK_CONTROL_MASK},
431 {'u', GDK_CONTROL_MASK},
432 {'v', GDK_CONTROL_MASK},
433 {'w', GDK_CONTROL_MASK},
434 {'x', GDK_CONTROL_MASK},
435 {'y', GDK_CONTROL_MASK},
436 {'z', GDK_CONTROL_MASK},
438 {'\\', GDK_CONTROL_MASK},
439 {']', GDK_CONTROL_MASK},
440 {'^', GDK_CONTROL_MASK},
441 {'_', GDK_CONTROL_MASK},
683 iscode (char *code, char *str, int str_max)
687 for (i = 0; code[i] && (i < str_max); i++)
689 if (code[i] != str[i])
692 return (code[i] == 0);
696 xlate_io (GIOChannel *gioc,
700 GdkFBKeyboard *keyb = (GdkFBKeyboard *)data;
708 n = read (keyb->fd, buf, sizeof(buf));
710 g_error ("Nothing from keyboard!");
716 if ((buf[i] == 27) && (i+1 != n)) /* Escape */
718 /* Esc is not the last char in buffer, interpret as code sequence */
726 for (j=0;j<G_N_ELEMENTS (xlate_codes);j++)
728 if (iscode (xlate_codes[j].str, &buf[i], left))
730 /* Ctrl-Alt Return can't be pressed in the XLATE driver,
731 * use Shift F1 instead */
732 if ((xlate_codes[j].code == GDK_F1) &&
733 (xlate_codes[j].modifier & GDK_SHIFT_MASK))
734 gdk_fb_redraw_all ();
736 if ((xlate_codes[j].code == GDK_F2) &&
737 (xlate_codes[j].modifier & GDK_SHIFT_MASK))
742 gdk_fb_set_rotation (deg);
745 if ((xlate_codes[j].code == GDK_F8) &&
746 (xlate_codes[j].modifier & GDK_SHIFT_MASK))
750 gdk_fb_handle_key (xlate_codes[j].code,
752 xlate_codes[j].modifier,
757 gdk_fb_handle_key (xlate_codes[j].code,
759 xlate_codes[j].modifier,
764 i += strlen (xlate_codes[j].str);
773 modifier |= GDK_MOD1_MASK;
782 keycode = xlate_chars[buf[i]].code;
785 modifier |= xlate_chars[buf[i]].modifier;
790 len = ((keycode < 255) && isprint (keycode)) ? 1 : 0;
791 gdk_fb_handle_key (keycode,
795 (len)?g_strdup(dummy) : NULL,
798 gdk_fb_handle_key (keycode,
802 (len)?g_strdup(dummy) : NULL,
812 write_string (gint fd,
815 gsize to_write = strlen (str);
819 gssize count = write (fd, str, to_write);
836 xlate_open (GdkFBKeyboard *kb)
838 const char cursoroff_str[] = "\033[?1;0;0c";
841 tcgetattr (gdk_display->tty_fd, &ts);
844 ts.c_lflag &= ~(ICANON|ECHO|ISIG);
846 tcsetattr (gdk_display->tty_fd, TCSAFLUSH, &ts);
848 tcsetpgrp (gdk_display->tty_fd, getpgrp());
850 write_string (gdk_display->tty_fd, cursoroff_str);
852 ioctl (gdk_display->tty_fd, KDSKBMODE, K_XLATE);
854 kb->fd = gdk_display->tty_fd;
855 kb->io = g_io_channel_unix_new (kb->fd);
856 kb->io_tag = g_io_add_watch (kb->io,
857 G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
865 xlate_close (GdkFBKeyboard *kb)
868 const char cursoron_str[] = "\033c\033[3g\033]R";
870 write_string (gdk_display->tty_fd, cursoron_str);
872 tcgetattr (gdk_display->tty_fd, &ts);
873 ts.c_lflag |= (ICANON|ECHO|ISIG);
874 tcsetattr (gdk_display->tty_fd, TCSAFLUSH, &ts);
876 g_source_remove (kb->io_tag);
877 g_io_channel_unref (kb->io);
879 /* don't close kb->fd, it is the tty from gdk_display */
883 xlate_lookup (GdkFBKeyboard *kb,
884 const GdkKeymapKey *key)
894 xlate_translate (GdkFBKeyboard *kb,
895 guint hardware_keycode,
896 GdkModifierType state,
899 gint *effective_group,
901 GdkModifierType *consumed_modifiers)
904 *keyval = hardware_keycode;
906 *effective_group = 0;
909 if (consumed_modifiers)
910 *consumed_modifiers = 0;
915 xlate_get_for_keyval (GdkFBKeyboard *kb,
921 *keys = g_new (GdkKeymapKey, 1);
922 (*keys)->keycode = keyval;
929 xlate_get_for_keycode (GdkFBKeyboard *kb,
930 guint hardware_keycode,
937 *keys = g_new (GdkKeymapKey, 1);
938 (*keys)->keycode = hardware_keycode;
944 *keyvals = g_new (guint, 1);
945 **keyvals = hardware_keycode;
953 /* Raw keyboard support */
955 static const guint trans_table[256][3] = {
971 {GDK_BackSpace, 0, 0},
988 {GDK_Control_L, 0, 0}, /* mod */
1003 {GDK_Shift_L, 0, 0}, /* mod */
1018 {GDK_Shift_R, 0, 0}, /* mod */
1019 {GDK_KP_Multiply, 0, 0},
1074 {GDK_Page_Up, 0, 0},
1079 {GDK_Page_Down, 0, 0},
1247 raw_io (GIOChannel *gioc,
1251 GdkFBKeyboard *k = data;
1255 n = read (k->fd, buf, sizeof(buf));
1257 g_error("Nothing from keyboard!");
1259 for (i = 0; i < n; i++)
1268 keycode = buf[i] & 0x7F;
1269 key_up = buf[i] & 0x80;
1271 if (keycode > G_N_ELEMENTS (trans_table))
1273 g_warning ("Unknown keycode");
1277 if ( (keycode == 0x1D) /* left Ctrl */
1278 || (keycode == 0x9D) /* right Ctrl */
1279 || (keycode == 0x38) /* left Alt */
1280 || (keycode == 0xB8) /* right Alt */
1281 || (keycode == 0x2A) /* left Shift */
1282 || (keycode == 0x36) /* right Shift */)
1286 case 0x1D: /* Left Ctrl */
1287 case 0x9D: /* Right Ctrl */
1289 k->modifier_state &= ~GDK_CONTROL_MASK;
1291 k->modifier_state |= GDK_CONTROL_MASK;
1293 case 0x38: /* Left Alt */
1294 case 0xB8: /* Right Alt */
1296 k->modifier_state &= ~GDK_MOD1_MASK;
1298 k->modifier_state |= GDK_MOD1_MASK;
1300 case 0x2A: /* Left Shift */
1301 case 0x36: /* Right Shift */
1303 k->modifier_state &= ~GDK_SHIFT_MASK;
1305 k->modifier_state |= GDK_SHIFT_MASK;
1308 continue; /* Don't generate events for modifiers */
1311 if (keycode == 0x3A /* Caps lock */)
1314 k->caps_lock = !k->caps_lock;
1316 ioctl (k->fd, KDSETLED, k->caps_lock ? LED_CAP : 0);
1320 if (trans_table[keycode][0] >= GDK_F1 &&
1321 trans_table[keycode][0] <= GDK_F35 &&
1322 (k->modifier_state & GDK_MOD1_MASK))
1324 if (key_up) /* Only switch on release */
1326 gint vtnum = trans_table[keycode][0] - GDK_F1 + 1;
1328 /* Do the whole funky VT switch thing */
1329 ioctl (gdk_display->console_fd, VT_ACTIVATE, vtnum);
1330 ioctl (gdk_display->console_fd, VT_WAITACTIVE, gdk_display->vt);
1331 gdk_fb_redraw_all ();
1339 if (k->modifier_state & GDK_CONTROL_MASK)
1341 else if (k->modifier_state & GDK_SHIFT_MASK)
1344 keyval = trans_table[keycode][mod--];
1345 } while (!keyval && (mod >= 0));
1347 if (k->caps_lock && (keyval >= 'a') && (keyval <= 'z'))
1348 keyval = toupper (keyval);
1353 len = isprint (keyval) ? 1 : 0;
1357 gdk_fb_handle_key (keycode,
1361 (len)?g_strdup(dummy):NULL,
1370 raw_open (GdkFBKeyboard *kb)
1372 const char cursoroff_str[] = "\033[?1;0;0c";
1375 tcgetattr (gdk_display->tty_fd, &ts);
1378 ts.c_lflag &= ~(ICANON|ECHO|ISIG);
1380 tcsetattr (gdk_display->tty_fd, TCSAFLUSH, &ts);
1382 tcsetpgrp (gdk_display->tty_fd, getpgrp());
1384 write_string (gdk_display->tty_fd, cursoroff_str);
1386 if (ioctl (gdk_display->tty_fd, KDSKBMODE, K_MEDIUMRAW) < 0)
1388 g_warning ("setting tty to K_MEDIUMRAW failed (are you root?)");
1392 kb->fd = gdk_display->tty_fd;
1393 kb->io = g_io_channel_unix_new (kb->fd);
1394 kb->io_tag = g_io_add_watch (kb->io,
1395 G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
1403 raw_close (GdkFBKeyboard *kb)
1406 const char cursoron_str[] = "\033c";
1408 write_string (gdk_display->tty_fd, cursoron_str);
1410 tcgetattr (gdk_display->tty_fd, &ts);
1411 ts.c_lflag |= (ICANON|ECHO|ISIG);
1412 tcsetattr (gdk_display->tty_fd, TCSAFLUSH, &ts);
1414 ioctl (gdk_display->tty_fd, KDSKBMODE, K_XLATE);
1416 g_source_remove (kb->io_tag);
1417 g_io_channel_unref (kb->io);
1418 /* don't close kb->fd, it is the tty from gdk_display */
1422 raw_lookup (GdkFBKeyboard *kb,
1423 const GdkKeymapKey *key)
1425 if (key->group != 0)
1427 if ((key->keycode < 0) || (key->keycode >= 256))
1429 if ((key->level < 0) || (key->level >= 3))
1431 return trans_table[key->keycode][key->level];
1435 raw_translate (GdkFBKeyboard *kb,
1436 guint hardware_keycode,
1437 GdkModifierType state,
1440 gint *effective_group,
1442 GdkModifierType *consumed_modifiers)
1449 if (effective_group)
1450 *effective_group = 0;
1453 if (consumed_modifiers)
1454 *consumed_modifiers = 0;
1456 if ((hardware_keycode < 0) || (hardware_keycode >= 256))
1462 if (state & GDK_CONTROL_MASK)
1464 else if (state & GDK_SHIFT_MASK)
1470 tmp_keyval = trans_table[hardware_keycode][tmp_level --];
1471 } while (!tmp_keyval && (tmp_level >= 0));
1474 *keyval = tmp_keyval;
1482 raw_get_for_keyval (GdkFBKeyboard *kb,
1484 GdkKeymapKey **keys,
1490 retval = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
1492 for (i = 0; i < 256; i++)
1493 for (j = 0; j < 3; j++)
1494 if (trans_table[i][j] == keyval)
1502 g_array_append_val (retval, key);
1505 if (retval->len > 0)
1507 *keys = (GdkKeymapKey*) retval->data;
1508 *n_keys = retval->len;
1516 g_array_free (retval, retval->len > 0 ? FALSE : TRUE);
1522 raw_get_for_keycode (GdkFBKeyboard *kb,
1523 guint hardware_keycode,
1524 GdkKeymapKey **keys,
1529 GArray *keyval_array;
1532 if (hardware_keycode <= 0 ||
1533 hardware_keycode >= 256)
1545 key_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
1550 keyval_array = g_array_new (FALSE, FALSE, sizeof (guint));
1552 keyval_array = NULL;
1554 for (i = 0; i < 3; i++)
1560 key.keycode = hardware_keycode;
1564 g_array_append_val (key_array, key);
1569 g_array_append_val (keyval_array, trans_table[hardware_keycode][i]);
1573 if ((key_array && key_array->len > 0) ||
1574 (keyval_array && keyval_array->len > 0))
1577 *keys = (GdkKeymapKey*) key_array->data;
1580 *keyvals = (guint*) keyval_array->data;
1583 *n_entries = key_array->len;
1585 *n_entries = keyval_array->len;
1599 g_array_free (key_array, key_array->len > 0 ? FALSE : TRUE);
1601 g_array_free (keyval_array, keyval_array->len > 0 ? FALSE : TRUE);
1603 return *n_entries > 0;