Mailing List Archive

r19311 - in projects/haf/trunk/hildon-input-method-plugins-example: . src
Author: jrocha
Date: 2009-09-09 17:01:35 +0300 (Wed, 09 Sep 2009)
New Revision: 19311

Added:
projects/haf/trunk/hildon-input-method-plugins-example/src/hildon-im-onehand-fkb.c
Modified:
projects/haf/trunk/hildon-input-method-plugins-example/AUTHORS
projects/haf/trunk/hildon-input-method-plugins-example/configure.ac
projects/haf/trunk/hildon-input-method-plugins-example/src/Makefile.am
Log:
* Created one-hand FKB example plugin
* Added myself to authors

Modified: projects/haf/trunk/hildon-input-method-plugins-example/AUTHORS
===================================================================
--- projects/haf/trunk/hildon-input-method-plugins-example/AUTHORS 2009-09-09 12:43:46 UTC (rev 19310)
+++ projects/haf/trunk/hildon-input-method-plugins-example/AUTHORS 2009-09-09 14:01:35 UTC (rev 19311)
@@ -1,3 +1,4 @@
Mohammad Anwari <mohammad.anwari@nokia.com>
Tomas Junnonen <tomas.junnonen@nokia.com>
Felipe Erias Morandeira <femorandeira@igalia.com>
+Joaquim Rocha <jrocha@maemo.org>
\ No newline at end of file

Modified: projects/haf/trunk/hildon-input-method-plugins-example/configure.ac
===================================================================
--- projects/haf/trunk/hildon-input-method-plugins-example/configure.ac 2009-09-09 12:43:46 UTC (rev 19310)
+++ projects/haf/trunk/hildon-input-method-plugins-example/configure.ac 2009-09-09 14:01:35 UTC (rev 19311)
@@ -15,7 +15,9 @@
hildon-input-method-framework-3.0 >= 1.99.0 hildon-input-method-ui-3.0 >= 1.99.0
gtk+-2.0 >= 2.4.0 gconf-2.0 > 2.0
dbus-1 >= 0.60
- hildon-1 >= 1.0.0)
+ hildon-1 >= 1.0.0
+ mce >= 1.8.0
+ libosso >= 2.20)
AC_SUBST(HIM_PLUGINS_EXAMPLE_CFLAGS)
AC_SUBST(HIM_PLUGINS_EXAMPLE_LIBS)


Modified: projects/haf/trunk/hildon-input-method-plugins-example/src/Makefile.am
===================================================================
--- projects/haf/trunk/hildon-input-method-plugins-example/src/Makefile.am 2009-09-09 12:43:46 UTC (rev 19310)
+++ projects/haf/trunk/hildon-input-method-plugins-example/src/Makefile.am 2009-09-09 14:01:35 UTC (rev 19311)
@@ -13,18 +13,21 @@
# /usr/lib/hildon-input-method/, where it will be found by the
# hildon-input-method framework:
implugindir = $(libdir)/hildon-input-method
-implugin_LTLIBRARIES = him_vkb_example.la hildon_im_example_fkb.la
+implugin_LTLIBRARIES = him_vkb_example.la hildon_im_example_fkb.la hildon_im_onehand_fkb.la

-# Build the plugin (shared library):
+# Build the plugins (shared libraries):
him_vkb_example_la_SOURCES = him-vkb-example.c
him_vkb_example_la_LIBADD = $(HIM_PLUGINS_EXAMPLE_LIBS)
him_vkb_example_la_LDFLAGS = -avoid-version -module

-# Build the plugin (shared library):
hildon_im_example_fkb_la_SOURCES = hildon-im-example-fkb.c
hildon_im_example_fkb_la_LIBADD = $(HIM_PLUGINS_EXAMPLE_LIBS)
hildon_im_example_fkb_la_LDFLAGS = -avoid-version -module

+hildon_im_onehand_fkb_la_SOURCES = hildon-im-onehand-fkb.c
+hildon_im_onehand_fkb_la_LIBADD = $(HIM_PLUGINS_EXAMPLE_LIBS)
+hildon_im_onehand_fkb_la_LDFLAGS = -avoid-version -module
+
# After installation, update the cache so that hildon-input-method knows about
# the new plugin:
install-data-hook:

