Back to index

im-sdk  12.3.91
vkb_aux.c
Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include "SunIM.h"
00003 #include "vkb_aux.h"
00004 
00005 enum {
00006     BUTTON_STATE_NORMAL = 0,
00007     BUTTON_STATE_FOCUSED,
00008     BUTTON_STATE_PRESSED,
00009 };
00010 
00011 static void vkb_window_init_attributes(vkb_window_t *vkb_window);
00012 static void vkb_window_set_position(vkb_window_t *vkb_window,
00013                                    gint pos_x, gint pos_y);
00014 static gboolean vkb_window_expose_event_handler(GtkWidget *widget,
00015                                    GdkEventExpose *event,
00016                                    vkb_window_t *vkb_window);
00017 static gboolean vkb_window_configure_event_handler(GtkWidget *widget,
00018                                    GdkEventConfigure *event,
00019                                    vkb_window_t *vkb_window);
00020 static gboolean vkb_window_leave_event_handler(GtkWidget *widget,
00021                                    GdkEventCrossing *event,
00022                                    vkb_window_t *vkb_window);
00023 static gboolean vkb_window_pointer_motion_event_handler(GtkWidget *widget,
00024                                    GdkEventMotion *event,
00025                                    vkb_window_t *vkb_window);
00026 static gboolean vkb_window_pointer_press_event_handler(GtkWidget *widget,
00027                                    GdkEventButton *event,
00028                                    vkb_window_t *vkb_window);
00029 static gboolean vkb_window_pointer_release_event_handler(GtkWidget *widget,
00030                                    GdkEventButton *event,
00031                                    vkb_window_t *vkb_window);
00032 
00033 #define DATA_VKB_AUX_WINDOW_INFO   "vkb_window_info"
00034 
00035 vkb_window_t *vkb_window_new()
00036 {
00037     vkb_window_t *vkb_window = NULL;
00038 
00039     vkb_window = (vkb_window_t *)calloc(1, sizeof (vkb_window_t));
00040     if (vkb_window == NULL)
00041         return NULL;
00042 
00043     vkb_window->window = gtk_window_new(GTK_WINDOW_POPUP);
00044     gtk_window_set_modal (GTK_WINDOW (vkb_window->window), FALSE);
00045     gtk_window_set_destroy_with_parent (GTK_WINDOW (vkb_window->window), TRUE);
00046 
00047     gtk_container_set_border_width(GTK_CONTAINER(vkb_window->window), 0);
00048 
00049     vkb_window->drawing_area = gtk_drawing_area_new();
00050 
00051     gtk_widget_set_events(vkb_window->drawing_area,
00052                        GDK_EXPOSURE_MASK |
00053                        GDK_LEAVE_NOTIFY_MASK |
00054                        GDK_BUTTON_PRESS_MASK |
00055                        GDK_BUTTON_RELEASE_MASK |
00056                        GDK_POINTER_MOTION_MASK);
00057 
00058     g_signal_connect(G_OBJECT(vkb_window->drawing_area),
00059                    "expose_event",
00060                    G_CALLBACK(vkb_window_expose_event_handler),
00061                    (gpointer)vkb_window);
00062 
00063     g_signal_connect(G_OBJECT(vkb_window->drawing_area),
00064                    "configure_event",
00065                    G_CALLBACK(vkb_window_configure_event_handler),
00066                    (gpointer)vkb_window);
00067 
00068     g_signal_connect(G_OBJECT(vkb_window->drawing_area),
00069                    "leave_notify_event",
00070                    G_CALLBACK(vkb_window_leave_event_handler),
00071                    (gpointer)vkb_window);
00072 
00073     g_signal_connect(G_OBJECT(vkb_window->drawing_area),
00074                    "button_press_event",
00075                    G_CALLBACK(vkb_window_pointer_press_event_handler),
00076                    (gpointer)vkb_window);
00077 
00078     g_signal_connect(G_OBJECT(vkb_window->drawing_area),
00079                    "button_release_event",
00080                    G_CALLBACK(vkb_window_pointer_release_event_handler),
00081                    (gpointer)vkb_window);
00082 
00083     g_signal_connect(G_OBJECT(vkb_window->drawing_area),
00084                    "motion-notify-event",
00085                    G_CALLBACK(vkb_window_pointer_motion_event_handler),
00086                    (gpointer)vkb_window);
00087 
00088     gtk_container_add(GTK_CONTAINER(vkb_window->window),
00089                     vkb_window->drawing_area);
00090 
00091     gtk_widget_realize(GTK_WIDGET(vkb_window->window));
00092 
00093     vkb_window_init_attributes(vkb_window);
00094 
00095     gtk_widget_set_size_request(GTK_WIDGET(vkb_window->drawing_area),
00096                             vkb_window->width,
00097                             vkb_window->height);
00098 
00099     gtk_window_move(GTK_WINDOW(vkb_window->window),
00100                   vkb_window->pos_x,
00101                   vkb_window->pos_y);
00102 
00103     return (vkb_window);
00104 }
00105 
00106 void
00107 vkb_window_destroy(vkb_window_t *vkb_window)
00108 {
00109     if (!vkb_window)
00110        return;
00111 
00112     if (vkb_window->fontdesc_basekey)
00113        pango_font_description_free(vkb_window->fontdesc_basekey);
00114 
00115     if (vkb_window->fontdesc_ctrlkey)
00116        pango_font_description_free(vkb_window->fontdesc_ctrlkey);
00117 
00118     if (vkb_window->pango_layout)
00119        g_object_unref(vkb_window->pango_layout);
00120 
00121     if (vkb_window->moving_cursor)
00122        gdk_cursor_unref(vkb_window->moving_cursor);
00123 
00124     if (vkb_window->normal_cursor)
00125        gdk_cursor_unref(vkb_window->normal_cursor);
00126 
00127     if (vkb_window->pixmap)
00128         gdk_pixmap_unref(vkb_window->pixmap);
00129 
00130     if (vkb_window->window)
00131        gtk_widget_destroy(vkb_window->window);
00132 
00133     free ((char *)vkb_window);
00134 }
00135 
00136 static void
00137 vkb_window_init_attributes(vkb_window_t *vkb_window)
00138 {
00139     GdkRectangle *buttons;
00140 
00141     int pos_x, pos_y, margin_x, margin_y;
00142     int height, width, button_height, button_width;
00143     int delta_y = 1;
00144     int i, j;
00145 
00146     vkb_window->context = gtk_widget_get_pango_context(vkb_window->drawing_area);
00147     vkb_window->pango_layout = pango_layout_new(vkb_window->context);
00148 
00149     vkb_window->fontdesc_basekey = pango_font_description_from_string("sans 9");
00150     vkb_window->fontdesc_ctrlkey = pango_font_description_from_string("sans 10");
00151 
00152     vkb_window->pixmap = NULL;
00153 
00154     vkb_window->moving_cursor = gdk_cursor_new (GDK_FLEUR);
00155     vkb_window->normal_cursor = gdk_cursor_new (GDK_LEFT_PTR);
00156 
00157     vkb_window->button_id_pressed = -1;
00158     vkb_window->button_id_focused = -1;
00159 
00160     buttons = vkb_window->buttons;
00161 
00162     button_height = 27;
00163     button_width = button_height - 1;
00164 
00165     margin_x = 2;
00166     margin_y = 2;
00167 
00168     /* layout for the first line */
00169     pos_x = margin_x;
00170     pos_y = margin_y;
00171 
00172     for (i = VK_quotedbl; i <= VK_equal; i++) {
00173        width = button_width;
00174        buttons[i].x = pos_x;
00175        buttons[i].y = pos_y;
00176        buttons[i].width = width;
00177        buttons[i].height = button_height;
00178        pos_x += width;
00179     }
00180 
00181     i = VK_BackSpace + MAX_BASEKEY_NUM;
00182     width = button_width * 2;
00183     buttons[i].x = pos_x;
00184     buttons[i].y = pos_y;
00185     buttons[i].width = width;
00186     buttons[i].height = button_height;
00187 
00188     /* layout for the second line */
00189     pos_x = margin_x;
00190     pos_y += button_height + delta_y;
00191 
00192     i = VK_Tab + MAX_BASEKEY_NUM;
00193     width = button_width * 3 / 2;
00194     buttons[i].x = pos_x;
00195     buttons[i].y = pos_y;
00196     buttons[i].width = width;
00197     buttons[i].height = button_height;
00198     pos_x += width;
00199 
00200     for (i = VK_q; i <= VK_backslash; i++) {
00201        width = button_width;
00202        if (i == VK_backslash)
00203            width = button_width * 3 / 2;
00204 
00205        buttons[i].x = pos_x;
00206        buttons[i].y = pos_y;
00207        buttons[i].width = width;
00208        buttons[i].height = button_height;
00209        pos_x += width;
00210     }
00211 
00212     /* layout for the third line */
00213     pos_x = margin_x;
00214     pos_y += button_height + delta_y;
00215 
00216     i = VK_CapsLock + MAX_BASEKEY_NUM;
00217     width = button_width * 2;
00218     buttons[i].x = pos_x;
00219     buttons[i].y = pos_y;
00220     buttons[i].width = width;
00221     buttons[i].height = button_height;
00222     pos_x += width;
00223 
00224     for (i = VK_a; i <= VK_apostrophe; i++) {
00225        width = button_width;
00226        buttons[i].x = pos_x;
00227        buttons[i].y = pos_y;
00228        buttons[i].width = width;
00229        buttons[i].height = button_height;
00230        pos_x += width;
00231     }
00232 
00233     i = VK_Enter + MAX_BASEKEY_NUM;
00234     width = button_width * 2;
00235     buttons[i].x = pos_x;
00236     buttons[i].y = pos_y;
00237     buttons[i].width = width;
00238     buttons[i].height = button_height;
00239     pos_x += width;
00240 
00241     /* layout for the fourth line */
00242     pos_x = margin_x;
00243     pos_y += button_height + delta_y;
00244 
00245     i = VK_Shift_L + MAX_BASEKEY_NUM;
00246     width = button_width * 5 / 2;
00247     buttons[i].x = pos_x;
00248     buttons[i].y = pos_y;
00249     buttons[i].width = width;
00250     buttons[i].height = button_height;
00251     pos_x += width;
00252 
00253     for (i = VK_z; i <= VK_slash; i++) {
00254        width = button_width;
00255        buttons[i].x = pos_x;
00256        buttons[i].y = pos_y;
00257        buttons[i].width = width;
00258        buttons[i].height = button_height;
00259        pos_x += width;
00260     }
00261 
00262     /* layout for the fifth line */
00263     pos_x = margin_x;
00264     pos_y += button_height + delta_y;
00265 
00266     for (i = VK_Control_L; i <= VK_Escape; i++) {
00267        width = 2 * button_width;
00268        if (i == VK_Space)
00269            width = 7 * button_width;
00270        if (i == VK_Escape)
00271            pos_x += 2 * button_width;
00272        j = i + MAX_BASEKEY_NUM;
00273        buttons[j].x = pos_x;
00274        buttons[j].y = pos_y;
00275        buttons[j].width = width;
00276        buttons[j].height = button_height;
00277        pos_x += width;
00278     }
00279 
00280     /* Calculate the frame dimension of the Virtual keyboard */
00281     width = 15 * button_width + 2 * margin_x;
00282     height = 5 * button_height + 2 * margin_y + 4 * delta_y;
00283 
00284     vkb_window->width = width;
00285     vkb_window->height = height;
00286 
00287     vkb_window->pos_x = gdk_screen_width() - vkb_window->width;
00288     vkb_window->pos_y = gdk_screen_height() - vkb_window->height - 70;
00289 
00290     vkb_window->draging = FALSE;
00291     vkb_window->draw_draging_frame = TRUE;
00292 }
00293 
00294 static void
00295 vkb_window_draw_button(vkb_window_t *vkb_window,
00296                      int button_id,
00297                      int button_state)
00298 {
00299     GdkGC *label_gc;
00300     GdkRectangle *rect;
00301     GtkShadowType shadow_type = GTK_SHADOW_OUT;
00302     GtkStateType  state_type = GTK_STATE_NORMAL;
00303     GdkRectangle *buttons = vkb_window->buttons;
00304     int pos_x, pos_y;
00305 
00306     gchar *str;
00307 
00308     if (!vkb_window || !vkb_window->pixmap)
00309        return;
00310 
00311     if (button_id < 0 || button_id >= MAX_VK_NUM)
00312        return;
00313 
00314     rect = &buttons[button_id];
00315 
00316     if (button_state == BUTTON_STATE_PRESSED) {
00317        state_type = GTK_STATE_ACTIVE;
00318        shadow_type = GTK_SHADOW_IN;
00319     } else if (button_state == BUTTON_STATE_FOCUSED) {
00320        state_type = GTK_STATE_PRELIGHT;
00321        shadow_type = GTK_SHADOW_OUT;
00322     }
00323 
00324     /* draw button frame */
00325     gtk_paint_box(vkb_window->drawing_area->style, vkb_window->pixmap,
00326                 state_type, shadow_type,
00327                 NULL, vkb_window->drawing_area, "button",
00328                 rect->x, rect->y, rect->width, rect->height);
00329 
00330     if (!vkb_window->layout)
00331        return;
00332 
00333     label_gc = vkb_window->drawing_area->style->text_gc[GTK_STATE_NORMAL];
00334 
00335     if (button_id >= MAX_BASEKEY_NUM) {
00336        /* if is Control Keys */
00337        str = vkb_window->layout->ctrlkey[button_id - MAX_BASEKEY_NUM].label_str;
00338        if (str && *str) {
00339            PangoRectangle logical_rect;
00340            int str_width, str_height;
00341 
00342            pango_layout_set_font_description(vkb_window->pango_layout,
00343                                          vkb_window->fontdesc_ctrlkey);
00344            pango_layout_set_text(vkb_window->pango_layout, str, strlen(str));
00345            pango_layout_get_extents(vkb_window->pango_layout, NULL, &logical_rect);
00346 
00347            str_width = PANGO_PIXELS(logical_rect.width);
00348            str_height = PANGO_PIXELS(logical_rect.height);
00349            pos_x = rect->x + (rect->width - str_width)/2;
00350            pos_y = rect->y + (rect->height - str_height)/2;
00351            gdk_draw_layout(vkb_window->pixmap, label_gc,
00352                          pos_x, pos_y, vkb_window->pango_layout);
00353        }
00354     } else {
00355        /* if is Base Keys */
00356        str = vkb_window->layout->basekey[button_id].lower_str;
00357         if(!strcmp(str, "\\"))
00358        {
00359                g_unichar_to_utf8(0x20a9, str);
00360                 str[3] = '\0';
00361                 str[4] = '\0';
00362        }
00363        pango_layout_set_font_description(vkb_window->pango_layout,
00364                                      vkb_window->fontdesc_basekey);
00365        if (str && *str) {
00366            pango_layout_set_text(vkb_window->pango_layout, str, strlen(str));
00367            pos_x = rect->x + 2;
00368            pos_y = rect->y + 11;
00369            gdk_draw_layout(vkb_window->pixmap, label_gc,
00370                          pos_x, pos_y, vkb_window->pango_layout);
00371        }
00372 
00373        str = vkb_window->layout->basekey[button_id].upper_str;
00374        if (str && *str) {
00375            pango_layout_set_text(vkb_window->pango_layout, str, strlen(str));
00376            pos_x = rect->x + rect->width - 14;
00377            pos_y = rect->y + 1;
00378            gdk_draw_layout(vkb_window->pixmap, label_gc,
00379                          pos_x, pos_y, vkb_window->pango_layout);
00380        }
00381     }
00382 
00383     return;
00384 }
00385 
00386 void vkb_window_draw_layout(vkb_window_t *vkb_window)
00387 {
00388 
00389     gint button_id;
00390     gint ctrl_button_id;
00391     gint button_state;
00392 
00393     if (!vkb_window || !vkb_window->pixmap)
00394        return;
00395 
00396     gtk_paint_box(vkb_window->drawing_area->style, vkb_window->pixmap,
00397                 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
00398                 NULL, vkb_window->drawing_area, "button",
00399                 0, 0,
00400                 vkb_window->width,
00401                 vkb_window->height);
00402 
00403     for (button_id = 0; button_id < MAX_VK_NUM; button_id ++) {
00404         button_state = BUTTON_STATE_NORMAL;
00405 
00406        if (button_id >= MAX_BASEKEY_NUM) {
00407            /* if is Control Keys */
00408            ctrl_button_id = button_id - MAX_BASEKEY_NUM;
00409            if (ctrl_button_id == VK_CapsLock) {
00410               if (vkb_window->status_capslockkey)
00411                   button_state = BUTTON_STATE_PRESSED;
00412            } else if (ctrl_button_id == VK_Control_L) {
00413               if (vkb_window->status_ctrlkey)
00414                   button_state = BUTTON_STATE_PRESSED;
00415            } else if (ctrl_button_id == VK_Shift_L) {
00416               if (vkb_window->status_shiftkey)
00417                   button_state = BUTTON_STATE_PRESSED;
00418            } else if (ctrl_button_id == VK_Alt_L) {
00419               if (vkb_window->status_altkey)
00420                   button_state = BUTTON_STATE_PRESSED;
00421            }
00422        } else if (button_id == vkb_window->button_id_pressed) {
00423            button_state = BUTTON_STATE_PRESSED;
00424        }
00425 
00426        vkb_window_draw_button(vkb_window, button_id, button_state);
00427     }
00428 }
00429 
00430 void vkb_window_update_layout(vkb_window_t *vkb_window,
00431                            vkb_layout_t *vkb_layout)
00432 {
00433     if (!vkb_window)
00434        return;
00435 
00436     if (vkb_layout == NULL) {
00437        gtk_widget_hide(vkb_window->window);
00438        return;
00439     }
00440 
00441     vkb_window->layout = vkb_layout;
00442 
00443     vkb_window_draw_layout(vkb_window);
00444 
00445     gtk_widget_show_all(vkb_window->window);
00446     gtk_widget_queue_draw(vkb_window->drawing_area);
00447 }
00448 
00449 static gboolean vkb_window_rect_has_pos(GdkRectangle * rect, int x, int y)
00450 {
00451     return ((rect->x <= x) && (rect->x + rect->width >= x) &&
00452            (rect->y <= y) && (rect->y + rect->height >= y));
00453 }
00454 
00455 static gint vkb_window_get_button_id_from_pos(vkb_window_t *vkb_window, int x, int y)
00456 {
00457     gint i;
00458     for (i = 0; i < MAX_VK_NUM; i++) {
00459        if (vkb_window_rect_has_pos(&vkb_window->buttons[i], x, y))
00460            return i;
00461     }
00462     return -1;
00463 }
00464 
00465 static void
00466 vkb_window_set_position(vkb_window_t *vkb_window,
00467                      gint pos_x, gint pos_y)
00468 {
00469     GtkRequisition ws;
00470     gint screen_width;
00471     gint screen_height;
00472 
00473     gtk_widget_size_request(vkb_window->window, &ws);
00474 
00475     screen_width = gdk_screen_width();
00476     screen_height = gdk_screen_height();
00477 
00478     if (pos_x < 0) {
00479         pos_x = 0;
00480     } else if (pos_x + ws.width > screen_width) {
00481         pos_x = screen_width - ws.width;
00482     }
00483 
00484     if (pos_y < 0) {
00485         pos_y = 0;
00486     } else if (pos_y + ws.height > screen_height) {
00487         pos_y = screen_height - ws.height;
00488     }
00489 
00490     if (vkb_window->pos_x != pos_x || vkb_window->pos_y != pos_y) {
00491         gtk_window_move(GTK_WINDOW(vkb_window->window), pos_x, pos_y);
00492         vkb_window->pos_x = pos_x;
00493         vkb_window->pos_y = pos_y;
00494     }
00495 }
00496 
00497 /********************************************************************/
00498 /*       key status functions                                       */
00499 /********************************************************************/
00500 static int vkb_base_keycode[MAX_BASEKEY_NUM] = {
00501     IM_VK_BACK_QUOTE,
00502     IM_VK_1,
00503     IM_VK_2,
00504     IM_VK_3,
00505     IM_VK_4,
00506     IM_VK_5,
00507     IM_VK_6,
00508     IM_VK_7,
00509     IM_VK_8,
00510     IM_VK_9,
00511     IM_VK_0,
00512     IM_VK_MINUS,
00513     IM_VK_EQUALS,
00514 
00515     IM_VK_Q,
00516     IM_VK_W,
00517     IM_VK_E,
00518     IM_VK_R,
00519     IM_VK_T,
00520     IM_VK_Y,
00521     IM_VK_U,
00522     IM_VK_I,
00523     IM_VK_O,
00524     IM_VK_P,
00525     IM_VK_OPEN_BRACKET,
00526     IM_VK_CLOSE_BRACKET,
00527     IM_VK_BACK_SLASH,
00528 
00529     IM_VK_A,
00530     IM_VK_S,
00531     IM_VK_D,
00532     IM_VK_F,
00533     IM_VK_G,
00534     IM_VK_H,
00535     IM_VK_J,
00536     IM_VK_K,
00537     IM_VK_L,
00538     IM_VK_SEMICOLON,
00539     IM_VK_QUOTE,
00540 
00541     IM_VK_Z,
00542     IM_VK_X,
00543     IM_VK_C,
00544     IM_VK_V,
00545     IM_VK_B,
00546     IM_VK_N,
00547     IM_VK_M,
00548     IM_VK_COMMA,
00549     IM_VK_PERIOD, 
00550     IM_VK_SLASH,
00551 };
00552 
00553 static int vkb_ctrl_keycode[MAX_CTRLKEY_NUM] = {
00554     IM_VK_BACK_SPACE,
00555     IM_VK_TAB,
00556     IM_VK_CAPS_LOCK,
00557     IM_VK_ENTER,
00558     0,
00559     0,
00560     0,
00561     IM_VK_SPACE,
00562     IM_VK_ESCAPE
00563 };
00564 
00565 void vkb_window_clear_keystatus(vkb_window_t *vkb_window)
00566 {
00567     vkb_window->status_ctrlkey = 0;
00568     vkb_window->status_shiftkey = 0;
00569     vkb_window->status_altkey = 0;
00570 
00571     return;
00572 }
00573 
00574 void vkb_window_get_keyevent(vkb_window_t *vkb_window,
00575                           int button_id,
00576                           int *keycode,
00577                           int *keychar,
00578                           int *keystatus)
00579 {
00580     char *keychar_list;
00581 
00582     *keycode = 0;
00583     *keychar = 0;
00584     *keystatus = 0;
00585 
00586     if (button_id < 0 || button_id >= MAX_VK_NUM)
00587        return;
00588 
00589     if (button_id >= MAX_BASEKEY_NUM) {
00590        *keycode = vkb_ctrl_keycode[button_id - MAX_BASEKEY_NUM];
00591        *keychar = 0;
00592        if (button_id - MAX_BASEKEY_NUM == VK_Space)
00593            *keychar = 0x20;
00594     } else {
00595        *keycode = vkb_base_keycode[button_id];
00596 
00597        keychar_list = (char *)KEYLIST_LOWER;
00598        if (vkb_window->status_capslockkey ^ vkb_window->status_shiftkey)
00599            keychar_list = (char *)KEYLIST_UPPER;
00600        *keychar = *(keychar_list + button_id);
00601     } 
00602 
00603     if (vkb_window->status_ctrlkey)
00604        *keystatus |= IM_CTRL_MASK;
00605     if (vkb_window->status_shiftkey)
00606        *keystatus |= IM_SHIFT_MASK;
00607     if (vkb_window->status_altkey)
00608        *keystatus |= IM_ALT_MASK;
00609 
00610     return;
00611 }
00612 
00613 void vkb_window_redraw_ctrl_buttons(vkb_window_t *vkb_window)
00614 {
00615     int button_id, button_state;
00616 
00617     for (button_id = MAX_BASEKEY_NUM; button_id < MAX_VK_NUM; button_id++) {
00618        button_state = BUTTON_STATE_NORMAL;
00619         if (button_id - MAX_BASEKEY_NUM == VK_CapsLock) {
00620            if (vkb_window->status_capslockkey)
00621               button_state = BUTTON_STATE_PRESSED;
00622         } else if (button_id - MAX_BASEKEY_NUM == VK_Control_L) {
00623            if (vkb_window->status_ctrlkey)
00624               button_state = BUTTON_STATE_PRESSED;
00625         } else if (button_id - MAX_BASEKEY_NUM == VK_Shift_L) {
00626            if (vkb_window->status_shiftkey)
00627               button_state = BUTTON_STATE_PRESSED;
00628         } else if (button_id - MAX_BASEKEY_NUM == VK_Alt_L) {
00629            if (vkb_window->status_altkey)
00630               button_state = BUTTON_STATE_PRESSED;
00631         }
00632 
00633        vkb_window_draw_button(vkb_window, button_id, button_state);
00634     }
00635     gtk_widget_queue_draw(vkb_window->drawing_area);
00636     return;
00637 }
00638 
00639 void vkb_window_press_key(vkb_window_t *vkb_window,
00640                        int button_id_pressed)
00641 {
00642     int keycode, keychar, keystatus;
00643     char *commit_str, *keylist_str, base_str[2];
00644     int ctrl_key_id;
00645     int button_state = BUTTON_STATE_NORMAL;
00646 
00647     DEBUG_printf("vkb_window_press_key() is called\n");
00648 
00649     if (vkb_window == NULL || vkb_window->layout == NULL)
00650         return;
00651 
00652     if (button_id_pressed < 0 || button_id_pressed >= MAX_VK_NUM)
00653         return;
00654 
00655     if (button_id_pressed >= MAX_BASEKEY_NUM) {
00656        /* if is Control Keys, set key status or commit as virtual key. */
00657        ctrl_key_id = button_id_pressed - MAX_BASEKEY_NUM;
00658 
00659        if (ctrl_key_id == VK_BackSpace ||
00660             ctrl_key_id == VK_Tab ||
00661             ctrl_key_id == VK_Enter ||
00662             ctrl_key_id == VK_Space ||
00663             ctrl_key_id == VK_Escape) {
00664             /* if not Control status key, commit as key event */
00665             vkb_window_get_keyevent(vkb_window, button_id_pressed,
00666                                 &keycode, &keychar, &keystatus);
00667             palette_aux_Commit_Key_Request(keycode, keychar, keystatus);
00668             vkb_window_clear_keystatus(vkb_window);
00669         } else if (ctrl_key_id == VK_CapsLock) {
00670            vkb_window->status_capslockkey = vkb_window->status_capslockkey ? 0 : 1;
00671         } else if (ctrl_key_id == VK_Control_L) {
00672            vkb_window->status_ctrlkey = vkb_window->status_ctrlkey ? 0 : 1;
00673         } else if (ctrl_key_id == VK_Shift_L) {
00674            vkb_window->status_shiftkey = vkb_window->status_shiftkey ? 0 : 1;
00675         } else if (ctrl_key_id == VK_Alt_L) {
00676            vkb_window->status_altkey = vkb_window->status_altkey ? 0 : 1;
00677         }
00678 
00679        /* redraw the pressed button */
00680        vkb_window_redraw_ctrl_buttons(vkb_window);
00681        return;
00682     }
00683 
00684     if (vkb_window->layout->type == KEYBOARD_KEY_TYPE) {
00685         vkb_window_get_keyevent(vkb_window, button_id_pressed,
00686                             &keycode, &keychar, &keystatus);
00687         palette_aux_Commit_Key_Request(keycode, keychar, keystatus);
00688     } else {
00689        if (vkb_window->status_ctrlkey || vkb_window->status_altkey) {
00690             vkb_window_get_keyevent(vkb_window, button_id_pressed,
00691                                 &keycode, &keychar, &keystatus);
00692             palette_aux_Commit_Key_Request(keycode, keychar, keystatus);
00693        } else {
00694            if (vkb_window->status_capslockkey ^ vkb_window->status_shiftkey) {
00695               /* commit upper string */
00696               commit_str = vkb_window->layout->basekey[button_id_pressed].upper_str;
00697               if (!commit_str || !*commit_str) {
00698                   keylist_str = (char *)KEYLIST_UPPER;
00699                   base_str[0] = *(keylist_str + button_id_pressed);
00700                   base_str[1] = 0;
00701                   commit_str = base_str;
00702               }
00703            } else {
00704               /* commit lower string */
00705               commit_str = vkb_window->layout->basekey[button_id_pressed].lower_str;
00706               if (!commit_str || !*commit_str) {
00707                   keylist_str = (char *)KEYLIST_LOWER;
00708                   base_str[0] = *(keylist_str + button_id_pressed);
00709                   base_str[1] = 0;
00710                   commit_str = base_str;
00711               }
00712            }
00713            palette_aux_Commit_String_Request(commit_str);
00714        }
00715     }
00716 
00717     vkb_window_clear_keystatus(vkb_window);
00718     vkb_window_draw_button(vkb_window, button_id_pressed, BUTTON_STATE_NORMAL);
00719     vkb_window_redraw_ctrl_buttons(vkb_window);
00720     return;
00721 }
00722 
00723 /********************************************************************/
00724 /*       draging functions                                          */
00725 /********************************************************************/
00726 static void
00727 vkb_window_draw_draging_frame(vkb_window_t *vkb_window,
00728                            int pos_x, int pos_y)
00729 {
00730     GdkGC *xor_gc;
00731     GdkGCValues values;
00732     GdkWindow *root_window;
00733 
00734     values.foreground = (vkb_window->drawing_area->style->white.pixel==0 ?
00735                          vkb_window->drawing_area->style->black:
00736                       vkb_window->drawing_area->style->white);
00737     values.function = GDK_XOR;
00738     values.subwindow_mode = GDK_INCLUDE_INFERIORS; 
00739 
00740     root_window = gtk_widget_get_root_window (vkb_window->drawing_area);
00741     xor_gc = gdk_gc_new_with_values (root_window,
00742                                      &values,
00743                                      GDK_GC_FOREGROUND |
00744                                      GDK_GC_FUNCTION |
00745                                      GDK_GC_SUBWINDOW);
00746 
00747     gdk_draw_rectangle (root_window, xor_gc, FALSE,
00748                         pos_x, pos_y,
00749                         vkb_window->width - 1,
00750                         vkb_window->height - 1);
00751 }
00752 
00753 static void
00754 vkb_window_begin_draging(vkb_window_t *vkb_window,
00755                           GdkEventButton *event)
00756 {
00757     /* begin draging */
00758     vkb_window->drag_x_start = (gint) event->x_root;
00759     vkb_window->drag_y_start = (gint) event->y_root;
00760     vkb_window->drag_x_save = (gint) event->x_root;
00761     vkb_window->drag_y_save = (gint) event->y_root;
00762 
00763     /* Grab the cursor to prevent losing events. */
00764     gdk_pointer_grab (vkb_window->drawing_area->window, FALSE,
00765                     GDK_BUTTON_RELEASE_MASK |
00766                     GDK_POINTER_MOTION_MASK,
00767                     NULL, vkb_window->moving_cursor, event->time);
00768 
00769     vkb_window_draw_draging_frame(vkb_window,
00770                                   vkb_window->pos_x,
00771                                   vkb_window->pos_y);
00772 
00773     return;
00774 }
00775 
00776 static void
00777 vkb_window_end_draging(vkb_window_t *vkb_window,
00778                      GdkEventButton *event)
00779 {
00780     gint pos_x, pos_y;
00781 
00782     if (vkb_window->draw_draging_frame) {
00783         pos_x = vkb_window->pos_x;
00784         pos_y = vkb_window->pos_y;
00785 
00786         pos_x += ((gint) event->x_root - vkb_window->drag_x_start);
00787         pos_y += ((gint) event->y_root - vkb_window->drag_y_start);
00788 
00789         vkb_window_set_position(vkb_window, pos_x, pos_y);
00790         gtk_widget_queue_draw(vkb_window->drawing_area);
00791     }
00792 
00793     gdk_pointer_ungrab(event->time);
00794 
00795     return;
00796 }
00797 
00798 static void
00799 vkb_window_do_draging(vkb_window_t *vkb_window,
00800                     GdkEventMotion *event)
00801 {
00802     gint pos_x, pos_y;
00803 
00804     pos_x = vkb_window->pos_x;
00805     pos_y = vkb_window->pos_y;
00806 
00807     if (vkb_window->draw_draging_frame) {
00808        /* remove the old draging frame */
00809         pos_x += (vkb_window->drag_x_save - vkb_window->drag_x_start);
00810         pos_y += (vkb_window->drag_y_save - vkb_window->drag_y_start);
00811         vkb_window_draw_draging_frame(vkb_window,
00812                                       pos_x, pos_y);
00813 
00814        /* draw the new draging frame */
00815         pos_x += (event->x_root - vkb_window->drag_x_save);
00816         pos_y += (event->y_root - vkb_window->drag_y_save);
00817         vkb_window_draw_draging_frame(vkb_window,
00818                                       pos_x, pos_y);
00819     } else {
00820         pos_x += ((gint) event->x_root - vkb_window->drag_x_start);
00821         pos_y += ((gint) event->y_root - vkb_window->drag_y_start);
00822 
00823        vkb_window->drag_x_start = event->x_root;
00824        vkb_window->drag_y_start = event->y_root;
00825 
00826        /* directly move the vkb window */
00827         vkb_window_set_position(vkb_window, pos_x, pos_y);
00828     }
00829 
00830     /* save the curent draging pointer position */
00831     vkb_window->drag_x_save = event->x_root;
00832     vkb_window->drag_y_save = event->y_root;
00833 }
00834 
00835 /********************************************************************/
00836 /*            event functions                                       */
00837 /********************************************************************/
00838 static gboolean
00839 vkb_window_expose_event_handler(GtkWidget *widget,
00840                             GdkEventExpose *event,
00841                             vkb_window_t *vkb_window)
00842 {
00843     DEBUG_printf("vkb_window_expose_event_handler =\n");
00844     if (!vkb_window->pixmap)
00845        return FALSE;
00846 
00847     gdk_draw_drawable(vkb_window->drawing_area->window,
00848                     widget->style->base_gc[GTK_STATE_NORMAL],
00849                     vkb_window->pixmap,
00850                     event->area.x, event->area.y,
00851                     event->area.x, event->area.y,
00852                     event->area.width, event->area.height);
00853     return FALSE;
00854 }
00855 
00856 static gboolean
00857 vkb_window_configure_event_handler(GtkWidget *widget,
00858                                GdkEventConfigure *event,
00859                                vkb_window_t *vkb_window)
00860 {
00861     DEBUG_printf("vkb_window_configure_event_handler =\n");
00862     if (vkb_window->pixmap)
00863         gdk_pixmap_unref(vkb_window->pixmap);
00864 
00865     vkb_window->pixmap = gdk_pixmap_new(widget->window,
00866                             widget->allocation.width,
00867                             widget->allocation.height,
00868                             -1);
00869 
00870     vkb_window_draw_layout(vkb_window);
00871 
00872     return TRUE;
00873 }
00874 
00875 static gboolean
00876 vkb_window_leave_event_handler(GtkWidget *widget,
00877                             GdkEventCrossing *event,
00878                             vkb_window_t *vkb_window)
00879 {
00880     DEBUG_printf("vkb_window_leave_event_handler =\n");
00881 
00882     /* if any button already pressed then do nothing */
00883     if (vkb_window->button_id_pressed != -1)
00884        return TRUE;
00885 
00886     /* reset the old focus button */
00887     if (vkb_window->button_id_focused != -1) {
00888         vkb_window_draw_button(vkb_window, vkb_window->button_id_focused,
00889                             BUTTON_STATE_NORMAL);
00890         gtk_widget_queue_draw(vkb_window->drawing_area);
00891     }
00892 
00893     vkb_window->button_id_focused = -1;
00894 
00895     return TRUE;
00896 }
00897 
00898 static gboolean
00899 vkb_window_pointer_press_event_handler(GtkWidget *widget,
00900                                    GdkEventButton *event,
00901                                    vkb_window_t *vkb_window)
00902 {
00903     gint button_id_pressed;
00904 
00905     DEBUG_printf("vkb_window_pointer_press_event_handler =\n");
00906     if (!vkb_window)
00907        return TRUE;
00908 
00909     if (event->button > 1)
00910        return TRUE;
00911     
00912     if (vkb_window->draging)
00913        return TRUE;
00914 
00915     button_id_pressed = vkb_window_get_button_id_from_pos(vkb_window, event->x, event->y);
00916     if (button_id_pressed == -1) {
00917         vkb_window->draging = TRUE;
00918        vkb_window_begin_draging(vkb_window, event);
00919     } else {
00920         vkb_window->button_id_pressed = button_id_pressed;
00921         vkb_window_draw_button(vkb_window, button_id_pressed, BUTTON_STATE_PRESSED);
00922         gtk_widget_queue_draw(vkb_window->drawing_area);
00923     }
00924 
00925     return TRUE;
00926 }
00927 
00928 static gboolean
00929 vkb_window_pointer_release_event_handler(GtkWidget *widget,
00930                                     GdkEventButton *event,
00931                                     vkb_window_t *vkb_window)
00932 {
00933     int button_id_pressed;
00934     int button_id_released;
00935 
00936     DEBUG_printf("vkb_window_pointer_release_event_handler =\n");
00937     if (!vkb_window)
00938        return TRUE;
00939 
00940     if (event->button > 1)
00941        return TRUE;
00942     
00943     /* button released */
00944     if (vkb_window->draging == TRUE) {
00945         vkb_window->draging = FALSE;
00946        vkb_window_end_draging(vkb_window, event);
00947        return TRUE;
00948     }
00949 
00950     button_id_pressed = vkb_window->button_id_pressed;
00951     button_id_released = vkb_window_get_button_id_from_pos(vkb_window, event->x, event->y);
00952 
00953     vkb_window->draging = FALSE;
00954     vkb_window->button_id_pressed = -1;
00955 
00956     if (button_id_pressed == button_id_released) {
00957        /* begin process the key release event on the button */
00958        vkb_window_press_key(vkb_window, button_id_pressed);
00959     } else {
00960        /* redraw the pressed and released buttons */
00961         vkb_window_draw_button(vkb_window, button_id_pressed, BUTTON_STATE_NORMAL);
00962         vkb_window_draw_button(vkb_window, button_id_released, BUTTON_STATE_FOCUSED);
00963         gtk_widget_queue_draw(vkb_window->drawing_area);
00964     }
00965 
00966     return TRUE;
00967 }
00968 
00969 static gboolean
00970 vkb_window_pointer_motion_event_handler(GtkWidget *widget,
00971                                    GdkEventMotion *event,
00972                                    vkb_window_t *vkb_window)
00973 {
00974     if (!vkb_window)
00975        return TRUE;
00976 
00977     if ((event->state & GDK_BUTTON1_MASK) != 0 &&
00978         vkb_window->draging) {
00979        /* in draging status */
00980         vkb_window_do_draging(vkb_window, event);
00981     } else {
00982        int button_id;
00983 
00984        /* if any button already pressed then do nothing */
00985        if (vkb_window->button_id_pressed != -1)
00986            return TRUE;
00987 
00988         button_id = vkb_window_get_button_id_from_pos(vkb_window, event->x, event->y);
00989        if (button_id == vkb_window->button_id_focused)
00990            return TRUE;
00991 
00992        /* set the cursor for button/draging area */
00993        if (button_id == -1) {
00994             gdk_window_set_cursor(vkb_window->drawing_area->window,
00995                                   vkb_window->moving_cursor);
00996         } else {
00997             gdk_window_set_cursor(vkb_window->drawing_area->window,
00998                                   vkb_window->normal_cursor);
00999         }
01000 
01001        /* reset the old focus button */
01002        if (vkb_window->button_id_focused != -1)
01003            vkb_window_draw_button(vkb_window, vkb_window->button_id_focused,
01004                                BUTTON_STATE_NORMAL);
01005 
01006        /* draw the new focus button */
01007        if (button_id != -1)
01008            vkb_window_draw_button(vkb_window, button_id,
01009                                BUTTON_STATE_FOCUSED);
01010 
01011         vkb_window_redraw_ctrl_buttons(vkb_window);
01012        vkb_window->button_id_focused = button_id;
01013     }
01014 
01015     return TRUE;
01016 }