From 3af13fb38a63bc4d46bd2b8bff37339fad29f6a4 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Fri, 18 Jun 2010 13:27:50 +0900 Subject: [PATCH] libeek: refine GtkDrawingArea based UI --- configure.ac | 2 + eek/eek-container.c | 1 - eek/eek-drawing.c | 38 +++++ eek/eek-drawing.h | 7 +- eek/eek-gtk-keyboard.c | 353 ++++++++++++++++++++++++++++++----------- src/Makefile.am | 4 +- src/eekboard.c | 51 +++++- 7 files changed, 347 insertions(+), 109 deletions(-) diff --git a/configure.ac b/configure.ac index 717f4380..3af52ba2 100644 --- a/configure.ac +++ b/configure.ac @@ -44,6 +44,8 @@ PKG_CHECK_MODULES([LIBXKLAVIER], [libxklavier x11], , [AC_MSG_ERROR([Libxklavier not found])]) PKG_CHECK_MODULES([LIBFAKEKEY], [libfakekey], , [AC_MSG_ERROR([libfakekey not found])]) +PKG_CHECK_MODULES([ATK], [atk], , + [AC_MSG_ERROR([ATK not found])]) GTK_DOC_CHECK([1.14],[--flavour no-tmpl]) diff --git a/eek/eek-container.c b/eek/eek-container.c index e16fbb20..d5c15c07 100644 --- a/eek/eek-container.c +++ b/eek/eek-container.c @@ -133,7 +133,6 @@ eek_container_real_find_by_position (EekContainer *self, { EekBounds bounds; FbpData data; - EekElement *element; eek_element_get_bounds (EEK_ELEMENT(self), &bounds); data.x = x - bounds.x; diff --git a/eek/eek-drawing.c b/eek/eek-drawing.c index 733193a0..1200eb94 100644 --- a/eek/eek-drawing.c +++ b/eek/eek-drawing.c @@ -207,6 +207,44 @@ eek_draw_outline (cairo_t *cr, EekOutline *outline) outline->num_points); } +void +eek_draw_key_label (cairo_t *cr, + EekKey *key, + PangoFontDescription **fonts) +{ + guint keysym; + EekKeysymCategory category; + const gchar *label; + PangoLayout *layout; + PangoRectangle logical_rect = { 0, }; + EekBounds bounds; + + keysym = eek_key_get_keysym (key); + if (keysym == EEK_INVALID_KEYSYM) + return; + + category = eek_keysym_get_category (keysym); + if (category == EEK_KEYSYM_CATEGORY_UNKNOWN) + return; + + label = eek_keysym_to_string (keysym); + if (!label) + return; + + eek_element_get_bounds (EEK_ELEMENT(key), &bounds); + layout = pango_cairo_create_layout (cr); + pango_layout_set_font_description (layout, fonts[category]); + pango_layout_set_width (layout, PANGO_SCALE * bounds.width); + pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); + pango_layout_set_text (layout, label, -1); + pango_layout_get_extents (layout, NULL, &logical_rect); + cairo_rel_move_to (cr, + (bounds.width - logical_rect.width / PANGO_SCALE) / 2, + (bounds.height - logical_rect.height / PANGO_SCALE) / 2); + pango_cairo_show_layout (cr, layout); + g_object_unref (layout); +} + /* * The functions below are borrowed from * libgnomekbd/gkbd-keyboard-drawing.c. diff --git a/eek/eek-drawing.h b/eek/eek-drawing.h index 9f23c2a1..df2ea64f 100644 --- a/eek/eek-drawing.h +++ b/eek/eek-drawing.h @@ -1,8 +1,7 @@ #ifndef EEK_DRAWING_H #define EEK_DRAWING_H 1 -#include -#include +#include #include "eek-keyboard.h" #include "eek-keysym.h" #include "eek-types.h" @@ -19,6 +18,10 @@ void eek_get_fonts (EekKeyboard *keyboard, void eek_draw_outline (cairo_t *cr, EekOutline *outline); +void eek_draw_key_label (cairo_t *cr, + EekKey *key, + PangoFontDescription **fonts); + void eek_draw_rounded_polygon (cairo_t *cr, gboolean filled, gdouble radius, diff --git a/eek/eek-gtk-keyboard.c b/eek/eek-gtk-keyboard.c index 87b7411d..2fe25f82 100644 --- a/eek/eek-gtk-keyboard.c +++ b/eek/eek-gtk-keyboard.c @@ -40,17 +40,55 @@ G_DEFINE_TYPE (EekGtkKeyboard, eek_gtk_keyboard, EEK_TYPE_KEYBOARD); #define EEK_GTK_KEYBOARD_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_GTK_KEYBOARD, EekGtkKeyboardPrivate)) +#define SCALE 1.5 struct _EekGtkKeyboardPrivate { - GtkWidget *widget; /* GtkDrawingArea */ + GtkWidget *widget; + + /* pixmap of entire keyboard (for expose event) */ GdkPixmap *pixmap; - GdkColor *dark_color; - cairo_t *cr; - PangoLayout *layout; + + /* mapping from outline pointer to pixmap */ + GHashTable *outline_pixmaps; + + /* mapping from outline pointer to large pixmap */ + GHashTable *outline_large_pixmaps; + PangoFontDescription *fonts[EEK_KEYSYM_CATEGORY_LAST]; }; +static void prepare_keyboard_pixmap (EekGtkKeyboard *keyboard); + +static void +eek_gtk_keyboard_real_set_keysym_index (EekKeyboard *self, + gint group, + gint level) +{ + gint g, l; + + eek_keyboard_get_keysym_index (self, &g, &l); + EEK_KEYBOARD_CLASS(eek_gtk_keyboard_parent_class)-> + set_keysym_index (self, group, level); + if (g != group || l != level) { + EekGtkKeyboard *keyboard = EEK_GTK_KEYBOARD(self); + EekGtkKeyboardPrivate *priv = + EEK_GTK_KEYBOARD_GET_PRIVATE(keyboard); + GtkStateType state; + GtkAllocation allocation; + + prepare_keyboard_pixmap (keyboard); + state = gtk_widget_get_state (GTK_WIDGET (priv->widget)); + gtk_widget_get_allocation (GTK_WIDGET (priv->widget), &allocation); + gdk_draw_drawable (gtk_widget_get_window (priv->widget), + gtk_widget_get_style (priv->widget)->fg_gc[state], + priv->pixmap, + 0, 0, + 0, 0, + allocation.width, allocation.height); + } +} + static void eek_gtk_keyboard_dispose (GObject *object) { @@ -69,6 +107,9 @@ eek_gtk_keyboard_finalize (GObject *object) EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(object); gint i; + g_hash_table_unref (priv->outline_pixmaps); + g_hash_table_unref (priv->outline_large_pixmaps); + for (i = 0; i < EEK_KEYSYM_CATEGORY_LAST; i++) pango_font_description_free (priv->fonts[i]); } @@ -76,11 +117,13 @@ eek_gtk_keyboard_finalize (GObject *object) static void eek_gtk_keyboard_class_init (EekGtkKeyboardClass *klass) { + EekKeyboardClass *keyboard_class = EEK_KEYBOARD_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass); g_type_class_add_private (gobject_class, sizeof (EekGtkKeyboardPrivate)); + keyboard_class->set_keysym_index = eek_gtk_keyboard_real_set_keysym_index; gobject_class->dispose = eek_gtk_keyboard_dispose; gobject_class->finalize = eek_gtk_keyboard_finalize; } @@ -93,6 +136,16 @@ eek_gtk_keyboard_init (EekGtkKeyboard *self) priv = self->priv = EEK_GTK_KEYBOARD_GET_PRIVATE(self); priv->widget = NULL; priv->pixmap = NULL; + priv->outline_pixmaps = + g_hash_table_new_full (g_direct_hash, + g_direct_equal, + NULL, + g_object_unref); + priv->outline_large_pixmaps = + g_hash_table_new_full (g_direct_hash, + g_direct_equal, + NULL, + g_object_unref); memset (priv->fonts, 0, sizeof priv->fonts); } @@ -107,123 +160,143 @@ eek_gtk_keyboard_new (void) return g_object_new (EEK_TYPE_GTK_KEYBOARD, NULL); } -static void -draw_key (EekElement *element, gpointer user_data) +struct _DrawingContext { - EekKeyboard *keyboard = user_data; - EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(keyboard); + EekGtkKeyboard *keyboard; + cairo_t *cr; + GdkColor *fg, *bg; +}; +typedef struct _DrawingContext DrawingContext; + +static void +prepare_keyboard_pixmap_key_callback (EekElement *element, + gpointer user_data) +{ + DrawingContext *context = user_data; + EekGtkKeyboardPrivate *priv = + EEK_GTK_KEYBOARD_GET_PRIVATE(context->keyboard); EekKey *key = EEK_KEY(element); - EekOutline *outline; EekBounds bounds; - guint keysym; + EekOutline *outline; + GdkPixmap *pixmap; + + eek_element_get_bounds (element, &bounds); - cairo_save (priv->cr); - eek_element_get_bounds (EEK_ELEMENT(key), &bounds); - cairo_translate (priv->cr, bounds.x, bounds.y); outline = eek_key_get_outline (key); - eek_draw_outline (priv->cr, outline); + pixmap = g_hash_table_lookup (priv->outline_pixmaps, outline); + if (!pixmap) { + cairo_t *cr; - gdk_cairo_set_source_color (priv->cr, priv->dark_color); - - keysym = eek_key_get_keysym (key); - if (keysym != EEK_INVALID_KEYSYM) { - const gchar *label = eek_keysym_to_string (keysym); - PangoRectangle logical_rect = { 0, }; - EekKeysymCategory category = eek_keysym_get_category (keysym); - - if (category != EEK_KEYSYM_CATEGORY_UNKNOWN && label) { - pango_layout_set_font_description (priv->layout, - priv->fonts[category]); - pango_layout_set_text (priv->layout, label, -1); - pango_layout_get_extents (priv->layout, NULL, &logical_rect); - - cairo_move_to - (priv->cr, - (bounds.width - logical_rect.width / PANGO_SCALE) / 2, - (bounds.height - logical_rect.height / PANGO_SCALE) / 2); - - pango_layout_set_width (priv->layout, PANGO_SCALE * bounds.width); - pango_layout_set_ellipsize (priv->layout, PANGO_ELLIPSIZE_END); - pango_cairo_show_layout (priv->cr, priv->layout); - } + pixmap = + gdk_pixmap_new (gtk_widget_get_window (GTK_WIDGET (priv->widget)), + bounds.width, bounds.height, -1); + cr = gdk_cairo_create (GDK_DRAWABLE (pixmap)); + gdk_cairo_set_source_color (cr, context->bg); + cairo_rectangle (cr, 0, 0, bounds.width, bounds.height); + gdk_cairo_set_source_color (cr, context->fg); + eek_draw_outline (cr, outline); + cairo_destroy (cr); + g_hash_table_insert (priv->outline_pixmaps, outline, pixmap); } - cairo_restore (priv->cr); + + cairo_save (context->cr); + cairo_translate (context->cr, bounds.x, bounds.y); + + gdk_cairo_set_source_pixmap (context->cr, pixmap, 0, 0); + cairo_rectangle (context->cr, 0, 0, bounds.width, bounds.height); + cairo_fill (context->cr); + + cairo_move_to (context->cr, 0, 0); + gdk_cairo_set_source_color (context->cr, context->fg); + eek_draw_key_label (context->cr, key, priv->fonts); + + cairo_restore (context->cr); } static void -draw_section (EekElement *element, gpointer user_data) +prepare_keyboard_pixmap_section_callback (EekElement *element, + gpointer user_data) { - EekKeyboard *keyboard = user_data; - EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(keyboard); + DrawingContext *context = user_data; EekBounds bounds; - gdk_cairo_set_source_color (priv->cr, priv->dark_color); eek_element_get_bounds (element, &bounds); + cairo_save (context->cr); + cairo_translate (context->cr, bounds.x, bounds.y); + eek_container_foreach_child (EEK_CONTAINER(element), + prepare_keyboard_pixmap_key_callback, + context); + cairo_restore (context->cr); +} - cairo_save (priv->cr); - cairo_translate (priv->cr, bounds.x, bounds.y); +static void +drawing_context_init (DrawingContext *context, EekGtkKeyboard *keyboard) +{ + EekGtkKeyboardPrivate *priv = keyboard->priv; + GtkStateType state; + GdkColormap *colormap; -#if 0 - cairo_rectangle (priv->cr, 0, 0, bounds.width, bounds.height); - cairo_stroke (priv->cr); -#endif + state = gtk_widget_get_state (GTK_WIDGET (priv->widget)); + context->keyboard = keyboard; + context->fg = >k_widget_get_style (GTK_WIDGET (priv->widget))->fg[state]; + context->bg = >k_widget_get_style (GTK_WIDGET (priv->widget))->bg[state]; +} - eek_container_foreach_child (EEK_CONTAINER(element), draw_key, - keyboard); - cairo_restore (priv->cr); +static void +prepare_keyboard_pixmap (EekGtkKeyboard *keyboard) +{ + EekGtkKeyboardPrivate *priv = keyboard->priv; + GtkAllocation allocation; + GtkStateType state; + DrawingContext context; + + gtk_widget_get_allocation (GTK_WIDGET (priv->widget), &allocation); + priv->pixmap = + gdk_pixmap_new (gtk_widget_get_window (GTK_WIDGET (priv->widget)), + allocation.width, allocation.height, -1); + + /* blank background */ + state = gtk_widget_get_state (GTK_WIDGET (priv->widget)); + gdk_draw_rectangle + (priv->pixmap, + gtk_widget_get_style (GTK_WIDGET(priv->widget))->base_gc[state], + TRUE, + 0, 0, allocation.width, allocation.height); + + /* draw sections on the canvas */ + drawing_context_init (&context, keyboard); + context.cr = gdk_cairo_create (GDK_DRAWABLE (priv->pixmap)); + eek_container_foreach_child (EEK_CONTAINER(keyboard), + prepare_keyboard_pixmap_section_callback, + &context); + cairo_destroy (context.cr); } static gboolean -on_gtk_expose_event (GtkWidget *widget, - GdkEventExpose *event, - gpointer user_data) +on_expose_event (GtkWidget *widget, + GdkEventExpose *event, + gpointer user_data) { EekGtkKeyboard *keyboard = user_data; EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(keyboard); - GtkStateType state = gtk_widget_get_state (GTK_WIDGET (widget)); + GtkStateType state = gtk_widget_get_state (widget); if (!priv->pixmap) { - GtkStateType state = gtk_widget_get_state (GTK_WIDGET (priv->widget)); - GtkAllocation allocation; - PangoContext *context; - PangoFontDescription *default_font_desc; - - context = gtk_widget_get_pango_context (GTK_WIDGET (priv->widget)); - priv->layout = pango_layout_new (context); + /* compute font sizes which fit in each key shape */ + PangoFontDescription *base_font; + PangoContext *context; + PangoLayout *layout; - /* compute font sizes */ - default_font_desc = - gtk_widget_get_style (GTK_WIDGET(priv->widget))->font_desc; - pango_layout_set_font_description (priv->layout, default_font_desc); - eek_get_fonts (EEK_KEYBOARD(keyboard), priv->layout, priv->fonts); + context = gtk_widget_get_pango_context (priv->widget); + layout = pango_layout_new (context); + base_font = gtk_widget_get_style (priv->widget)->font_desc; + pango_layout_set_font_description (layout, base_font); + eek_get_fonts (EEK_KEYBOARD(keyboard), layout, priv->fonts); - /* create priv->pixmap */ - gtk_widget_set_double_buffered (GTK_WIDGET (priv->widget), FALSE); - gtk_widget_get_allocation (GTK_WIDGET (priv->widget), &allocation); - priv->pixmap = - gdk_pixmap_new (gtk_widget_get_window (GTK_WIDGET (priv->widget)), - allocation.width, allocation.height, -1); - - /* blank background */ - gdk_draw_rectangle - (priv->pixmap, - gtk_widget_get_style (GTK_WIDGET(priv->widget))->base_gc[state], - TRUE, - 0, 0, allocation.width, allocation.height); - - /* draw sections on the canvas */ - priv->cr = gdk_cairo_create (GDK_DRAWABLE (priv->pixmap)); - priv->dark_color = - >k_widget_get_style (GTK_WIDGET (priv->widget))->dark[state]; - - eek_container_foreach_child (EEK_CONTAINER(keyboard), draw_section, - keyboard); - - cairo_destroy (priv->cr); - priv->cr = NULL; - priv->dark_color = NULL; + prepare_keyboard_pixmap (keyboard); } + g_return_val_if_fail (priv->pixmap, FALSE); gdk_draw_drawable (gtk_widget_get_window (widget), gtk_widget_get_style (widget)->fg_gc[state], @@ -234,8 +307,92 @@ on_gtk_expose_event (GtkWidget *widget, return TRUE; } +static void +key_enlarge (EekGtkKeyboard *keyboard, EekKey *key) +{ + EekGtkKeyboardPrivate *priv = + EEK_GTK_KEYBOARD_GET_PRIVATE(keyboard); + EekBounds bounds; + EekOutline *outline; + gdouble ax, ay; + GdkPixmap *pixmap, *texture; + DrawingContext context; + GtkStateType state; + cairo_t *cr; + + drawing_context_init (&context, keyboard); + + eek_element_get_bounds (EEK_ELEMENT(key), &bounds); + eek_element_get_absolute_position (EEK_ELEMENT(key), &ax, &ay); + + outline = eek_key_get_outline (key); + texture = g_hash_table_lookup (priv->outline_large_pixmaps, outline); + if (!texture) { + texture = + gdk_pixmap_new (gtk_widget_get_window (GTK_WIDGET (priv->widget)), + bounds.width * SCALE, bounds.height * SCALE, -1); + cr = gdk_cairo_create (GDK_DRAWABLE (texture)); + cairo_scale (cr, SCALE, SCALE); + gdk_cairo_set_source_color (cr, context.bg); + cairo_rectangle (cr, 0, 0, bounds.width, bounds.height); + gdk_cairo_set_source_color (cr, context.fg); + eek_draw_outline (cr, outline); + cairo_destroy (cr); + g_hash_table_insert (priv->outline_large_pixmaps, outline, texture); + } + + pixmap = + gdk_pixmap_new (gtk_widget_get_window (GTK_WIDGET (priv->widget)), + bounds.width * SCALE, bounds.height * SCALE, -1); + cr = gdk_cairo_create (GDK_DRAWABLE (pixmap)); + gdk_cairo_set_source_pixmap (cr, texture, 0, 0); + cairo_rectangle (cr, 0, 0, bounds.width * SCALE, bounds.height * SCALE); + cairo_fill (cr); + + cairo_move_to (cr, 0, 0); + cairo_scale (cr, SCALE, SCALE); + gdk_cairo_set_source_color (cr, context.fg); + eek_draw_key_label (cr, key, priv->fonts); + cairo_destroy (cr); + + state = gtk_widget_get_state (GTK_WIDGET (priv->widget)); + gdk_draw_drawable (gtk_widget_get_window (priv->widget), + gtk_widget_get_style (priv->widget)->fg_gc[state], + pixmap, + 0, 0, + ax - (bounds.width * SCALE - bounds.width) / 2, + ay - (bounds.height * SCALE - bounds.height) / 2, + bounds.width * SCALE, bounds.height * SCALE); + g_object_unref (pixmap); +} + +static void +key_shrink (EekGtkKeyboard *keyboard, EekKey *key) +{ + EekGtkKeyboardPrivate *priv = + EEK_GTK_KEYBOARD_GET_PRIVATE(keyboard); + EekBounds bounds; + gdouble ax, ay; + GtkStateType state; + + g_return_if_fail (priv->pixmap); + eek_element_get_bounds (EEK_ELEMENT(key), &bounds); + eek_element_get_absolute_position (EEK_ELEMENT(key), &ax, &ay); + state = gtk_widget_get_state (GTK_WIDGET (priv->widget)); + + ax -= (bounds.width * SCALE - bounds.width) / 2; + ay -= (bounds.height * SCALE - bounds.height) / 2; + + gdk_draw_drawable (gtk_widget_get_window (priv->widget), + gtk_widget_get_style (priv->widget)->fg_gc[state], + priv->pixmap, + ax, ay, + ax, ay, + bounds.width * SCALE, bounds.height * SCALE); +} + static gboolean -on_gtk_button_event (GtkWidget *widget, +on_button_event (GtkWidget *widget, GdkEventButton *event, gpointer user_data) { @@ -254,9 +411,11 @@ on_gtk_button_event (GtkWidget *widget, if (key) switch (event->type) { case GDK_BUTTON_PRESS: + key_enlarge (EEK_GTK_KEYBOARD(keyboard), EEK_KEY(key)); g_signal_emit_by_name (keyboard, "key-pressed", key); return TRUE; case GDK_BUTTON_RELEASE: + key_shrink (EEK_GTK_KEYBOARD(keyboard), EEK_KEY(key)); g_signal_emit_by_name (keyboard, "key-released", key); return TRUE; default: @@ -275,17 +434,19 @@ eek_gtk_keyboard_get_widget (EekGtkKeyboard *keyboard) if (!priv->widget) { priv->widget = gtk_drawing_area_new (); g_object_ref_sink (priv->widget); + + gtk_widget_set_double_buffered (priv->widget, FALSE); gtk_widget_set_events (priv->widget, GDK_EXPOSURE_MASK | GDK_KEY_PRESS_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); g_signal_connect (priv->widget, "expose_event", - G_CALLBACK (on_gtk_expose_event), keyboard); + G_CALLBACK (on_expose_event), keyboard); g_signal_connect (priv->widget, "button-press-event", - G_CALLBACK (on_gtk_button_event), keyboard); + G_CALLBACK (on_button_event), keyboard); g_signal_connect (priv->widget, "button-release-event", - G_CALLBACK (on_gtk_button_event), keyboard); + G_CALLBACK (on_button_event), keyboard); eek_keyboard_realize (EEK_KEYBOARD(keyboard)); } return priv->widget; diff --git a/src/Makefile.am b/src/Makefile.am index 6c0a8427..c90ba5d7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -17,5 +17,5 @@ # 02110-1301 USA bin_PROGRAMS = eekboard -eekboard_CFLAGS = -I$(top_srcdir) $(GOBJECT2_CFLAGS) $(CLUTTER_CFLAGS) $(CLUTTER_GTK_CFLAGS) $(GTK2_CFLAGS) $(XKB_CFLAGS) $(LIBXKLAVIER_CFLAGS) $(LIBFAKEKEY_CFLAGS) -eekboard_LDFLAGS = $(top_builddir)/eek/libeek.la $(top_builddir)/eek/libeek-xkl.la $(top_builddir)/eek/libeek-clutter.la $(top_builddir)/eek/libeek-gtk.la $(GOBJECT2_LIBS) $(CLUTTER_LIBS) $(CLUTTER_GTK_LIBS) $(GTK2_CFLAGS) $(XKB_LIBS) $(LIBXKLAVIER_LIBS) $(LIBFAKEKEY_LIBS) +eekboard_CFLAGS = -I$(top_srcdir) $(GOBJECT2_CFLAGS) $(CLUTTER_CFLAGS) $(CLUTTER_GTK_CFLAGS) $(GTK2_CFLAGS) $(XKB_CFLAGS) $(LIBXKLAVIER_CFLAGS) $(LIBFAKEKEY_CFLAGS) $(ATK_CFLAGS) +eekboard_LDFLAGS = $(top_builddir)/eek/libeek.la $(top_builddir)/eek/libeek-xkl.la $(top_builddir)/eek/libeek-clutter.la $(top_builddir)/eek/libeek-gtk.la $(GOBJECT2_LIBS) $(CLUTTER_LIBS) $(CLUTTER_GTK_LIBS) $(GTK2_CFLAGS) $(XKB_LIBS) $(LIBXKLAVIER_LIBS) $(LIBFAKEKEY_LIBS) $(ATK_LIBS) diff --git a/src/eekboard.c b/src/eekboard.c index ea8d8b32..4a4faf88 100644 --- a/src/eekboard.c +++ b/src/eekboard.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -58,6 +59,7 @@ struct _Eekboard { FakeKey *fakekey; GtkWidget *widget; gfloat width, height; + guint key_event_listener; EekKeyboard *keyboard; EekLayout *layout; /* FIXME: eek_keyboard_get_layout() */ @@ -143,11 +145,30 @@ on_about (GtkAction * action, GtkWidget *window) "wrap-license", TRUE, NULL); } +static gint +key_snoop (AtkKeyEventStruct *event, gpointer func_data) +{ + g_debug ("key_snoop"); + return FALSE; +} + static void on_monitor_key_event_toggled (GtkToggleAction *action, GtkWidget *window) { - g_warning ("not implemented"); + + Eekboard *eekboard = g_object_get_data (G_OBJECT(window), "eekboard"); + + if (gtk_toggle_action_get_active (action)) { + if (eekboard->key_event_listener == 0) + eekboard->key_event_listener = + atk_add_key_event_listener (key_snoop, eekboard); + g_warning ("failed to enable ATK key event listener"); + } else + if (eekboard->key_event_listener != 0) { + atk_remove_key_event_listener (eekboard->key_event_listener); + eekboard->key_event_listener = 0; + } } static void @@ -162,7 +183,6 @@ on_key_pressed (EekKeyboard *keyboard, #if DEBUG g_debug ("%s %X", eek_keysym_to_string (keysym), eekboard->modifiers); #endif - fakekey_press_keysym (eekboard->fakekey, keysym, eekboard->modifiers); if (keysym == XK_Shift_L || keysym == XK_Shift_R) { gint group, level; @@ -174,7 +194,8 @@ on_key_pressed (EekKeyboard *keyboard, eekboard->modifiers ^= ControlMask; } else if (keysym == XK_Alt_L || keysym == XK_Alt_R) { eekboard->modifiers ^= Mod1Mask; - } + } else + fakekey_press_keysym (eekboard->fakekey, keysym, eekboard->modifiers); } static void @@ -505,12 +526,25 @@ main (int argc, char *argv[]) if (env && g_strcmp0 (env, "1") == 0) use_clutter = FALSE; - if (use_clutter) { - if (gtk_clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) { - g_warning ("Can't init Clutter-Gtk"); - use_clutter = FALSE; - } + if (use_clutter && + clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS) && +#ifdef CLUTTER_GTK_CHECK_VERSION + !CLUTTER_GTK_CHECK_VERSION(0, 10, 5) +#else + TRUE +#endif + ) { + g_warning ("Clutter-Gtk <= 0.10.4 does not work well with " + "Clutter >= 1.2...fallback to GTK"); + use_clutter = FALSE; } + + if (use_clutter && + gtk_clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) { + g_warning ("Can't init Clutter-Gtk...fallback to GTK"); + use_clutter = FALSE; + } + if (!use_clutter && !gtk_init_check (&argc, &argv)) { g_warning ("Can't init GTK"); exit (1); @@ -526,6 +560,7 @@ main (int argc, char *argv[]) vbox = gtk_vbox_new (FALSE, 0); eekboard = eekboard_new (use_clutter); + g_object_set_data (G_OBJECT(window), "eekboard", eekboard); widget = create_widget (eekboard, CSW, CSH); ui_manager = gtk_ui_manager_new ();