Revive Clutter support.
This commit is contained in:
@ -147,7 +147,7 @@ AC_MSG_CHECKING([whether you enable Clutter])
|
|||||||
AC_ARG_ENABLE(clutter,
|
AC_ARG_ENABLE(clutter,
|
||||||
AS_HELP_STRING([--enable-clutter=no/yes],
|
AS_HELP_STRING([--enable-clutter=no/yes],
|
||||||
[Enable Clutter user interface default=yes]),,
|
[Enable Clutter user interface default=yes]),,
|
||||||
enable_clutter=yes)
|
enable_clutter=no)
|
||||||
AC_MSG_RESULT($enable_clutter)
|
AC_MSG_RESULT($enable_clutter)
|
||||||
|
|
||||||
if test x$enable_clutter = xyes; then
|
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,
|
AC_DEFINE_UNQUOTED([NEED_SWAP_EVENT_WORKAROUND], $need_swap_event_workaround,
|
||||||
[Define if GLX_INTEL_swap_event work around is needed])
|
[Define if GLX_INTEL_swap_event work around is needed])
|
||||||
fi
|
fi
|
||||||
dnl AM_CONDITIONAL(HAVE_CLUTTER, [test x$enable_clutter = xyes])
|
AM_CONDITIONAL(HAVE_CLUTTER, [test x$enable_clutter = xyes])
|
||||||
AM_CONDITIONAL(HAVE_CLUTTER, [false])
|
|
||||||
|
|
||||||
GTK_DOC_CHECK([1.14],[--flavour no-tmpl])
|
GTK_DOC_CHECK([1.14],[--flavour no-tmpl])
|
||||||
|
|
||||||
|
|||||||
@ -88,12 +88,14 @@ libeek_clutter_public_headers = \
|
|||||||
|
|
||||||
libeek_clutter_private_headers = \
|
libeek_clutter_private_headers = \
|
||||||
$(srcdir)/eek-clutter-section.h \
|
$(srcdir)/eek-clutter-section.h \
|
||||||
$(srcdir)/eek-clutter-key.h
|
$(srcdir)/eek-clutter-key.h \
|
||||||
|
$(srcdir)/eek-clutter-renderer.h
|
||||||
|
|
||||||
libeek_clutter_sources = \
|
libeek_clutter_sources = \
|
||||||
$(srcdir)/eek-clutter-keyboard.c \
|
$(srcdir)/eek-clutter-keyboard.c \
|
||||||
$(srcdir)/eek-clutter-section.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_SOURCES = $(libeek_clutter_sources)
|
||||||
libeek_clutter_la_CFLAGS = $(CLUTTER_CFLAGS)
|
libeek_clutter_la_CFLAGS = $(CLUTTER_CFLAGS)
|
||||||
|
|||||||
@ -1,138 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
|
|
||||||
* 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 <string.h>
|
|
||||||
|
|
||||||
#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);
|
|
||||||
}
|
|
||||||
@ -1,82 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
|
|
||||||
* 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 <clutter/clutter.h>
|
|
||||||
#include <pango/pango.h>
|
|
||||||
|
|
||||||
#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 */
|
|
||||||
@ -1,373 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2006 Sergey V. Udaltsov <svu@gnome.org>
|
|
||||||
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
|
|
||||||
* 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 <cogl/cogl.h>
|
|
||||||
#include <cogl/cogl-pango.h>
|
|
||||||
|
|
||||||
#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);
|
|
||||||
}
|
|
||||||
@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
|
|
||||||
* 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 <clutter/clutter.h>
|
|
||||||
#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 */
|
|
||||||
@ -23,98 +23,144 @@
|
|||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include "eek-clutter-key.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) \
|
#define EEK_CLUTTER_KEY_GET_PRIVATE(obj) \
|
||||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_CLUTTER_KEY, EekClutterKeyPrivate))
|
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_CLUTTER_KEY, EekClutterKeyPrivate))
|
||||||
|
|
||||||
struct _EekClutterKeyPrivate
|
struct _EekClutterKeyPrivate
|
||||||
{
|
{
|
||||||
EekClutterDrawingContext *context;
|
EekKey *key;
|
||||||
ClutterActor *actor;
|
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
|
static void
|
||||||
eek_clutter_key_dispose (GObject *object)
|
eek_clutter_key_dispose (GObject *object)
|
||||||
{
|
{
|
||||||
EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(object);
|
EekClutterKeyPrivate *priv = EEK_CLUTTER_KEY_GET_PRIVATE(object);
|
||||||
|
|
||||||
if (priv->context) {
|
if (priv->renderer) {
|
||||||
g_object_unref (priv->context);
|
g_object_unref (priv->renderer);
|
||||||
priv->context = NULL;
|
priv->renderer = NULL;
|
||||||
}
|
}
|
||||||
if (priv->actor) {
|
|
||||||
g_object_unref (priv->actor);
|
if (priv->key && g_object_is_floating (priv->key)) {
|
||||||
priv->actor = NULL;
|
g_object_unref (priv->key);
|
||||||
|
priv->key = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
G_OBJECT_CLASS (eek_clutter_key_parent_class)->dispose (object);
|
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
|
static void
|
||||||
eek_clutter_key_class_init (EekClutterKeyClass *klass)
|
eek_clutter_key_class_init (EekClutterKeyClass *klass)
|
||||||
{
|
{
|
||||||
|
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||||
GObjectClass *gobject_class = G_OBJECT_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,
|
g_type_class_add_private (gobject_class,
|
||||||
sizeof (EekClutterKeyPrivate));
|
sizeof (EekClutterKeyPrivate));
|
||||||
|
|
||||||
element_class->set_name = eek_clutter_key_real_set_name;
|
actor_class->paint = eek_clutter_key_real_paint;
|
||||||
element_class->set_bounds = eek_clutter_key_real_set_bounds;
|
actor_class->get_preferred_width =
|
||||||
gobject_class->dispose = eek_clutter_key_dispose;
|
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 */
|
/* signals */
|
||||||
key_class->pressed = eek_clutter_key_real_pressed;
|
actor_class->button_press_event =
|
||||||
key_class->released = eek_clutter_key_real_released;
|
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
|
static void
|
||||||
@ -122,33 +168,73 @@ eek_clutter_key_init (EekClutterKey *self)
|
|||||||
{
|
{
|
||||||
EekClutterKeyPrivate *priv;
|
EekClutterKeyPrivate *priv;
|
||||||
priv = self->priv = EEK_CLUTTER_KEY_GET_PRIVATE (self);
|
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 *
|
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) {
|
actor = g_object_new (EEK_TYPE_CLUTTER_KEY, NULL);
|
||||||
g_return_val_if_fail (priv->context, NULL);
|
priv = EEK_CLUTTER_KEY_GET_PRIVATE(actor);
|
||||||
priv->actor = eek_clutter_key_actor_new (priv->context, EEK_KEY(key));
|
priv->key = g_object_ref_sink (key);
|
||||||
g_object_ref_sink (priv->actor);
|
priv->renderer = g_object_ref (renderer);
|
||||||
}
|
|
||||||
return priv->actor;
|
eek_element_get_bounds (EEK_ELEMENT(key), &bounds);
|
||||||
}
|
scale = eek_renderer_get_scale (EEK_RENDERER(priv->renderer));
|
||||||
|
|
||||||
EekKey *
|
clutter_actor_set_position (actor,
|
||||||
eek_clutter_key_new (EekClutterDrawingContext *context, gint column, gint row)
|
bounds.x * scale,
|
||||||
{
|
bounds.y * scale);
|
||||||
EekClutterKey *key;
|
|
||||||
|
clutter_actor_set_reactive (actor, TRUE);
|
||||||
g_return_val_if_fail (context, NULL);
|
|
||||||
key = g_object_new (EEK_TYPE_CLUTTER_KEY,
|
g_signal_connect (priv->key, "pressed",
|
||||||
"column", column,
|
G_CALLBACK(on_pressed), actor);
|
||||||
"row", row,
|
g_signal_connect (priv->key, "released",
|
||||||
NULL);
|
G_CALLBACK(on_released), actor);
|
||||||
key->priv->context = context;
|
|
||||||
g_object_ref_sink (key->priv->context);
|
return actor;
|
||||||
return EEK_KEY(key);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,8 +21,8 @@
|
|||||||
#define EEK_CLUTTER_KEY_H 1
|
#define EEK_CLUTTER_KEY_H 1
|
||||||
|
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
#include "eek-clutter-drawing-context.h"
|
|
||||||
#include "eek-key.h"
|
#include "eek-key.h"
|
||||||
|
#include "eek-clutter-renderer.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
#define EEK_TYPE_CLUTTER_KEY (eek_clutter_key_get_type())
|
#define EEK_TYPE_CLUTTER_KEY (eek_clutter_key_get_type())
|
||||||
@ -39,7 +39,7 @@ typedef struct _EekClutterKeyPrivate EekClutterKeyPrivate;
|
|||||||
struct _EekClutterKey
|
struct _EekClutterKey
|
||||||
{
|
{
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
EekKey parent;
|
ClutterActor parent;
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
EekClutterKeyPrivate *priv;
|
EekClutterKeyPrivate *priv;
|
||||||
@ -48,7 +48,7 @@ struct _EekClutterKey
|
|||||||
struct _EekClutterKeyClass
|
struct _EekClutterKeyClass
|
||||||
{
|
{
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
EekKeyClass parent_class;
|
ClutterActorClass parent_class;
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
/* padding */
|
/* padding */
|
||||||
@ -56,10 +56,8 @@ struct _EekClutterKeyClass
|
|||||||
};
|
};
|
||||||
|
|
||||||
GType eek_clutter_key_get_type (void) G_GNUC_CONST;
|
GType eek_clutter_key_get_type (void) G_GNUC_CONST;
|
||||||
EekKey * eek_clutter_key_new (EekClutterDrawingContext *context,
|
ClutterActor *eek_clutter_key_new (EekKey *key,
|
||||||
gint column,
|
EekClutterRenderer *renderer);
|
||||||
gint row);
|
|
||||||
ClutterActor *eek_clutter_key_get_actor (EekClutterKey *key);
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
#endif /* EEK_CLUTTER_KEY_H */
|
#endif /* EEK_CLUTTER_KEY_H */
|
||||||
|
|||||||
@ -20,107 +20,73 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION:eek-clutter-keyboard
|
* SECTION:eek-clutter-keyboard
|
||||||
* @short_description: #EekKeyboard that can be converted into a #ClutterActor
|
* @short_description: a #ClutterActor displaying #EekKeyboard
|
||||||
*/
|
*/
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include "eek-clutter-keyboard.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-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) \
|
#define EEK_CLUTTER_KEYBOARD_GET_PRIVATE(obj) \
|
||||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_CLUTTER_KEYBOARD, EekClutterKeyboardPrivate))
|
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_CLUTTER_KEYBOARD, EekClutterKeyboardPrivate))
|
||||||
|
|
||||||
|
|
||||||
struct _EekClutterKeyboardPrivate
|
struct _EekClutterKeyboardPrivate
|
||||||
{
|
{
|
||||||
EekClutterDrawingContext *context;
|
EekKeyboard *keyboard;
|
||||||
ClutterActor *actor;
|
EekClutterRenderer *renderer;
|
||||||
|
|
||||||
guint key_press_event_handler;
|
|
||||||
guint key_release_event_handler;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
eek_clutter_keyboard_real_set_name (EekElement *self,
|
eek_clutter_keyboard_real_get_preferred_width (ClutterActor *self,
|
||||||
const gchar *name)
|
float for_height,
|
||||||
|
float *min_width_p,
|
||||||
|
float *natural_width_p)
|
||||||
{
|
{
|
||||||
EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self);
|
EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self);
|
||||||
|
gdouble width;
|
||||||
|
|
||||||
EEK_ELEMENT_CLASS (eek_clutter_keyboard_parent_class)->
|
eek_renderer_get_size (EEK_RENDERER(priv->renderer), &width, NULL);
|
||||||
set_name (self, name);
|
*min_width_p = 0.0f;
|
||||||
|
*natural_width_p = width;
|
||||||
if (priv->actor)
|
|
||||||
clutter_actor_set_name (priv->actor, name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
eek_clutter_keyboard_real_set_bounds (EekElement *self,
|
eek_clutter_keyboard_real_get_preferred_height (ClutterActor *self,
|
||||||
EekBounds *bounds)
|
float for_width,
|
||||||
|
float *min_height_p,
|
||||||
|
float *natural_height_p)
|
||||||
{
|
{
|
||||||
EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self);
|
EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self);
|
||||||
|
gdouble height;
|
||||||
|
|
||||||
EEK_ELEMENT_CLASS (eek_clutter_keyboard_parent_class)->
|
eek_renderer_get_size (EEK_RENDERER(priv->renderer), NULL, &height);
|
||||||
set_bounds (self, bounds);
|
*min_height_p = 0.0f;
|
||||||
|
*natural_height_p = height;
|
||||||
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
|
static void
|
||||||
key_pressed_event (EekSection *section,
|
eek_clutter_keyboard_real_allocate (ClutterActor *self,
|
||||||
EekKey *key,
|
const ClutterActorBox *box,
|
||||||
EekKeyboard *keyboard)
|
ClutterAllocationFlags flags)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self);
|
EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self);
|
||||||
EekSection *section;
|
|
||||||
ClutterActor *actor;
|
|
||||||
|
|
||||||
if (!priv->context) {
|
g_assert (priv->renderer);
|
||||||
priv->context = eek_clutter_drawing_context_new ();
|
eek_renderer_set_allocation_size (EEK_RENDERER(priv->renderer),
|
||||||
g_object_ref_sink (G_OBJECT(priv->context));
|
box->x2 - box->x1,
|
||||||
}
|
box->y2 - box->y1);
|
||||||
|
|
||||||
section = eek_clutter_section_new (priv->context);
|
CLUTTER_ACTOR_CLASS (eek_clutter_keyboard_parent_class)->
|
||||||
g_return_val_if_fail (section, NULL);
|
allocate (self, box, flags);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -128,39 +94,34 @@ eek_clutter_keyboard_dispose (GObject *object)
|
|||||||
{
|
{
|
||||||
EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(object);
|
EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(object);
|
||||||
|
|
||||||
if (priv->context) {
|
if (priv->renderer) {
|
||||||
g_object_unref (G_OBJECT(priv->context));
|
g_object_unref (G_OBJECT(priv->renderer));
|
||||||
priv->context = NULL;
|
priv->renderer = NULL;
|
||||||
}
|
}
|
||||||
if (priv->actor) {
|
|
||||||
ClutterActor *stage;
|
|
||||||
|
|
||||||
stage = clutter_actor_get_stage (priv->actor);
|
if (priv->keyboard && g_object_is_floating (priv->keyboard)) {
|
||||||
if (stage) {
|
g_object_unref (priv->keyboard);
|
||||||
g_signal_handler_disconnect (stage,
|
priv->keyboard = NULL;
|
||||||
priv->key_press_event_handler);
|
|
||||||
g_signal_handler_disconnect (stage,
|
|
||||||
priv->key_release_event_handler);
|
|
||||||
}
|
|
||||||
g_object_unref (priv->actor);
|
|
||||||
priv->actor = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
G_OBJECT_CLASS (eek_clutter_keyboard_parent_class)->dispose (object);
|
G_OBJECT_CLASS (eek_clutter_keyboard_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
eek_clutter_keyboard_class_init (EekClutterKeyboardClass *klass)
|
eek_clutter_keyboard_class_init (EekClutterKeyboardClass *klass)
|
||||||
{
|
{
|
||||||
|
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||||
GObjectClass *gobject_class = G_OBJECT_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,
|
g_type_class_add_private (gobject_class,
|
||||||
sizeof (EekClutterKeyboardPrivate));
|
sizeof (EekClutterKeyboardPrivate));
|
||||||
|
|
||||||
keyboard_class->create_section = eek_clutter_keyboard_real_create_section;
|
actor_class->get_preferred_width =
|
||||||
element_class->set_name = eek_clutter_keyboard_real_set_name;
|
eek_clutter_keyboard_real_get_preferred_width;
|
||||||
element_class->set_bounds = eek_clutter_keyboard_real_set_bounds;
|
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;
|
gobject_class->dispose = eek_clutter_keyboard_dispose;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,147 +131,67 @@ eek_clutter_keyboard_init (EekClutterKeyboard *self)
|
|||||||
EekClutterKeyboardPrivate *priv;
|
EekClutterKeyboardPrivate *priv;
|
||||||
|
|
||||||
priv = self->priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self);
|
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:
|
* eek_clutter_keyboard_new:
|
||||||
|
* @keyboard: an #EekKeyboard
|
||||||
*
|
*
|
||||||
* Create a new #EekClutterKeyboard.
|
* 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 *
|
ClutterActor *
|
||||||
eek_clutter_keyboard_get_actor (EekClutterKeyboard *keyboard)
|
eek_clutter_keyboard_new (EekKeyboard *keyboard)
|
||||||
{
|
{
|
||||||
EekClutterKeyboardPrivate *priv =
|
ClutterActor *actor;
|
||||||
EEK_CLUTTER_KEYBOARD_GET_PRIVATE(keyboard);
|
EekClutterKeyboardPrivate *priv;
|
||||||
if (!priv->actor) {
|
PangoContext *pcontext;
|
||||||
priv->actor = clutter_group_new ();
|
CreateSectionCallbackData data;
|
||||||
g_object_ref_sink (priv->actor);
|
EekBounds bounds;
|
||||||
g_signal_connect (priv->actor, "realize",
|
gdouble scale;
|
||||||
G_CALLBACK (on_clutter_realize), keyboard);
|
PangoFontDescription *font;
|
||||||
g_return_val_if_fail (priv->actor, NULL);
|
|
||||||
|
|
||||||
eek_keyboard_realize (EEK_KEYBOARD(keyboard));
|
actor = g_object_new (EEK_TYPE_CLUTTER_KEYBOARD, NULL);
|
||||||
update_category_fonts (keyboard);
|
priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(actor);
|
||||||
}
|
priv->keyboard = g_object_ref_sink (keyboard);
|
||||||
return priv->actor;
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,7 +20,7 @@
|
|||||||
#ifndef EEK_CLUTTER_KEYBOARD_H
|
#ifndef EEK_CLUTTER_KEYBOARD_H
|
||||||
#define EEK_CLUTTER_KEYBOARD_H 1
|
#define EEK_CLUTTER_KEYBOARD_H 1
|
||||||
|
|
||||||
#include "eek-clutter-section.h"
|
#include <clutter/clutter.h>
|
||||||
#include "eek-keyboard.h"
|
#include "eek-keyboard.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
@ -38,7 +38,7 @@ typedef struct _EekClutterKeyboardPrivate EekClutterKeyboardPrivate;
|
|||||||
struct _EekClutterKeyboard
|
struct _EekClutterKeyboard
|
||||||
{
|
{
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
EekKeyboard parent;
|
ClutterGroup parent;
|
||||||
|
|
||||||
EekClutterKeyboardPrivate *priv;
|
EekClutterKeyboardPrivate *priv;
|
||||||
};
|
};
|
||||||
@ -46,7 +46,7 @@ struct _EekClutterKeyboard
|
|||||||
struct _EekClutterKeyboardClass
|
struct _EekClutterKeyboardClass
|
||||||
{
|
{
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
EekKeyboardClass parent_class;
|
ClutterGroupClass parent_class;
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
/* padding */
|
/* padding */
|
||||||
@ -54,8 +54,7 @@ struct _EekClutterKeyboardClass
|
|||||||
};
|
};
|
||||||
|
|
||||||
GType eek_clutter_keyboard_get_type (void) G_GNUC_CONST;
|
GType eek_clutter_keyboard_get_type (void) G_GNUC_CONST;
|
||||||
EekKeyboard *eek_clutter_keyboard_new (void);
|
ClutterActor *eek_clutter_keyboard_new (EekKeyboard *keyboard);
|
||||||
ClutterActor *eek_clutter_keyboard_get_actor (EekClutterKeyboard *keyboard);
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
#endif /* EEK_CLUTTER_KEYBOARD_H */
|
#endif /* EEK_CLUTTER_KEYBOARD_H */
|
||||||
|
|||||||
184
eek/eek-clutter-renderer.c
Normal file
184
eek/eek-clutter-renderer.c
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||||
|
#include <cogl/cogl.h>
|
||||||
|
#include <cogl/cogl-pango.h>
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
|
#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 <cinamod@hotmail.com>
|
||||||
|
Copyright © 2005 Caleb Moore <c.moore@student.unsw.edu.au>
|
||||||
|
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;
|
||||||
|
}
|
||||||
44
eek/eek-clutter-renderer.h
Normal file
44
eek/eek-clutter-renderer.h
Normal file
@ -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 */
|
||||||
@ -23,106 +23,58 @@
|
|||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include "eek-clutter-section.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) \
|
#define EEK_CLUTTER_SECTION_GET_PRIVATE(obj) \
|
||||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_CLUTTER_SECTION, EekClutterSectionPrivate))
|
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_CLUTTER_SECTION, EekClutterSectionPrivate))
|
||||||
|
|
||||||
struct _EekClutterSectionPrivate
|
struct _EekClutterSectionPrivate
|
||||||
{
|
{
|
||||||
EekClutterDrawingContext *context;
|
EekSection *section;
|
||||||
ClutterActor *actor;
|
EekClutterRenderer *renderer;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
eek_clutter_section_real_set_name (EekElement *self,
|
eek_clutter_section_real_get_preferred_width (ClutterActor *self,
|
||||||
const gchar *name)
|
float for_height,
|
||||||
|
float *min_width_p,
|
||||||
|
float *natural_width_p)
|
||||||
{
|
{
|
||||||
EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(self);
|
EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(self);
|
||||||
|
EekBounds bounds;
|
||||||
|
gdouble scale;
|
||||||
|
|
||||||
EEK_ELEMENT_CLASS (eek_clutter_section_parent_class)->
|
scale = eek_renderer_get_scale (EEK_RENDERER(priv->renderer));
|
||||||
set_name (self, name);
|
eek_element_get_bounds (EEK_ELEMENT(priv->section), &bounds);
|
||||||
|
*min_width_p = 0.0f;
|
||||||
if (priv->actor)
|
*natural_width_p = bounds.width * scale;
|
||||||
clutter_actor_set_name (priv->actor, name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
eek_clutter_section_real_set_bounds (EekElement *self,
|
eek_clutter_section_real_get_preferred_height (ClutterActor *self,
|
||||||
EekBounds *bounds)
|
float for_width,
|
||||||
|
float *min_height_p,
|
||||||
|
float *natural_height_p)
|
||||||
{
|
{
|
||||||
EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(self);
|
EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(self);
|
||||||
|
EekBounds bounds;
|
||||||
|
gdouble scale;
|
||||||
|
|
||||||
EEK_ELEMENT_CLASS (eek_clutter_section_parent_class)->
|
scale = eek_renderer_get_scale (EEK_RENDERER(priv->renderer));
|
||||||
set_bounds (self, bounds);
|
eek_element_get_bounds (EEK_ELEMENT(priv->section), &bounds);
|
||||||
|
*min_height_p = 0.0f;
|
||||||
if (priv->actor) {
|
*natural_height_p = bounds.height * scale;
|
||||||
clutter_actor_set_position (priv->actor, bounds->x, bounds->y);
|
|
||||||
clutter_actor_set_size (priv->actor, bounds->width, bounds->height);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
eek_clutter_section_real_set_angle (EekSection *self,
|
eek_clutter_section_real_allocate (ClutterActor *self,
|
||||||
gint angle)
|
const ClutterActorBox *box,
|
||||||
|
ClutterAllocationFlags flags)
|
||||||
{
|
{
|
||||||
EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(self);
|
CLUTTER_ACTOR_CLASS (eek_clutter_section_parent_class)->
|
||||||
|
allocate (self, box, flags);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -130,30 +82,32 @@ eek_clutter_section_dispose (GObject *object)
|
|||||||
{
|
{
|
||||||
EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(object);
|
EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(object);
|
||||||
|
|
||||||
if (priv->context) {
|
if (priv->renderer) {
|
||||||
g_object_unref (priv->context);
|
g_object_unref (priv->renderer);
|
||||||
priv->context = NULL;
|
priv->renderer = NULL;
|
||||||
}
|
}
|
||||||
if (priv->actor) {
|
|
||||||
g_object_unref (priv->actor);
|
if (priv->section && g_object_is_floating (priv->section)) {
|
||||||
priv->actor = NULL;
|
g_object_unref (priv->section);
|
||||||
|
priv->section = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
G_OBJECT_CLASS (eek_clutter_section_parent_class)->dispose (object);
|
G_OBJECT_CLASS (eek_clutter_section_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
eek_clutter_section_class_init (EekClutterSectionClass *klass)
|
eek_clutter_section_class_init (EekClutterSectionClass *klass)
|
||||||
{
|
{
|
||||||
|
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||||
GObjectClass *gobject_class = G_OBJECT_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));
|
g_type_class_add_private (gobject_class, sizeof (EekClutterSectionPrivate));
|
||||||
|
|
||||||
section_class->set_angle = eek_clutter_section_real_set_angle;
|
actor_class->get_preferred_width =
|
||||||
section_class->create_key = eek_clutter_section_real_create_key;
|
eek_clutter_section_real_get_preferred_width;
|
||||||
element_class->set_name = eek_clutter_section_real_set_name;
|
actor_class->get_preferred_height =
|
||||||
element_class->set_bounds = eek_clutter_section_real_set_bounds;
|
eek_clutter_section_real_get_preferred_height;
|
||||||
|
actor_class->allocate = eek_clutter_section_real_allocate;
|
||||||
gobject_class->dispose = eek_clutter_section_dispose;
|
gobject_class->dispose = eek_clutter_section_dispose;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,29 +116,54 @@ eek_clutter_section_init (EekClutterSection *self)
|
|||||||
{
|
{
|
||||||
EekClutterSectionPrivate *priv;
|
EekClutterSectionPrivate *priv;
|
||||||
priv = self->priv = EEK_CLUTTER_SECTION_GET_PRIVATE (self);
|
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 *
|
ClutterActor *
|
||||||
eek_clutter_section_get_actor (EekClutterSection *section)
|
eek_clutter_section_new (EekSection *section,
|
||||||
|
EekClutterRenderer *renderer)
|
||||||
{
|
{
|
||||||
EekClutterSectionPrivate *priv = EEK_CLUTTER_SECTION_GET_PRIVATE(section);
|
ClutterActor *actor;
|
||||||
if (!priv->actor) {
|
EekClutterSectionPrivate *priv;
|
||||||
priv->actor = clutter_group_new ();
|
CreateKeyCallbackData data;
|
||||||
g_object_ref_sink (priv->actor);
|
EekBounds bounds;
|
||||||
}
|
gdouble scale;
|
||||||
return priv->actor;
|
|
||||||
}
|
actor = g_object_new (EEK_TYPE_CLUTTER_SECTION, NULL);
|
||||||
|
priv = EEK_CLUTTER_SECTION_GET_PRIVATE(actor);
|
||||||
EekSection *
|
priv->section = g_object_ref_sink (section);
|
||||||
eek_clutter_section_new (EekClutterDrawingContext *context)
|
priv->renderer = g_object_ref (renderer);
|
||||||
{
|
|
||||||
EekClutterSection *section;
|
eek_element_get_bounds (EEK_ELEMENT(section), &bounds);
|
||||||
|
scale = eek_renderer_get_scale (EEK_RENDERER(priv->renderer));
|
||||||
g_return_val_if_fail (context, NULL);
|
clutter_actor_set_position (actor, bounds.x * scale, bounds.y * scale);
|
||||||
section = g_object_new (EEK_TYPE_CLUTTER_SECTION, NULL);
|
clutter_actor_set_rotation (actor,
|
||||||
section->priv->context = context;
|
CLUTTER_Z_AXIS,
|
||||||
g_object_ref_sink (G_OBJECT(section->priv->context));
|
eek_section_get_angle (section),
|
||||||
|
0.0f, 0.0f, 0.0f);
|
||||||
return EEK_SECTION(section);
|
|
||||||
|
data.actor = actor;
|
||||||
|
data.renderer = priv->renderer;
|
||||||
|
eek_container_foreach_child (EEK_CONTAINER(priv->section),
|
||||||
|
create_key,
|
||||||
|
&data);
|
||||||
|
|
||||||
|
return actor;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,9 +20,9 @@
|
|||||||
#ifndef EEK_CLUTTER_SECTION_H
|
#ifndef EEK_CLUTTER_SECTION_H
|
||||||
#define EEK_CLUTTER_SECTION_H 1
|
#define EEK_CLUTTER_SECTION_H 1
|
||||||
|
|
||||||
#include "eek-clutter-drawing-context.h"
|
#include <clutter/clutter.h>
|
||||||
#include "eek-clutter-key.h"
|
|
||||||
#include "eek-section.h"
|
#include "eek-section.h"
|
||||||
|
#include "eek-clutter-renderer.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
#define EEK_TYPE_CLUTTER_SECTION (eek_clutter_section_get_type())
|
#define EEK_TYPE_CLUTTER_SECTION (eek_clutter_section_get_type())
|
||||||
@ -39,7 +39,7 @@ typedef struct _EekClutterSectionPrivate EekClutterSectionPrivate;
|
|||||||
struct _EekClutterSection
|
struct _EekClutterSection
|
||||||
{
|
{
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
EekSection parent;
|
ClutterGroup parent;
|
||||||
|
|
||||||
EekClutterSectionPrivate *priv;
|
EekClutterSectionPrivate *priv;
|
||||||
};
|
};
|
||||||
@ -47,7 +47,7 @@ struct _EekClutterSection
|
|||||||
struct _EekClutterSectionClass
|
struct _EekClutterSectionClass
|
||||||
{
|
{
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
EekSectionClass parent_class;
|
ClutterGroupClass parent_class;
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
/* padding */
|
/* padding */
|
||||||
@ -55,8 +55,8 @@ struct _EekClutterSectionClass
|
|||||||
};
|
};
|
||||||
|
|
||||||
GType eek_clutter_section_get_type (void) G_GNUC_CONST;
|
GType eek_clutter_section_get_type (void) G_GNUC_CONST;
|
||||||
EekSection * eek_clutter_section_new (EekClutterDrawingContext *context);
|
ClutterActor *eek_clutter_section_new (EekSection *section,
|
||||||
ClutterActor *eek_clutter_section_get_actor (EekClutterSection *section);
|
EekClutterRenderer *renderer);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
#endif /* EEK_CLUTTER_SECTION_H */
|
#endif /* EEK_CLUTTER_SECTION_H */
|
||||||
|
|||||||
@ -200,7 +200,6 @@ eek_keyboard_set_property (GObject *object,
|
|||||||
{
|
{
|
||||||
gint group, level;
|
gint group, level;
|
||||||
|
|
||||||
g_return_if_fail (EEK_IS_KEYBOARD(object));
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_GROUP:
|
case PROP_GROUP:
|
||||||
eek_keyboard_get_keysym_index (EEK_KEYBOARD(object), &group, &level);
|
eek_keyboard_get_keysym_index (EEK_KEYBOARD(object), &group, &level);
|
||||||
|
|||||||
@ -36,6 +36,11 @@
|
|||||||
#include "eek/eek-gtk.h"
|
#include "eek/eek-gtk.h"
|
||||||
#include "eek/eek-xkl.h"
|
#include "eek/eek-xkl.h"
|
||||||
|
|
||||||
|
#if HAVE_CLUTTER_GTK
|
||||||
|
#include <clutter-gtk/clutter-gtk.h>
|
||||||
|
#include "eek/eek-clutter.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define CSW 640
|
#define CSW 640
|
||||||
#define CSH 480
|
#define CSH 480
|
||||||
|
|
||||||
@ -79,7 +84,9 @@ struct _Eekboard {
|
|||||||
XklConfigRegistry *registry;
|
XklConfigRegistry *registry;
|
||||||
GtkUIManager *ui_manager;
|
GtkUIManager *ui_manager;
|
||||||
gulong on_key_pressed_id, on_key_released_id;
|
gulong on_key_pressed_id, on_key_released_id;
|
||||||
|
#if HAVE_CLUTTER_GTK
|
||||||
|
ClutterActor *actor;
|
||||||
|
#endif
|
||||||
guint countries_merge_id;
|
guint countries_merge_id;
|
||||||
GtkActionGroup *countries_action_group;
|
GtkActionGroup *countries_action_group;
|
||||||
|
|
||||||
@ -1025,11 +1032,33 @@ create_menus (Eekboard *eekboard,
|
|||||||
-1);
|
-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 *
|
static GtkWidget *
|
||||||
create_widget (Eekboard *eekboard,
|
create_widget (Eekboard *eekboard,
|
||||||
gint initial_width,
|
gint initial_width,
|
||||||
gint initial_height)
|
gint initial_height)
|
||||||
{
|
{
|
||||||
|
#if HAVE_CLUTTER_GTK
|
||||||
|
ClutterActor *stage;
|
||||||
|
ClutterColor stage_color = { 0xff, 0xff, 0xff, 0xff };
|
||||||
|
#endif
|
||||||
EekBounds bounds;
|
EekBounds bounds;
|
||||||
|
|
||||||
eekboard->keyboard = eek_keyboard_new (eekboard->layout,
|
eekboard->keyboard = eek_keyboard_new (eekboard->layout,
|
||||||
@ -1042,8 +1071,27 @@ create_widget (Eekboard *eekboard,
|
|||||||
g_signal_connect (eekboard->keyboard, "key-released",
|
g_signal_connect (eekboard->keyboard, "key-released",
|
||||||
G_CALLBACK(on_key_released), eekboard);
|
G_CALLBACK(on_key_released), eekboard);
|
||||||
|
|
||||||
eekboard->widget = eek_gtk_keyboard_new (eekboard->keyboard);
|
|
||||||
eek_element_get_bounds (EEK_ELEMENT(eekboard->keyboard), &bounds);
|
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->width = bounds.width;
|
||||||
eekboard->height = bounds.height;
|
eekboard->height = bounds.height;
|
||||||
return eekboard->widget;
|
return eekboard->widget;
|
||||||
@ -1397,6 +1445,8 @@ main (int argc, char *argv[])
|
|||||||
GConfClient *gconfc;
|
GConfClient *gconfc;
|
||||||
GError *error;
|
GError *error;
|
||||||
|
|
||||||
|
g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL);
|
||||||
|
|
||||||
context = g_option_context_new ("eekboard");
|
context = g_option_context_new ("eekboard");
|
||||||
g_option_context_add_main_entries (context, options, NULL);
|
g_option_context_add_main_entries (context, options, NULL);
|
||||||
g_option_context_parse (context, &argc, &argv, NULL);
|
g_option_context_parse (context, &argc, &argv, NULL);
|
||||||
@ -1426,10 +1476,17 @@ main (int argc, char *argv[])
|
|||||||
g_warning("AT-SPI initialization failed");
|
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)) {
|
if (!gtk_init_check (&argc, &argv)) {
|
||||||
g_warning ("Can't init GTK");
|
g_warning ("Can't init GTK");
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
eekboard = eekboard_new (accessibility_enabled);
|
eekboard = eekboard_new (accessibility_enabled);
|
||||||
if (opt_list_models) {
|
if (opt_list_models) {
|
||||||
@ -1623,8 +1680,6 @@ main (int argc, char *argv[])
|
|||||||
g_warning ("failed to register keystroke listener");
|
g_warning ("failed to register keystroke listener");
|
||||||
}
|
}
|
||||||
|
|
||||||
g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL);
|
|
||||||
|
|
||||||
if (combo)
|
if (combo)
|
||||||
gtk_combo_box_set_active (GTK_COMBO_BOX(combo), 0);
|
gtk_combo_box_set_active (GTK_COMBO_BOX(combo), 0);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user