Added: projects/haf/trunk/hildon-input-method-plugins-example/src/hildon-im-onehand-fkb.c
===================================================================
--- projects/haf/trunk/hildon-input-method-plugins-example/src/hildon-im-onehand-fkb.c 2009-09-09 12:43:46 UTC (rev 19310)
+++ projects/haf/trunk/hildon-input-method-plugins-example/src/hildon-im-onehand-fkb.c 2009-09-09 14:01:35 UTC (rev 19311)
@@ -0,0 +1,994 @@
+/*
+ * This file is part of hildon-input-method-plugins-example
+ *
+ * Copyright (C) 2006-2007 Nokia Corporation. All rights reserved.
+ *
+ * Author: Joaquim Rocha <jrocha@maemo.org>
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ * Neither the name of Nokia Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+*/
+
+#include "hildon-im-plugin.h"
+#include "hildon-im-ui.h"
+
+#include <string.h>
+#include <glib.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <libosso.h>
+#include <mce/dbus-names.h>
+#include <gtk/gtk.h>
+#include <hildon/hildon.h>
+
+#define SLIDING_TIMEOUT 1000
+
+#define MCE_RULE "type='signal', interface='" MCE_SIGNAL_IF "', member='" MCE_DEVICE_ORIENTATION_SIG "'"
+#define MCE_PORTRAIT_MODE_NAME "portrait"
+
+#define HILDON_IM_ONEHAND_FKB_TYPE hildon_im_onehand_fkb_get_type ()
+#define HILDON_IM_ONEHAND_FKB(obj) GTK_CHECK_CAST(obj, hildon_im_onehand_fkb_get_type (), HildonIMOneHandFKB)
+#define HILDON_IM_ONEHAND_FKB_CLASS(klass) \
+ GTK_CHECK_CLASS_CAST(klass, hildon_im_onehand_fkb_get_type, \
+ HildonIMOneHandFKBClass)
+#define HILDON_IS_IM_ONEHAND_FKB(obj) \
+ GTK_CHECK_TYPE(obj, hildon_im_onehand_fkb_get_type ())
+#define HILDON_IM_ONEHAND_FKB_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_IM_ONEHAND_FKB_TYPE,\
+ HildonIMOneHandFKBPrivate))
+
+static gchar* sliding_keys[] = {".,-_1'?!¿¡:;€£$\"~()[]{}%&/\\|", "abc2çčæáàãâäå",
+ "def3éèêë", "ghi4íìîïı", "jkl5", "mno6ñóòõöø",
+ "pqrs7š", "tuv8úùûü", "wxyz9"};
+
+typedef enum
+{
+ PORTRAIT,
+ LANDSCAPE
+} ScreenMode;
+
+typedef struct
+{
+ GtkContainerClass parent;
+}
+HildonIMOneHandFKBClass;
+
+typedef struct
+{
+ GtkContainer parent;
+
+}
+HildonIMOneHandFKB;
+
+typedef struct
+{
+ HildonIMUI *ui;
+
+ GtkWidget *window;
+ GtkWidget *text_view;
+ GtkWidget *keyboard;
+ GtkWidget *caps_button;
+
+ gint saved_offset;
+
+ gint keys_width;
+
+ ScreenMode screen_mode;
+ gint fkb_width;
+ gint fkb_height;
+
+ gint slide_index;
+ gint replace_previous_char;
+ gint timeout_id;
+
+ GtkWidget *repeating_key;
+}
+HildonIMOneHandFKBPrivate;
+
+static GType hildon_im_onehand_fkb_type = 0;
+static GtkWidgetClass *parent_class = NULL;
+
+GType hildon_im_onehand_fkb_get_type (void);
+GtkWidget *hildon_im_onehand_fkb_new (HildonIMUI *kbd);
+
+/*
+ * HildonIMPlugin interface
+ */
+static void hildon_im_onehand_fkb_iface_init (HildonIMPluginIface *iface);
+
+static void hildon_im_onehand_fkb_enable (HildonIMPlugin *plugin, gboolean init);
+static void hildon_im_onehand_fkb_disable (HildonIMPlugin *plugin);
+static void hildon_im_onehand_fkb_surrounding_received (HildonIMPlugin *plugin,
+ const gchar *surrounding,
+ gint offset);
+
+/*
+ * GObject functions
+ */
+static void hildon_im_onehand_fkb_finalize (GObject *obj);
+static void hildon_im_onehand_fkb_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void hildon_im_onehand_fkb_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+
+static void hildon_im_onehand_fkb_class_init (HildonIMOneHandFKBClass *klass);
+static void hildon_im_onehand_fkb_init (HildonIMOneHandFKB *self);
+
+/*
+ * Internal functions
+ */
+static void create_window (HildonIMOneHandFKB *self);
+static void set_fkb_size (HildonIMOneHandFKB *self);
+static void set_kb_mode (HildonIMOneHandFKB *self, ScreenMode mode);
+static void backspace (HildonIMOneHandFKB *self);
+static void write (HildonIMOneHandFKB *self, const gchar *text);
+static gboolean get_cursor_offset (HildonIMOneHandFKB *self);
+static void clear_timeout_id (HildonIMOneHandFKB *self);
+
+/*
+ * Module functions
+ */
+
+HildonIMPlugin*
+module_create (HildonIMUI *keyboard)
+{
+ return HILDON_IM_PLUGIN (hildon_im_onehand_fkb_new (keyboard));
+}
+
+void
+module_exit(void)
+{
+ /* empty */
+}
+
+void
+module_init(GTypeModule *module)
+{
+ static const GTypeInfo type_info = {
+ sizeof(HildonIMOneHandFKBClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) hildon_im_onehand_fkb_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof(HildonIMOneHandFKB),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) hildon_im_onehand_fkb_init,
+ };
+
+ static const GInterfaceInfo plugin_info = {
+ (GInterfaceInitFunc) hildon_im_onehand_fkb_iface_init,
+ NULL, /* interface_finalize */
+ NULL, /* interface_data */
+ };
+
+ hildon_im_onehand_fkb_type =
+ g_type_module_register_type(module,
+ GTK_TYPE_CONTAINER, "HildonIMOneHandFKB",
+ &type_info,
+ 0);
+
+ g_type_module_add_interface(module,
+ HILDON_IM_ONEHAND_FKB_TYPE,
+ HILDON_IM_TYPE_PLUGIN,
+ &plugin_info);
+}
+
+/*
+ * This is used to know the plugin's information when loading the module
+ */
+const HildonIMPluginInfo *
+hildon_im_plugin_get_info(void)
+{
+ static const HildonIMPluginInfo info =
+ {
+ "HIM One Hand FKB", /* description */
+ "hildon_im_onehand_fkb", /* name */
+ NULL, /* menu title */
+ NULL, /* gettext domain */
+ TRUE, /* visible in menu */
+ FALSE, /* cached */
+ HILDON_IM_TYPE_FULLSCREEN, /* UI type */
+ HILDON_IM_GROUP_LATIN, /* group */
+ HILDON_IM_DEFAULT_PLUGIN_PRIORITY, /* priority */
+ NULL, /* special character plugin */
+ NULL, /* help page */
+ TRUE, /* disable common UI buttons */
+ 0, /* plugin height */
+ HILDON_IM_TRIGGER_FINGER /* trigger */
+ };
+
+ return &info;
+}
+
+/*
+ * This function returns the list of available languages supported
+ * by the plugin.
+ */
+gchar **
+hildon_im_plugin_get_available_languages (gboolean *free)
+{
+ static gchar *langs[] = {"en_GB", NULL};
+ *free = FALSE;
+
+ return langs;
+}
+
+GType
+hildon_im_onehand_fkb_get_type (void)
+{
+ return hildon_im_onehand_fkb_type;
+}
+
+/*
+ * Implement the interface.
+ */
+static void
+hildon_im_onehand_fkb_iface_init (HildonIMPluginIface *iface)
+{
+ iface->enable = hildon_im_onehand_fkb_enable;
+ iface->disable = hildon_im_onehand_fkb_disable;
+ iface->surrounding_received = hildon_im_onehand_fkb_surrounding_received;
+}
+
+static void
+hildon_im_onehand_fkb_class_init (HildonIMOneHandFKBClass *klass)
+{
+ GObjectClass *object_class;
+ GtkObjectClass *gtk_object_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+
+ parent_class = g_type_class_peek_parent (klass);
+ g_type_class_add_private (klass, sizeof (HildonIMOneHandFKBPrivate));
+
+ object_class = G_OBJECT_CLASS(klass);
+ gtk_object_class = GTK_OBJECT_CLASS(klass);
+ widget_class = GTK_WIDGET_CLASS(klass);
+ container_class = GTK_CONTAINER_CLASS(klass);
+
+ object_class->set_property = hildon_im_onehand_fkb_set_property;
+ object_class->get_property = hildon_im_onehand_fkb_get_property;
+ object_class->finalize = hildon_im_onehand_fkb_finalize;
+
+ g_object_class_install_property (object_class, HILDON_IM_PROP_UI,
+ g_param_spec_object (HILDON_IM_PROP_UI_DESCRIPTION,
+ HILDON_IM_PROP_UI_DESCRIPTION,
+ "UI that uses plugin",
+ HILDON_IM_TYPE_UI,
+ G_PARAM_READWRITE
+ | G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+hildon_im_onehand_fkb_init (HildonIMOneHandFKB *self)
+{
+ HildonIMOneHandFKBPrivate *priv;
+
+ g_return_if_fail (HILDON_IS_IM_ONEHAND_FKB (self));
+ priv = HILDON_IM_ONEHAND_FKB_GET_PRIVATE (self);
+
+ priv->text_view = NULL;
+ priv->keyboard = NULL;
+ priv->caps_button = NULL;
+
+ priv->screen_mode = LANDSCAPE;
+ priv->replace_previous_char = FALSE;
+ priv->slide_index = -1;
+ priv->timeout_id = 0;
+}
+
+static void
+hildon_im_onehand_fkb_finalize(GObject *obj)
+{
+ if (G_OBJECT_CLASS (parent_class)->finalize)
+ {
+ G_OBJECT_CLASS (parent_class)->finalize (obj);
+ }
+}
+
+GtkWidget *
+hildon_im_onehand_fkb_new (HildonIMUI *kbd)
+{
+ return g_object_new (HILDON_IM_ONEHAND_FKB_TYPE,
+ HILDON_IM_PROP_UI_DESCRIPTION, kbd, NULL);
+}
+
+static void
+hildon_im_onehand_fkb_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ HildonIMOneHandFKBPrivate *priv;
+
+ g_return_if_fail (HILDON_IS_IM_ONEHAND_FKB(object));
+ priv = HILDON_IM_ONEHAND_FKB_GET_PRIVATE(object);
+
+ switch (prop_id)
+ {
+ case HILDON_IM_PROP_UI:
+ g_value_set_object(value, priv->ui);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+hildon_im_onehand_fkb_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ HildonIMOneHandFKBPrivate *priv;
+
+ g_return_if_fail (HILDON_IS_IM_ONEHAND_FKB (object));
+ priv = HILDON_IM_ONEHAND_FKB_GET_PRIVATE(object);
+
+ switch (prop_id)
+ {
+ case HILDON_IM_PROP_UI:
+ priv->ui = g_value_get_object(value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+static DBusHandlerResult
+screen_mode_dbus_handler (DBusConnection *connection,
+ DBusMessage *message,
+ gpointer data)
+{
+ HildonIMOneHandFKB *self;
+ HildonIMOneHandFKBPrivate *priv;
+ DBusMessageIter iter;
+ const gchar *mode = NULL;
+
+ self = HILDON_IM_ONEHAND_FKB (data);
+ priv = HILDON_IM_ONEHAND_FKB_GET_PRIVATE (self);
+
+ if (dbus_message_is_signal (message, MCE_SIGNAL_IF, MCE_DEVICE_ORIENTATION_SIG) &&
+ dbus_message_iter_init (message, &iter))
+ {
+ dbus_message_iter_get_basic(&iter, &mode);
+ if (mode != NULL)
+ {
+ ScreenMode screen_mode = priv->screen_mode;
+
+ if (g_strcmp0 (mode, MCE_PORTRAIT_MODE_NAME) == 0)
+ {
+ screen_mode = PORTRAIT;
+ }
+ else
+ {
+ screen_mode = LANDSCAPE;
+ }
+
+ if (screen_mode != priv->screen_mode)
+ {
+ priv->screen_mode = screen_mode;
+
+ hildon_gtk_window_set_portrait_flags (GTK_WINDOW (priv->window), priv->screen_mode == PORTRAIT ?
+ HILDON_PORTRAIT_MODE_REQUEST :
+ HILDON_PORTRAIT_MODE_SUPPORT);
+ set_fkb_size (self);
+ set_kb_mode (self, priv->screen_mode);
+ }
+ }
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static ScreenMode
+get_screen_mode (osso_context_t* context)
+{
+ ScreenMode mode = LANDSCAPE;
+ osso_return_t ret;
+ osso_rpc_t return_value;
+
+ ret = osso_rpc_run_system (context,
+ MCE_SERVICE, MCE_REQUEST_PATH,
+ MCE_REQUEST_IF,
+ MCE_DEVICE_ORIENTATION_GET,
+ &return_value,
+ DBUS_TYPE_INVALID);
+ if (ret == OSSO_OK)
+ {
+ if (g_strcmp0 (return_value.value.s, MCE_PORTRAIT_MODE_NAME) == 0)
+ {
+ mode = PORTRAIT;
+ }
+ osso_rpc_free_val(&return_value);
+ }
+
+ return mode;
+}
+
+
+static void
+hildon_im_onehand_fkb_enable (HildonIMPlugin *plugin, gboolean init)
+{
+ DBusConnection *connection;
+ HildonIMOneHandFKB *self;
+ HildonIMOneHandFKBPrivate *priv;
+
+ g_return_if_fail (HILDON_IS_IM_ONEHAND_FKB (plugin));
+ self = HILDON_IM_ONEHAND_FKB(plugin);
+ priv = HILDON_IM_ONEHAND_FKB_GET_PRIVATE(self);
+
+ connection = osso_get_sys_dbus_connection (priv->ui->osso);
+
+ priv->screen_mode = get_screen_mode (priv->ui->osso);
+
+ set_fkb_size (self);
+
+ if (priv->window == NULL)
+ {
+ create_window (self);
+
+ dbus_bus_add_match (connection, MCE_RULE, NULL);
+ dbus_connection_add_filter (connection, screen_mode_dbus_handler, self, NULL);
+ }
+
+ hildon_im_ui_send_communication_message (priv->ui,
+ HILDON_IM_CONTEXT_REQUEST_SURROUNDING_FULL);
+
+ gtk_window_fullscreen (GTK_WINDOW (priv->window));
+ gtk_widget_show_all (priv->window);
+
+ gdk_window_set_transient_for (GTK_WIDGET (priv->window)->window,
+ gtk_widget_get_root_window(GTK_WIDGET(priv->window)));
+
+ priv->saved_offset = get_cursor_offset (self);
+}
+
+static void
+hildon_im_onehand_fkb_disable (HildonIMPlugin *plugin)
+{
+ DBusConnection *connection;
+ HildonIMOneHandFKB *self;
+ HildonIMOneHandFKBPrivate *priv;
+
+ g_return_if_fail (HILDON_IS_IM_ONEHAND_FKB (plugin));
+ self = HILDON_IM_ONEHAND_FKB (plugin);
+ priv = HILDON_IM_ONEHAND_FKB_GET_PRIVATE (self);
+
+ connection = osso_get_sys_dbus_connection (priv->ui->osso);
+ dbus_connection_remove_filter (connection, screen_mode_dbus_handler, NULL);
+
+ gtk_widget_hide (GTK_WIDGET (priv->window));
+ hildon_im_ui_restore_previous_mode (priv->ui);
+}
+
+static void
+hildon_im_onehand_fkb_surrounding_received(HildonIMPlugin *plugin,
+ const gchar *surrounding,
+ gint offset)
+{
+ HildonIMOneHandFKB *self;
+ HildonIMOneHandFKBPrivate *priv;
+ GtkTextBuffer *buffer;
+ GtkTextIter cursor_iter;
+
+ self = HILDON_IM_ONEHAND_FKB(plugin);
+ priv = HILDON_IM_ONEHAND_FKB_GET_PRIVATE(self);
+
+ buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(priv->text_view));
+
+ /* I don't know why, but the view doesn't reflect the changes immediately */
+ gtk_text_buffer_set_text(buffer, surrounding, -1);
+ gtk_text_buffer_get_iter_at_offset(buffer, &cursor_iter, offset);
+ gtk_text_buffer_place_cursor(buffer, &cursor_iter);
+
+ priv->saved_offset = offset;
+}
+
+static gint
+get_cursor_offset (HildonIMOneHandFKB *self)
+{
+ HildonIMOneHandFKBPrivate *priv;
+ GtkTextBuffer *buffer;
+ GtkTextIter iter;
+
+ priv = HILDON_IM_ONEHAND_FKB_GET_PRIVATE (self);
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->text_view));
+ gtk_text_buffer_get_iter_at_mark (buffer,
+ &iter,
+ gtk_text_buffer_get_selection_bound (buffer));
+
+ return gtk_text_iter_get_offset (&iter);
+}
+
+static gboolean
+textview_button_press_cb (GtkWidget *textview, GdkEventButton *event, gpointer data)
+{
+ HildonIMOneHandFKB *self;
+ HildonIMOneHandFKBPrivate *priv;
+ gint offset;
+
+ g_return_val_if_fail (HILDON_IS_IM_ONEHAND_FKB (data), FALSE);
+ self = HILDON_IM_ONEHAND_FKB (data);
+ priv = HILDON_IM_ONEHAND_FKB_GET_PRIVATE (self);
+
+ priv->saved_offset = get_cursor_offset (self);
+
+ GTK_WIDGET_GET_CLASS (priv->text_view)->button_press_event (priv->text_view, event);
+
+ if (hildon_im_ui_get_commit_mode (priv->ui) == HILDON_IM_COMMIT_REDIRECT)
+ {
+ offset = get_cursor_offset (self);
+
+ hildon_im_ui_send_surrounding_offset (priv->ui,
+ TRUE,
+ offset - priv->saved_offset);
+ priv->saved_offset = offset;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+delete_selection (HildonIMOneHandFKB *self)
+{
+ HildonIMOneHandFKBPrivate *priv;
+ GtkTextIter start, end;
+ GtkTextBuffer *buffer;
+
+ priv = HILDON_IM_ONEHAND_FKB_GET_PRIVATE (self);
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->text_view));
+
+ if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
+ {
+ if (hildon_im_ui_get_commit_mode (priv->ui) == HILDON_IM_COMMIT_REDIRECT)
+ {
+ gchar *selected_text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
+
+ hildon_im_ui_send_surrounding_offset (priv->ui,
+ TRUE,
+ gtk_text_iter_get_offset (&end) - get_cursor_offset (self));
+
+ gint i;
+ for (i = 0; i < g_utf8_strlen (selected_text, -1); i++)
+ {
+ hildon_im_ui_send_communication_message (priv->ui,
+ HILDON_IM_CONTEXT_HANDLE_BACKSPACE);
+ }
+ }
+ gtk_text_buffer_delete (buffer, &start, &end);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+close_fkb_cb (GtkWidget *widget, gpointer data)
+{
+ hildon_im_onehand_fkb_disable (HILDON_IM_PLUGIN (data));
+}
+
+static void
+backspace_pressed_cb (GtkWidget *widget, gpointer data)
+{
+ HildonIMOneHandFKB *self = HILDON_IM_ONEHAND_FKB (data);
+
+ if (! delete_selection (self))
+ {
+ backspace (self);
+ }
+}
+
+static void
+enter_key_pressed_cb (GtkWidget *widget, gpointer data)
+{
+ HildonIMOneHandFKB *self = HILDON_IM_ONEHAND_FKB (data);
+ HildonIMOneHandFKBPrivate *priv;
+
+ priv = HILDON_IM_ONEHAND_FKB_GET_PRIVATE (self);
+
+ clear_timeout_id (self);
+
+ write (self, "\n");
+}
+
+static void
+backspace (HildonIMOneHandFKB *self)
+{
+ HildonIMOneHandFKBPrivate *priv;
+ GtkTextIter iter;
+ GtkTextBuffer *buffer;
+
+ priv = HILDON_IM_ONEHAND_FKB_GET_PRIVATE (self);
+
+ clear_timeout_id (self);
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->text_view));
+ gtk_text_buffer_get_iter_at_mark(buffer,
+ &iter,
+ gtk_text_buffer_get_insert (buffer));
+
+ gtk_text_buffer_backspace (buffer, &iter, TRUE, TRUE);
+
+ if (hildon_im_ui_get_commit_mode(priv->ui) == HILDON_IM_COMMIT_REDIRECT)
+ {
+ hildon_im_ui_send_communication_message(priv->ui,
+ HILDON_IM_CONTEXT_HANDLE_BACKSPACE);
+ gtk_text_buffer_get_iter_at_mark(buffer,
+ &iter,
+ gtk_text_buffer_get_selection_bound (buffer));
+ priv->saved_offset = gtk_text_iter_get_offset(&iter);
+ }
+}
+
+static void
+write (HildonIMOneHandFKB *self, const gchar *text)
+{
+ HildonIMOneHandFKBPrivate *priv;
+ GtkTextBuffer *buffer;
+
+ priv = HILDON_IM_ONEHAND_FKB_GET_PRIVATE(self);
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->text_view));
+
+ priv = HILDON_IM_ONEHAND_FKB_GET_PRIVATE(self);
+
+ if (hildon_im_ui_get_commit_mode (priv->ui) == HILDON_IM_COMMIT_REDIRECT)
+ {
+ delete_selection (self);
+ hildon_im_ui_send_utf8(priv->ui, text);
+ }
+
+ gtk_text_buffer_insert_at_cursor (buffer, text, -1);
+}
+
+static GtkWidget *
+create_special_key (HildonIMOneHandFKB *self,
+ HildonSizeType size,
+ gchar *icon_name,
+ GCallback callback)
+{
+ GtkWidget *image;
+ GtkWidget *key;
+
+ key = hildon_gtk_button_new (size);
+
+ if (icon_name != NULL)
+ {
+ image = gtk_image_new_from_icon_name (icon_name, -1);
+ gtk_container_add (GTK_CONTAINER (key), image);
+ }
+
+ if (callback != NULL)
+ {
+ g_signal_connect (key,
+ "clicked",
+ G_CALLBACK (callback),
+ self);
+ }
+
+ return key;
+}
+
+static void
+set_fkb_size (HildonIMOneHandFKB *self)
+{
+ HildonIMOneHandFKBPrivate *priv;
+ GdkScreen *screen;
+
+ priv = HILDON_IM_ONEHAND_FKB_GET_PRIVATE(self);
+ screen = gdk_screen_get_default ();
+
+ priv->fkb_width = gdk_screen_get_width (screen);
+ priv->fkb_height = gdk_screen_get_height (screen);
+}
+
+static gchar *
+get_first_char (gchar *full_string)
+{
+ gunichar chr = g_utf8_get_char_validated (full_string, -1);
+ gchar character[7];
+ int len = g_unichar_to_utf8 (chr, character);
+ character[len] = '\0';
+
+ return g_strndup (character, len);
+}
+
+static void
+clear_timeout_id (HildonIMOneHandFKB *self)
+{
+ HildonIMOneHandFKBPrivate *priv;
+ priv = HILDON_IM_ONEHAND_FKB_GET_PRIVATE (self);
+
+ if (priv->timeout_id > 0)
+ {
+ g_source_remove (priv->timeout_id);
+ }
+}
+
+static gint
+slide_expired (gpointer data)
+{
+ HildonIMOneHandFKB *self = HILDON_IM_ONEHAND_FKB (data);
+ HildonIMOneHandFKBPrivate *priv;
+ priv = HILDON_IM_ONEHAND_FKB_GET_PRIVATE (self);
+
+ priv->replace_previous_char = FALSE;
+ priv->slide_index = -1;
+ priv->repeating_key = NULL;
+
+ return FALSE;
+}
+
+static void
+sliding_key_pressed_cb (GtkWidget *key, gpointer data)
+{
+ const gchar *key_value = NULL;
+ gchar *sub_str = NULL;
+ gint nr_values = 1;
+ gboolean is_slide_key = TRUE;
+ gboolean caps_on = FALSE;
+ HildonIMOneHandFKB *self = HILDON_IM_ONEHAND_FKB (data);
+ HildonIMOneHandFKBPrivate *priv;
+ priv = HILDON_IM_ONEHAND_FKB_GET_PRIVATE (self);
+
+ caps_on = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->caps_button));
+
+ key_value = g_object_get_data (G_OBJECT (key), "key_values");
+ nr_values = g_utf8_strlen (key_value, -1);
+
+ if (nr_values <= 1)
+ {
+ is_slide_key = FALSE;
+ }
+
+ clear_timeout_id (self);
+
+ if (is_slide_key)
+ {
+ if (priv->repeating_key == key)
+ {
+ priv->slide_index++;
+ }
+ else
+ {
+ priv->slide_index = 0;
+ }
+
+ if (priv->slide_index >= nr_values)
+ {
+ priv->slide_index = 0;
+ }
+
+ sub_str = g_utf8_offset_to_pointer (key_value, priv->slide_index);
+ key_value = g_strdup (get_first_char (sub_str));
+
+ if (key_value == NULL)
+ return;
+
+ if (priv->replace_previous_char && priv->repeating_key == key)
+ {
+ backspace (self);
+ }
+
+ priv->timeout_id = g_timeout_add (SLIDING_TIMEOUT, slide_expired, self);
+ priv->replace_previous_char = TRUE;
+ }
+
+ priv->repeating_key = key;
+ write (self, caps_on ? g_utf8_strup (key_value, -1) : key_value);
+}
+
+static GtkWidget *
+create_sliding_key (HildonIMOneHandFKB *self, gchar *title, gchar *key_values, gint visible_offset)
+{
+ gchar *label = key_values;
+ GtkWidget *key = hildon_button_new (HILDON_SIZE_THUMB_HEIGHT,
+ HILDON_BUTTON_ARRANGEMENT_VERTICAL);
+
+ g_object_set_data (G_OBJECT (key), "key_values", key_values);
+
+ if (visible_offset > 0)
+ {
+ gint byte_count = g_utf8_offset_to_pointer (key_values, visible_offset) - key_values;
+ label = g_strndup (key_values, byte_count);
+ }
+
+ hildon_button_set_value (HILDON_BUTTON (key), label);
+ hildon_button_set_title (HILDON_BUTTON (key), title);
+
+ g_signal_connect (key,
+ "clicked",
+ G_CALLBACK (sliding_key_pressed_cb),
+ self);
+
+ return key;
+}
+
+static void
+unparent_contents (HildonIMOneHandFKB *self)
+{
+ GtkWidget *container;
+ HildonIMOneHandFKBPrivate *priv;
+ priv = HILDON_IM_ONEHAND_FKB_GET_PRIVATE (self);
+
+ container = gtk_bin_get_child (GTK_BIN (priv->window));
+
+ if (!GTK_IS_WIDGET (container))
+ {
+ return;
+ }
+
+ g_object_ref (priv->text_view);
+ g_object_ref (priv->keyboard);
+
+ gtk_container_remove (GTK_CONTAINER (container), priv->text_view);
+ gtk_container_remove (GTK_CONTAINER (container), priv->keyboard);
+ gtk_container_remove (GTK_CONTAINER (priv->window), container);
+}
+
+static void
+set_kb_mode (HildonIMOneHandFKB *self, ScreenMode mode)
+{
+ GtkWidget *container;
+ HildonIMOneHandFKBPrivate *priv;
+ priv = HILDON_IM_ONEHAND_FKB_GET_PRIVATE (self);
+
+ unparent_contents (self);
+
+ if (mode == LANDSCAPE)
+ {
+ container = gtk_hbox_new (FALSE, 0);
+ gtk_widget_set_size_request (priv->text_view, priv->fkb_width / 2, -1);
+ gtk_widget_set_size_request (priv->keyboard, priv->fkb_width / 2, -1);
+ }
+ else
+ {
+ container = gtk_vbox_new (FALSE, 0);
+ gtk_widget_set_size_request (priv->text_view, -1, priv->fkb_height / 2);
+ gtk_widget_set_size_request (priv->keyboard, -1, priv->fkb_height / 2);
+ }
+
+ gtk_container_add (GTK_CONTAINER (container), priv->text_view);
+ gtk_container_add (GTK_CONTAINER (container), priv->keyboard);
+
+ if (mode == LANDSCAPE)
+ {
+ gtk_widget_set_size_request (priv->text_view, priv->fkb_width / 2, -1);
+ }
+ else
+ {
+ gtk_widget_set_size_request (priv->text_view, -1, priv->fkb_height / 2);
+ }
+
+ gtk_container_add (GTK_CONTAINER (priv->window), container);
+
+ gtk_widget_show_all (container);
+}
+
+static GtkWidget *
+create_sliding_keyboard (HildonIMOneHandFKB *self, gchar **keys)
+{
+ HildonIMOneHandFKBPrivate *priv;
+ GtkWidget *image;
+ GtkWidget *key;
+ priv = HILDON_IM_ONEHAND_FKB_GET_PRIVATE(self);
+ GtkSizeGroup *group = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);
+ GtkWidget *contents = gtk_vbox_new (FALSE, 0);
+ GtkWidget *row = gtk_hbox_new (FALSE, 0);
+
+ key = create_special_key (self,
+ HILDON_SIZE_THUMB_HEIGHT,
+ "keyboard_close",
+ G_CALLBACK (close_fkb_cb));
+
+ gtk_size_group_add_widget (group, key);
+
+ gtk_box_pack_start (GTK_BOX (row), key, TRUE, TRUE, 0);
+
+ priv->caps_button = hildon_gtk_toggle_button_new (HILDON_SIZE_THUMB_HEIGHT);
+ image = gtk_image_new_from_icon_name ("keyboard_move_up", -1);
+ gtk_container_add (GTK_CONTAINER (priv->caps_button), image);
+
+ gtk_size_group_add_widget (group, priv->caps_button);
+
+ gtk_box_pack_start (GTK_BOX (row), priv->caps_button, TRUE, TRUE, 0);
+
+ key = create_special_key (self,
+ HILDON_SIZE_THUMB_HEIGHT,
+ "keyboard_backspace",
+ G_CALLBACK (backspace_pressed_cb));
+
+ gtk_size_group_add_widget (group, key);
+
+ gtk_box_pack_start (GTK_BOX (row), key, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (contents), row, TRUE, TRUE, 0);
+
+ row = gtk_hbox_new (FALSE, 0);
+ gint num_keys = G_N_ELEMENTS (sliding_keys);
+ gint i;
+ for (i = 0; i < num_keys; i++)
+ {
+ gint visible_offset = i == 6 || i == 8 || i == 0? 4 : 3;
+ gchar *title = g_strdup_printf ("%d", i + 1);
+ key = create_sliding_key (self, title, keys[i], visible_offset);
+ gtk_size_group_add_widget (group, key);
+ gtk_box_pack_start (GTK_BOX (row), key, TRUE, TRUE, 0);
+
+ if ((i+1) % 3 == 0)
+ {
+ gtk_box_pack_start (GTK_BOX (contents), row, TRUE, TRUE, 0);
+ row = gtk_hbox_new (FALSE, 0);
+ }
+ }
+
+ key = create_sliding_key (self, NULL, "#*+@", 4);
+ gtk_size_group_add_widget (group, key);
+ gtk_box_pack_start (GTK_BOX (row), key, TRUE, TRUE, 0);
+
+ key = create_sliding_key (self, "0", " 0", 1);
+ gtk_size_group_add_widget (group, key);
+ gtk_box_pack_start (GTK_BOX (row), key, TRUE, TRUE, 0);
+
+ key = create_special_key (self,
+ HILDON_SIZE_THUMB_HEIGHT,
+ "keyboard_enter",
+ G_CALLBACK (enter_key_pressed_cb));
+ gtk_size_group_add_widget (group, key);
+
+ gtk_box_pack_start (GTK_BOX (row), key, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (contents), row, TRUE, TRUE, 0);
+
+ return contents;
+}
+
+static void
+create_window (HildonIMOneHandFKB *self)
+{
+ HildonIMOneHandFKBPrivate *priv;
+ priv = HILDON_IM_ONEHAND_FKB_GET_PRIVATE(self);
+
+ priv->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_type_hint (GTK_WINDOW (priv->window), GDK_WINDOW_TYPE_HINT_DIALOG);
+ gtk_window_set_decorated (GTK_WINDOW (priv->window), FALSE);
+ gtk_window_fullscreen (GTK_WINDOW (priv->window));
+ hildon_gtk_window_set_portrait_flags (GTK_WINDOW (priv->window),
+ priv->screen_mode == PORTRAIT ?
+ HILDON_PORTRAIT_MODE_REQUEST :
+ HILDON_PORTRAIT_MODE_SUPPORT);
+
+ priv->text_view = gtk_text_view_new ();
+ gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->text_view), GTK_WRAP_WORD_CHAR);
+ gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (priv->text_view), TRUE);
+ gtk_widget_set_name (priv->text_view, "him-textview");
+ g_signal_connect (priv->text_view,
+ "button-press-event",
+ G_CALLBACK (textview_button_press_cb),
+ self);
+
+ priv->keyboard = create_sliding_keyboard (self, sliding_keys);
+
+ set_kb_mode (self, priv->screen_mode);
+}

_______________________________________________
maemo-commits mailing list
maemo-commits@maemo.org
https://lists.maemo.org/mailman/listinfo/maemo-commits