From 420b8014f86745ca6ad6e338444d146aed110728 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Tue, 25 Jan 2011 10:40:25 +0900 Subject: [PATCH] Revive Clutter support. --- configure.ac | 5 +- eek/Makefile.am | 6 +- eek/eek-clutter-drawing-context.c | 138 ----------- eek/eek-clutter-drawing-context.h | 82 ------- eek/eek-clutter-key-actor.c | 373 ------------------------------ eek/eek-clutter-key-actor.h | 68 ------ eek/eek-clutter-key.c | 260 ++++++++++++++------- eek/eek-clutter-key.h | 14 +- eek/eek-clutter-keyboard.c | 317 ++++++++----------------- eek/eek-clutter-keyboard.h | 9 +- eek/eek-clutter-renderer.c | 184 +++++++++++++++ eek/eek-clutter-renderer.h | 44 ++++ eek/eek-clutter-section.c | 199 +++++++--------- eek/eek-clutter-section.h | 14 +- eek/eek-keyboard.c | 9 +- src/eekboard.c | 63 ++++- 16 files changed, 675 insertions(+), 1110 deletions(-) delete mode 100644 eek/eek-clutter-drawing-context.c delete mode 100644 eek/eek-clutter-drawing-context.h delete mode 100644 eek/eek-clutter-key-actor.c delete mode 100644 eek/eek-clutter-key-actor.h create mode 100644 eek/eek-clutter-renderer.c create mode 100644 eek/eek-clutter-renderer.h diff --git a/configure.ac b/configure.ac index ac58f424..e6d87bfc 100644 --- a/configure.ac +++ b/configure.ac @@ -147,7 +147,7 @@ AC_MSG_CHECKING([whether you enable Clutter]) AC_ARG_ENABLE(clutter, AS_HELP_STRING([--enable-clutter=no/yes], [Enable Clutter user interface default=yes]),, - enable_clutter=yes) + enable_clutter=no) AC_MSG_RESULT($enable_clutter) if test x$enable_clutter = xyes; then @@ -164,8 +164,7 @@ if test x$enable_clutter = xyes; then AC_DEFINE_UNQUOTED([NEED_SWAP_EVENT_WORKAROUND], $need_swap_event_workaround, [Define if GLX_INTEL_swap_event work around is needed]) fi -dnl AM_CONDITIONAL(HAVE_CLUTTER, [test x$enable_clutter = xyes]) -AM_CONDITIONAL(HAVE_CLUTTER, [false]) +AM_CONDITIONAL(HAVE_CLUTTER, [test x$enable_clutter = xyes]) GTK_DOC_CHECK([1.14],[--flavour no-tmpl]) diff --git a/eek/Makefile.am b/eek/Makefile.am index 3f655c88..d8759d59 100644 --- a/eek/Makefile.am +++ b/eek/Makefile.am @@ -88,12 +88,14 @@ libeek_clutter_public_headers = \ libeek_clutter_private_headers = \ $(srcdir)/eek-clutter-section.h \ - $(srcdir)/eek-clutter-key.h + $(srcdir)/eek-clutter-key.h \ + $(srcdir)/eek-clutter-renderer.h libeek_clutter_sources = \ $(srcdir)/eek-clutter-keyboard.c \ $(srcdir)/eek-clutter-section.c \ - $(srcdir)/eek-clutter-key.c + $(srcdir)/eek-clutter-key.c \ + $(srcdir)/eek-clutter-renderer.c libeek_clutter_la_SOURCES = $(libeek_clutter_sources) libeek_clutter_la_CFLAGS = $(CLUTTER_CFLAGS) diff --git a/eek/eek-clutter-drawing-context.c b/eek/eek-clutter-drawing-context.c deleted file mode 100644 index 984f8e1e..00000000 --- a/eek/eek-clutter-drawing-context.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2010 Daiki Ueno - * Copyright (C) 2010 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -#include - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif /* HAVE_CONFIG_H */ - -#include "eek-clutter-drawing-context.h" - -G_DEFINE_TYPE (EekClutterDrawingContext, eek_clutter_drawing_context, - G_TYPE_INITIALLY_UNOWNED); - -#define EEK_CLUTTER_DRAWING_CONTEXT_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_CLUTTER_DRAWING_CONTEXT, EekClutterDrawingContextPrivate)) - -struct _EekClutterDrawingContextPrivate -{ - /* outline pointer -> ClutterTexture */ - GHashTable *outline_textures; - - /* keysym category -> PangoFontDescription * */ - PangoFontDescription *category_fonts[EEK_KEYSYM_CATEGORY_LAST]; -}; - -static void -eek_clutter_drawing_context_dispose (GObject *object) -{ - EekClutterDrawingContextPrivate *priv = - EEK_CLUTTER_DRAWING_CONTEXT_GET_PRIVATE(object); - if (priv->outline_textures) { - g_hash_table_unref (priv->outline_textures); - priv->outline_textures = NULL; - } -} - -static void -eek_clutter_drawing_context_finalize (GObject *object) -{ - EekClutterDrawingContextPrivate *priv = - EEK_CLUTTER_DRAWING_CONTEXT_GET_PRIVATE(object); - gint i; - - for (i = 0; i < EEK_KEYSYM_CATEGORY_LAST; i++) - pango_font_description_free (priv->category_fonts[i]); -} - -static void -eek_clutter_drawing_context_class_init (EekClutterDrawingContextClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (gobject_class, - sizeof (EekClutterDrawingContextPrivate)); - - gobject_class->finalize = eek_clutter_drawing_context_finalize; - gobject_class->dispose = eek_clutter_drawing_context_dispose; -} - -static void -eek_clutter_drawing_context_init (EekClutterDrawingContext *self) -{ - EekClutterDrawingContextPrivate *priv; - - priv = self->priv = EEK_CLUTTER_DRAWING_CONTEXT_GET_PRIVATE(self); - priv->outline_textures = g_hash_table_new (g_direct_hash, g_direct_equal); - memset (priv->category_fonts, 0, sizeof *priv->category_fonts); -} - -void -eek_clutter_drawing_context_set_outline_texture - (EekClutterDrawingContext *context, - EekOutline *outline, - ClutterActor *texture) -{ - EekClutterDrawingContextPrivate *priv = - EEK_CLUTTER_DRAWING_CONTEXT_GET_PRIVATE(context); - g_return_if_fail (priv); - g_hash_table_insert (context->priv->outline_textures, outline, texture); -} - -ClutterActor * -eek_clutter_drawing_context_get_outline_texture - (EekClutterDrawingContext *context, - EekOutline *outline) -{ - EekClutterDrawingContextPrivate *priv = - EEK_CLUTTER_DRAWING_CONTEXT_GET_PRIVATE(context); - g_return_val_if_fail (priv, NULL); - return g_hash_table_lookup (context->priv->outline_textures, outline); -} - -void -eek_clutter_drawing_context_set_category_font - (EekClutterDrawingContext *context, - EekKeysymCategory category, - PangoFontDescription *font) -{ - EekClutterDrawingContextPrivate *priv = - EEK_CLUTTER_DRAWING_CONTEXT_GET_PRIVATE(context); - g_return_if_fail (priv); - priv->category_fonts[category] = pango_font_description_copy (font); -} - -PangoFontDescription * -eek_clutter_drawing_context_get_category_font - (EekClutterDrawingContext *context, - EekKeysymCategory category) -{ - EekClutterDrawingContextPrivate *priv = - EEK_CLUTTER_DRAWING_CONTEXT_GET_PRIVATE(context); - g_return_val_if_fail (priv, NULL); - return priv->category_fonts[category]; -} - -EekClutterDrawingContext * -eek_clutter_drawing_context_new (void) -{ - return g_object_new (EEK_TYPE_CLUTTER_DRAWING_CONTEXT, NULL); -} diff --git a/eek/eek-clutter-drawing-context.h b/eek/eek-clutter-drawing-context.h deleted file mode 100644 index 70d8afe8..00000000 --- a/eek/eek-clutter-drawing-context.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2010 Daiki Ueno - * Copyright (C) 2010 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301 USA - */ -#ifndef EEK_CLUTTER_DRAWING_CONTEXT_H -#define EEK_CLUTTER_DRAWING_CONTEXT_H 1 - -#include -#include - -#include "eek-keysym.h" -#include "eek-types.h" - -G_BEGIN_DECLS -#define EEK_TYPE_CLUTTER_DRAWING_CONTEXT (eek_clutter_drawing_context_get_type()) -#define EEK_CLUTTER_DRAWING_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_CLUTTER_DRAWING_CONTEXT, EekClutterDrawingContext)) -#define EEK_CLUTTER_DRAWING_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_CLUTTER_DRAWING_CONTEXT, EekClutterDrawingContextClass)) -#define EEK_IS_CLUTTER_DRAWING_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_CLUTTER_DRAWING_CONTEXT)) -#define EEK_IS_CLUTTER_DRAWING_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_CLUTTER_DRAWING_CONTEXT)) -#define EEK_CLUTTER_DRAWING_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_CLUTTER_DRAWING_CONTEXT, EekClutterDrawingContextClass)) - -typedef struct _EekClutterDrawingContext EekClutterDrawingContext; -typedef struct _EekClutterDrawingContextClass EekClutterDrawingContextClass; -typedef struct _EekClutterDrawingContextPrivate EekClutterDrawingContextPrivate; - -struct _EekClutterDrawingContext -{ - /*< private >*/ - GInitiallyUnowned parent; - - /*< private >*/ - EekClutterDrawingContextPrivate *priv; -}; - -struct _EekClutterDrawingContextClass -{ - /*< private >*/ - GInitiallyUnownedClass parent_class; - - /*< private >*/ - /* padding */ - gpointer pdummy[24]; -}; - -GType eek_clutter_drawing_context_get_type - (void) G_GNUC_CONST; -EekClutterDrawingContext *eek_clutter_drawing_context_new - (void); - -void eek_clutter_drawing_context_set_outline_texture - (EekClutterDrawingContext *context, - EekOutline *outline, - ClutterActor *texture); -ClutterActor *eek_clutter_drawing_context_get_outline_texture - (EekClutterDrawingContext *context, - EekOutline *outline); - -void eek_clutter_drawing_context_set_category_font - (EekClutterDrawingContext *context, - EekKeysymCategory category, - PangoFontDescription *fonts); -PangoFontDescription *eek_clutter_drawing_context_get_category_font - (EekClutterDrawingContext *context, - EekKeysymCategory category); - -G_END_DECLS -#endif /* EEK_CLUTTER_DRAWING_CONTEXT_H */ diff --git a/eek/eek-clutter-key-actor.c b/eek/eek-clutter-key-actor.c deleted file mode 100644 index 1f4df7ee..00000000 --- a/eek/eek-clutter-key-actor.c +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Copyright (C) 2006 Sergey V. Udaltsov - * Copyright (C) 2010 Daiki Ueno - * Copyright (C) 2010 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -#include -#include - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif /* HAVE_CONFIG_H */ -#include "eek-clutter-key-actor.h" -#include "eek-keysym.h" -#include "eek-drawing.h" -#include "eek-section.h" -#include "eek-keyboard.h" - -#define noKBDRAW_DEBUG - -enum { - PRESSED, - RELEASED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0, }; - -G_DEFINE_TYPE (EekClutterKeyActor, eek_clutter_key_actor, - CLUTTER_TYPE_GROUP); - -#define EEK_CLUTTER_KEY_ACTOR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_CLUTTER_KEY_ACTOR, EekClutterKeyActorPrivate)) - -struct _EekClutterKeyActorPrivate -{ - EekClutterDrawingContext *context; - EekKey *key; - ClutterActor *texture; - gboolean is_pressed; -}; - -static ClutterActor *get_texture (EekClutterKeyActor *actor); -static void draw_key_on_layout (EekClutterKeyActor *actor, - PangoLayout *layout); -static void key_enlarge (ClutterActor *actor); -static void key_shrink (ClutterActor *actor); - -static void -eek_clutter_key_actor_real_paint (ClutterActor *self) -{ - EekClutterKeyActorPrivate *priv = EEK_CLUTTER_KEY_ACTOR_GET_PRIVATE (self); - PangoLayout *layout; - PangoRectangle logical_rect = { 0, }; - CoglColor color; - ClutterGeometry geom; - EekBounds bounds; - - eek_element_get_bounds (EEK_ELEMENT(priv->key), &bounds); - clutter_actor_set_anchor_point_from_gravity (self, - CLUTTER_GRAVITY_CENTER); - clutter_actor_set_position (self, - bounds.x + bounds.width / 2, - bounds.y + bounds.height / 2); - - if (!priv->texture) { - priv->texture = get_texture (EEK_CLUTTER_KEY_ACTOR(self)); - clutter_actor_set_position (priv->texture, 0, 0); - clutter_container_add_actor (CLUTTER_CONTAINER(self), priv->texture); - } - - CLUTTER_ACTOR_CLASS (eek_clutter_key_actor_parent_class)-> - paint (self); - - /* Draw the label on the key. */ - layout = clutter_actor_create_pango_layout (self, NULL); - draw_key_on_layout (EEK_CLUTTER_KEY_ACTOR(self), layout); - pango_layout_get_extents (layout, NULL, &logical_rect); - - /* FIXME: Color should be configurable through a property. */ - cogl_color_set_from_4ub (&color, 0x80, 0x00, 0x00, 0xff); - clutter_actor_get_allocation_geometry (self, &geom); - cogl_pango_render_layout - (layout, - (geom.width - logical_rect.width / PANGO_SCALE) / 2, - (geom.height - logical_rect.height / PANGO_SCALE) / 2, - &color, - 0); - g_object_unref (layout); -} - -static void -eek_clutter_key_actor_real_pressed (EekClutterKeyActor *self) -{ - ClutterActor *actor, *section; - - actor = CLUTTER_ACTOR(self); - - /* Make sure the enlarged key show up on the keys which belong - to other sections. */ - section = clutter_actor_get_parent (actor); - clutter_actor_raise_top (section); - clutter_actor_raise_top (actor); - key_enlarge (actor); -} - -static void -eek_clutter_key_actor_real_released (EekClutterKeyActor *self) -{ - ClutterActor *actor, *section; - - actor = CLUTTER_ACTOR(self); - - /* Make sure the enlarged key show up on the keys which belong - to other sections. */ - section = clutter_actor_get_parent (actor); - clutter_actor_raise_top (section); - clutter_actor_raise_top (actor); - key_shrink (actor); -} - -static void -eek_clutter_key_actor_dispose (GObject *object) -{ - EekClutterKeyActorPrivate *priv = EEK_CLUTTER_KEY_ACTOR_GET_PRIVATE(object); - - if (priv->context) { - g_object_unref (priv->context); - priv->context = NULL; - } - if (priv->key) { - g_object_unref (priv->key); - priv->key = NULL; - } - G_OBJECT_CLASS (eek_clutter_key_actor_parent_class)->dispose (object); -} - -static void -eek_clutter_key_actor_class_init (EekClutterKeyActorClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); - - g_type_class_add_private (gobject_class, - sizeof (EekClutterKeyActorPrivate)); - - actor_class->paint = eek_clutter_key_actor_real_paint; - - gobject_class->dispose = eek_clutter_key_actor_dispose; - - /* signals */ - klass->pressed = eek_clutter_key_actor_real_pressed; - klass->released = eek_clutter_key_actor_real_released; - - signals[PRESSED] = - g_signal_new ("pressed", - G_TYPE_FROM_CLASS(gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(EekClutterKeyActorClass, pressed), - NULL, - NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - signals[RELEASED] = - g_signal_new ("released", - G_TYPE_FROM_CLASS(gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(EekClutterKeyActorClass, released), - NULL, - NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); -} - -static void -on_button_press_event (ClutterActor *actor, - ClutterEvent *event, - gpointer user_data) -{ - EekClutterKeyActorPrivate *priv = - EEK_CLUTTER_KEY_ACTOR_GET_PRIVATE(actor); - - if (!priv->is_pressed) { - priv->is_pressed = TRUE; - /* priv->key will send back PRESSED event of actor. */ - g_signal_emit_by_name (priv->key, "pressed"); - } -} - -static void -on_button_release_event (ClutterActor *actor, - ClutterEvent *event, - gpointer user_data) -{ - EekClutterKeyActorPrivate *priv = - EEK_CLUTTER_KEY_ACTOR_GET_PRIVATE(actor); - - if (priv->is_pressed) { - priv->is_pressed = FALSE; - /* priv->key will send back RELEASED event of actor. */ - g_signal_emit_by_name (priv->key, "released"); - } -} - -static gboolean -on_leave_event (ClutterActor *actor, - ClutterEvent *event, - gpointer user_data) -{ - EekClutterKeyActorPrivate *priv = - EEK_CLUTTER_KEY_ACTOR_GET_PRIVATE(actor); - - if (priv->is_pressed) { - priv->is_pressed = FALSE; - /* priv->key will send back RELEASED event of actor. */ - g_signal_emit_by_name (priv->key, "released"); - } - return FALSE; -} - -static void -eek_clutter_key_actor_init (EekClutterKeyActor *self) -{ - EekClutterKeyActorPrivate *priv; - - priv = self->priv = EEK_CLUTTER_KEY_ACTOR_GET_PRIVATE(self); - priv->key = NULL; - priv->texture = NULL; - - clutter_actor_set_reactive (CLUTTER_ACTOR(self), TRUE); - - g_signal_connect (self, "button-press-event", - G_CALLBACK (on_button_press_event), NULL); - g_signal_connect (self, "button-release-event", - G_CALLBACK (on_button_release_event), NULL); - g_signal_connect (self, "leave-event", - G_CALLBACK (on_leave_event), NULL); -} - -ClutterActor * -eek_clutter_key_actor_new (EekClutterDrawingContext *context, EekKey *key) -{ - EekClutterKeyActor *actor; - - actor = g_object_new (EEK_TYPE_CLUTTER_KEY_ACTOR, NULL); - actor->priv->context = context; - g_object_ref_sink (actor->priv->context); - actor->priv->key = key; - g_object_ref_sink (actor->priv->key); - return CLUTTER_ACTOR(actor); -} - -#if 0 -static void -on_key_animate_complete (ClutterAnimation *animation, - gpointer user_data) -{ - ClutterActor *actor = (ClutterActor*)user_data; - - /* reset after effect */ - clutter_actor_set_opacity (actor, 0xff); - clutter_actor_set_scale (actor, 1.0, 1.0); -} -#endif - -static void -key_enlarge (ClutterActor *actor) -{ - clutter_actor_set_scale (actor, 1.0, 1.0); - clutter_actor_animate (actor, CLUTTER_EASE_IN_SINE, 150, - "scale-x", 1.5, - "scale-y", 1.5, - NULL); -} - -static void -key_shrink (ClutterActor *actor) -{ - clutter_actor_set_scale (actor, 1.5, 1.5); - clutter_actor_animate (actor, CLUTTER_EASE_OUT_SINE, 150, - "scale-x", 1.0, - "scale-y", 1.0, - NULL); -} - - -static ClutterActor * -create_texture_for_key (EekKey *key) -{ - ClutterActor *texture; - cairo_t *cr; - EekOutline *outline; - EekBounds bounds; - - outline = eek_key_get_outline (EEK_KEY(key)); - eek_element_get_bounds (EEK_ELEMENT(key), &bounds); - - texture = clutter_cairo_texture_new (bounds.width, bounds.height); - cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE(texture)); - eek_draw_outline (cr, outline); - cairo_destroy (cr); - return texture; -} - -static ClutterActor * -get_texture (EekClutterKeyActor *actor) -{ - ClutterActor *texture; - EekOutline *outline; - - outline = eek_key_get_outline (actor->priv->key); - texture = - eek_clutter_drawing_context_get_outline_texture (actor->priv->context, - outline); - if (texture == NULL) { - texture = create_texture_for_key (actor->priv->key); - eek_clutter_drawing_context_set_outline_texture (actor->priv->context, - outline, - texture); - } else - texture = clutter_clone_new (texture); - return texture; -} - -static void -draw_key_on_layout (EekClutterKeyActor *self, - PangoLayout *layout) -{ - EekClutterKeyActorPrivate *priv = EEK_CLUTTER_KEY_ACTOR_GET_PRIVATE (self); - guint keysym; - const gchar *label, *empty_label = ""; - EekKeysymCategory category; - EekBounds bounds; - PangoFontDescription *font; - - keysym = eek_key_get_keysym (priv->key); - if (keysym == EEK_INVALID_KEYSYM) - return; - category = eek_keysym_get_category (keysym); - if (category == EEK_KEYSYM_CATEGORY_UNKNOWN) - return; - - font = eek_clutter_drawing_context_get_category_font (priv->context, - category); - pango_layout_set_font_description (layout, font); - - eek_element_get_bounds (EEK_ELEMENT(priv->key), &bounds); - pango_layout_set_width (layout, PANGO_SCALE * bounds.width); - pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); - - label = eek_keysym_to_string (keysym); - if (!label) - label = empty_label; - eek_draw_text_on_layout (layout, label); - if (label != empty_label) - g_free ((gpointer)label); -} diff --git a/eek/eek-clutter-key-actor.h b/eek/eek-clutter-key-actor.h deleted file mode 100644 index 5b9a7924..00000000 --- a/eek/eek-clutter-key-actor.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2010 Daiki Ueno - * Copyright (C) 2010 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301 USA - */ -#ifndef EEK_CLUTTER_KEY_ACTOR_H -#define EEK_CLUTTER_KEY_ACTOR_H 1 - -#include -#include "eek-clutter-drawing-context.h" -#include "eek-key.h" - -G_BEGIN_DECLS -#define EEK_TYPE_CLUTTER_KEY_ACTOR (eek_clutter_key_actor_get_type()) -#define EEK_CLUTTER_KEY_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_CLUTTER_KEY_ACTOR, EekClutterKeyActor)) -#define EEK_CLUTTER_KEY_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_CLUTTER_KEY_ACTOR, EekClutterKeyActorClass)) -#define EEK_IS_CLUTTER_KEY_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_CLUTTER_KEY_ACTOR)) -#define EEK_IS_CLUTTER_KEY_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_CLUTTER_KEY_ACTOR)) -#define EEK_CLUTTER_KEY_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_CLUTTER_KEY_ACTOR, EekClutterKeyActorClass)) - -typedef struct _EekClutterKeyActor EekClutterKeyActor; -typedef struct _EekClutterKeyActorClass EekClutterKeyActorClass; -typedef struct _EekClutterKeyActorPrivate EekClutterKeyActorPrivate; - -struct _EekClutterKeyActor -{ - /*< private >*/ - ClutterGroup parent; - - /*< private >*/ - EekClutterKeyActorPrivate *priv; -}; - -struct _EekClutterKeyActorClass -{ - /*< private >*/ - ClutterGroupClass parent_class; - - /* signals */ - void (* pressed) (EekClutterKeyActor *self); - void (* released) (EekClutterKeyActor *self); - - /*< private >*/ - /* padding */ - gpointer pdummy[24]; -}; - -GType eek_clutter_key_actor_get_type - (void) G_GNUC_CONST; -ClutterActor *eek_clutter_key_actor_new (EekClutterDrawingContext *context, - EekKey *key); - -G_END_DECLS -#endif /* EEK_CLUTTER_KEY_ACTOR_H */ diff --git a/eek/eek-clutter-key.c b/eek/eek-clutter-key.c index 0762c21b..c5fce722 100644 --- a/eek/eek-clutter-key.c +++ b/eek/eek-clutter-key.c @@ -23,98 +23,144 @@ #endif /* HAVE_CONFIG_H */ #include "eek-clutter-key.h" -#include "eek-clutter-key-actor.h" -G_DEFINE_TYPE (EekClutterKey, eek_clutter_key, EEK_TYPE_KEY); +G_DEFINE_TYPE (EekClutterKey, eek_clutter_key, CLUTTER_TYPE_ACTOR); #define EEK_CLUTTER_KEY_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_CLUTTER_KEY, EekClutterKeyPrivate)) struct _EekClutterKeyPrivate { - EekClutterDrawingContext *context; - ClutterActor *actor; + EekKey *key; + EekClutterRenderer *renderer; }; -static void -eek_clutter_key_real_set_name (EekElement *self, - const gchar *name) -{ - EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(self); - - EEK_ELEMENT_CLASS (eek_clutter_key_parent_class)-> - set_name (self, name); - - if (priv->actor) - clutter_actor_set_name (CLUTTER_ACTOR(priv->actor), name); -} - -static void -eek_clutter_key_real_set_bounds (EekElement *self, - EekBounds *bounds) -{ - EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(self); - - EEK_ELEMENT_CLASS (eek_clutter_key_parent_class)-> - set_bounds (self, bounds); - - if (priv->actor) { - clutter_actor_set_position (priv->actor, bounds->x, bounds->y); - clutter_actor_set_size (priv->actor, bounds->width, bounds->height); - } -} - -static void -eek_clutter_key_real_pressed (EekKey *key) -{ - EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(key); - - if (priv->actor) - g_signal_emit_by_name (priv->actor, "pressed"); -} - -static void -eek_clutter_key_real_released (EekKey *key) -{ - EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(key); - - if (priv->actor) - g_signal_emit_by_name (priv->actor, "released"); -} - static void eek_clutter_key_dispose (GObject *object) { EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(object); - if (priv->context) { - g_object_unref (priv->context); - priv->context = NULL; + if (priv->renderer) { + g_object_unref (priv->renderer); + priv->renderer = NULL; } - if (priv->actor) { - g_object_unref (priv->actor); - priv->actor = NULL; + + if (priv->key && g_object_is_floating (priv->key)) { + g_object_unref (priv->key); + priv->key = NULL; } + G_OBJECT_CLASS (eek_clutter_key_parent_class)->dispose (object); } +static void +eek_clutter_key_real_paint (ClutterActor *self) +{ + EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(self); + + eek_clutter_renderer_render_key (priv->renderer, self, priv->key); +} + +static void +eek_clutter_key_real_get_preferred_width (ClutterActor *self, + gfloat for_height, + gfloat *min_width_p, + gfloat *natural_width_p) +{ + EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(self); + EekBounds bounds; + gdouble scale; + + scale = eek_renderer_get_scale (EEK_RENDERER(priv->renderer)); + eek_element_get_bounds (EEK_ELEMENT(priv->key), &bounds); + *min_width_p = 0.0f; + *natural_width_p = bounds.width * scale; +} + +static void +eek_clutter_key_real_get_preferred_height (ClutterActor *self, + gfloat for_width, + gfloat *min_height_p, + gfloat *natural_height_p) +{ + EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(self); + EekBounds bounds; + gdouble scale; + + scale = eek_renderer_get_scale (EEK_RENDERER(priv->renderer)); + eek_element_get_bounds (EEK_ELEMENT(priv->key), &bounds); + *min_height_p = 0.0f; + *natural_height_p = bounds.height * scale; +} + +static void +eek_clutter_key_real_allocate (ClutterActor *self, + const ClutterActorBox *box, + ClutterAllocationFlags flags) +{ + CLUTTER_ACTOR_CLASS (eek_clutter_key_parent_class)-> + allocate (self, box, flags); +} + +static gboolean +eek_clutter_key_real_button_press_event (ClutterActor *self, + ClutterButtonEvent *event) +{ + EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(self); + + g_signal_emit_by_name (priv->key, "pressed"); + + return TRUE; +} + +static gboolean +eek_clutter_key_real_button_release_event (ClutterActor *self, + ClutterButtonEvent *event) +{ + EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(self); + + g_signal_emit_by_name (priv->key, "released"); + + return TRUE; +} + +static gboolean +eek_clutter_key_real_leave_event (ClutterActor *self, + ClutterCrossingEvent *event) +{ + EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(self); + + if (eek_key_is_pressed (priv->key)) + g_signal_emit_by_name (priv->key, "released"); + + return TRUE; +} + static void eek_clutter_key_class_init (EekClutterKeyClass *klass) { + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - EekElementClass *element_class = EEK_ELEMENT_CLASS (klass); - EekKeyClass *key_class = EEK_KEY_CLASS (klass); g_type_class_add_private (gobject_class, sizeof (EekClutterKeyPrivate)); - element_class->set_name = eek_clutter_key_real_set_name; - element_class->set_bounds = eek_clutter_key_real_set_bounds; - gobject_class->dispose = eek_clutter_key_dispose; + actor_class->paint = eek_clutter_key_real_paint; + actor_class->get_preferred_width = + eek_clutter_key_real_get_preferred_width; + actor_class->get_preferred_height = + eek_clutter_key_real_get_preferred_height; + actor_class->allocate = eek_clutter_key_real_allocate; /* signals */ - key_class->pressed = eek_clutter_key_real_pressed; - key_class->released = eek_clutter_key_real_released; + actor_class->button_press_event = + eek_clutter_key_real_button_press_event; + actor_class->button_release_event = + eek_clutter_key_real_button_release_event; + actor_class->leave_event = + eek_clutter_key_real_leave_event; + + gobject_class->dispose = eek_clutter_key_dispose; } static void @@ -122,33 +168,73 @@ eek_clutter_key_init (EekClutterKey *self) { EekClutterKeyPrivate *priv; priv = self->priv = EEK_CLUTTER_KEY_GET_PRIVATE (self); - priv->actor = NULL; + priv->key = NULL; + priv->renderer = NULL; +} + +static void +on_pressed (EekKey *key, gpointer user_data) +{ + ClutterActor *actor = user_data, *parent; + + parent = clutter_actor_get_parent (actor); + clutter_actor_raise_top (parent); + clutter_actor_raise_top (actor); + clutter_actor_set_scale_with_gravity (actor, + 1.0, + 1.0, + CLUTTER_GRAVITY_CENTER); + + clutter_actor_animate (actor, CLUTTER_EASE_IN_SINE, 150, + "scale-x", 1.5, + "scale-y", 1.5, + NULL); +} + +static void +on_released (EekKey *key, gpointer user_data) +{ + ClutterActor *actor = user_data, *parent; + + parent = clutter_actor_get_parent (actor); + clutter_actor_raise_top (parent); + clutter_actor_raise_top (actor); + clutter_actor_set_scale_with_gravity (actor, + 1.5, + 1.5, + CLUTTER_GRAVITY_CENTER); + clutter_actor_animate (actor, CLUTTER_EASE_OUT_SINE, 150, + "scale-x", 1.0, + "scale-y", 1.0, + NULL); } ClutterActor * -eek_clutter_key_get_actor (EekClutterKey *key) +eek_clutter_key_new (EekKey *key, EekClutterRenderer *renderer) { - EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(key); + ClutterActor *actor; + EekClutterKeyPrivate *priv; + EekBounds bounds; + gdouble scale; - if (!priv->actor) { - g_return_val_if_fail (priv->context, NULL); - priv->actor = eek_clutter_key_actor_new (priv->context, EEK_KEY(key)); - g_object_ref_sink (priv->actor); - } - return priv->actor; -} - -EekKey * -eek_clutter_key_new (EekClutterDrawingContext *context, gint column, gint row) -{ - EekClutterKey *key; - - g_return_val_if_fail (context, NULL); - key = g_object_new (EEK_TYPE_CLUTTER_KEY, - "column", column, - "row", row, - NULL); - key->priv->context = context; - g_object_ref_sink (key->priv->context); - return EEK_KEY(key); + actor = g_object_new (EEK_TYPE_CLUTTER_KEY, NULL); + priv = EEK_CLUTTER_KEY_GET_PRIVATE(actor); + priv->key = g_object_ref_sink (key); + priv->renderer = g_object_ref (renderer); + + eek_element_get_bounds (EEK_ELEMENT(key), &bounds); + scale = eek_renderer_get_scale (EEK_RENDERER(priv->renderer)); + + clutter_actor_set_position (actor, + bounds.x * scale, + bounds.y * scale); + + clutter_actor_set_reactive (actor, TRUE); + + g_signal_connect (priv->key, "pressed", + G_CALLBACK(on_pressed), actor); + g_signal_connect (priv->key, "released", + G_CALLBACK(on_released), actor); + + return actor; } diff --git a/eek/eek-clutter-key.h b/eek/eek-clutter-key.h index 58c13edc..3de52e63 100644 --- a/eek/eek-clutter-key.h +++ b/eek/eek-clutter-key.h @@ -21,8 +21,8 @@ #define EEK_CLUTTER_KEY_H 1 #include -#include "eek-clutter-drawing-context.h" #include "eek-key.h" +#include "eek-clutter-renderer.h" G_BEGIN_DECLS #define EEK_TYPE_CLUTTER_KEY (eek_clutter_key_get_type()) @@ -39,7 +39,7 @@ typedef struct _EekClutterKeyPrivate EekClutterKeyPrivate; struct _EekClutterKey { /*< private >*/ - EekKey parent; + ClutterActor parent; /*< private >*/ EekClutterKeyPrivate *priv; @@ -48,18 +48,16 @@ struct _EekClutterKey struct _EekClutterKeyClass { /*< private >*/ - EekKeyClass parent_class; + ClutterActorClass parent_class; /*< private >*/ /* padding */ gpointer pdummy[24]; }; -GType eek_clutter_key_get_type (void) G_GNUC_CONST; -EekKey * eek_clutter_key_new (EekClutterDrawingContext *context, - gint column, - gint row); -ClutterActor *eek_clutter_key_get_actor (EekClutterKey *key); +GType eek_clutter_key_get_type (void) G_GNUC_CONST; +ClutterActor *eek_clutter_key_new (EekKey *key, + EekClutterRenderer *renderer); G_END_DECLS #endif /* EEK_CLUTTER_KEY_H */ diff --git a/eek/eek-clutter-keyboard.c b/eek/eek-clutter-keyboard.c index 4dd24884..63840a1c 100644 --- a/eek/eek-clutter-keyboard.c +++ b/eek/eek-clutter-keyboard.c @@ -20,107 +20,73 @@ /** * SECTION:eek-clutter-keyboard - * @short_description: #EekKeyboard that can be converted into a #ClutterActor + * @short_description: a #ClutterActor displaying #EekKeyboard */ #include +#include #ifdef HAVE_CONFIG_H #include "config.h" #endif /* HAVE_CONFIG_H */ #include "eek-clutter-keyboard.h" -#include "eek-clutter-drawing-context.h" +#include "eek-clutter-section.h" +#include "eek-clutter-renderer.h" #include "eek-keyboard.h" -#include "eek-drawing.h" -G_DEFINE_TYPE (EekClutterKeyboard, eek_clutter_keyboard, EEK_TYPE_KEYBOARD); +G_DEFINE_TYPE (EekClutterKeyboard, eek_clutter_keyboard, CLUTTER_TYPE_GROUP); #define EEK_CLUTTER_KEYBOARD_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_CLUTTER_KEYBOARD, EekClutterKeyboardPrivate)) - struct _EekClutterKeyboardPrivate { - EekClutterDrawingContext *context; - ClutterActor *actor; - - guint key_press_event_handler; - guint key_release_event_handler; + EekKeyboard *keyboard; + EekClutterRenderer *renderer; }; static void -eek_clutter_keyboard_real_set_name (EekElement *self, - const gchar *name) +eek_clutter_keyboard_real_get_preferred_width (ClutterActor *self, + float for_height, + float *min_width_p, + float *natural_width_p) { EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self); + gdouble width; - EEK_ELEMENT_CLASS (eek_clutter_keyboard_parent_class)-> - set_name (self, name); - - if (priv->actor) - clutter_actor_set_name (priv->actor, name); + eek_renderer_get_size (EEK_RENDERER(priv->renderer), &width, NULL); + *min_width_p = 0.0f; + *natural_width_p = width; } static void -eek_clutter_keyboard_real_set_bounds (EekElement *self, - EekBounds *bounds) +eek_clutter_keyboard_real_get_preferred_height (ClutterActor *self, + float for_width, + float *min_height_p, + float *natural_height_p) { EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self); + gdouble height; - EEK_ELEMENT_CLASS (eek_clutter_keyboard_parent_class)-> - set_bounds (self, bounds); - - if (priv->actor) { - clutter_actor_set_position (priv->actor, bounds->x, bounds->y); - clutter_actor_set_size (priv->actor, bounds->width, bounds->height); - } + eek_renderer_get_size (EEK_RENDERER(priv->renderer), NULL, &height); + *min_height_p = 0.0f; + *natural_height_p = height; } static void -key_pressed_event (EekSection *section, - EekKey *key, - EekKeyboard *keyboard) -{ - g_signal_emit_by_name (keyboard, "key-pressed", key); -} - -static void -key_released_event (EekSection *section, - EekKey *key, - EekKeyboard *keyboard) -{ - g_signal_emit_by_name (keyboard, "key-released", key); -} - -static EekSection * -eek_clutter_keyboard_real_create_section (EekKeyboard *self) +eek_clutter_keyboard_real_allocate (ClutterActor *self, + const ClutterActorBox *box, + ClutterAllocationFlags flags) { EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self); - EekSection *section; - ClutterActor *actor; - if (!priv->context) { - priv->context = eek_clutter_drawing_context_new (); - g_object_ref_sink (G_OBJECT(priv->context)); - } + g_assert (priv->renderer); + eek_renderer_set_allocation_size (EEK_RENDERER(priv->renderer), + box->x2 - box->x1, + box->y2 - box->y1); - section = eek_clutter_section_new (priv->context); - g_return_val_if_fail (section, NULL); - - g_signal_connect (section, "key-pressed", - G_CALLBACK(key_pressed_event), self); - g_signal_connect (section, "key-released", - G_CALLBACK(key_released_event), self); - - EEK_CONTAINER_GET_CLASS(self)->add_child (EEK_CONTAINER(self), - EEK_ELEMENT(section)); - - actor = eek_clutter_keyboard_get_actor (EEK_CLUTTER_KEYBOARD(self)); - clutter_container_add_actor - (CLUTTER_CONTAINER(actor), - eek_clutter_section_get_actor (EEK_CLUTTER_SECTION(section))); - - return section; + CLUTTER_ACTOR_CLASS (eek_clutter_keyboard_parent_class)-> + allocate (self, box, flags); } static void @@ -128,39 +94,34 @@ eek_clutter_keyboard_dispose (GObject *object) { EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(object); - if (priv->context) { - g_object_unref (G_OBJECT(priv->context)); - priv->context = NULL; + if (priv->renderer) { + g_object_unref (G_OBJECT(priv->renderer)); + priv->renderer = NULL; } - if (priv->actor) { - ClutterActor *stage; - stage = clutter_actor_get_stage (priv->actor); - if (stage) { - g_signal_handler_disconnect (stage, - priv->key_press_event_handler); - g_signal_handler_disconnect (stage, - priv->key_release_event_handler); - } - g_object_unref (priv->actor); - priv->actor = NULL; + if (priv->keyboard && g_object_is_floating (priv->keyboard)) { + g_object_unref (priv->keyboard); + priv->keyboard = NULL; } + G_OBJECT_CLASS (eek_clutter_keyboard_parent_class)->dispose (object); } static void eek_clutter_keyboard_class_init (EekClutterKeyboardClass *klass) { + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - EekElementClass *element_class = EEK_ELEMENT_CLASS (klass); - EekKeyboardClass *keyboard_class = EEK_KEYBOARD_CLASS (klass); g_type_class_add_private (gobject_class, sizeof (EekClutterKeyboardPrivate)); - keyboard_class->create_section = eek_clutter_keyboard_real_create_section; - element_class->set_name = eek_clutter_keyboard_real_set_name; - element_class->set_bounds = eek_clutter_keyboard_real_set_bounds; + actor_class->get_preferred_width = + eek_clutter_keyboard_real_get_preferred_width; + actor_class->get_preferred_height = + eek_clutter_keyboard_real_get_preferred_height; + actor_class->allocate = eek_clutter_keyboard_real_allocate; + gobject_class->dispose = eek_clutter_keyboard_dispose; } @@ -170,147 +131,67 @@ eek_clutter_keyboard_init (EekClutterKeyboard *self) EekClutterKeyboardPrivate *priv; priv = self->priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self); - priv->actor = NULL; + priv->keyboard = NULL; + priv->renderer = NULL; +} + +struct _CreateSectionCallbackData { + ClutterActor *actor; + EekClutterRenderer *renderer; +}; +typedef struct _CreateSectionCallbackData CreateSectionCallbackData; + +static void +create_section (EekElement *element, gpointer user_data) +{ + CreateSectionCallbackData *data = user_data; + ClutterActor *section; + + section = eek_clutter_section_new (EEK_SECTION(element), data->renderer); + clutter_container_add_actor (CLUTTER_CONTAINER(data->actor), section); } /** * eek_clutter_keyboard_new: + * @keyboard: an #EekKeyboard * * Create a new #EekClutterKeyboard. */ -EekKeyboard* -eek_clutter_keyboard_new (void) -{ - return g_object_new (EEK_TYPE_CLUTTER_KEYBOARD, NULL); -} - -static gboolean -on_clutter_key_press_event (ClutterActor *actor, - ClutterEvent *event, - gpointer user_data) -{ - guint keycode; - EekKey *key; - - keycode = clutter_event_get_key_code (event); - key = eek_keyboard_find_key_by_keycode (user_data, keycode); - if (key) { - g_signal_emit_by_name (key, "pressed", NULL); - return TRUE; - } - return FALSE; -} - -static gboolean -on_clutter_key_release_event (ClutterActor *actor, - ClutterEvent *event, - gpointer user_data) -{ - guint keycode; - EekKey *key; - - keycode = clutter_event_get_key_code (event); - key = eek_keyboard_find_key_by_keycode (user_data, keycode); - if (key) { - g_signal_emit_by_name (key, "released", NULL); - return TRUE; - } - return FALSE; -} - -static void -on_clutter_stage_resize (GObject *object, - GParamSpec *param_spec, - gpointer user_data) -{ - ClutterActor *stage = CLUTTER_ACTOR(object); - EekClutterKeyboard *keyboard = user_data; - GValue value = {0}; - gfloat width, height, scale; - EekBounds bounds; - - eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds); - g_object_get (G_OBJECT(stage), "width", &width, NULL); - g_object_get (G_OBJECT(stage), "height", &height, NULL); - - g_value_init (&value, G_TYPE_DOUBLE); - - scale = width > height ? width / bounds.width : height / bounds.height; - - g_value_set_double (&value, scale); - g_object_set_property (G_OBJECT (stage), - "scale-x", - &value); - - g_value_set_double (&value, scale); - g_object_set_property (G_OBJECT (stage), - "scale-y", - &value); -} - -static void -on_clutter_realize (ClutterActor *actor, - gpointer user_data) -{ - EekClutterKeyboard *keyboard = user_data; - EekClutterKeyboardPrivate *priv = - EEK_CLUTTER_KEYBOARD_GET_PRIVATE(keyboard); - ClutterActor *stage; - - stage = clutter_actor_get_stage (priv->actor); - priv->key_press_event_handler = - g_signal_connect (stage, "key-press-event", - G_CALLBACK (on_clutter_key_press_event), keyboard); - priv->key_release_event_handler = - g_signal_connect (stage, "key-release-event", - G_CALLBACK (on_clutter_key_release_event), keyboard); - g_signal_connect (stage, "notify::width", - G_CALLBACK (on_clutter_stage_resize), keyboard); - g_signal_connect (stage, "notify::height", - G_CALLBACK (on_clutter_stage_resize), keyboard); -} - -static void -update_category_fonts (EekClutterKeyboard *keyboard) -{ - EekClutterKeyboardPrivate *priv = - EEK_CLUTTER_KEYBOARD_GET_PRIVATE(keyboard); - PangoContext *context; - PangoLayout *layout; - PangoFontDescription *fonts[EEK_KEYSYM_CATEGORY_LAST], *base_font; - gint i; - - context = clutter_actor_get_pango_context (priv->actor); - layout = pango_layout_new (context); - base_font = pango_font_description_from_string ("Sans"); - pango_layout_set_font_description (layout, base_font); - pango_font_description_free (base_font); - eek_get_fonts (EEK_KEYBOARD(keyboard), - layout, - (PangoFontDescription **)&fonts); - for (i = 0; i < EEK_KEYSYM_CATEGORY_LAST; i++) { - eek_clutter_drawing_context_set_category_font (priv->context, - i, - fonts[i]); - pango_font_description_free (fonts[i]); - } - g_object_unref (G_OBJECT(layout)); -} - ClutterActor * -eek_clutter_keyboard_get_actor (EekClutterKeyboard *keyboard) +eek_clutter_keyboard_new (EekKeyboard *keyboard) { - EekClutterKeyboardPrivate *priv = - EEK_CLUTTER_KEYBOARD_GET_PRIVATE(keyboard); - if (!priv->actor) { - priv->actor = clutter_group_new (); - g_object_ref_sink (priv->actor); - g_signal_connect (priv->actor, "realize", - G_CALLBACK (on_clutter_realize), keyboard); - g_return_val_if_fail (priv->actor, NULL); + ClutterActor *actor; + EekClutterKeyboardPrivate *priv; + PangoContext *pcontext; + CreateSectionCallbackData data; + EekBounds bounds; + gdouble scale; + PangoFontDescription *font; - eek_keyboard_realize (EEK_KEYBOARD(keyboard)); - update_category_fonts (keyboard); - } - return priv->actor; + actor = g_object_new (EEK_TYPE_CLUTTER_KEYBOARD, NULL); + priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(actor); + priv->keyboard = g_object_ref_sink (keyboard); + + pcontext = clutter_actor_get_pango_context (actor); + font = pango_font_description_from_string ("Sans 48px"); + pango_context_set_font_description (pcontext, font); + pango_font_description_free (font); + + priv->renderer = eek_clutter_renderer_new (priv->keyboard, pcontext); + + eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds); + eek_renderer_set_allocation_size (EEK_RENDERER(priv->renderer), + bounds.width, + bounds.height); + scale = eek_renderer_get_scale (EEK_RENDERER(priv->renderer)); + clutter_actor_set_position (actor, bounds.x * scale, bounds.y * scale); + + data.actor = actor; + data.renderer = priv->renderer; + + eek_container_foreach_child (EEK_CONTAINER(priv->keyboard), + create_section, + &data); + + return actor; } diff --git a/eek/eek-clutter-keyboard.h b/eek/eek-clutter-keyboard.h index e321f9a3..4c61ae62 100644 --- a/eek/eek-clutter-keyboard.h +++ b/eek/eek-clutter-keyboard.h @@ -20,7 +20,7 @@ #ifndef EEK_CLUTTER_KEYBOARD_H #define EEK_CLUTTER_KEYBOARD_H 1 -#include "eek-clutter-section.h" +#include #include "eek-keyboard.h" G_BEGIN_DECLS @@ -38,7 +38,7 @@ typedef struct _EekClutterKeyboardPrivate EekClutterKeyboardPrivate; struct _EekClutterKeyboard { /*< private >*/ - EekKeyboard parent; + ClutterGroup parent; EekClutterKeyboardPrivate *priv; }; @@ -46,7 +46,7 @@ struct _EekClutterKeyboard struct _EekClutterKeyboardClass { /*< private >*/ - EekKeyboardClass parent_class; + ClutterGroupClass parent_class; /*< private >*/ /* padding */ @@ -54,8 +54,7 @@ struct _EekClutterKeyboardClass }; GType eek_clutter_keyboard_get_type (void) G_GNUC_CONST; -EekKeyboard *eek_clutter_keyboard_new (void); -ClutterActor *eek_clutter_keyboard_get_actor (EekClutterKeyboard *keyboard); +ClutterActor *eek_clutter_keyboard_new (EekKeyboard *keyboard); G_END_DECLS #endif /* EEK_CLUTTER_KEYBOARD_H */ diff --git a/eek/eek-clutter-renderer.c b/eek/eek-clutter-renderer.c new file mode 100644 index 00000000..e77047fb --- /dev/null +++ b/eek/eek-clutter-renderer.c @@ -0,0 +1,184 @@ +#include +#include +#include +#include +#include + +#include "eek-clutter-renderer.h" +#include "eek-key.h" + +G_DEFINE_TYPE (EekClutterRenderer, eek_clutter_renderer, EEK_TYPE_RENDERER); + +#define EEK_CLUTTER_RENDERER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_CLUTTER_RENDERER, EekClutterRendererPrivate)) + +struct _EekClutterRendererPrivate +{ + GHashTable *outline_texture_cache; +}; + +/* This routine is copied from librsvg: + Copyright © 2005 Dom Lachowicz + Copyright © 2005 Caleb Moore + Copyright © 2005 Red Hat, Inc. + */ +static void +cairo_pixels_to_pixbuf (guint8 *pixels, + int rowstride, + int height) +{ + int row; + + /* un-premultiply data */ + for (row = 0; row < height; row++) { + guint8 *row_data = (pixels + (row * rowstride)); + int i; + + for (i = 0; i < rowstride; i += 4) { + guint8 *b = &row_data[i]; + guint32 pixel; + guint8 alpha; + + memcpy (&pixel, b, sizeof (guint32)); + alpha = (pixel & 0xff000000) >> 24; + if (alpha == 0) { + b[0] = b[1] = b[2] = b[3] = 0; + } else { + b[0] = (((pixel & 0xff0000) >> 16) * 255 + alpha / 2) / alpha; + b[1] = (((pixel & 0x00ff00) >> 8) * 255 + alpha / 2) / alpha; + b[2] = (((pixel & 0x0000ff) >> 0) * 255 + alpha / 2) / alpha; + b[3] = alpha; + } + } + } +} + +static void +eek_clutter_renderer_class_init (EekClutterRendererClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (gobject_class, + sizeof (EekClutterRendererPrivate)); +} + +static void +eek_clutter_renderer_init (EekClutterRenderer *self) +{ + EekClutterRendererPrivate *priv; + + priv = self->priv = EEK_CLUTTER_RENDERER_GET_PRIVATE(self); + priv->outline_texture_cache = + g_hash_table_new_full (g_direct_hash, + g_direct_equal, + NULL, + cogl_handle_unref); +} + +void +eek_clutter_renderer_render_key (EekClutterRenderer *renderer, + ClutterActor *actor, + EekKey *key) +{ + EekClutterRendererPrivate *priv; + EekOutline *outline; + CoglHandle *outline_texture; + PangoLayout *layout; + PangoRectangle extents = { 0, }; + CoglColor color = { 0x00, 0x00, 0x00, 0xFF }; + ClutterGeometry geom; + + g_assert (EEK_IS_CLUTTER_RENDERER(renderer)); + g_assert (CLUTTER_IS_ACTOR(actor)); + g_assert (EEK_IS_KEY(key)); + + priv = EEK_CLUTTER_RENDERER_GET_PRIVATE(renderer); + + outline = eek_key_get_outline (key); + + outline_texture = g_hash_table_lookup (priv->outline_texture_cache, + outline); + if (!outline_texture) { + gint rowstride; + guint8 *data; + cairo_surface_t *surface; + cairo_t *cr; + EekBounds bounds; + gdouble scale; + GdkPixbuf *pixbuf; + + eek_element_get_bounds (EEK_ELEMENT(key), &bounds); + scale = eek_renderer_get_scale (EEK_RENDERER(renderer)); + rowstride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, + bounds.width * scale); + + data = g_malloc0 (rowstride * bounds.height); + surface = cairo_image_surface_create_for_data (data, + CAIRO_FORMAT_ARGB32, + bounds.width * scale, + bounds.height * scale, + rowstride); + cr = cairo_create (surface); + eek_renderer_render_key_outline (EEK_RENDERER(renderer), + cr, + key, + 1.0, + FALSE); + cairo_destroy (cr); + cairo_surface_destroy (surface); + cairo_pixels_to_pixbuf (data, rowstride, bounds.height * scale); + + pixbuf = gdk_pixbuf_new_from_data (data, + GDK_COLORSPACE_RGB, + TRUE, + 8, + bounds.width * scale, + bounds.height * scale, + rowstride, + (GdkPixbufDestroyNotify) g_free, + data); + + outline_texture = + cogl_texture_new_from_data (gdk_pixbuf_get_width (pixbuf), + gdk_pixbuf_get_height (pixbuf), + COGL_TEXTURE_NONE, + gdk_pixbuf_get_has_alpha (pixbuf) + ? COGL_PIXEL_FORMAT_RGBA_8888 + : COGL_PIXEL_FORMAT_RGB_888, + COGL_PIXEL_FORMAT_ANY, + gdk_pixbuf_get_rowstride (pixbuf), + gdk_pixbuf_get_pixels (pixbuf)); + g_object_unref (pixbuf); + + g_hash_table_insert (priv->outline_texture_cache, + outline, + outline_texture); + } + + clutter_actor_get_allocation_geometry (actor, &geom); + cogl_set_source_texture (outline_texture); + cogl_rectangle (0.0f, 0.0f, geom.width, geom.height); + + layout = eek_renderer_create_pango_layout (EEK_RENDERER(renderer)); + eek_renderer_render_key_label (EEK_RENDERER(renderer), layout, key); + pango_layout_get_extents (layout, NULL, &extents); + cogl_pango_render_layout (layout, + (geom.width - extents.width / PANGO_SCALE) / 2, + (geom.height - extents.height / PANGO_SCALE) / 2, + &color, + 0); + g_object_unref (layout); +} + +EekClutterRenderer * +eek_clutter_renderer_new (EekKeyboard *keyboard, + PangoContext *pcontext) +{ + EekClutterRenderer *renderer; + + renderer = g_object_new (EEK_TYPE_CLUTTER_RENDERER, + "keyboard", keyboard, + "pango-context", pcontext); + + return renderer; +} diff --git a/eek/eek-clutter-renderer.h b/eek/eek-clutter-renderer.h new file mode 100644 index 00000000..b32b4732 --- /dev/null +++ b/eek/eek-clutter-renderer.h @@ -0,0 +1,44 @@ +#ifndef EEK_CLUTTER_RENDERER_H +#define EEK_CLUTTER_RENDERER_H 1 + +#include "eek-renderer.h" + +G_BEGIN_DECLS + +#define EEK_TYPE_CLUTTER_RENDERER (eek_clutter_renderer_get_type()) +#define EEK_CLUTTER_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_CLUTTER_RENDERER, EekClutterRenderer)) +#define EEK_CLUTTER_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_CLUTTER_RENDERER, EekClutterRendererClass)) +#define EEK_IS_CLUTTER_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_CLUTTER_RENDERER)) +#define EEK_IS_CLUTTER_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_CLUTTER_RENDERER)) +#define EEK_CLUTTER_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_CLUTTER_RENDERER, EekClutterRendererClass)) + +typedef struct _EekClutterRenderer EekClutterRenderer; +typedef struct _EekClutterRendererClass EekClutterRendererClass; +typedef struct _EekClutterRendererPrivate EekClutterRendererPrivate; + +struct _EekClutterRenderer { + EekRenderer parent; + + EekClutterRendererPrivate *priv; +}; + +struct _EekClutterRendererClass +{ + EekRendererClass parent_class; + + /*< private >*/ + /* padding */ + gpointer pdummy[24]; +}; + +GType eek_clutter_renderer_get_type + (void) G_GNUC_CONST; +EekClutterRenderer *eek_clutter_renderer_new (EekKeyboard *keyboard, + PangoContext *pcontext); +void eek_clutter_renderer_render_key + (EekClutterRenderer *renderer, + ClutterActor *actor, + EekKey *key); + +G_END_DECLS +#endif /* EEK_CLUTTER_RENDERER_H */ diff --git a/eek/eek-clutter-section.c b/eek/eek-clutter-section.c index 042d9c2b..c35c16fc 100644 --- a/eek/eek-clutter-section.c +++ b/eek/eek-clutter-section.c @@ -23,106 +23,58 @@ #endif /* HAVE_CONFIG_H */ #include "eek-clutter-section.h" +#include "eek-clutter-key.h" -G_DEFINE_TYPE (EekClutterSection, eek_clutter_section, EEK_TYPE_SECTION); +G_DEFINE_TYPE (EekClutterSection, eek_clutter_section, CLUTTER_TYPE_GROUP); #define EEK_CLUTTER_SECTION_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_CLUTTER_SECTION, EekClutterSectionPrivate)) struct _EekClutterSectionPrivate { - EekClutterDrawingContext *context; - ClutterActor *actor; + EekSection *section; + EekClutterRenderer *renderer; }; static void -eek_clutter_section_real_set_name (EekElement *self, - const gchar *name) +eek_clutter_section_real_get_preferred_width (ClutterActor *self, + float for_height, + float *min_width_p, + float *natural_width_p) { EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(self); + EekBounds bounds; + gdouble scale; - EEK_ELEMENT_CLASS (eek_clutter_section_parent_class)-> - set_name (self, name); - - if (priv->actor) - clutter_actor_set_name (priv->actor, name); + scale = eek_renderer_get_scale (EEK_RENDERER(priv->renderer)); + eek_element_get_bounds (EEK_ELEMENT(priv->section), &bounds); + *min_width_p = 0.0f; + *natural_width_p = bounds.width * scale; } static void -eek_clutter_section_real_set_bounds (EekElement *self, - EekBounds *bounds) +eek_clutter_section_real_get_preferred_height (ClutterActor *self, + float for_width, + float *min_height_p, + float *natural_height_p) { EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(self); + EekBounds bounds; + gdouble scale; - EEK_ELEMENT_CLASS (eek_clutter_section_parent_class)-> - set_bounds (self, bounds); - - if (priv->actor) { - clutter_actor_set_position (priv->actor, bounds->x, bounds->y); - clutter_actor_set_size (priv->actor, bounds->width, bounds->height); - } + scale = eek_renderer_get_scale (EEK_RENDERER(priv->renderer)); + eek_element_get_bounds (EEK_ELEMENT(priv->section), &bounds); + *min_height_p = 0.0f; + *natural_height_p = bounds.height * scale; } static void -eek_clutter_section_real_set_angle (EekSection *self, - gint angle) +eek_clutter_section_real_allocate (ClutterActor *self, + const ClutterActorBox *box, + ClutterAllocationFlags flags) { - EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(self); - - EEK_SECTION_CLASS (eek_clutter_section_parent_class)-> - set_angle (self, angle); - - g_return_if_fail (priv->actor); - - clutter_actor_set_rotation (priv->actor, - CLUTTER_Z_AXIS, - eek_section_get_angle (self), - 0, 0, 0); -} - -static void -pressed_event (EekKey *key, gpointer user_data) -{ - g_signal_emit_by_name (user_data, "key-pressed", key); -} - -static void -released_event (EekKey *key, gpointer user_data) -{ - g_signal_emit_by_name (user_data, "key-released", key); -} - -static EekKey * -eek_clutter_section_real_create_key (EekSection *self, - gint column, - gint row) -{ - EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(self); - EekKey *key; - gint num_columns, num_rows; - EekOrientation orientation; - ClutterActor *actor; - - num_rows = eek_section_get_n_rows (self); - g_return_val_if_fail (0 <= row && row < num_rows, NULL); - eek_section_get_row (self, row, &num_columns, &orientation); - g_return_val_if_fail (column < num_columns, NULL); - - key = eek_clutter_key_new (priv->context, column, row); - g_return_val_if_fail (key, NULL); - - g_signal_connect (key, "pressed", G_CALLBACK(pressed_event), self); - g_signal_connect (key, "released", G_CALLBACK(released_event), self); - - EEK_CONTAINER_GET_CLASS(self)->add_child (EEK_CONTAINER(self), - EEK_ELEMENT(key)); - - actor = eek_clutter_section_get_actor (EEK_CLUTTER_SECTION(self)); - clutter_container_add_actor - (CLUTTER_CONTAINER(actor), - eek_clutter_key_get_actor (EEK_CLUTTER_KEY(key))); - - return key; + CLUTTER_ACTOR_CLASS (eek_clutter_section_parent_class)-> + allocate (self, box, flags); } static void @@ -130,30 +82,32 @@ eek_clutter_section_dispose (GObject *object) { EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(object); - if (priv->context) { - g_object_unref (priv->context); - priv->context = NULL; + if (priv->renderer) { + g_object_unref (priv->renderer); + priv->renderer = NULL; } - if (priv->actor) { - g_object_unref (priv->actor); - priv->actor = NULL; + + if (priv->section && g_object_is_floating (priv->section)) { + g_object_unref (priv->section); + priv->section = NULL; } + G_OBJECT_CLASS (eek_clutter_section_parent_class)->dispose (object); } static void eek_clutter_section_class_init (EekClutterSectionClass *klass) { + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - EekElementClass *element_class = EEK_ELEMENT_CLASS (klass); - EekSectionClass *section_class = EEK_SECTION_CLASS (klass); g_type_class_add_private (gobject_class, sizeof (EekClutterSectionPrivate)); - section_class->set_angle = eek_clutter_section_real_set_angle; - section_class->create_key = eek_clutter_section_real_create_key; - element_class->set_name = eek_clutter_section_real_set_name; - element_class->set_bounds = eek_clutter_section_real_set_bounds; + actor_class->get_preferred_width = + eek_clutter_section_real_get_preferred_width; + actor_class->get_preferred_height = + eek_clutter_section_real_get_preferred_height; + actor_class->allocate = eek_clutter_section_real_allocate; gobject_class->dispose = eek_clutter_section_dispose; } @@ -162,29 +116,54 @@ eek_clutter_section_init (EekClutterSection *self) { EekClutterSectionPrivate *priv; priv = self->priv = EEK_CLUTTER_SECTION_GET_PRIVATE (self); - priv->actor = NULL; + priv->section = NULL; + priv->renderer = NULL; +} + +struct _CreateKeyCallbackData { + ClutterActor *actor; + EekClutterRenderer *renderer; +}; +typedef struct _CreateKeyCallbackData CreateKeyCallbackData; + +static void +create_key (EekElement *element, gpointer user_data) +{ + CreateKeyCallbackData *data = user_data; + ClutterActor *key; + + key = eek_clutter_key_new (EEK_KEY(element), data->renderer); + clutter_container_add_actor (CLUTTER_CONTAINER(data->actor), key); } ClutterActor * -eek_clutter_section_get_actor (EekClutterSection *section) +eek_clutter_section_new (EekSection *section, + EekClutterRenderer *renderer) { - EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(section); - if (!priv->actor) { - priv->actor = clutter_group_new (); - g_object_ref_sink (priv->actor); - } - return priv->actor; -} - -EekSection * -eek_clutter_section_new (EekClutterDrawingContext *context) -{ - EekClutterSection *section; - - g_return_val_if_fail (context, NULL); - section = g_object_new (EEK_TYPE_CLUTTER_SECTION, NULL); - section->priv->context = context; - g_object_ref_sink (G_OBJECT(section->priv->context)); - - return EEK_SECTION(section); + ClutterActor *actor; + EekClutterSectionPrivate *priv; + CreateKeyCallbackData data; + EekBounds bounds; + gdouble scale; + + actor = g_object_new (EEK_TYPE_CLUTTER_SECTION, NULL); + priv = EEK_CLUTTER_SECTION_GET_PRIVATE(actor); + priv->section = g_object_ref_sink (section); + priv->renderer = g_object_ref (renderer); + + eek_element_get_bounds (EEK_ELEMENT(section), &bounds); + scale = eek_renderer_get_scale (EEK_RENDERER(priv->renderer)); + clutter_actor_set_position (actor, bounds.x * scale, bounds.y * scale); + clutter_actor_set_rotation (actor, + CLUTTER_Z_AXIS, + eek_section_get_angle (section), + 0.0f, 0.0f, 0.0f); + + data.actor = actor; + data.renderer = priv->renderer; + eek_container_foreach_child (EEK_CONTAINER(priv->section), + create_key, + &data); + + return actor; } diff --git a/eek/eek-clutter-section.h b/eek/eek-clutter-section.h index f8d29d86..884189a7 100644 --- a/eek/eek-clutter-section.h +++ b/eek/eek-clutter-section.h @@ -20,9 +20,9 @@ #ifndef EEK_CLUTTER_SECTION_H #define EEK_CLUTTER_SECTION_H 1 -#include "eek-clutter-drawing-context.h" -#include "eek-clutter-key.h" +#include #include "eek-section.h" +#include "eek-clutter-renderer.h" G_BEGIN_DECLS #define EEK_TYPE_CLUTTER_SECTION (eek_clutter_section_get_type()) @@ -39,7 +39,7 @@ typedef struct _EekClutterSectionPrivate EekClutterSectionPrivate; struct _EekClutterSection { /*< private >*/ - EekSection parent; + ClutterGroup parent; EekClutterSectionPrivate *priv; }; @@ -47,16 +47,16 @@ struct _EekClutterSection struct _EekClutterSectionClass { /*< private >*/ - EekSectionClass parent_class; + ClutterGroupClass parent_class; /*< private >*/ /* padding */ gpointer pdummy[24]; }; -GType eek_clutter_section_get_type (void) G_GNUC_CONST; -EekSection * eek_clutter_section_new (EekClutterDrawingContext *context); -ClutterActor *eek_clutter_section_get_actor (EekClutterSection *section); +GType eek_clutter_section_get_type (void) G_GNUC_CONST; +ClutterActor *eek_clutter_section_new (EekSection *section, + EekClutterRenderer *renderer); G_END_DECLS #endif /* EEK_CLUTTER_SECTION_H */ diff --git a/eek/eek-keyboard.c b/eek/eek-keyboard.c index 2940df69..bbe33865 100644 --- a/eek/eek-keyboard.c +++ b/eek/eek-keyboard.c @@ -193,14 +193,13 @@ eek_keyboard_real_find_key_by_keycode (EekKeyboard *self, } static void -eek_keyboard_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) +eek_keyboard_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) { gint group, level; - g_return_if_fail (EEK_IS_KEYBOARD(object)); switch (prop_id) { case PROP_GROUP: eek_keyboard_get_keysym_index (EEK_KEYBOARD(object), &group, &level); diff --git a/src/eekboard.c b/src/eekboard.c index f5608697..e96de36e 100644 --- a/src/eekboard.c +++ b/src/eekboard.c @@ -36,6 +36,11 @@ #include "eek/eek-gtk.h" #include "eek/eek-xkl.h" +#if HAVE_CLUTTER_GTK +#include +#include "eek/eek-clutter.h" +#endif + #define CSW 640 #define CSH 480 @@ -79,7 +84,9 @@ struct _Eekboard { XklConfigRegistry *registry; GtkUIManager *ui_manager; gulong on_key_pressed_id, on_key_released_id; - +#if HAVE_CLUTTER_GTK + ClutterActor *actor; +#endif guint countries_merge_id; GtkActionGroup *countries_action_group; @@ -1025,11 +1032,33 @@ create_menus (Eekboard *eekboard, -1); } +#if HAVE_CLUTTER_GTK +static void +on_allocation_changed (ClutterActor *stage, + ClutterActorBox *box, + ClutterAllocationFlags flags, + gpointer user_data) +{ + Eekboard *eekboard = user_data; + EekBounds bounds; + gfloat scale; + + eek_element_get_bounds (EEK_ELEMENT(eekboard->keyboard), &bounds); + scale = MIN((box->x2 - box->x1) / bounds.width, + (box->y2 - box->y1) / bounds.height); + clutter_actor_set_scale (eekboard->actor, scale, scale); +} +#endif + static GtkWidget * create_widget (Eekboard *eekboard, gint initial_width, gint initial_height) { +#if HAVE_CLUTTER_GTK + ClutterActor *stage; + ClutterColor stage_color = { 0xff, 0xff, 0xff, 0xff }; +#endif EekBounds bounds; eekboard->keyboard = eek_keyboard_new (eekboard->layout, @@ -1042,8 +1071,27 @@ create_widget (Eekboard *eekboard, g_signal_connect (eekboard->keyboard, "key-released", G_CALLBACK(on_key_released), eekboard); - eekboard->widget = eek_gtk_keyboard_new (eekboard->keyboard); eek_element_get_bounds (EEK_ELEMENT(eekboard->keyboard), &bounds); + +#if HAVE_CLUTTER_GTK + eekboard->widget = gtk_clutter_embed_new (); + stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED(eekboard->widget)); + eekboard->actor = eek_clutter_keyboard_new (eekboard->keyboard); + clutter_container_add_actor (CLUTTER_CONTAINER(stage), eekboard->actor); + + clutter_stage_set_color (CLUTTER_STAGE(stage), &stage_color); + clutter_stage_set_user_resizable (CLUTTER_STAGE(stage), TRUE); + clutter_stage_set_minimum_size (CLUTTER_STAGE(stage), + bounds.width / 3, + bounds.height / 3); + g_signal_connect (stage, + "allocation-changed", + G_CALLBACK(on_allocation_changed), + eekboard); +#else + eekboard->widget = eek_gtk_keyboard_new (eekboard->keyboard); +#endif + eekboard->width = bounds.width; eekboard->height = bounds.height; return eekboard->widget; @@ -1397,6 +1445,8 @@ main (int argc, char *argv[]) GConfClient *gconfc; GError *error; + g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL); + context = g_option_context_new ("eekboard"); g_option_context_add_main_entries (context, options, NULL); g_option_context_parse (context, &argc, &argv, NULL); @@ -1426,10 +1476,17 @@ main (int argc, char *argv[]) g_warning("AT-SPI initialization failed"); } +#if HAVE_CLUTTER_GTK + if (gtk_clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) { + g_warning ("Can't init GTK with Clutter"); + exit (1); + } +#else if (!gtk_init_check (&argc, &argv)) { g_warning ("Can't init GTK"); exit (1); } +#endif eekboard = eekboard_new (accessibility_enabled); if (opt_list_models) { @@ -1623,8 +1680,6 @@ main (int argc, char *argv[]) g_warning ("failed to register keystroke listener"); } - g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL); - if (combo) gtk_combo_box_set_active (GTK_COMBO_BOX(combo), 0);