Use GtkIMContext instead of ClutterIMContext
Add StIMText, which is a drop-in replacement for ClutterIMText but uses GtkIMContext instead of ClutterIMContext. StIMText doesn't have preedit support (would need ClutterText changes), so isn't going to be useful for complicated input methods, but is good enough to get dead keys and similar working. entry.js: Simple test case of StEntry gnome-shell.modules: Remove clutter-imcontext module https://bugzilla.gnome.org/show_bug.cgi?id=597471
This commit is contained in:
parent
4bdd40911f
commit
53fbabe2ca
@ -57,7 +57,7 @@ PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-unix-2.0 gtk+-2.0 dbus-glib-1 mutter-plugin
|
|||||||
gnome-desktop-2.0 >= 2.26 libstartup-notification-1.0
|
gnome-desktop-2.0 >= 2.26 libstartup-notification-1.0
|
||||||
gobject-introspection-1.0 >= 0.6.5)
|
gobject-introspection-1.0 >= 0.6.5)
|
||||||
PKG_CHECK_MODULES(TIDY, clutter-1.0)
|
PKG_CHECK_MODULES(TIDY, clutter-1.0)
|
||||||
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-2.0 clutter-imcontext-0.1 libcroco-0.6)
|
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-2.0 libcroco-0.6)
|
||||||
PKG_CHECK_MODULES(BIG, clutter-1.0 gtk+-2.0 librsvg-2.0)
|
PKG_CHECK_MODULES(BIG, clutter-1.0 gtk+-2.0 librsvg-2.0)
|
||||||
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-2.0)
|
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-2.0)
|
||||||
PKG_CHECK_MODULES(TRAY, gtk+-2.0)
|
PKG_CHECK_MODULES(TRAY, gtk+-2.0)
|
||||||
|
@ -74,6 +74,7 @@ st_source_h = \
|
|||||||
st/st-button.h \
|
st/st-button.h \
|
||||||
st/st-clipboard.h \
|
st/st-clipboard.h \
|
||||||
st/st-entry.h \
|
st/st-entry.h \
|
||||||
|
st/st-im-text.h \
|
||||||
st/st-label.h \
|
st/st-label.h \
|
||||||
st/st-private.h \
|
st/st-private.h \
|
||||||
st/st-scrollable.h \
|
st/st-scrollable.h \
|
||||||
@ -109,6 +110,7 @@ st_source_c = \
|
|||||||
st/st-button.c \
|
st/st-button.c \
|
||||||
st/st-clipboard.c \
|
st/st-clipboard.c \
|
||||||
st/st-entry.c \
|
st/st-entry.c \
|
||||||
|
st/st-im-text.c \
|
||||||
st/st-label.c \
|
st/st-label.c \
|
||||||
st/st-private.c \
|
st/st-private.c \
|
||||||
st/st-scrollable.c \
|
st/st-scrollable.c \
|
||||||
|
@ -53,10 +53,10 @@
|
|||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
#include <clutter-imcontext/clutter-imtext.h>
|
|
||||||
|
|
||||||
#include "st-entry.h"
|
#include "st-entry.h"
|
||||||
|
|
||||||
|
#include "st-im-text.h"
|
||||||
#include "st-widget.h"
|
#include "st-widget.h"
|
||||||
#include "st-texture-cache.h"
|
#include "st-texture-cache.h"
|
||||||
#include "st-marshal.h"
|
#include "st-marshal.h"
|
||||||
@ -645,7 +645,7 @@ st_entry_init (StEntry *entry)
|
|||||||
|
|
||||||
priv = entry->priv = ST_ENTRY_GET_PRIVATE (entry);
|
priv = entry->priv = ST_ENTRY_GET_PRIVATE (entry);
|
||||||
|
|
||||||
priv->entry = g_object_new (CLUTTER_TYPE_IMTEXT,
|
priv->entry = g_object_new (ST_TYPE_IM_TEXT,
|
||||||
"line-alignment", PANGO_ALIGN_LEFT,
|
"line-alignment", PANGO_ALIGN_LEFT,
|
||||||
"editable", TRUE,
|
"editable", TRUE,
|
||||||
"reactive", TRUE,
|
"reactive", TRUE,
|
||||||
|
477
src/st/st-im-text.c
Normal file
477
src/st/st-im-text.c
Normal file
@ -0,0 +1,477 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
/*
|
||||||
|
* st-im-text.c
|
||||||
|
*
|
||||||
|
* This started as a copy of ClutterIMText converted to use
|
||||||
|
* GtkIMContext rather than ClutterIMContext. Original code:
|
||||||
|
*
|
||||||
|
* Author: raymond liu <raymond.liu@intel.com>
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009, Intel Corporation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* 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 St, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:StIMText
|
||||||
|
* @short_description: Text widget with input method support
|
||||||
|
* @stability: Unstable
|
||||||
|
* @see_also: #ClutterText
|
||||||
|
* @include: st-imtext/st-imtext.h
|
||||||
|
*
|
||||||
|
* #StIMText derives from ClutterText and hooks up better text input
|
||||||
|
* via #GtkIMContext. It is meant to be a drop-in replacement for
|
||||||
|
* ClutterIMText but using GtkIMContext rather than ClutterIMContext.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Places where this actor doesn't support all of GtkIMContext:
|
||||||
|
*
|
||||||
|
* A) It doesn't support preedit. This makes it fairly useless for
|
||||||
|
* most complicated input methods. Fixing this requires support
|
||||||
|
* directly in ClutterText, since there is no way to wedge a
|
||||||
|
* preedit string in externally.
|
||||||
|
* B) It doesn't support surrounding context via the
|
||||||
|
* :retrieve-surrounding and :delete-surrounding signals. This could
|
||||||
|
* be added here, but only affects a small number of input methods
|
||||||
|
* and really doesn't make a lot of sense without A)
|
||||||
|
*
|
||||||
|
* Another problem that will show up with usage in GNOME Shell's overview
|
||||||
|
* is that the user may have trouble seeing and interacting with ancilliary
|
||||||
|
* windows shown by the IM.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
#include <clutter/x11/clutter-x11.h>
|
||||||
|
#include <glib.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <gdk/gdkkeysyms.h>
|
||||||
|
#include <X11/extensions/XKB.h>
|
||||||
|
|
||||||
|
#include "st-im-text.h"
|
||||||
|
|
||||||
|
#define ST_IM_TEXT_GET_PRIVATE(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), ST_TYPE_IM_TEXT, StIMTextPrivate))
|
||||||
|
|
||||||
|
struct _StIMTextPrivate
|
||||||
|
{
|
||||||
|
GtkIMContext *im_context;
|
||||||
|
GdkWindow *window;
|
||||||
|
|
||||||
|
guint need_im_reset : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void st_im_text_commit_cb (GtkIMContext *context,
|
||||||
|
const gchar *str,
|
||||||
|
StIMText *imtext);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (StIMText, st_im_text, CLUTTER_TYPE_TEXT)
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_im_text_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
StIMTextPrivate *priv = ST_IM_TEXT (object)->priv;
|
||||||
|
|
||||||
|
g_signal_handlers_disconnect_by_func (priv->im_context,
|
||||||
|
(void *) st_im_text_commit_cb,
|
||||||
|
object);
|
||||||
|
|
||||||
|
g_object_unref (priv->im_context);
|
||||||
|
priv->im_context = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_im_cursor_location (StIMText *self)
|
||||||
|
{
|
||||||
|
StIMTextPrivate *priv = self->priv;
|
||||||
|
ClutterText *clutter_text = CLUTTER_TEXT (self);
|
||||||
|
ClutterActor *parent;
|
||||||
|
gint position;
|
||||||
|
gfloat cursor_x, cursor_y, cursor_height;
|
||||||
|
gfloat actor_x, actor_y;
|
||||||
|
GdkRectangle area;
|
||||||
|
|
||||||
|
position = clutter_text_get_cursor_position (clutter_text);
|
||||||
|
clutter_text_position_to_coords (clutter_text, position,
|
||||||
|
&cursor_x, &cursor_y, &cursor_height);
|
||||||
|
|
||||||
|
/* This is a workaround for a bug in Clutter where
|
||||||
|
* clutter_actor_get_transformed_position doesn't work during
|
||||||
|
* clutter_actor_paint() because the actor has already set up
|
||||||
|
* a model-view matrix.
|
||||||
|
*
|
||||||
|
* http://bugzilla.openedhand.com/show_bug.cgi?id=1115
|
||||||
|
*/
|
||||||
|
actor_x = actor_y = 0.;
|
||||||
|
parent = CLUTTER_ACTOR (self);
|
||||||
|
while (parent)
|
||||||
|
{
|
||||||
|
gfloat x, y;
|
||||||
|
|
||||||
|
clutter_actor_get_position (parent, &x, &y);
|
||||||
|
actor_x += x;
|
||||||
|
actor_y += y;
|
||||||
|
|
||||||
|
parent = clutter_actor_get_parent (parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
area.x = (int)(0.5 + cursor_x + actor_x);
|
||||||
|
area.y = (int)(0.5 + cursor_y + actor_y);
|
||||||
|
area.width = 0;
|
||||||
|
area.height = (int)(0.5 + cursor_height);
|
||||||
|
|
||||||
|
gtk_im_context_set_cursor_location (priv->im_context, &area);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_im_text_commit_cb (GtkIMContext *context,
|
||||||
|
const gchar *str,
|
||||||
|
StIMText *imtext)
|
||||||
|
{
|
||||||
|
ClutterText *clutter_text = CLUTTER_TEXT (imtext);
|
||||||
|
|
||||||
|
if (clutter_text_get_editable (clutter_text))
|
||||||
|
{
|
||||||
|
clutter_text_delete_selection (clutter_text);
|
||||||
|
clutter_text_insert_text (clutter_text, str,
|
||||||
|
clutter_text_get_cursor_position (clutter_text));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
reset_im_context (StIMText *self)
|
||||||
|
{
|
||||||
|
StIMTextPrivate *priv = self->priv;
|
||||||
|
|
||||||
|
if (priv->need_im_reset)
|
||||||
|
{
|
||||||
|
gtk_im_context_reset (priv->im_context);
|
||||||
|
priv->need_im_reset = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_im_text_paint (ClutterActor *actor)
|
||||||
|
{
|
||||||
|
StIMText *self = ST_IM_TEXT (actor);
|
||||||
|
ClutterText *clutter_text = CLUTTER_TEXT (actor);
|
||||||
|
|
||||||
|
/* This updates the cursor position as a side-effect */
|
||||||
|
if (CLUTTER_ACTOR_CLASS (st_im_text_parent_class)->paint)
|
||||||
|
CLUTTER_ACTOR_CLASS (st_im_text_parent_class)->paint (actor);
|
||||||
|
|
||||||
|
if (clutter_text_get_editable (clutter_text))
|
||||||
|
update_im_cursor_location (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns a new reference to window */
|
||||||
|
static GdkWindow *
|
||||||
|
window_for_actor (ClutterActor *actor)
|
||||||
|
{
|
||||||
|
GdkDisplay *display = gdk_display_get_default ();
|
||||||
|
ClutterActor *stage;
|
||||||
|
Window xwindow;
|
||||||
|
GdkWindow *window;
|
||||||
|
|
||||||
|
stage = clutter_actor_get_stage (actor);
|
||||||
|
xwindow = clutter_x11_get_stage_window ((ClutterStage *)stage);
|
||||||
|
|
||||||
|
window = gdk_window_lookup_for_display (display, xwindow);
|
||||||
|
if (window)
|
||||||
|
g_object_ref (window);
|
||||||
|
else
|
||||||
|
window = gdk_window_foreign_new_for_display (display, xwindow);
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_im_text_realize (ClutterActor *actor)
|
||||||
|
{
|
||||||
|
StIMTextPrivate *priv = ST_IM_TEXT (actor)->priv;
|
||||||
|
|
||||||
|
priv->window = window_for_actor (actor);
|
||||||
|
gtk_im_context_set_client_window (priv->im_context, priv->window);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_im_text_unrealize (ClutterActor *actor)
|
||||||
|
{
|
||||||
|
StIMText *self = ST_IM_TEXT (actor);
|
||||||
|
StIMTextPrivate *priv = self->priv;
|
||||||
|
|
||||||
|
reset_im_context (self);
|
||||||
|
gtk_im_context_set_client_window (priv->im_context, NULL);
|
||||||
|
g_object_unref (priv->window);
|
||||||
|
priv->window = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
key_is_modifier (guint16 keyval)
|
||||||
|
{
|
||||||
|
/* See gdkkeys-x11.c:_gdk_keymap_key_is_modifier() for how this
|
||||||
|
* really should be implemented */
|
||||||
|
|
||||||
|
switch (keyval)
|
||||||
|
{
|
||||||
|
case GDK_Shift_L:
|
||||||
|
case GDK_Shift_R:
|
||||||
|
case GDK_Control_L:
|
||||||
|
case GDK_Control_R:
|
||||||
|
case GDK_Caps_Lock:
|
||||||
|
case GDK_Shift_Lock:
|
||||||
|
case GDK_Meta_L:
|
||||||
|
case GDK_Meta_R:
|
||||||
|
case GDK_Alt_L:
|
||||||
|
case GDK_Alt_R:
|
||||||
|
case GDK_Super_L:
|
||||||
|
case GDK_Super_R:
|
||||||
|
case GDK_Hyper_L:
|
||||||
|
case GDK_Hyper_R:
|
||||||
|
case GDK_ISO_Lock:
|
||||||
|
case GDK_ISO_Level2_Latch:
|
||||||
|
case GDK_ISO_Level3_Shift:
|
||||||
|
case GDK_ISO_Level3_Latch:
|
||||||
|
case GDK_ISO_Level3_Lock:
|
||||||
|
case GDK_ISO_Level5_Shift:
|
||||||
|
case GDK_ISO_Level5_Latch:
|
||||||
|
case GDK_ISO_Level5_Lock:
|
||||||
|
case GDK_ISO_Group_Shift:
|
||||||
|
case GDK_ISO_Group_Latch:
|
||||||
|
case GDK_ISO_Group_Lock:
|
||||||
|
return TRUE;
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkEventKey *
|
||||||
|
key_event_to_gdk (ClutterKeyEvent *event_clutter)
|
||||||
|
{
|
||||||
|
GdkDisplay *display = gdk_display_get_default ();
|
||||||
|
GdkKeymap *keymap = gdk_keymap_get_for_display (display);
|
||||||
|
GdkEventKey *event_gdk;
|
||||||
|
event_gdk = (GdkEventKey *)gdk_event_new ((event_clutter->type == CLUTTER_KEY_PRESS) ?
|
||||||
|
GDK_KEY_PRESS : GDK_KEY_RELEASE);
|
||||||
|
|
||||||
|
event_gdk->window = window_for_actor ((ClutterActor *)event_clutter->stage);
|
||||||
|
event_gdk->send_event = FALSE;
|
||||||
|
event_gdk->time = event_clutter->time;
|
||||||
|
/* This depends on ClutterModifierType and GdkModifierType being
|
||||||
|
* identical, which they are currently. (They both match the X
|
||||||
|
* modifier state in the low 16-bits and have the same extensions.) */
|
||||||
|
event_gdk->state = event_clutter->modifier_state;
|
||||||
|
event_gdk->keyval = event_clutter->keyval;
|
||||||
|
event_gdk->hardware_keycode = event_clutter->hardware_keycode;
|
||||||
|
/* For non-proper non-XKB support, we'd need a huge cut-and-paste
|
||||||
|
* from gdkkeys-x11.c; this is a macro that just shifts a few bits
|
||||||
|
* out of state, so won't make the situation worse if the server
|
||||||
|
* doesn't support XKB; we'll just end up with group == 0 */
|
||||||
|
event_gdk->group = XkbGroupForCoreState (event_gdk->state);
|
||||||
|
|
||||||
|
gdk_keymap_translate_keyboard_state (keymap, event_gdk->hardware_keycode,
|
||||||
|
event_gdk->state, event_gdk->group,
|
||||||
|
&event_gdk->keyval, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
if (event_clutter->unicode_value)
|
||||||
|
{
|
||||||
|
/* This is not particularly close to what GDK does - event_gdk->string
|
||||||
|
* is supposed to be in the locale encoding, and have control keys
|
||||||
|
* as control characters, etc. See gdkevents-x11.c:translate_key_event().
|
||||||
|
* Hopefully no input method is using event.string.
|
||||||
|
*/
|
||||||
|
char buf[6];
|
||||||
|
|
||||||
|
event_gdk->length = g_unichar_to_utf8 (event_clutter->unicode_value, buf);
|
||||||
|
event_gdk->string = g_strndup (buf, event_gdk->length);
|
||||||
|
}
|
||||||
|
|
||||||
|
event_gdk->is_modifier = key_is_modifier (event_gdk->keyval);
|
||||||
|
|
||||||
|
return event_gdk;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
st_im_text_button_press_event (ClutterActor *actor,
|
||||||
|
ClutterButtonEvent *event)
|
||||||
|
{
|
||||||
|
/* The button press indicates the user moving the cursor, or selecting
|
||||||
|
* etc, so we should abort any current preedit operation. ClutterText
|
||||||
|
* treats all buttons identically, so so do we.
|
||||||
|
*/
|
||||||
|
reset_im_context (ST_IM_TEXT (actor));
|
||||||
|
|
||||||
|
if (CLUTTER_ACTOR_CLASS (st_im_text_parent_class)->button_press_event)
|
||||||
|
return CLUTTER_ACTOR_CLASS (st_im_text_parent_class)->button_press_event (actor, event);
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
st_im_text_key_press_event (ClutterActor *actor,
|
||||||
|
ClutterKeyEvent *event)
|
||||||
|
{
|
||||||
|
StIMText *self = ST_IM_TEXT (actor);
|
||||||
|
StIMTextPrivate *priv = self->priv;
|
||||||
|
ClutterText *clutter_text = CLUTTER_TEXT (actor);
|
||||||
|
gboolean result = FALSE;
|
||||||
|
int old_position;
|
||||||
|
|
||||||
|
if (clutter_text_get_editable (clutter_text))
|
||||||
|
{
|
||||||
|
GdkEventKey *event_gdk = key_event_to_gdk (event);
|
||||||
|
|
||||||
|
if (gtk_im_context_filter_keypress (priv->im_context, event_gdk))
|
||||||
|
{
|
||||||
|
priv->need_im_reset = TRUE;
|
||||||
|
result = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gdk_event_free ((GdkEvent *)event_gdk);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ClutterText:position isn't properly notified, so we have to
|
||||||
|
* check before/after to catch a keypress (like an arrow key)
|
||||||
|
* moving the cursor position, which should reset the IM context.
|
||||||
|
* (Resetting on notify::position would require a sentinel when
|
||||||
|
* committing text)
|
||||||
|
*
|
||||||
|
* http://bugzilla.openedhand.com/show_bug.cgi?id=1830
|
||||||
|
*/
|
||||||
|
old_position = clutter_text_get_cursor_position (clutter_text);
|
||||||
|
|
||||||
|
if (!result &&
|
||||||
|
CLUTTER_ACTOR_CLASS (st_im_text_parent_class)->key_press_event)
|
||||||
|
result = CLUTTER_ACTOR_CLASS (st_im_text_parent_class)->key_press_event (actor, event);
|
||||||
|
|
||||||
|
if (clutter_text_get_cursor_position (clutter_text) != old_position)
|
||||||
|
reset_im_context (self);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
st_im_text_key_release_event (ClutterActor *actor,
|
||||||
|
ClutterKeyEvent *event)
|
||||||
|
{
|
||||||
|
StIMText *self = ST_IM_TEXT (actor);
|
||||||
|
StIMTextPrivate *priv = self->priv;
|
||||||
|
ClutterText *clutter_text = CLUTTER_TEXT (actor);
|
||||||
|
GdkEventKey *event_gdk;
|
||||||
|
gboolean result = FALSE;
|
||||||
|
|
||||||
|
if (clutter_text_get_editable (clutter_text))
|
||||||
|
{
|
||||||
|
event_gdk = key_event_to_gdk (event);
|
||||||
|
|
||||||
|
if (gtk_im_context_filter_keypress (priv->im_context, event_gdk))
|
||||||
|
{
|
||||||
|
priv->need_im_reset = TRUE;
|
||||||
|
result = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gdk_event_free ((GdkEvent *)event_gdk);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result &&
|
||||||
|
CLUTTER_ACTOR_CLASS (st_im_text_parent_class)->key_release_event)
|
||||||
|
result = CLUTTER_ACTOR_CLASS (st_im_text_parent_class)->key_release_event (actor, event);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_im_text_key_focus_in (ClutterActor *actor)
|
||||||
|
{
|
||||||
|
StIMTextPrivate *priv = ST_IM_TEXT (actor)->priv;
|
||||||
|
ClutterText *clutter_text = CLUTTER_TEXT (actor);
|
||||||
|
|
||||||
|
if (clutter_text_get_editable (clutter_text))
|
||||||
|
{
|
||||||
|
priv->need_im_reset = TRUE;
|
||||||
|
gtk_im_context_focus_in (priv->im_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CLUTTER_ACTOR_CLASS (st_im_text_parent_class)->key_focus_in)
|
||||||
|
CLUTTER_ACTOR_CLASS (st_im_text_parent_class)->key_focus_in (actor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_im_text_key_focus_out (ClutterActor *actor)
|
||||||
|
{
|
||||||
|
StIMTextPrivate *priv = ST_IM_TEXT (actor)->priv;
|
||||||
|
ClutterText *clutter_text = CLUTTER_TEXT (actor);
|
||||||
|
|
||||||
|
if (clutter_text_get_editable (clutter_text))
|
||||||
|
{
|
||||||
|
priv->need_im_reset = TRUE;
|
||||||
|
gtk_im_context_focus_out (priv->im_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CLUTTER_ACTOR_CLASS (st_im_text_parent_class)->key_focus_out)
|
||||||
|
CLUTTER_ACTOR_CLASS (st_im_text_parent_class)->key_focus_out (actor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_im_text_class_init (StIMTextClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (StIMTextPrivate));
|
||||||
|
|
||||||
|
object_class->dispose = st_im_text_dispose;
|
||||||
|
|
||||||
|
actor_class->paint = st_im_text_paint;
|
||||||
|
actor_class->realize = st_im_text_realize;
|
||||||
|
actor_class->unrealize = st_im_text_unrealize;
|
||||||
|
|
||||||
|
actor_class->button_press_event = st_im_text_button_press_event;
|
||||||
|
actor_class->key_press_event = st_im_text_key_press_event;
|
||||||
|
actor_class->key_release_event = st_im_text_key_release_event;
|
||||||
|
actor_class->key_focus_in = st_im_text_key_focus_in;
|
||||||
|
actor_class->key_focus_out = st_im_text_key_focus_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_im_text_init (StIMText *self)
|
||||||
|
{
|
||||||
|
StIMTextPrivate *priv;
|
||||||
|
|
||||||
|
self->priv = priv = ST_IM_TEXT_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
priv->im_context = gtk_im_multicontext_new ();
|
||||||
|
g_signal_connect (priv->im_context, "commit",
|
||||||
|
G_CALLBACK (st_im_text_commit_cb), self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_im_text_new:
|
||||||
|
* @text: text to set to
|
||||||
|
*
|
||||||
|
* Create a new #StIMText with the specified text
|
||||||
|
*
|
||||||
|
* Returns: a new #ClutterActor
|
||||||
|
*/
|
||||||
|
ClutterActor *
|
||||||
|
st_im_text_new (const gchar *text)
|
||||||
|
{
|
||||||
|
return g_object_new (ST_TYPE_IM_TEXT,
|
||||||
|
"text", text,
|
||||||
|
NULL);
|
||||||
|
}
|
69
src/st/st-im-text.h
Normal file
69
src/st/st-im-text.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
/*
|
||||||
|
* st-imtext.h
|
||||||
|
*
|
||||||
|
* This is a copy of ClutterIMText converted to use GtkIMContext rather
|
||||||
|
* than ClutterIMContext. Original code:
|
||||||
|
*
|
||||||
|
* Author: raymond liu <raymond.liu@intel.com>
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009, Intel Corporation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* version 2.1 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* 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 St, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(ST_H_INSIDE) && !defined(ST_COMPILATION)
|
||||||
|
#error "Only <st/st.h> can be included directly.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __ST_IM_TEXT_H__
|
||||||
|
#define __ST_IM_TEXT_H__
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
|
#define ST_TYPE_IM_TEXT (st_im_text_get_type ())
|
||||||
|
#define ST_IM_TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_IM_TEXT, StIMText))
|
||||||
|
#define ST_IS_IM_TEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_IM_TEXT))
|
||||||
|
#define ST_IM_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_IM_TEXT, StIMTextClass))
|
||||||
|
#define ST_IS_IM_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_IM_TEXT))
|
||||||
|
#define ST_IM_TEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_IM_TEXT, StIMTextClass))
|
||||||
|
|
||||||
|
typedef struct _StIMText StIMText;
|
||||||
|
typedef struct _StIMTextPrivate StIMTextPrivate;
|
||||||
|
typedef struct _StIMTextClass StIMTextClass;
|
||||||
|
|
||||||
|
struct _StIMText
|
||||||
|
{
|
||||||
|
ClutterText parent_instance;
|
||||||
|
|
||||||
|
StIMTextPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _StIMTextClass
|
||||||
|
{
|
||||||
|
ClutterTextClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType st_im_text_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
ClutterActor *st_im_text_new (const gchar *text);
|
||||||
|
void st_im_text_set_autoshow_im (StIMText *self,
|
||||||
|
gboolean autoshow);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __ST_IM_TEXT_H__ */
|
@ -6,6 +6,7 @@ TEST_JS = \
|
|||||||
interactive/box-layout.js \
|
interactive/box-layout.js \
|
||||||
interactive/calendar.js \
|
interactive/calendar.js \
|
||||||
interactive/css-fonts.js \
|
interactive/css-fonts.js \
|
||||||
|
interactive/entry.js \
|
||||||
interactive/inline-style.js \
|
interactive/inline-style.js \
|
||||||
interactive/scrolling.js \
|
interactive/scrolling.js \
|
||||||
interactive/table.js \
|
interactive/table.js \
|
||||||
|
32
tests/interactive/entry.js
Normal file
32
tests/interactive/entry.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const Gtk = imports.gi.Gtk;
|
||||||
|
const Lang = imports.lang;
|
||||||
|
const St = imports.gi.St;
|
||||||
|
|
||||||
|
const Calendar = imports.ui.calendar;
|
||||||
|
const UI = imports.testcommon.ui;
|
||||||
|
|
||||||
|
Gtk.init(null, null);
|
||||||
|
|
||||||
|
UI.init();
|
||||||
|
let stage = Clutter.Stage.get_default();
|
||||||
|
stage.width = stage.height = 400;
|
||||||
|
stage.show();
|
||||||
|
|
||||||
|
let vbox = new St.BoxLayout({ vertical: true,
|
||||||
|
width: stage.width,
|
||||||
|
height: stage.height,
|
||||||
|
style: 'padding: 10px; spacing: 10px; font: 15px sans-serif;' });
|
||||||
|
stage.add_actor(vbox);
|
||||||
|
|
||||||
|
let entry = new St.Entry({ style: 'border: 1px solid black;' });
|
||||||
|
vbox.add(entry,
|
||||||
|
{ expand: true,
|
||||||
|
y_fill: false, y_align: St.Align.MIDDLE });
|
||||||
|
entry.grab_key_focus();
|
||||||
|
|
||||||
|
stage.show();
|
||||||
|
Clutter.main();
|
||||||
|
stage.destroy();
|
@ -39,13 +39,6 @@
|
|||||||
</dependencies>
|
</dependencies>
|
||||||
</autotools>
|
</autotools>
|
||||||
|
|
||||||
<autotools id="clutter-imcontext">
|
|
||||||
<branch repo="git.moblin.org" module="clutter-imcontext"/>
|
|
||||||
<dependencies>
|
|
||||||
<dep package="clutter"/>
|
|
||||||
</dependencies>
|
|
||||||
</autotools>
|
|
||||||
|
|
||||||
<autotools id="gconf" autogenargs="--disable-defaults-service">
|
<autotools id="gconf" autogenargs="--disable-defaults-service">
|
||||||
<branch repo="git.gnome.org" module="gconf"/>
|
<branch repo="git.gnome.org" module="gconf"/>
|
||||||
</autotools>
|
</autotools>
|
||||||
@ -62,7 +55,6 @@
|
|||||||
<autotools id="gnome-shell">
|
<autotools id="gnome-shell">
|
||||||
<branch repo="git.gnome.org" module="gnome-shell"/>
|
<branch repo="git.gnome.org" module="gnome-shell"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dep package="clutter-imcontext"/>
|
|
||||||
<dep package="gobject-introspection"/>
|
<dep package="gobject-introspection"/>
|
||||||
<dep package="gir-repository"/>
|
<dep package="gir-repository"/>
|
||||||
<dep package="mutter"/>
|
<dep package="mutter"/>
|
||||||
|
Loading…
Reference in New Issue
Block a user