2 * AT-SPI - Assistive Technology Service Provider Interface
3 * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
5 * Copyright 2001 Sun Microsystems Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
28 #define LABELMAXLEN 20
30 #define CAPSLOCK_KEYCODE 66
31 #define SHIFT_L_KEYCODE 50
32 #define SHIFT_R_KEYCODE 62
34 /* these can be increased to access more keys */
36 #define MAX_COLUMNS 14
38 static KeystrokeListener *key_listener;
39 static KeystrokeListener *switch_listener;
41 static boolean shift_latched = False;
42 static boolean caps_lock = False;
43 static GtkButton **buttons[MAX_ROWS];
46 label_buttons(boolean shifted)
50 KeyCode keycode = MIN_KEYCODE;
51 char label[LABELMAXLEN] = " ";
55 for (i=0; i<MAX_ROWS; ++i)
57 for (j=0; j<MAX_COLUMNS; ++j, ++keycode)
59 keysym = (KeySym) XKeycodeToKeysym (GDK_DISPLAY(), keycode, shifted ? 1 : 0);
60 /* Note: these routines are not i18n-savvy, we need to use XIM, other methods here */
61 if (keysym && g_ascii_isprint((int)keysym))
63 snprintf (label, 2, "%c", (int) keysym);
67 keysymstring = XKeysymToString (keysym);
70 /* KP_ means keypad... we won't expose this difference */
71 if (!strncmp (keysymstring, "KP_", 3))
72 strncpy (label, (char *)(keysymstring+3), LABELMAXLEN);
73 else strncpy (label, keysymstring, LABELMAXLEN);
78 *label==' ' ? " space " : label;
79 gtk_button_set_label (buttons[i][j], button_label);
85 show_shift (GtkButton *button, boolean *is_shifted)
87 label_buttons (*is_shifted ^ caps_lock);
91 do_shift (GtkButton *button)
93 static KeyCode shift_keycode = 0;
94 if (!shift_keycode) shift_keycode = XKeysymToKeycode(GDK_DISPLAY(), (KeySym) 0xFFE1);
95 /* Note: in a real onscreen keyboard shift keycode should not be hard-coded! */
96 shift_latched = !shift_latched;
97 generateKeyEvent (shift_keycode, shift_latched ? KEY_PRESS : KEY_RELEASE);
98 if (buttons) label_buttons (caps_lock || shift_latched);
104 if (shift_latched) do_shift (NULL);
105 deregisterKeystrokeListener (key_listener, KEYMASK_ALT );
106 deregisterKeystrokeListener (switch_listener, KEYMASK_UNMODIFIED );
111 keysynth_realize (GtkWidget *widget)
114 Atom wm_window_protocols[2];
115 static gboolean initialized = FALSE;
119 wm_window_protocols[0] = gdk_x11_get_xatom_by_name ("WM_DELETE_WINDOW");
120 wm_window_protocols[1] = gdk_x11_get_xatom_by_name ("_NET_WM_PING");
123 wm_hints.flags = InputHint;
124 wm_hints.input = False;
126 XSetWMHints (GDK_WINDOW_XDISPLAY (widget->window),
127 GDK_WINDOW_XWINDOW (widget->window), &wm_hints);
129 XSetWMProtocols (GDK_WINDOW_XDISPLAY (widget->window),
130 GDK_WINDOW_XWINDOW (widget->window), wm_window_protocols, 2);
134 button_exit(GtkButton *notused, void *alsonotused)
140 is_command_key (void *p)
142 KeyStroke *key = (KeyStroke *)p;
148 return TRUE; /* not reached */
153 switch_callback (void *p)
159 synth_keycode (GtkButton *button, KeyCode *keycode)
161 if (shift_latched) do_shift (button);
164 if (*keycode == CAPSLOCK_KEYCODE)
166 caps_lock = !caps_lock;
167 label_buttons (caps_lock || shift_latched);
169 generateKeyEvent ((long) *keycode, KEY_PRESSRELEASE);
176 GtkWidget *window, *button, *container, *hbox;
178 KeyCode *keycodeptr, keycode = MIN_KEYCODE;
179 static boolean true_val = True;
180 static boolean false_val = False;
182 window = g_object_connect (gtk_widget_new (gtk_window_get_type (),
185 "type", GTK_WINDOW_TOPLEVEL,
186 "window-position", GTK_WIN_POS_CENTER,
189 "allow_shrink", FALSE,
192 "signal::realize", keysynth_realize, NULL,
193 "signal::destroy", keysynth_exit, NULL,
196 container = gtk_widget_new (GTK_TYPE_VBOX,
197 "GtkWidget::parent", window,
198 "GtkWidget::visible", TRUE,
200 for (i=0; i<MAX_ROWS; ++i)
202 hbox = gtk_widget_new (gtk_hbox_get_type(),
203 "GtkWidget::parent", container,
204 "GtkWidget::visible", TRUE,
206 buttons[i] = g_new0 (GtkButton*, MAX_COLUMNS);
207 for (j=0; j<MAX_COLUMNS; ++j)
209 keycodeptr = (KeyCode *) g_new0 (KeyCode, 1);
210 *keycodeptr = keycode;
211 buttons[i][j] = g_object_connect (gtk_widget_new (gtk_button_get_type (),
212 "GtkWidget::parent", hbox,
213 "GtkWidget::visible", TRUE,
216 synth_keycode, keycodeptr,
218 if (keycode == SHIFT_L_KEYCODE || keycode == SHIFT_R_KEYCODE)
220 g_object_connect (buttons[i][j], "signal::pressed", show_shift,
222 g_object_connect (buttons[i][j], "signal::released", show_shift,
228 hbox = gtk_widget_new (gtk_hbox_get_type(),
229 "GtkWidget::parent", container,
230 "GtkWidget::visible", TRUE,
232 button = g_object_connect (gtk_widget_new (gtk_button_get_type (),
233 "GtkButton::label", "Quit",
234 "GtkWidget::parent", hbox,
235 "GtkWidget::visible", TRUE,
240 button = g_object_connect (gtk_widget_new (gtk_button_get_type (),
241 "GtkButton::label", "ShiftLatch",
242 "GtkWidget::parent", hbox,
243 "GtkWidget::visible", TRUE,
248 label_buttons (caps_lock || shift_latched);
249 gtk_widget_show (window);
253 main(int argc, char **argv)
257 if ((argc > 1) && (!strncmp(argv[1],"-h",2)))
259 printf ("Usage: keysynth-demo\n");
263 gtk_init (&argc, &argv); /* must call, because this program uses GTK+ */
267 key_listener = createKeystrokeListener(is_command_key);
268 /* will listen only to Alt-key combinations */
269 registerKeystrokeListener(key_listener,
272 (unsigned long) ( KeyPress | KeyRelease),
273 KEYLISTENER_CANCONSUME | KEYLISTENER_ALLWINDOWS);
276 /* register a listener on the spacebar, to serve as a 'single switch' */
277 spacebar_set.keysyms = g_new0 (unsigned long, 1);
278 spacebar_set.keycodes = g_new0 (unsigned short, 1);
279 spacebar_set.len = 1;
280 spacebar_set.keysyms[0] = (unsigned long) ' ';
281 spacebar_set.keycodes[0] = (unsigned short) 0;
282 switch_listener = createKeystrokeListener(switch_callback);
283 /* registerKeystrokeListener(switch_listener,
286 (unsigned long) ( KeyPress | KeyRelease),
287 KEYLISTENER_CANCONSUME);
290 SPI_event_main(TRUE);