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 = 29;
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 
00305     PangoRectangle logical_rect;
00306     int str_width, str_height;
00307 
00308     int pos_x, pos_y;
00309 
00310     gchar *str;
00311 
00312     if (!vkb_window || !vkb_window->pixmap)
00313        return;
00314 
00315     if (button_id < 0 || button_id >= MAX_VK_NUM)
00316        return;
00317 
00318     rect = &buttons[button_id];
00319 
00320     if (button_state == BUTTON_STATE_PRESSED) {
00321        state_type = GTK_STATE_ACTIVE;
00322        shadow_type = GTK_SHADOW_IN;
00323     } else if (button_state == BUTTON_STATE_FOCUSED) {
00324        state_type = GTK_STATE_PRELIGHT;
00325        shadow_type = GTK_SHADOW_OUT;
00326     }
00327 
00328     /* draw button frame */
00329     gtk_paint_box(vkb_window->drawing_area->style, vkb_window->pixmap,
00330                 state_type, shadow_type,
00331                 NULL, vkb_window->drawing_area, "button",
00332                 rect->x, rect->y, rect->width, rect->height);
00333 
00334     if (!vkb_window->layout)
00335        return;
00336 
00337     label_gc = vkb_window->drawing_area->style->text_gc[GTK_STATE_NORMAL];
00338 
00339     if (button_id >= MAX_BASEKEY_NUM) {
00340        /* if is Control Keys */
00341        str = vkb_window->layout->ctrlkey[button_id - MAX_BASEKEY_NUM].label_str;
00342        if (str && *str) {
00343            pango_layout_set_font_description(vkb_window->pango_layout,
00344                                          vkb_window->fontdesc_ctrlkey);
00345            pango_layout_set_text(vkb_window->pango_layout, str, strlen(str));
00346            pango_layout_get_extents(vkb_window->pango_layout, NULL, &logical_rect);
00347 
00348            str_width = PANGO_PIXELS(logical_rect.width);
00349            str_height = PANGO_PIXELS(logical_rect.height);
00350            pos_x = rect->x + (rect->width - str_width)/2;
00351            pos_y = rect->y + (rect->height - str_height)/2;
00352            gdk_draw_layout(vkb_window->pixmap, label_gc,
00353                          pos_x, pos_y, vkb_window->pango_layout);
00354        }
00355     } else {
00356         char key_str[2], *keychar_list;
00357 
00358        /* if is Base Keys */
00359        pango_layout_set_font_description(vkb_window->pango_layout,
00360                                      vkb_window->fontdesc_basekey);
00361 
00362        str = vkb_window->layout->basekey[button_id].lower_str;
00363        if (!str || !*str) {
00364            keychar_list = (char *)KEYLIST_LOWER;
00365             key_str[0] = *(keychar_list + button_id);
00366             key_str[1] = 0;
00367             str = key_str;
00368         }
00369 
00370        if (str && *str) {
00371            pango_layout_set_text(vkb_window->pango_layout, str, strlen(str));
00372            pango_layout_get_extents(vkb_window->pango_layout, NULL, &logical_rect);
00373 
00374            str_height = PANGO_PIXELS(logical_rect.height);
00375            pos_x = rect->x + 2;
00376            pos_y = rect->y + rect->height - str_height - 1;
00377            gdk_draw_layout(vkb_window->pixmap, label_gc,
00378                          pos_x, pos_y, vkb_window->pango_layout);
00379        }
00380 
00381        str = vkb_window->layout->basekey[button_id].upper_str;
00382        if (!str || !*str) {
00383            keychar_list = (char *)KEYLIST_UPPER;
00384             key_str[0] = *(keychar_list + button_id);
00385             key_str[1] = 0;
00386             str = key_str;
00387         }
00388 
00389        if (str && *str) {
00390            pango_layout_set_text(vkb_window->pango_layout, str, strlen(str));
00391            pango_layout_get_extents(vkb_window->pango_layout, NULL, &logical_rect);
00392 
00393            str_width = PANGO_PIXELS(logical_rect.width);
00394            pos_x = rect->x + rect->width - str_width - 2;
00395            pos_y = rect->y + 1;
00396            gdk_draw_layout(vkb_window->pixmap, label_gc,
00397                          pos_x, pos_y, vkb_window->pango_layout);
00398        }
00399     }
00400 
00401     return;
00402 }
00403 
00404 void vkb_window_draw_layout(vkb_window_t *vkb_window)
00405 {
00406 
00407     gint button_id;
00408     gint ctrl_button_id;
00409     gint button_state;
00410 
00411     if (!vkb_window || !vkb_window->pixmap)
00412        return;
00413 
00414     gtk_paint_box(vkb_window->drawing_area->style, vkb_window->pixmap,
00415                 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
00416                 NULL, vkb_window->drawing_area, "button",
00417                 0, 0,
00418                 vkb_window->width,
00419                 vkb_window->height);
00420 
00421     for (button_id = 0; button_id < MAX_VK_NUM; button_id ++) {
00422         button_state = BUTTON_STATE_NORMAL;
00423 
00424        if (button_id >= MAX_BASEKEY_NUM) {
00425            /* if is Control Keys */
00426            ctrl_button_id = button_id - MAX_BASEKEY_NUM;
00427            if (ctrl_button_id == VK_CapsLock) {
00428               if (vkb_window->status_capslockkey)
00429                   button_state = BUTTON_STATE_PRESSED;
00430            } else if (ctrl_button_id == VK_Control_L) {
00431               if (vkb_window->status_ctrlkey)
00432                   button_state = BUTTON_STATE_PRESSED;
00433            } else if (ctrl_button_id == VK_Shift_L) {
00434               if (vkb_window->status_shiftkey)
00435                   button_state = BUTTON_STATE_PRESSED;
00436            } else if (ctrl_button_id == VK_Alt_L) {
00437               if (vkb_window->status_altkey)
00438                   button_state = BUTTON_STATE_PRESSED;
00439            }
00440        } else if (button_id == vkb_window->button_id_pressed) {
00441            button_state = BUTTON_STATE_PRESSED;
00442        }
00443 
00444        vkb_window_draw_button(vkb_window, button_id, button_state);
00445     }
00446 }
00447 
00448 void vkb_window_hide(vkb_window_t *vkb_window)
00449 {
00450     if (!vkb_window)
00451        return;
00452 
00453     gtk_widget_hide(vkb_window->window);
00454 }
00455 
00456 void vkb_window_update_layout(vkb_window_t *vkb_window,
00457                            vkb_layout_t *vkb_layout)
00458 {
00459     if (!vkb_window)
00460        return;
00461 
00462     if (vkb_layout == NULL) {
00463        gtk_widget_hide(vkb_window->window);
00464        return;
00465     }
00466 
00467     vkb_window->layout = vkb_layout;
00468 
00469     vkb_window_draw_layout(vkb_window);
00470 
00471     gtk_widget_show_all(vkb_window->window);
00472     gtk_widget_queue_draw(vkb_window->drawing_area);
00473 }
00474 
00475 static gboolean vkb_window_rect_has_pos(GdkRectangle * rect, int x, int y)
00476 {
00477     return ((rect->x <= x) && (rect->x + rect->width >= x) &&
00478            (rect->y <= y) && (rect->y + rect->height >= y));
00479 }
00480 
00481 static gint vkb_window_get_button_id_from_pos(vkb_window_t *vkb_window, int x, int y)
00482 {
00483     gint i;
00484     for (i = 0; i < MAX_VK_NUM; i++) {
00485        if (vkb_window_rect_has_pos(&vkb_window->buttons[i], x, y))
00486            return i;
00487     }
00488     return -1;
00489 }
00490 
00491 static void
00492 vkb_window_set_position(vkb_window_t *vkb_window,
00493                      gint pos_x, gint pos_y)
00494 {
00495     GtkRequisition ws;
00496     gint screen_width;
00497     gint screen_height;
00498 
00499     gtk_widget_size_request(vkb_window->window, &ws);
00500 
00501     screen_width = gdk_screen_width();
00502     screen_height = gdk_screen_height();
00503 
00504     if (pos_x < 0) {
00505         pos_x = 0;
00506     } else if (pos_x + ws.width > screen_width) {
00507         pos_x = screen_width - ws.width;
00508     }
00509 
00510     if (pos_y < 0) {
00511         pos_y = 0;
00512     } else if (pos_y + ws.height > screen_height) {
00513         pos_y = screen_height - ws.height;
00514     }
00515 
00516     if (vkb_window->pos_x != pos_x || vkb_window->pos_y != pos_y) {
00517         gtk_window_move(GTK_WINDOW(vkb_window->window), pos_x, pos_y);
00518         vkb_window->pos_x = pos_x;
00519         vkb_window->pos_y = pos_y;
00520     }
00521 }
00522 
00523 /********************************************************************/
00524 /*       key status functions                                       */
00525 /********************************************************************/
00526 static int vkb_base_keycode[MAX_BASEKEY_NUM] = {
00527     IM_VK_BACK_QUOTE,
00528     IM_VK_1,
00529     IM_VK_2,
00530     IM_VK_3,
00531     IM_VK_4,
00532     IM_VK_5,
00533     IM_VK_6,
00534     IM_VK_7,
00535     IM_VK_8,
00536     IM_VK_9,
00537     IM_VK_0,
00538     IM_VK_MINUS,
00539     IM_VK_EQUALS,
00540 
00541     IM_VK_Q,
00542     IM_VK_W,
00543     IM_VK_E,
00544     IM_VK_R,
00545     IM_VK_T,
00546     IM_VK_Y,
00547     IM_VK_U,
00548     IM_VK_I,
00549     IM_VK_O,
00550     IM_VK_P,
00551     IM_VK_OPEN_BRACKET,
00552     IM_VK_CLOSE_BRACKET,
00553     IM_VK_BACK_SLASH,
00554 
00555     IM_VK_A,
00556     IM_VK_S,
00557     IM_VK_D,
00558     IM_VK_F,
00559     IM_VK_G,
00560     IM_VK_H,
00561     IM_VK_J,
00562     IM_VK_K,
00563     IM_VK_L,
00564     IM_VK_SEMICOLON,
00565     IM_VK_QUOTE,
00566 
00567     IM_VK_Z,
00568     IM_VK_X,
00569     IM_VK_C,
00570     IM_VK_V,
00571     IM_VK_B,
00572     IM_VK_N,
00573     IM_VK_M,
00574     IM_VK_COMMA,
00575     IM_VK_PERIOD, 
00576     IM_VK_SLASH,
00577 };
00578 
00579 static int vkb_ctrl_keycode[MAX_CTRLKEY_NUM] = {
00580     IM_VK_BACK_SPACE,
00581     IM_VK_TAB,
00582     IM_VK_CAPS_LOCK,
00583     IM_VK_ENTER,
00584     0,
00585     0,
00586     0,
00587     IM_VK_SPACE,
00588     IM_VK_ESCAPE
00589 };
00590 
00591 void vkb_window_clear_keystatus(vkb_window_t *vkb_window)
00592 {
00593     vkb_window->status_ctrlkey = 0;
00594     vkb_window->status_shiftkey = 0;
00595     vkb_window->status_altkey = 0;
00596 
00597     return;
00598 }
00599 
00600 void vkb_window_get_keyevent(vkb_window_t *vkb_window,
00601                           int button_id,
00602                           int *keycode,
00603                           int *keychar,
00604                           int *keystatus)
00605 {
00606     char *keychar_list;
00607 
00608     *keycode = 0;
00609     *keychar = 0;
00610     *keystatus = 0;
00611 
00612     if (button_id < 0 || button_id >= MAX_VK_NUM)
00613        return;
00614 
00615     if (button_id >= MAX_BASEKEY_NUM) {
00616        *keycode = vkb_ctrl_keycode[button_id - MAX_BASEKEY_NUM];
00617        *keychar = 0;
00618        if (button_id - MAX_BASEKEY_NUM == VK_Space)
00619            *keychar = 0x20;
00620     } else {
00621        *keycode = vkb_base_keycode[button_id];
00622 
00623        keychar_list = (char *)KEYLIST_LOWER;
00624        if (vkb_window->status_capslockkey ^ vkb_window->status_shiftkey)
00625            keychar_list = (char *)KEYLIST_UPPER;
00626        *keychar = *(keychar_list + button_id);
00627     } 
00628 
00629     if (vkb_window->status_ctrlkey)
00630        *keystatus |= IM_CTRL_MASK;
00631     if (vkb_window->status_shiftkey)
00632        *keystatus |= IM_SHIFT_MASK;
00633     if (vkb_window->status_altkey)
00634        *keystatus |= IM_ALT_MASK;
00635 
00636     return;
00637 }
00638 
00639 void vkb_window_redraw_ctrl_buttons(vkb_window_t *vkb_window)
00640 {
00641     int button_id, button_state;
00642 
00643     for (button_id = MAX_BASEKEY_NUM; button_id < MAX_VK_NUM; button_id++) {
00644        button_state = BUTTON_STATE_NORMAL;
00645         if (button_id - MAX_BASEKEY_NUM == VK_CapsLock) {
00646            if (vkb_window->status_capslockkey)
00647               button_state = BUTTON_STATE_PRESSED;
00648         } else if (button_id - MAX_BASEKEY_NUM == VK_Control_L) {
00649            if (vkb_window->status_ctrlkey)
00650               button_state = BUTTON_STATE_PRESSED;
00651         } else if (button_id - MAX_BASEKEY_NUM == VK_Shift_L) {
00652            if (vkb_window->status_shiftkey)
00653               button_state = BUTTON_STATE_PRESSED;
00654         } else if (button_id - MAX_BASEKEY_NUM == VK_Alt_L) {
00655            if (vkb_window->status_altkey)
00656               button_state = BUTTON_STATE_PRESSED;
00657         }
00658 
00659        vkb_window_draw_button(vkb_window, button_id, button_state);
00660     }
00661     gtk_widget_queue_draw(vkb_window->drawing_area);
00662     return;
00663 }
00664 
00665 void vkb_window_press_key(vkb_window_t *vkb_window,
00666                        int button_id_pressed)
00667 {
00668     int keycode, keychar, keystatus;
00669     char *commit_str, *keylist_str, base_str[2];
00670     int ctrl_key_id;
00671     int button_state = BUTTON_STATE_NORMAL;
00672 
00673     if (vkb_window == NULL || vkb_window->layout == NULL)
00674         return;
00675 
00676     if (button_id_pressed < 0 || button_id_pressed >= MAX_VK_NUM)
00677         return;
00678 
00679     if (button_id_pressed >= MAX_BASEKEY_NUM) {
00680        /* if is Control Keys, set key status or commit as virtual key. */
00681        ctrl_key_id = button_id_pressed - MAX_BASEKEY_NUM;
00682 
00683        if (ctrl_key_id == VK_BackSpace ||
00684             ctrl_key_id == VK_Tab ||
00685             ctrl_key_id == VK_Enter ||
00686             ctrl_key_id == VK_Space ||
00687             ctrl_key_id == VK_Escape) {
00688             /* if not Control status key, commit as key event */
00689             vkb_window_get_keyevent(vkb_window, button_id_pressed,
00690                                 &keycode, &keychar, &keystatus);
00691             palette_aux_Commit_Key_Request(keycode, keychar, keystatus);
00692             vkb_window_clear_keystatus(vkb_window);
00693         } else if (ctrl_key_id == VK_CapsLock) {
00694            vkb_window->status_capslockkey = vkb_window->status_capslockkey ? 0 : 1;
00695         } else if (ctrl_key_id == VK_Control_L) {
00696            vkb_window->status_ctrlkey = vkb_window->status_ctrlkey ? 0 : 1;
00697         } else if (ctrl_key_id == VK_Shift_L) {
00698            vkb_window->status_shiftkey = vkb_window->status_shiftkey ? 0 : 1;
00699         } else if (ctrl_key_id == VK_Alt_L) {
00700            vkb_window->status_altkey = vkb_window->status_altkey ? 0 : 1;
00701         }
00702 
00703        /* redraw the pressed button */
00704        vkb_window_redraw_ctrl_buttons(vkb_window);
00705        return;
00706     }
00707 
00708     if (vkb_window->layout->type == KEYBOARD_KEY_TYPE) {
00709         vkb_window_get_keyevent(vkb_window, button_id_pressed,
00710                             &keycode, &keychar, &keystatus);
00711         palette_aux_Commit_Key_Request(keycode, keychar, keystatus);
00712     } else {
00713        if (vkb_window->status_ctrlkey || vkb_window->status_altkey) {
00714             vkb_window_get_keyevent(vkb_window, button_id_pressed,
00715                                 &keycode, &keychar, &keystatus);
00716             palette_aux_Commit_Key_Request(keycode, keychar, keystatus);
00717        } else {
00718            if (vkb_window->status_capslockkey ^ vkb_window->status_shiftkey) {
00719               /* commit upper string */
00720               commit_str = vkb_window->layout->basekey[button_id_pressed].upper_str;
00721               if (!commit_str || !*commit_str) {
00722                   keylist_str = (char *)KEYLIST_UPPER;
00723                   base_str[0] = *(keylist_str + button_id_pressed);
00724                   base_str[1] = 0;
00725                   commit_str = base_str;
00726               }
00727            } else {
00728               /* commit lower string */
00729               commit_str = vkb_window->layout->basekey[button_id_pressed].lower_str;
00730               if (!commit_str || !*commit_str) {
00731                   keylist_str = (char *)KEYLIST_LOWER;
00732                   base_str[0] = *(keylist_str + button_id_pressed);
00733                   base_str[1] = 0;
00734                   commit_str = base_str;
00735               }
00736            }
00737            palette_aux_Commit_String_Request(commit_str);
00738        }
00739     }
00740 
00741     vkb_window_clear_keystatus(vkb_window);
00742     vkb_window_draw_button(vkb_window, button_id_pressed, BUTTON_STATE_NORMAL);
00743     vkb_window_redraw_ctrl_buttons(vkb_window);
00744     return;
00745 }
00746 
00747 /********************************************************************/
00748 /*       draging functions                                          */
00749 /********************************************************************/
00750 static void
00751 vkb_window_draw_draging_frame(vkb_window_t *vkb_window,
00752                            int pos_x, int pos_y)
00753 {
00754     GdkGC *xor_gc;
00755     GdkGCValues values;
00756     GdkWindow *root_window;
00757 
00758     values.foreground = (vkb_window->drawing_area->style->white.pixel==0 ?
00759                          vkb_window->drawing_area->style->black:
00760                       vkb_window->drawing_area->style->white);
00761     values.function = GDK_XOR;
00762     values.subwindow_mode = GDK_INCLUDE_INFERIORS; 
00763 
00764     root_window = gtk_widget_get_root_window (vkb_window->drawing_area);
00765     xor_gc = gdk_gc_new_with_values (root_window,
00766                                      &values,
00767                                      GDK_GC_FOREGROUND |
00768                                      GDK_GC_FUNCTION |
00769                                      GDK_GC_SUBWINDOW);
00770 
00771     gdk_draw_rectangle (root_window, xor_gc, FALSE,
00772                         pos_x, pos_y,
00773                         vkb_window->width - 1,
00774                         vkb_window->height - 1);
00775 }
00776 
00777 static void
00778 vkb_window_begin_draging(vkb_window_t *vkb_window,
00779                           GdkEventButton *event)
00780 {
00781     /* begin draging */
00782     vkb_window->drag_x_start = (gint) event->x_root;
00783     vkb_window->drag_y_start = (gint) event->y_root;
00784     vkb_window->drag_x_save = (gint) event->x_root;
00785     vkb_window->drag_y_save = (gint) event->y_root;
00786 
00787     /* Grab the cursor to prevent losing events. */
00788     gdk_pointer_grab (vkb_window->drawing_area->window, FALSE,
00789                     GDK_BUTTON_RELEASE_MASK |
00790                     GDK_POINTER_MOTION_MASK,
00791                     NULL, vkb_window->moving_cursor, event->time);
00792 
00793     vkb_window_draw_draging_frame(vkb_window,
00794                                   vkb_window->pos_x,
00795                                   vkb_window->pos_y);
00796 
00797     return;
00798 }
00799 
00800 static void
00801 vkb_window_end_draging(vkb_window_t *vkb_window,
00802                      GdkEventButton *event)
00803 {
00804     gint pos_x, pos_y;
00805 
00806     if (vkb_window->draw_draging_frame) {
00807         pos_x = vkb_window->pos_x;
00808         pos_y = vkb_window->pos_y;
00809 
00810         pos_x += ((gint) event->x_root - vkb_window->drag_x_start);
00811         pos_y += ((gint) event->y_root - vkb_window->drag_y_start);
00812 
00813         vkb_window_set_position(vkb_window, pos_x, pos_y);
00814         gtk_widget_queue_draw(vkb_window->drawing_area);
00815     }
00816 
00817     gdk_pointer_ungrab(event->time);
00818 
00819     return;
00820 }
00821 
00822 static void
00823 vkb_window_do_draging(vkb_window_t *vkb_window,
00824                     GdkEventMotion *event)
00825 {
00826     gint pos_x, pos_y;
00827 
00828     pos_x = vkb_window->pos_x;
00829     pos_y = vkb_window->pos_y;
00830 
00831     if (vkb_window->draw_draging_frame) {
00832        /* remove the old draging frame */
00833         pos_x += (vkb_window->drag_x_save - vkb_window->drag_x_start);
00834         pos_y += (vkb_window->drag_y_save - vkb_window->drag_y_start);
00835         vkb_window_draw_draging_frame(vkb_window,
00836                                       pos_x, pos_y);
00837 
00838        /* draw the new draging frame */
00839         pos_x += (event->x_root - vkb_window->drag_x_save);
00840         pos_y += (event->y_root - vkb_window->drag_y_save);
00841         vkb_window_draw_draging_frame(vkb_window,
00842                                       pos_x, pos_y);
00843     } else {
00844         pos_x += ((gint) event->x_root - vkb_window->drag_x_start);
00845         pos_y += ((gint) event->y_root - vkb_window->drag_y_start);
00846 
00847        vkb_window->drag_x_start = event->x_root;
00848        vkb_window->drag_y_start = event->y_root;
00849 
00850        /* directly move the vkb window */
00851         vkb_window_set_position(vkb_window, pos_x, pos_y);
00852     }
00853 
00854     /* save the curent draging pointer position */
00855     vkb_window->drag_x_save = event->x_root;
00856     vkb_window->drag_y_save = event->y_root;
00857 }
00858 
00859 /********************************************************************/
00860 /*            event functions                                       */
00861 /********************************************************************/
00862 static gboolean
00863 vkb_window_expose_event_handler(GtkWidget *widget,
00864                             GdkEventExpose *event,
00865                             vkb_window_t *vkb_window)
00866 {
00867     DEBUG_printf("vkb_window_expose_event_handler =\n");
00868     if (!vkb_window->pixmap)
00869        return FALSE;
00870 
00871     gdk_draw_drawable(vkb_window->drawing_area->window,
00872                     widget->style->base_gc[GTK_STATE_NORMAL],
00873                     vkb_window->pixmap,
00874                     event->area.x, event->area.y,
00875                     event->area.x, event->area.y,
00876                     event->area.width, event->area.height);
00877     return FALSE;
00878 }
00879 
00880 static gboolean
00881 vkb_window_configure_event_handler(GtkWidget *widget,
00882                                GdkEventConfigure *event,
00883                                vkb_window_t *vkb_window)
00884 {
00885     DEBUG_printf("vkb_window_configure_event_handler =\n");
00886     if (vkb_window->pixmap)
00887         gdk_pixmap_unref(vkb_window->pixmap);
00888 
00889     vkb_window->pixmap = gdk_pixmap_new(widget->window,
00890                             widget->allocation.width,
00891                             widget->allocation.height,
00892                             -1);
00893 
00894     vkb_window_draw_layout(vkb_window);
00895 
00896     return TRUE;
00897 }
00898 
00899 static gboolean
00900 vkb_window_leave_event_handler(GtkWidget *widget,
00901                             GdkEventCrossing *event,
00902                             vkb_window_t *vkb_window)
00903 {
00904     DEBUG_printf("vkb_window_leave_event_handler =\n");
00905 
00906     /* if any button already pressed then do nothing */
00907     if (vkb_window->button_id_pressed != -1)
00908        return TRUE;
00909 
00910     /* reset the old focus button */
00911     if (vkb_window->button_id_focused != -1) {
00912         vkb_window_draw_button(vkb_window, vkb_window->button_id_focused,
00913                             BUTTON_STATE_NORMAL);
00914         gtk_widget_queue_draw(vkb_window->drawing_area);
00915     }
00916 
00917     vkb_window->button_id_focused = -1;
00918 
00919     return TRUE;
00920 }
00921 
00922 static gboolean
00923 vkb_window_pointer_press_event_handler(GtkWidget *widget,
00924                                    GdkEventButton *event,
00925                                    vkb_window_t *vkb_window)
00926 {
00927     gint button_id_pressed;
00928 
00929     DEBUG_printf("vkb_window_pointer_press_event_handler =\n");
00930     if (!vkb_window)
00931        return TRUE;
00932 
00933     if (event->button > 1)
00934        return TRUE;
00935     
00936     if (vkb_window->draging)
00937        return TRUE;
00938 
00939     button_id_pressed = vkb_window_get_button_id_from_pos(vkb_window, event->x, event->y);
00940     if (button_id_pressed == -1) {
00941         vkb_window->draging = TRUE;
00942        vkb_window_begin_draging(vkb_window, event);
00943     } else {
00944         vkb_window->button_id_pressed = button_id_pressed;
00945         vkb_window_draw_button(vkb_window, button_id_pressed, BUTTON_STATE_PRESSED);
00946         gtk_widget_queue_draw(vkb_window->drawing_area);
00947     }
00948 
00949     return TRUE;
00950 }
00951 
00952 static gboolean
00953 vkb_window_pointer_release_event_handler(GtkWidget *widget,
00954                                     GdkEventButton *event,
00955                                     vkb_window_t *vkb_window)
00956 {
00957     int button_id_pressed;
00958     int button_id_released;
00959 
00960     DEBUG_printf("vkb_window_pointer_release_event_handler =\n");
00961     if (!vkb_window)
00962        return TRUE;
00963 
00964     if (event->button > 1)
00965        return TRUE;
00966     
00967     /* button released */
00968     if (vkb_window->draging == TRUE) {
00969         vkb_window->draging = FALSE;
00970        vkb_window_end_draging(vkb_window, event);
00971        return TRUE;
00972     }
00973 
00974     button_id_pressed = vkb_window->button_id_pressed;
00975     button_id_released = vkb_window_get_button_id_from_pos(vkb_window, event->x, event->y);
00976 
00977     vkb_window->draging = FALSE;
00978     vkb_window->button_id_pressed = -1;
00979 
00980     if (button_id_pressed == button_id_released) {
00981        /* begin process the key release event on the button */
00982        vkb_window_press_key(vkb_window, button_id_pressed);
00983     } else {
00984        /* redraw the pressed and released buttons */
00985         vkb_window_draw_button(vkb_window, button_id_pressed, BUTTON_STATE_NORMAL);
00986         vkb_window_draw_button(vkb_window, button_id_released, BUTTON_STATE_FOCUSED);
00987         gtk_widget_queue_draw(vkb_window->drawing_area);
00988     }
00989 
00990     return TRUE;
00991 }
00992 
00993 static gboolean
00994 vkb_window_pointer_motion_event_handler(GtkWidget *widget,
00995                                    GdkEventMotion *event,
00996                                    vkb_window_t *vkb_window)
00997 {
00998     DEBUG_printf("vkb_window_pointer_motion_event_handler =\n");
00999     if (!vkb_window)
01000        return TRUE;
01001 
01002     if ((event->state & GDK_BUTTON1_MASK) != 0 &&
01003         vkb_window->draging) {
01004        /* in draging status */
01005         vkb_window_do_draging(vkb_window, event);
01006     } else {
01007        int button_id;
01008 
01009        /* if any button already pressed then do nothing */
01010        if (vkb_window->button_id_pressed != -1)
01011            return TRUE;
01012 
01013         button_id = vkb_window_get_button_id_from_pos(vkb_window, event->x, event->y);
01014        if (button_id == vkb_window->button_id_focused)
01015            return TRUE;
01016 
01017        /* set the cursor for button/draging area */
01018        if (button_id == -1) {
01019             gdk_window_set_cursor(vkb_window->drawing_area->window,
01020                                   vkb_window->moving_cursor);
01021         } else {
01022             gdk_window_set_cursor(vkb_window->drawing_area->window,
01023                                   vkb_window->normal_cursor);
01024         }
01025 
01026        /* reset the old focus button */
01027        if (vkb_window->button_id_focused != -1)
01028            vkb_window_draw_button(vkb_window, vkb_window->button_id_focused,
01029                                BUTTON_STATE_NORMAL);
01030 
01031         vkb_window_redraw_ctrl_buttons(vkb_window);
01032 
01033        /* draw the new focus button */
01034        if (button_id != -1)
01035            vkb_window_draw_button(vkb_window, button_id,
01036                                BUTTON_STATE_FOCUSED);
01037 
01038        vkb_window->button_id_focused = button_id;
01039     }
01040 
01041     return TRUE;
01042 }