Added C binding for key synthesis, and a new test/demo program
[platform/core/uifw/at-spi2-atk.git] / test / keysynth-demo.c
1 /*
2  * AT-SPI - Assistive Technology Service Provider Interface
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4  *
5  * Copyright 2001 Sun Microsystems Inc.
6  *
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.
11  *
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.
16  *
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.
21  */
22
23 #include <stdlib.h>
24 #include <gtk/gtk.h>
25 #include <gdk/gdkx.h>
26 #include "spi.h"
27
28 #define LABELMAXLEN 20
29 #define MIN_KEYCODE 9
30 #define CAPSLOCK_KEYCODE 66
31
32 /* these can be increased to access more keys */
33 #define MAX_ROWS 5
34 #define MAX_COLUMNS 14
35
36 static KeystrokeListener *key_listener;
37
38 static boolean shift_latched = False;
39 static boolean caps_lock = False;
40 static GtkButton **buttons[MAX_ROWS];
41
42 static void
43 label_buttons()
44 {
45   int i, j;
46   KeySym keysym;
47   KeyCode keycode = MIN_KEYCODE;
48   char label[LABELMAXLEN] = " ";
49   char *button_label;
50   char *keysymstring;
51   boolean shifted;
52   
53   for (i=0; i<MAX_ROWS; ++i)
54     {
55       for (j=0; j<MAX_COLUMNS; ++j, ++keycode)
56         {
57           shifted = caps_lock || shift_latched;
58           keysym = (KeySym) XKeycodeToKeysym (GDK_DISPLAY(), keycode, shifted ? 1 : 0);
59           /* Note: these routines are not i18n-savvy,  we need to use XIM, other methods here */
60           if (keysym && g_ascii_isprint((int)keysym))
61             {
62               snprintf (label, 2, "%c", (int) keysym); 
63             }
64           else
65             {
66               keysymstring = XKeysymToString (keysym);
67               if (keysymstring)
68                 { 
69                   /* KP_ means keypad... we won't expose this difference */
70                   if (!strncmp (keysymstring, "KP_", 3))
71                        strncpy (label, (char *)(keysymstring+3), LABELMAXLEN);
72                   else strncpy (label, keysymstring, LABELMAXLEN);
73                 }
74               else *label = 0;
75             }
76           button_label =        
77           *label==' ' ? "   space   " : label;
78           gtk_button_set_label (buttons[i][j], button_label);    
79         }
80     }
81 }
82
83 static void
84 do_shift (GtkButton *button)
85 {
86   static KeyCode shift_keycode = 0;
87   if (!shift_keycode) shift_keycode = XKeysymToKeycode(GDK_DISPLAY(), (KeySym) 0xFFE1);
88   /* Note: in a real onscreen keyboard shift keycode should not be hard-coded! */
89   shift_latched = !shift_latched;
90   generateKeyEvent (shift_keycode, shift_latched ? KEY_PRESS : KEY_RELEASE);
91   if (buttons) label_buttons (buttons);
92 }
93
94 static void
95 keysynth_exit()
96 {
97   if (shift_latched) do_shift (NULL);
98   deregisterKeystrokeListener (key_listener, KEYMASK_ALT );
99   SPI_exit ();
100 }
101
102 static void
103 button_exit(GtkButton *notused, void *alsonotused)
104 {
105   keysynth_exit();
106 }
107
108 static boolean
109 is_command_key (void *p)
110 {
111   KeyStroke *key = (KeyStroke *)p;
112   switch (key->keyID)
113     {
114     case 'Q':
115     case 'q':
116             keysynth_exit(); 
117             return TRUE; /* not reached */
118     }
119 }
120
121 static void
122 synth_keycode (GtkButton *button, KeyCode *keycode)
123 {
124   if (*keycode)  generateKeyEvent ((long) *keycode, KEY_PRESSRELEASE);
125   if (shift_latched) do_shift (button);
126   if (*keycode == CAPSLOCK_KEYCODE)
127     {
128       caps_lock = !caps_lock;       
129       label_buttons ();
130     }
131 }
132
133 static void
134 create_vkbd()
135 {
136   GtkWidget *window, *button, *container, *hbox;
137   int i, j;
138   KeyCode *keycodeptr, keycode = MIN_KEYCODE;
139
140   window = g_object_connect (gtk_widget_new (gtk_window_get_type (),
141                                              "user_data", NULL,
142                                              "can_focus", FALSE,
143                                              "type", GTK_WINDOW_POPUP,
144                                              "window-position", GTK_WIN_POS_CENTER,
145                                              "title", "test",
146                                              "allow_grow", FALSE,
147                                              "allow_shrink", FALSE,
148                                              "border_width", 10,
149                                              NULL),
150                              "signal::destroy", keysynth_exit, NULL,
151                              NULL);
152   
153   container = gtk_widget_new (GTK_TYPE_VBOX,
154                               "GtkWidget::parent", window,
155                               "GtkWidget::visible", TRUE,
156                               NULL);
157   for (i=0; i<MAX_ROWS; ++i)
158     {
159       hbox = gtk_widget_new (gtk_hbox_get_type(),
160                              "GtkWidget::parent", container,
161                              "GtkWidget::visible", TRUE,
162                              NULL);
163       buttons[i] = g_new0 (GtkButton*, MAX_COLUMNS);
164       for (j=0; j<MAX_COLUMNS; ++j)
165         {
166           keycodeptr = (KeyCode *) g_new0 (KeyCode, 1);
167           *keycodeptr = keycode;
168           ++keycode;
169           buttons[i][j] = g_object_connect (gtk_widget_new (gtk_button_get_type (),
170                                                      "GtkWidget::parent", hbox,
171                                                      "GtkWidget::visible", TRUE,
172                                                      NULL),
173                                      "signal::clicked",
174                                      synth_keycode, keycodeptr,
175                                      NULL);
176         }
177     } 
178   hbox = gtk_widget_new (gtk_hbox_get_type(),
179                          "GtkWidget::parent", container,
180                          "GtkWidget::visible", TRUE,
181                          NULL);
182   button = g_object_connect (gtk_widget_new (gtk_button_get_type (),
183                                              "GtkButton::label", "Quit",
184                                              "GtkWidget::parent", hbox,
185                                              "GtkWidget::visible", TRUE,
186                                              NULL),
187                              "signal::clicked",
188                              button_exit, NULL,
189                              NULL);
190   button = g_object_connect (gtk_widget_new (gtk_button_get_type (),
191                                              "GtkButton::label", "ShiftLatch",
192                                              "GtkWidget::parent", hbox,
193                                              "GtkWidget::visible", TRUE,
194                                              NULL),
195                              "signal::clicked",
196                              do_shift, NULL,
197                              NULL);
198   label_buttons ();
199   gtk_widget_show (window);
200
201 }
202
203 int
204 main(int argc, char **argv)
205 {
206   if ((argc > 1) && (!strncmp(argv[1],"-h",2)))
207   {
208     printf ("Usage: keysynth-demo\n");
209     exit(0);
210   }
211
212   gtk_init (&argc, &argv); /* must call, because this program uses GTK+ */
213
214   SPI_init();
215
216   key_listener = createKeystrokeListener(is_command_key);
217   /* will listen only to Alt-key combinations */
218   registerKeystrokeListener(key_listener,
219                             (KeySet *) ALL_KEYS,
220                             KEYMASK_ALT,
221                             (unsigned long) ( KeyPress | KeyRelease),
222                             KEYLISTENER_CANCONSUME);
223   create_vkbd();  
224
225   SPI_event_main(TRUE);
226 }