ergtk-keyb.c

Go to the documentation of this file.
00001 /*
00002  * File Name: ergtk-keyb.c 
00003  */
00004 
00005 /*
00006  * This file is part of erkeyb.
00007  *
00008  * erkeyb is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation, either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * erkeyb is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00020  */
00021 
00022 /**
00023  * Copyright (C) 2009 iRex Technologies B.V.
00024  * All rights reserved.
00025  */
00026 
00027 //----------------------------------------------------------------------------
00028 // Include Files
00029 //----------------------------------------------------------------------------
00030 
00031 // system includes
00032 #include <stdio.h>
00033 #include <string.h>
00034 
00035 /* includes for fakekey */
00036 #include <X11/Xlib.h>
00037 #include <fakekey/fakekey.h>
00038 
00039 // gtk
00040 #include <gtk/gtk.h>
00041 
00042 // local include files, between " "
00043 #include "config.h"
00044 #include "ergtk-keyb.h"
00045 
00046 #include "erkeyb-display-sched.h"
00047 
00048 // logging
00049 #include "logging.h"
00050 
00051 //----------------------------------------------------------------------------
00052 // MACROS and definitions
00053 //----------------------------------------------------------------------------
00054 
00055 // table definitionss
00056 #define NUM_COLUMNS             20
00057 #define NUM_ROWS                 4
00058 
00059 #define NUM_KEYS                32
00060 #define NUM_KEYS_FIRST_ROW      10
00061 #define NUM_KEYS_SECOND_ROW      9
00062 #define NUM_KEYS_THIRD_ROW       9
00063 #define NUM_KEYS_FOURTH_ROW      4
00064 
00065 #define FIRST_ROW_START          0
00066 #define FIRST_ROW_END            ( FIRST_ROW_START + NUM_KEYS_FIRST_ROW -1 )
00067 #define SECOND_ROW_START         ( FIRST_ROW_END + 1 )
00068 #define SECOND_ROW_END           ( SECOND_ROW_START + NUM_KEYS_SECOND_ROW -1 ) 
00069 #define THIRD_ROW_START          ( SECOND_ROW_END + 1 )
00070 #define THIRD_ROW_END            ( THIRD_ROW_START + NUM_KEYS_THIRD_ROW - 1 )
00071 #define FOURTH_ROW_START         ( THIRD_ROW_END + 1 )
00072 #define FOURTH_ROW_END           ( FOURTH_ROW_START + NUM_KEYS_FOURTH_ROW - 1 )
00073 
00074 //----------------------------------------------------------------------------
00075 // Type Declarations
00076 //----------------------------------------------------------------------------
00077 
00078 #define ERGTK_KEYB_GET_PRIVATE(o)  \
00079            (G_TYPE_INSTANCE_GET_PRIVATE ((o), ERGTK_TYPE_KEYB, ErGtkKeybPrivate))
00080 
00081 
00082 G_DEFINE_TYPE (ErGtkKeyb, ergtk_keyb, GTK_TYPE_VBOX) ;
00083 
00084 /* we support at most 6 alternatives */
00085 typedef enum _key_alt key_alt;
00086 
00087 enum _key_alt {
00088     KEY_ALT0 = 0,
00089     KEY_ALT0_SHIFTED = 1,
00090     KEY_ALT1 = 2,
00091     KEY_ALT1_SHIFTED = 3,
00092     KEY_ALT2 = 4,
00093     KEY_ALT2_SHIFTED = 5,
00094     KEY_ALT_MAX = 6
00095 };
00096 
00097 typedef struct _rangetype rangetype;
00098 
00099 struct _rangetype { 
00100     int row;
00101     int column;
00102     int nrows;
00103     int ncolumns;
00104 } ;
00105 
00106 
00107 /* this is a temp solutions until we have dynamic keymaps that are loeaded from an
00108  * XML file
00109  */
00110 typedef struct _c_keyboardmap c_keyboardmap; /* keyboard map using c strings */
00111 
00112 struct _c_keyboardmap {
00113     int    key_num;    /* the keynumber on the keyboard layout */
00114     gchar*  alt[6];    /* the list of c strings that are the char alternatives for a key */ 
00115 };
00116 
00117 typedef struct _charmap charmap;
00118 
00119 struct _charmap {
00120     gint    key_num;    /* the keynumber on the keyboard layout */
00121     GList*  alt;        /* the list of GStrings that are the characters (1 per GString) assigned to this key */
00122 };
00123 
00124 typedef enum _ergtk_keyfacetype ergtk_keyfacetype;
00125 
00126 enum _ergtk_keyfacetype  {
00127     ergtk_keyfacetype_label = 0,
00128     ergtk_keyfacetype_image,
00129     ergtk_keyfacetype_unknown = 255,
00130 };
00131 
00132 typedef struct _ErGtkKey ErGtkKey;
00133 
00134 struct _ErGtkKey {
00135             ErGtkKeyb*          parent;
00136             gint                key_num;
00137             GtkWidget*          button;
00138             ergtk_keyfacetype   key_facetype;
00139     union {
00140         GtkWidget* label;
00141         GtkWidget* image;
00142     }                           u;
00143 };
00144 
00145 struct _ErGtkKeybPrivate
00146 {
00147     GString*    xmlfile;                /* xml file containing the keyboard keymap */
00148     charmap     keymap[32];             /* keynumber to keychar map */
00149     ErGtkKey    keyboard[32];           /* keyboard widget/layout */
00150     gint        current_alt_keyb_num;   /* the current alternative keymap */
00151     gint        num_alternatives;       /* total number of keyboard alternatives */
00152     gboolean    finalizing;             /* true when object is finalizing */
00153     guint       highlight_id;
00154 
00155     /* fakekeylib */
00156     Display*    Xdpy;                   /* X display reference */
00157     FakeKey*    fk;                     /* fakekey reference */
00158     GdkDisplay* Gdpy;                   /* Gdk Display reference */
00159 };
00160 
00161 enum {
00162     PROP_0,
00163     PROP_NUM_ALTERNATIVES,
00164 };
00165 
00166 //----------------------------------------------------------------------------
00167 // Static Variables
00168 //----------------------------------------------------------------------------
00169 
00170 // temp solution until we have XML based dynamic keymaps
00171 static c_keyboardmap g_mykeymap[NUM_KEYS] = 
00172 {
00173     { .key_num =  0, .alt = { "q", "Q", "1", "`", NULL, NULL, }, },
00174     { .key_num =  1, .alt = { "w", "W", "2", "'", NULL, NULL, }, },
00175     { .key_num =  2, .alt = { "e", "E", "3", "%", NULL, NULL, }, },
00176     { .key_num =  3, .alt = { "r", "R", "4", "^", NULL, NULL, }, },
00177     { .key_num =  4, .alt = { "t", "T", "5", "_", NULL, NULL, }, },
00178     { .key_num =  5, .alt = { "y", "Y", "6", "<", NULL, NULL, }, },
00179     { .key_num =  6, .alt = { "u", "U", "7", ">", NULL, NULL, }, },
00180     { .key_num =  7, .alt = { "i", "I", "8", "-", NULL, NULL, }, },
00181     { .key_num =  8, .alt = { "o", "O", "9", "+", NULL, NULL, }, },
00182     { .key_num =  9, .alt = { "p", "P", "0", "{", NULL, NULL, }, },
00183     { .key_num = 10, .alt = { "a", "A", "£", "}", NULL, NULL, }, },
00184     { .key_num = 11, .alt = { "s", "S", "=", "|", NULL, NULL, }, },
00185     { .key_num = 12, .alt = { "d", "D", "(", ";", NULL, NULL, }, },
00186     { .key_num = 13, .alt = { "f", "F", ")", "\"", NULL, NULL, }, },
00187     { .key_num = 14, .alt = { "g", "G", "\\", "\\", NULL, NULL, }, },
00188     { .key_num = 15, .alt = { "h", "H", "*", "*", NULL, NULL, }, },
00189     { .key_num = 16, .alt = { "j", "J", ":", ":", NULL, NULL, }, },
00190     { .key_num = 17, .alt = { "k", "K", ",", ",", NULL, NULL, }, },
00191     { .key_num = 18, .alt = { "l", "L", "/", "/", NULL, NULL, }, },
00192     { .key_num = 19, .alt = { "Shift", "Shift", "Shift", "Shift", "Shift", "Shift", }, },
00193     { .key_num = 20, .alt = { "z", "Z", "~", "~", NULL, NULL, }, },
00194     { .key_num = 21, .alt = { "x", "X", "@", "@", NULL, NULL, }, },
00195     { .key_num = 22, .alt = { "c", "C", "$", "€", NULL, NULL, }, },
00196     { .key_num = 23, .alt = { "v", "V", "&", "&", NULL, NULL, }, },
00197     { .key_num = 24, .alt = { "b", "B", "#", "#", NULL, NULL, }, },
00198     { .key_num = 25, .alt = { "n", "N", "!", "!", NULL, NULL, }, },
00199     { .key_num = 26, .alt = { "m", "M", "?", "?", NULL, NULL, }, },
00200     { .key_num = 27, .alt = { "Backspace", "Backspace", "Backspace", "Backspace", "Backspace", "Backspace", }, },
00201     { .key_num = 28, .alt = { "@123", "@123", "abc", "abc", "@123", "@123", }, },
00202     { .key_num = 29, .alt = { " ", " ", " ", " ", " ", " ", }, },
00203     { .key_num = 30, .alt = { ".", ".", ".", ".", ".", ".", }, },
00204     { .key_num = 31, .alt = { "Enter", "Enter", "Enter", "Enter", "Enter", "Enter", }, },
00205 };
00206 
00207 
00208 //----------------------------------------------------------------------------
00209 // Functions Prototypes 
00210 //----------------------------------------------------------------------------
00211 
00212 static void ergtk_keyb_class_init (ErGtkKeybClass* klass);
00213 static void ergtk_keyb_init (ErGtkKeyb* keyb);
00214 static void ergtk_keyb_finalize(GObject* object);
00215 
00216 static void ergtk_keyb_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec );
00217 static void ergtk_keyb_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec );
00218 
00219 static void ergtk_keyb_populate (ErGtkKeyb* keyb );
00220 static void  ergtk_keyb_populate_real(ErGtkKeyb* keyb );
00221 static void ergtk_keyb_create_key_in_table(ErGtkKeyb* keyb, GtkWidget* table, char* keyname, int keyindex, rangetype range);
00222 
00223 static gboolean ergtk_keyb_button_clicked_event_cb(GtkWidget* button,  gpointer data);
00224 static gboolean on_highlight_expired( gpointer data );
00225 
00226 static gint ergtk_keyb_send_key(ErGtkKeyb* keyb, char* keychar);
00227 static gint ergtk_keyb_send_keysym(ErGtkKeyb* keyb, KeySym keysym );
00228 static gint ergtk_keyb_redraw_keyboard(ErGtkKeyb* keyb);
00229 static int ergtk_keyb_init_fakekey(ErGtkKeyb* keyb);
00230 static void ergtk_keyb_string_free(gpointer data, gpointer user_data );
00231 
00232 
00233 static gboolean label_log_destroy ( GtkWidget* , gpointer );
00234 static gboolean image_log_destroy ( GtkWidget* , gpointer );
00235 static gboolean button_log_destroy ( GtkWidget* button, gpointer data );
00236 
00237 //============================================================================
00238 // Functions Implementation
00239 //============================================================================
00240 
00241 static void ergtk_keyb_class_init (ErGtkKeybClass* klass)
00242 {
00243     DBG_ENTRY;
00244 
00245     GObjectClass* object_class = G_OBJECT_CLASS(klass);
00246 
00247     object_class->set_property = ergtk_keyb_set_property;
00248     object_class->get_property = ergtk_keyb_get_property;
00249 
00250     object_class->finalize = ergtk_keyb_finalize;
00251 
00252     g_object_class_install_property( object_class, 
00253             PROP_NUM_ALTERNATIVES, 
00254             g_param_spec_int (
00255                 "num-alternatives",
00256                 "Number of keyboard alternatives",
00257                 "Specify the number of keyboard layout alternatives",
00258                 0,
00259                 6,
00260                 4,
00261                 G_PARAM_READWRITE ));
00262 
00263 
00264     g_type_class_add_private (klass, sizeof(ErGtkKeybPrivate));
00265 
00266     DBG_EXIT;
00267 }
00268 
00269 static void ergtk_keyb_init (ErGtkKeyb* keyb)
00270 {
00271     DBG_ENTRY;
00272 
00273     ErGtkKeybPrivate* priv = keyb->priv;
00274     priv = keyb->priv =  ERGTK_KEYB_GET_PRIVATE( keyb);
00275     priv->finalizing = FALSE; /* we are not finalizing */
00276     priv->highlight_id = 0;
00277     priv->xmlfile = NULL ; /* for now we do not have any XML keymap support */
00278 
00279     memset(priv->keymap,  0x0, sizeof(priv->keymap));
00280 
00281     int i = 0 ;
00282     for ( i = 0; i< NUM_KEYS; i++ )
00283     {
00284         int j = 0;
00285 
00286         priv->keymap[i].key_num = g_mykeymap[i].key_num;
00287 
00288         for ( j = 0; j<6; j++ )
00289         {
00290             if ( g_mykeymap[i].alt[j] != NULL )
00291             {
00292                 GString* tmp = g_string_new( g_mykeymap[i].alt[j] );
00293                 priv->keymap[i].alt = g_list_prepend(priv->keymap[i].alt, (gpointer) tmp);
00294             }
00295         }
00296         priv->keymap[i].alt = g_list_reverse(priv->keymap[i].alt);
00297     }
00298    
00299     memset(priv->keyboard, 0x0, NUM_KEYS * sizeof(ErGtkKey));
00300     priv->current_alt_keyb_num = 0;
00301     priv->num_alternatives = 4; /* hard coded to match static keymap def */
00302     priv->Xdpy = NULL;
00303     priv->fk = NULL; 
00304     priv->Gdpy = NULL; 
00305 
00306     ergtk_keyb_populate (keyb);
00307     ergtk_keyb_init_fakekey(keyb);
00308 
00309     priv->Gdpy = gdk_display_get_default(); // init gdk display reference
00310 
00311     DBG_EXIT;
00312 }
00313 
00314 GtkWidget* ergtk_keyb_new (void )
00315 {
00316     DBG_ENTRY;
00317 
00318     ErGtkKeyb* result = NULL ; 
00319 
00320     result = g_object_new(ergtk_keyb_get_type(), "num-alternatives", 4, NULL ) ;
00321 
00322     DBG_EXIT;
00323     return GTK_WIDGET( result );
00324 }
00325 
00326 void ergtk_keyb_reset_keymap(ErGtkKeyb* thiz)
00327 {
00328     DBG_ENTRY;
00329 
00330     ErGtkKeybPrivate* priv = thiz->priv;
00331 
00332     DBG("Resetting alternate keymap 0.\n");
00333     priv->current_alt_keyb_num = 0 ;
00334     ergtk_keyb_redraw_keyboard(thiz);
00335 
00336     DBG_EXIT;
00337 }
00338 
00339 static void ergtk_keyb_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec )
00340 {
00341     ErGtkKeyb*          keyb;
00342     ErGtkKeybPrivate*   priv;
00343     gint                num_alternatives;
00344 
00345     keyb = ERGTK_KEYB(object);
00346     priv = keyb->priv;
00347 
00348     switch (prop_id)
00349     {
00350         case PROP_NUM_ALTERNATIVES:
00351             num_alternatives = g_value_get_int(value);
00352             if ( priv->num_alternatives != num_alternatives )
00353             {
00354                 priv->num_alternatives = num_alternatives;
00355             }
00356             break;
00357 
00358         default:
00359             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
00360             break;
00361     }
00362 }
00363 
00364 static void ergtk_keyb_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec )
00365 {
00366     ErGtkKeyb* keyb;
00367     ErGtkKeybPrivate* priv;
00368 
00369     keyb = ERGTK_KEYB(object);
00370     priv = keyb->priv;
00371 
00372     switch (prop_id)
00373     {
00374         case PROP_NUM_ALTERNATIVES:
00375             g_value_set_int(value, priv->num_alternatives);
00376             break;
00377 
00378         default:
00379             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
00380             break;
00381     }
00382 
00383 }
00384 
00385 static void ergtk_keyb_string_free(gpointer data, gpointer user_data )
00386 {
00387     gboolean free_orig = *(gboolean*) user_data ;
00388     GString* to_delete = (GString*) data;
00389     gchar* orig = NULL ;
00390 
00391     orig = g_string_free(to_delete, free_orig);
00392 
00393     if ( free_orig == TRUE )
00394     {
00395         DBG_ASSERT( orig == NULL );
00396     }
00397 }
00398 
00399 static void ergtk_keyb_finalize(GObject* object)
00400 {
00401     DBG_ENTRY;
00402     ErGtkKeyb* keyb = ERGTK_KEYB(object);
00403     ErGtkKeybPrivate* priv = keyb->priv;
00404     priv->finalizing = TRUE;
00405     if ( priv->highlight_id != 0 )
00406     {
00407         g_source_remove(priv->highlight_id);
00408     }
00409     priv->highlight_id = 0;
00410 
00411     gchar* tmp = NULL;
00412     int i = 0 ;
00413 
00414     if ( priv->xmlfile != NULL )
00415     {
00416         tmp = g_string_free(priv->xmlfile, TRUE);
00417         DBG_ASSERT(tmp == NULL ) ;
00418     }
00419 
00420     for ( i = 0; i < NUM_KEYS; i++ )
00421     {
00422         if ( priv->keymap[i].alt != NULL )
00423         {
00424             gboolean weed_out = TRUE ; 
00425             g_list_foreach( priv->keymap[i].alt, ergtk_keyb_string_free, (gpointer) &weed_out);
00426             g_list_free( priv->keymap[i].alt );
00427             priv->keymap[i].alt = NULL ; 
00428         }
00429     }
00430 
00431     for (i = 0; i < NUM_KEYS; i++ )
00432     {
00433         if ( priv->keyboard[i].parent != NULL )
00434         {
00435             priv->keyboard[i].parent = NULL ; 
00436         }
00437         priv->keyboard[i].key_num = 0;
00438 
00439         DBG_ASSERT( priv->keyboard[i].button == NULL ) ;
00440         
00441         if ( priv->keyboard[i].key_facetype == ergtk_keyfacetype_label)
00442         {
00443             DBG_ASSERT( priv->keyboard[i].u.label == NULL ) ;
00444             ;
00445         }
00446         else if ( priv->keyboard[i].key_facetype == ergtk_keyfacetype_image)
00447         {
00448             DBG_ASSERT( priv->keyboard[i].u.image == NULL ) ;
00449             ;
00450         }
00451     }
00452     priv->current_alt_keyb_num = 0 ;
00453     priv->num_alternatives = 0 ;
00454     priv->fk = NULL ; 
00455     XCloseDisplay( priv->Xdpy);
00456     priv->Xdpy = NULL ; 
00457 
00458     G_OBJECT_CLASS (ergtk_keyb_parent_class)->finalize(object);
00459 
00460     // When the keyboard is destroyed, do a full screen update
00461     erkeyb_on_idle_display_yield(DM_HINT_FULL);
00462 
00463     DBG_EXIT;
00464 }
00465 
00466 
00467 static void ergtk_keyb_populate (ErGtkKeyb* keyb )
00468 {
00469     DBG_ENTRY; 
00470 
00471     ErGtkKeybPrivate* priv = keyb->priv;
00472 
00473     int i = 0;
00474     GList* ptr = NULL ;
00475     gchar* tmp = NULL ;
00476 
00477     for ( i = 0; i < NUM_KEYS; i++ )  
00478     {
00479         /* needed for reference from the button clicked callback */
00480         priv->keyboard[i].parent = keyb;
00481 
00482         priv->keyboard[i].key_num = i;
00483 
00484         ptr = g_list_nth(priv->keymap[i].alt, 1);
00485         DBG_ASSERT(ptr != NULL ) ;
00486         tmp = ((GString*)(ptr->data))->str;
00487 
00488         if (strcasecmp(tmp, "Shift") == 0)
00489         {
00490             // Shift has an image instead of a label
00491             priv->keyboard[i].key_facetype = ergtk_keyfacetype_image ; 
00492         }
00493         else if (strcasecmp(tmp, "Backspace") == 0)
00494         {
00495             // Backspace has an image instead of a label
00496             priv->keyboard[i].key_facetype = ergtk_keyfacetype_image ; 
00497         }
00498         else 
00499         {
00500             priv->keyboard[i].key_facetype = ergtk_keyfacetype_label ; 
00501         }
00502     }
00503 
00504     /* continue populating the keyboard widget */
00505     ergtk_keyb_populate_real(keyb);
00506 
00507     DBG_EXIT;
00508 }
00509 
00510 
00511 static void  ergtk_keyb_populate_real(ErGtkKeyb* keyb )
00512 {
00513     DBG_ENTRY;
00514 
00515     ErGtkKeybPrivate* priv = keyb->priv;
00516 
00517     GtkWidget* table = gtk_table_new( NUM_ROWS, NUM_COLUMNS, TRUE ); // 4 rows, 20 columns, homogeneous
00518     gtk_table_set_row_spacings(GTK_TABLE(table), 3 );
00519     gtk_table_set_col_spacings(GTK_TABLE(table), 3 );
00520 
00521     {
00522         int i ; // i is the row
00523         
00524         for ( i = 0; i < NUM_ROWS; i++ ) // for each row
00525         {
00526             switch (i)
00527             {
00528                 case 0: 
00529                     {
00530                         int j; // for each two columns
00531                         int c;
00532 
00533                         for (j = 0, c = FIRST_ROW_START; c < SECOND_ROW_START ; j+=2, c++ )
00534                         {
00535                             rangetype range = { 
00536                                 .row = i,
00537                                 .column = j,
00538                                 .nrows = 1,
00539                                 .ncolumns = 2 
00540                             };
00541                             GList* ptr = g_list_nth(priv->keymap[c].alt, 0);
00542                             DBG_ASSERT( ptr != NULL  ) ;
00543                             gchar* keyname = ((GString*)(ptr->data))->str;
00544                             ergtk_keyb_create_key_in_table(keyb, table, (char*) keyname, c, range);
00545                         }
00546                         break;
00547                     }
00548                 case 1:
00549                     {
00550                         int j=0; // for each two columns
00551                         int c;
00552 
00553                         for (j = 1, c = SECOND_ROW_START; c < THIRD_ROW_START ; j+=2, c++ )
00554                         {
00555                             rangetype range = { 
00556                                 .row = i,
00557                                 .column = j,
00558                                 .nrows = 1,
00559                                 .ncolumns = 2 
00560                             };
00561                             GList* ptr = g_list_nth(priv->keymap[c].alt, 0);
00562                             DBG_ASSERT( ptr != NULL  ) ;
00563                             gchar* keyname = ((GString*)(ptr->data))->str;
00564                             ergtk_keyb_create_key_in_table(keyb, table, (char*) keyname, c, range);
00565                         }
00566                         break;
00567                     }
00568                 case 2:
00569                     {
00570                         int j; // for each two columns
00571                         int c;
00572 
00573                         for (j = 0, c = THIRD_ROW_START; c < FOURTH_ROW_START ; j+=2, c++ )
00574                         {
00575                             if  ( c == THIRD_ROW_START ) // shift 
00576                             {
00577                                 rangetype range = { 
00578                                     .row = i,
00579                                     .column = j,
00580                                     .nrows = 1,
00581                                     .ncolumns = 3 
00582                                 };
00583                                 GList* ptr = g_list_nth(priv->keymap[c].alt, 0);
00584                                 DBG_ASSERT( ptr != NULL  ) ;
00585                                 gchar* keyname = ((GString*)(ptr->data))->str;
00586                                 ergtk_keyb_create_key_in_table(keyb, table, (char*) keyname, c, range);
00587                                 j++; // this key needs three columns -> compensate
00588                             } 
00589                             else if ( c == THIRD_ROW_END ) // BS
00590                             {
00591                                 rangetype range = { 
00592                                     .row = i,
00593                                     .column = j,
00594                                     .nrows = 1,
00595                                     .ncolumns = 3 
00596                                 };
00597                                 GList* ptr = g_list_nth(priv->keymap[c].alt, 0);
00598                                 DBG_ASSERT( ptr != NULL  ) ;
00599                                 gchar* keyname = ((GString*)(ptr->data))->str;
00600                                 ergtk_keyb_create_key_in_table(keyb, table, (char*) keyname, c, range);
00601                             }
00602                             else { // normal key
00603                                 rangetype range = { 
00604                                     .row = i,
00605                                     .column = j,
00606                                     .nrows = 1,
00607                                     .ncolumns = 2 
00608                                 };
00609                                 GList* ptr = g_list_nth(priv->keymap[c].alt, 0);
00610                                 DBG_ASSERT( ptr != NULL  ) ;
00611                                 gchar* keyname = ((GString*)(ptr->data))->str;
00612                                 ergtk_keyb_create_key_in_table(keyb, table, (char*) keyname, c, range);
00613                             }
00614                         }
00615                         break;
00616                     }
00617                 case 3:
00618                     {
00619                         int j=0;
00620                         int c;
00621 
00622                         for (c = FOURTH_ROW_START; c <= FOURTH_ROW_END ; c++ )
00623                         {
00624                             if ( j == 0 )
00625                             {
00626                                 rangetype range = { 
00627                                     .row = i,
00628                                     .column = j,
00629                                     .nrows = 1,
00630                                     .ncolumns = 4 
00631                                 };
00632                                 GList* ptr = g_list_nth(priv->keymap[c].alt, 0);
00633                                 DBG_ASSERT( ptr != NULL  ) ;
00634                                 gchar* keyname = ((GString*)(ptr->data))->str;
00635                                 ergtk_keyb_create_key_in_table(keyb, table, (char*) keyname, c, range);
00636                                 j+=4;  //  this key needs 4 columns
00637                                 continue;
00638                             }
00639                             if ( j == 4 )
00640                             {
00641                                 rangetype range = { 
00642                                     .row = i,
00643                                     .column = j,
00644                                     .nrows = 1,
00645                                     .ncolumns = 10 
00646                                 };
00647                                 GList* ptr = g_list_nth(priv->keymap[c].alt, 0);
00648                                 DBG_ASSERT( ptr != NULL  ) ;
00649                                 gchar* keyname = ((GString*)(ptr->data))->str;
00650                                 ergtk_keyb_create_key_in_table(keyb, table, (char*) keyname, c, range);
00651                                 j+=10; // tihs key needs 10 columns
00652                                 continue;
00653                             }
00654                             if ( j == 14 )
00655                             {
00656                                 rangetype range = { 
00657                                     .row = i,
00658                                     .column = j,
00659                                     .nrows = 1,
00660                                     .ncolumns = 2
00661                                 };
00662                                 GList* ptr = g_list_nth(priv->keymap[c].alt, 0);
00663                                 DBG_ASSERT( ptr != NULL  ) ;
00664                                 gchar* keyname = ((GString*)(ptr->data))->str;
00665                                 ergtk_keyb_create_key_in_table(keyb, table, (char*) keyname, c, range);
00666                                 j+=2;
00667                                 continue;
00668                             }
00669                             if ( j== 16 )
00670                             {
00671                                 rangetype range = { 
00672                                     .row = i,
00673                                     .column = j,
00674                                     .nrows = 1,
00675                                     .ncolumns = 4
00676                                 };
00677                                 GList* ptr = g_list_nth(priv->keymap[c].alt, 0);
00678                                 DBG_ASSERT( ptr != NULL  ) ;
00679                                 gchar* keyname = ((GString*)(ptr->data))->str;
00680                                 ergtk_keyb_create_key_in_table(keyb, table, (char*) keyname, c, range);
00681                                 j+=4;
00682                                 continue;
00683                             }
00684                             DBG_ASSERT( 0 );
00685                             break; // if we get here something is wrong.
00686                         }
00687                         break;
00688                     }
00689                 default:
00690                     {
00691                         DBG_ASSERT( 0 ) ;
00692                         break; // does not happen
00693                     }
00694             }
00695         }
00696     }
00697     gtk_container_add(GTK_CONTAINER(keyb), table);
00698     gtk_widget_show(table);
00699 
00700     DBG_EXIT;
00701 }
00702 
00703 static void ergtk_keyb_create_key_in_table(ErGtkKeyb* keyb, GtkWidget* table, char* keyname, int keyindex, rangetype range)
00704 {
00705     GtkWidget* thekey   = NULL;
00706     GtkWidget* thelabel = NULL;
00707     GtkWidget* theimage = NULL;
00708 
00709     ErGtkKeybPrivate* priv = keyb->priv;
00710 
00711     GList* ptr = g_list_nth(priv->keymap[keyindex].alt, 1);
00712     gchar* tmp = ((GString*)(ptr->data))->str;
00713 
00714     priv->keyboard[keyindex].button = gtk_button_new();
00715 
00716     g_signal_connect(
00717             GTK_OBJECT(priv->keyboard[keyindex].button), 
00718             "destroy", 
00719             GTK_SIGNAL_FUNC(gtk_widget_destroyed), 
00720             (gpointer) &priv->keyboard[keyindex].button
00721             );
00722     g_signal_connect(
00723             GTK_OBJECT(priv->keyboard[keyindex].button), 
00724             "destroy", 
00725             GTK_SIGNAL_FUNC(button_log_destroy), 
00726             (gpointer) NULL
00727             );
00728 
00729     thekey = priv->keyboard[keyindex].button   ;
00730     GTK_WIDGET_UNSET_FLAGS(thekey, GTK_CAN_FOCUS); // buttons can never steal the focus
00731 
00732     // TODO: the image files should be defined in the XML (XML not supported yet) -- open
00733     if (priv->keyboard[keyindex].key_facetype == ergtk_keyfacetype_image ) 
00734     {
00735         if (strcasecmp(tmp, "Shift") == 0)
00736         {
00737             char path[512];
00738             snprintf(path, 512, "%s/%s", PKGDATADIR, "key-shift.png");
00739             priv->keyboard[keyindex].u.image = gtk_image_new_from_file((gchar*) path ); 
00740         }
00741         else if (strcasecmp(tmp, "Backspace") == 0)
00742         {
00743             char path[512];
00744             snprintf(path, 512, "%s/%s", PKGDATADIR, "key-backspace.png");
00745             priv->keyboard[keyindex].u.image = gtk_image_new_from_file((gchar*) path ); 
00746         }
00747         g_signal_connect(
00748                 GTK_OBJECT(priv->keyboard[keyindex].u.image), 
00749                 "destroy", 
00750                 GTK_SIGNAL_FUNC(gtk_widget_destroyed), 
00751                 (gpointer) &priv->keyboard[keyindex].u.image
00752                 );
00753         g_signal_connect(
00754                 GTK_OBJECT(priv->keyboard[keyindex].u.image), 
00755                 "destroy", 
00756                 GTK_SIGNAL_FUNC(image_log_destroy),
00757                 (gpointer) NULL
00758                 );
00759 
00760         theimage = priv->keyboard[keyindex].u.image;
00761         gtk_container_add(GTK_CONTAINER(thekey), theimage);
00762         gtk_widget_show(theimage);
00763     }
00764     else 
00765     {
00766         if ( keyname != NULL )
00767         {
00768             priv->keyboard[keyindex].u.label = gtk_label_new(keyname); 
00769             gtk_widget_set_sensitive(priv->keyboard[keyindex].button, TRUE);
00770         }
00771         else
00772         {
00773             priv->keyboard[keyindex].u.label = gtk_label_new(" "); 
00774             //gtk_widget_set_sensitive(priv->keyboard[keyindex].button, FALSE);
00775             /* leave at true for the moment, looks ugly otherwise */
00776             gtk_widget_set_sensitive(priv->keyboard[keyindex].button, TRUE); 
00777         }
00778         g_signal_connect(
00779                 GTK_OBJECT(priv->keyboard[keyindex].u.label), 
00780                 "destroy", 
00781                 GTK_SIGNAL_FUNC(gtk_widget_destroyed), 
00782                 (gpointer) &priv->keyboard[keyindex].u.label
00783                 );
00784         g_signal_connect(
00785                 GTK_OBJECT(priv->keyboard[keyindex].u.label), 
00786                 "destroy", 
00787                 GTK_SIGNAL_FUNC(label_log_destroy),
00788                 (gpointer) NULL
00789                 );
00790 
00791         thelabel = priv->keyboard[keyindex].u.label ;
00792         gtk_container_add(GTK_CONTAINER(thekey), thelabel);
00793         gtk_widget_show(thelabel);
00794     }
00795 
00796     g_signal_connect(GTK_OBJECT(thekey), "clicked", G_CALLBACK(ergtk_keyb_button_clicked_event_cb), (gpointer) &priv->keyboard[keyindex]);
00797  
00798     gtk_widget_set_size_request(thekey, 35, 35) ;
00799     gtk_table_attach(GTK_TABLE(table), thekey, range.column, (range.column+range.ncolumns), 
00800             range.row, (range.row+range.nrows), GTK_EXPAND|GTK_FILL, GTK_SHRINK|GTK_FILL, 0, 0);
00801 
00802     gtk_widget_show(thekey);
00803 
00804     return;
00805 }
00806 
00807 
00808 static gboolean on_highlight_expired( gpointer data )
00809 {
00810     DBG_ENTRY;
00811 
00812     GtkWidget* button = (GtkWidget*) data ;
00813     GtkWidget* label = gtk_bin_get_child(GTK_BIN(button));
00814 
00815     GdkColor black;
00816     gdk_color_parse("black", &black);
00817     gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &black);
00818     gtk_widget_modify_fg(label, GTK_STATE_ACTIVE, &black);
00819     GdkColor white;
00820     gdk_color_parse("white", &white);
00821     gtk_widget_modify_bg(button, GTK_STATE_NORMAL, &white);
00822     gtk_widget_modify_bg(button, GTK_STATE_ACTIVE, &white);
00823     gtk_widget_queue_draw(button);
00824 
00825     erkeyb_on_idle_display_yield(DM_HINT_KEY);
00826 
00827     DBG_EXIT;
00828     return FALSE;
00829 }
00830 
00831 static gboolean ergtk_keyb_button_clicked_event_cb(GtkWidget* button,  gpointer data)
00832 {   
00833     DBG_ENTRY;
00834 
00835     DBG_ASSERT ( data != NULL ) ;
00836     DBG_ASSERT ( button != NULL );
00837 
00838     ErGtkKey* key = (ErGtkKey*) data;
00839     ErGtkKeyb* keyb = key->parent;
00840     ErGtkKeybPrivate* priv = keyb->priv;
00841     GtkWidget* label = gtk_bin_get_child(GTK_BIN(button));
00842 
00843     GList*  ptr = NULL ;
00844     gchar*  keychar = NULL ; 
00845 
00846     gint display_update_hint = DM_HINT_KEY;
00847 
00848     erkeyb_stop_display_update();
00849 
00850     GdkColor white;
00851     gdk_color_parse("white", &white);
00852     gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &white);
00853     gtk_widget_modify_fg(label, GTK_STATE_ACTIVE, &white);
00854     GdkColor black;
00855     gdk_color_parse("black", &black);
00856     gtk_widget_modify_bg(button, GTK_STATE_NORMAL, &black);
00857     gtk_widget_modify_bg(button, GTK_STATE_ACTIVE, &black);
00858     gtk_widget_queue_draw(button);
00859     
00860     ptr = g_list_nth(priv->keymap[key->key_num].alt, priv->current_alt_keyb_num);
00861 
00862     if ( ptr == NULL )
00863     {
00864         DBG("Key has no value!\n");
00865         goto cb_exit;
00866     }
00867 
00868     /* ptr != NULL */
00869 
00870     keychar = ((GString*)(ptr->data))->str;
00871     DBG_ASSERT(keychar != NULL );
00872     DBG_ASSERT(priv->current_alt_keyb_num < KEY_ALT_MAX ) ;
00873 
00874     if ( priv->current_alt_keyb_num % 2 == 1 ) /* shift pressed -> odd keymap */
00875     {
00876         if (strcasecmp (keychar, "Shift") == 0)
00877         {
00878             DBG("Shift key pressed\n");
00879             priv->current_alt_keyb_num -- ; 
00880             DBG_ASSERT(priv->current_alt_keyb_num >= KEY_ALT0 ) ;
00881             ergtk_keyb_redraw_keyboard(keyb);
00882             display_update_hint = DM_HINT_PARTIAL;
00883             goto cb_exit;
00884         }
00885         if ((strcasecmp (keychar, "@123") == 0) || (strcasecmp (keychar, "abc") == 0))
00886         {
00887             DBG("Switch to alternate keyboard layout key pressed \n");
00888             priv->current_alt_keyb_num += 1;
00889             DBG_ASSERT( priv->current_alt_keyb_num % 2 == 0); /* always a master layout -> even keymap */
00890             DBG_ASSERT( priv->num_alternatives < KEY_ALT_MAX ); /* always less than KEY_ALT_MAX */
00891             priv->current_alt_keyb_num %= priv->num_alternatives; /* wrap around */
00892             ergtk_keyb_redraw_keyboard(keyb);
00893             display_update_hint = DM_HINT_PARTIAL;
00894             goto cb_exit;
00895         }
00896         if (strcasecmp(keychar, "Enter") == 0 )
00897         {
00898             DBG("Return key pressed\n");
00899             ergtk_keyb_send_keysym(keyb, XK_Return);
00900             priv->current_alt_keyb_num --;
00901             DBG_ASSERT(priv->current_alt_keyb_num >= KEY_ALT0 ) ;
00902             ergtk_keyb_redraw_keyboard(keyb);
00903             display_update_hint = DM_HINT_PARTIAL;
00904             goto cb_exit;
00905         }
00906         if (strcasecmp (keychar, "Backspace") == 0)
00907         {
00908             DBG("Backspace pressed\n");
00909             ergtk_keyb_send_keysym(keyb, XK_BackSpace);
00910             priv->current_alt_keyb_num --;
00911             DBG_ASSERT(priv->current_alt_keyb_num >= KEY_ALT0 ) ;
00912             ergtk_keyb_redraw_keyboard(keyb);
00913             display_update_hint = DM_HINT_PARTIAL;
00914             goto cb_exit;
00915         }
00916 
00917         DBG("(Normal) Pressed key %s\n", (char*) keychar );
00918         ergtk_keyb_send_key(keyb, keychar);
00919         priv->current_alt_keyb_num -- ; 
00920         DBG_ASSERT(priv->current_alt_keyb_num >= KEY_ALT0 ) ;
00921         ergtk_keyb_redraw_keyboard(keyb);
00922         display_update_hint = DM_HINT_PARTIAL;
00923         goto cb_exit;
00924     }
00925 
00926     /* we are not in shifted mode -> normal operation */
00927     if (strcasecmp (keychar, "Shift") == 0)
00928     {
00929         DBG("Shift key pressed\n");
00930         DBG_ASSERT(priv->current_alt_keyb_num % 2 == 0 ) ;
00931         priv->current_alt_keyb_num ++ ; 
00932         ergtk_keyb_redraw_keyboard(keyb);
00933         display_update_hint = DM_HINT_PARTIAL;
00934         goto cb_exit;
00935     }
00936     if ((strcasecmp (keychar, "@123") == 0) || (strcasecmp (keychar, "abc") == 0))
00937     {
00938         DBG("Switch to alternate keyboard layout key pressed \n");
00939         DBG_ASSERT( priv->current_alt_keyb_num % 2 == 0); /* always a master layout -> even keymap */
00940         DBG_ASSERT( priv->num_alternatives < KEY_ALT_MAX ); /* always less than KEY_ALT_MAX */
00941         priv->current_alt_keyb_num += 2 ; 
00942         priv->current_alt_keyb_num %= priv->num_alternatives;
00943         ergtk_keyb_redraw_keyboard(keyb);
00944         display_update_hint = DM_HINT_PARTIAL;
00945         goto cb_exit;
00946     }
00947     if (strcasecmp (keychar, "Backspace") == 0)
00948     {
00949         DBG("Backspace pressed\n");
00950         ergtk_keyb_send_keysym(keyb, XK_BackSpace);
00951         display_update_hint = DM_HINT_KEY;
00952         goto cb_exit;
00953     }
00954     if (strcasecmp(keychar, "Enter") == 0 )
00955     {
00956         DBG("Return key pressed\n");
00957         ergtk_keyb_send_keysym(keyb, XK_Return);
00958         display_update_hint = DM_HINT_KEY;
00959         goto cb_exit;
00960     }
00961 
00962     DBG("(Normal) Pressed key %s\n", (char*) keychar );
00963     ergtk_keyb_send_key(keyb, keychar);
00964     display_update_hint = DM_HINT_KEY;
00965 
00966 cb_exit:
00967     gtk_widget_queue_draw(button);
00968     gdk_display_flush(priv->Gdpy);
00969     gdk_display_sync(priv->Gdpy);  /* this may be some serious overkill */
00970 
00971     erkeyb_on_timeout_display_update(50, display_update_hint);
00972 
00973     // schedule an unhighlight action for the same button 
00974     priv->highlight_id = g_timeout_add(200, on_highlight_expired, (gpointer) button );
00975 
00976     DBG_EXIT;
00977     return FALSE;
00978 }
00979 
00980 static gint ergtk_keyb_redraw_keyboard(ErGtkKeyb* keyb)
00981 {
00982     DBG_ENTRY;
00983 
00984     GList* ptr = NULL ; 
00985     gchar* tmp = NULL ; 
00986 
00987     ErGtkKeybPrivate* priv = keyb->priv;
00988 
00989     int i = 0;
00990 
00991     for (i=0; i < NUM_KEYS; i++ ) /* hard coded -> use define or so here */
00992     {
00993 
00994         ptr = g_list_nth( priv->keymap[i].alt, priv->current_alt_keyb_num);
00995 
00996         if ( NULL != ptr )
00997         {
00998             tmp = ((GString*)(ptr->data))->str;
00999         }
01000         else 
01001         {
01002             tmp = NULL ; 
01003         }
01004         
01005         switch (i)
01006         {
01007             case 19:
01008             case 27: 
01009             //case 31: // Enter key has label instead of image now
01010                 break;
01011             default:
01012                 if ( tmp  != NULL ) { 
01013                     gtk_label_set_label(GTK_LABEL(priv->keyboard[i].u.label), (const gchar*) tmp);
01014                     gtk_widget_set_sensitive(priv->keyboard[i].button, TRUE);
01015                 }
01016                 else {
01017                     gtk_label_set_label(GTK_LABEL(priv->keyboard[i].u.label), (const gchar*) " ");
01018                     // gtk_widget_set_sensitive(priv->keyboard[i].button, FALSE);
01019                     /* leave at true for the moment, looks ugly otherwise */
01020                     gtk_widget_set_sensitive(priv->keyboard[i].button, TRUE);
01021                 }
01022                 break;
01023         }
01024     }
01025 
01026     DBG_EXIT;
01027     return FALSE ;
01028 }
01029 
01030 static gint ergtk_keyb_send_key(ErGtkKeyb* keyb, char* keychar)
01031 {
01032     DBG_ENTRY;
01033     
01034     ErGtkKeybPrivate* priv = keyb->priv;
01035 
01036     DBG_ASSERT( priv->fk != NULL );
01037 
01038     fakekey_press(priv->fk, (const unsigned char*) keychar, -1 , 0);
01039     fakekey_release(priv->fk);
01040 
01041     DBG_EXIT;
01042     return 1;
01043 }
01044 
01045 static gint ergtk_keyb_send_keysym(ErGtkKeyb* keyb, KeySym keysym )
01046 {
01047     DBG_ENTRY;
01048 
01049     ErGtkKeybPrivate* priv = keyb->priv;
01050 
01051     DBG_ASSERT( priv->fk != NULL );
01052 
01053     fakekey_press_keysym(priv->fk, keysym, 0 );
01054     fakekey_release(priv->fk);
01055 
01056     DBG_EXIT;
01057     return 1;
01058 }
01059 
01060 static int ergtk_keyb_init_fakekey(ErGtkKeyb* keyb)
01061 {
01062     ErGtkKeybPrivate* priv = keyb->priv;
01063 
01064     priv->Xdpy = XOpenDisplay(getenv("DISPLAY"));
01065 
01066     if (priv->Xdpy  == NULL)
01067     {
01068             ERR("Could not open X display\n");
01069             DBG_EXIT;
01070             return 0;
01071     }
01072 
01073     priv->fk = fakekey_init(priv->Xdpy);
01074 
01075     if ( priv->fk == NULL)
01076     {
01077             ERR("Could not initialize fakekey\n");
01078             DBG_EXIT;
01079             return 0;
01080     }
01081 
01082     DBG("fakekey initialized\n");
01083     return 1;
01084 
01085 }
01086 
01087 static gboolean label_log_destroy ( GtkWidget* label, gpointer data )
01088 {
01089     DBG("-- LABEL  destroyed.\n");
01090     return FALSE;
01091 }
01092 
01093 static gboolean image_log_destroy ( GtkWidget* image, gpointer data )
01094 {
01095     DBG("-- IMAGE  destroyed.\n");
01096     return FALSE;
01097 }
01098 
01099 static gboolean button_log_destroy ( GtkWidget* button, gpointer data )
01100 {
01101     DBG("-- BUTTON  destroyed.\n");
01102     return FALSE;
01103 }
Generated by  doxygen 1.6.2-20100208