Compare commits
20 Commits
eekboard-0
...
eekboard-0
| Author | SHA1 | Date | |
|---|---|---|---|
| 551fb17e02 | |||
| b5b9864033 | |||
| a2d2ef3a5e | |||
| b09a586357 | |||
| 70f3bc5308 | |||
| 8bc7b754bc | |||
| 3d5160455a | |||
| 983cc22761 | |||
| 6d80e4cacb | |||
| 1c5a271177 | |||
| e4891ccf6b | |||
| 48bfc7485f | |||
| 2e297ab1ef | |||
| 828fc553b4 | |||
| 08e1a6c69a | |||
| 039ea44520 | |||
| 65c1abbe27 | |||
| 0ab5a0f114 | |||
| 94219bd31e | |||
| 7c2457e659 |
@ -18,4 +18,5 @@
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
SUBDIRS = eek src tests bindings docs po
|
||||
DISTCHECK_CONFIGURE_FLAGS = --enable-introspection
|
||||
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc --enable-introspection
|
||||
EXTRA_DIST = eekboard-sample.conf
|
||||
|
||||
2
TODO
2
TODO
@ -13,7 +13,5 @@
|
||||
-- Caribou layout engine (XML)
|
||||
-- matchbox-keyboard layout engine (XML)
|
||||
-- delay initialization of XKB and XKL layouts
|
||||
-- add eek_keyboard_find_by_position(), that takes account of section
|
||||
rotation, in addition to eek_container_find_by_position()
|
||||
-- add mechanism to change appearances (colors?) of UI widgets
|
||||
depending on modifier states
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301 USA
|
||||
|
||||
AC_INIT([eekboard], [0.0.4], [ueno@unixuser.org])
|
||||
AC_INIT([eekboard], [0.0.5], [ueno@unixuser.org])
|
||||
AC_CONFIG_SRCDIR([configure.ac])
|
||||
AC_PREREQ(2.63)
|
||||
AM_INIT_AUTOMAKE
|
||||
@ -35,12 +35,18 @@ PKG_CHECK_MODULES([PANGO], [pango], ,
|
||||
[AC_MSG_ERROR([Pango not found])])
|
||||
PKG_CHECK_MODULES([GTK2], [gtk+-2.0 gdk-2.0], ,
|
||||
[AC_MSG_ERROR([GTK2 not found])])
|
||||
PKG_CHECK_MODULES([GCONF2], [gconf-2.0], ,
|
||||
[AC_MSG_ERROR([GConf not found])])
|
||||
PKG_CHECK_MODULES([XKB], [x11], ,
|
||||
[AC_MSG_ERROR([XKB support not found])])
|
||||
PKG_CHECK_MODULES([LIBXKLAVIER], [libxklavier x11], ,
|
||||
[AC_MSG_ERROR([Libxklavier not found])])
|
||||
PKG_CHECK_MODULES([LIBFAKEKEY], [libfakekey], ,
|
||||
[AC_MSG_ERROR([libfakekey not found])])
|
||||
PKG_CHECK_MODULES([CSPI], [cspi-1.0], ,
|
||||
[AC_MSG_ERROR([AT-SPI C not found])])
|
||||
PKG_CHECK_MODULES([NOTIFY], [libnotify], ,
|
||||
[AC_MSG_ERROR([libnotify not found])])
|
||||
|
||||
AC_MSG_CHECKING([whether you enable Vala language support])
|
||||
AC_ARG_ENABLE(vala,
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
<bookinfo>
|
||||
<title>libeek Reference Manual</title>
|
||||
<releaseinfo>
|
||||
for libeek 0.0.4.
|
||||
for libeek 0.0.5.
|
||||
</releaseinfo>
|
||||
<copyright>
|
||||
<year>2010</year>
|
||||
|
||||
@ -27,68 +27,68 @@ lib_LTLIBRARIES += libeek-clutter.la
|
||||
endif
|
||||
|
||||
libeek_la_SOURCES = \
|
||||
eek-layout.c \
|
||||
eek-layout.h \
|
||||
eek-element.c \
|
||||
eek-element.h \
|
||||
eek-container.c \
|
||||
eek-container.h \
|
||||
eek-keyboard.c \
|
||||
eek-keyboard.h \
|
||||
eek-section.c \
|
||||
eek-section.h \
|
||||
eek-key.c \
|
||||
eek-key.h \
|
||||
eek-types.h \
|
||||
eek-types.c \
|
||||
eek-keysym.h \
|
||||
eek-keysym.c \
|
||||
eek-special-keysym-labels.h \
|
||||
eek-unicode-keysym-labels.h \
|
||||
eek-keyname-keysym-labels.h
|
||||
$(srcdir)/eek-layout.c \
|
||||
$(srcdir)/eek-layout.h \
|
||||
$(srcdir)/eek-element.c \
|
||||
$(srcdir)/eek-element.h \
|
||||
$(srcdir)/eek-container.c \
|
||||
$(srcdir)/eek-container.h \
|
||||
$(srcdir)/eek-keyboard.c \
|
||||
$(srcdir)/eek-keyboard.h \
|
||||
$(srcdir)/eek-section.c \
|
||||
$(srcdir)/eek-section.h \
|
||||
$(srcdir)/eek-key.c \
|
||||
$(srcdir)/eek-key.h \
|
||||
$(srcdir)/eek-types.h \
|
||||
$(srcdir)/eek-types.c \
|
||||
$(srcdir)/eek-keysym.h \
|
||||
$(srcdir)/eek-keysym.c \
|
||||
$(srcdir)/eek-special-keysym-labels.h \
|
||||
$(srcdir)/eek-unicode-keysym-labels.h \
|
||||
$(srcdir)/eek-keyname-keysym-labels.h
|
||||
libeek_la_CFLAGS = $(GOBJECT2_CFLAGS)
|
||||
libeek_la_LIBADD = $(GOBJECT2_LIBS)
|
||||
libeek_la_LIBADD = $(GOBJECT2_LIBS) -lm
|
||||
|
||||
if HAVE_CLUTTER
|
||||
libeek_clutter_la_SOURCES = \
|
||||
eek-clutter-keyboard.c \
|
||||
eek-clutter-keyboard.h \
|
||||
eek-clutter-section.c \
|
||||
eek-clutter-section.h \
|
||||
eek-clutter-key.c \
|
||||
eek-clutter-key.h \
|
||||
eek-clutter-key-actor.c \
|
||||
eek-clutter-key-actor.h \
|
||||
eek-clutter-drawing-context.c \
|
||||
eek-clutter-drawing-context.h \
|
||||
eek-drawing.h \
|
||||
eek-drawing.c \
|
||||
eek-clutter.h
|
||||
$(srcdir)/eek-clutter-keyboard.c \
|
||||
$(srcdir)/eek-clutter-keyboard.h \
|
||||
$(srcdir)/eek-clutter-section.c \
|
||||
$(srcdir)/eek-clutter-section.h \
|
||||
$(srcdir)/eek-clutter-key.c \
|
||||
$(srcdir)/eek-clutter-key.h \
|
||||
$(srcdir)/eek-clutter-key-actor.c \
|
||||
$(srcdir)/eek-clutter-key-actor.h \
|
||||
$(srcdir)/eek-clutter-drawing-context.c \
|
||||
$(srcdir)/eek-clutter-drawing-context.h \
|
||||
$(srcdir)/eek-drawing.h \
|
||||
$(srcdir)/eek-drawing.c \
|
||||
$(srcdir)/eek-clutter.h
|
||||
|
||||
libeek_clutter_la_CFLAGS = $(CLUTTER_CFLAGS) $(CAIRO_LIBS) $(PANGO_LIBS)
|
||||
libeek_clutter_la_LIBADD = libeek.la $(CLUTTER_LIBS) $(CAIRO_LIBS) $(PANGO_LIBS)
|
||||
endif
|
||||
|
||||
libeek_gtk_la_SOURCES = \
|
||||
eek-gtk-keyboard.c \
|
||||
eek-gtk-keyboard.h \
|
||||
eek-drawing.h \
|
||||
eek-drawing.c \
|
||||
eek-gtk.h
|
||||
$(srcdir)/eek-gtk-keyboard.c \
|
||||
$(srcdir)/eek-gtk-keyboard.h \
|
||||
$(srcdir)/eek-drawing.h \
|
||||
$(srcdir)/eek-drawing.c \
|
||||
$(srcdir)/eek-gtk.h
|
||||
|
||||
libeek_gtk_la_CFLAGS = $(GTK2_CFLAGS) $(CAIRO_LIBS) $(PANGO_LIBS)
|
||||
libeek_gtk_la_LIBADD = libeek.la $(GTK2_LIBS) $(CAIRO_LIBS) $(PANGO_LIBS)
|
||||
|
||||
libeek_xkb_la_SOURCES = \
|
||||
eek-xkb-layout.h \
|
||||
eek-xkb-layout.c
|
||||
$(srcdir)/eek-xkb-layout.h \
|
||||
$(srcdir)/eek-xkb-layout.c
|
||||
|
||||
libeek_xkb_la_CFLAGS = $(GTK2_CFLAGS) $(XKB_CFLAGS)
|
||||
libeek_xkb_la_LIBADD = libeek.la $(GTK2_LIBS) $(XKB_LIBS)
|
||||
|
||||
libeek_xkl_la_SOURCES = \
|
||||
eek-xkl-layout.h \
|
||||
eek-xkl-layout.c
|
||||
$(srcdir)/eek-xkl-layout.h \
|
||||
$(srcdir)/eek-xkl-layout.c
|
||||
|
||||
libeek_xkl_la_CFLAGS = $(GTK2_CFLAGS) $(LIBXKLAVIER_CFLAGS)
|
||||
libeek_xkl_la_LIBADD = libeek-xkb.la $(GTK2_LIBS) $(LIBXKLAVIER_LIBS)
|
||||
|
||||
@ -52,6 +52,7 @@ struct _EekClutterKeyActorPrivate
|
||||
EekClutterDrawingContext *context;
|
||||
EekKey *key;
|
||||
ClutterActor *texture;
|
||||
gboolean is_pressed;
|
||||
};
|
||||
|
||||
static ClutterActor *get_texture (EekClutterKeyActor *actor);
|
||||
@ -103,28 +104,6 @@ eek_clutter_key_actor_real_paint (ClutterActor *self)
|
||||
g_object_unref (layout);
|
||||
}
|
||||
|
||||
/* FIXME: This is a workaround for the bug
|
||||
* http://bugzilla.openedhand.com/show_bug.cgi?id=2137 A developer
|
||||
* says this is not a right way to solve the original problem.
|
||||
*/
|
||||
static void
|
||||
eek_clutter_key_actor_real_get_preferred_width (ClutterActor *self,
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p)
|
||||
{
|
||||
PangoLayout *layout;
|
||||
|
||||
/* Draw the label on the key - just to validate the glyph cache. */
|
||||
layout = clutter_actor_create_pango_layout (self, NULL);
|
||||
draw_key_on_layout (EEK_CLUTTER_KEY_ACTOR(self), layout);
|
||||
cogl_pango_ensure_glyph_cache_for_layout (layout);
|
||||
g_object_unref (layout);
|
||||
|
||||
CLUTTER_ACTOR_CLASS (eek_clutter_key_actor_parent_class)->
|
||||
get_preferred_width (self, for_height, min_width_p, natural_width_p);
|
||||
}
|
||||
|
||||
static void
|
||||
eek_clutter_key_actor_real_pressed (EekClutterKeyActor *self)
|
||||
{
|
||||
@ -181,12 +160,6 @@ eek_clutter_key_actor_class_init (EekClutterKeyActorClass *klass)
|
||||
sizeof (EekClutterKeyActorPrivate));
|
||||
|
||||
actor_class->paint = eek_clutter_key_actor_real_paint;
|
||||
/* FIXME: This is a workaround for the bug
|
||||
* http://bugzilla.openedhand.com/show_bug.cgi?id=2137 A developer
|
||||
* says this is not a right way to solve the original problem.
|
||||
*/
|
||||
actor_class->get_preferred_width =
|
||||
eek_clutter_key_actor_real_get_preferred_width;
|
||||
|
||||
gobject_class->dispose = eek_clutter_key_actor_dispose;
|
||||
|
||||
@ -223,8 +196,11 @@ on_button_press_event (ClutterActor *actor,
|
||||
EekClutterKeyActorPrivate *priv =
|
||||
EEK_CLUTTER_KEY_ACTOR_GET_PRIVATE(actor);
|
||||
|
||||
/* priv->key will send back PRESSED event of actor. */
|
||||
g_signal_emit_by_name (priv->key, "pressed");
|
||||
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
|
||||
@ -235,8 +211,27 @@ on_button_release_event (ClutterActor *actor,
|
||||
EekClutterKeyActorPrivate *priv =
|
||||
EEK_CLUTTER_KEY_ACTOR_GET_PRIVATE(actor);
|
||||
|
||||
/* priv->key will send back RELEASED event of actor. */
|
||||
g_signal_emit_by_name (priv->key, "released");
|
||||
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
|
||||
@ -247,12 +242,15 @@ eek_clutter_key_actor_init (EekClutterKeyActor *self)
|
||||
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 *
|
||||
|
||||
@ -231,23 +231,16 @@ eek_container_find (EekContainer *container,
|
||||
user_data);
|
||||
}
|
||||
|
||||
struct _FbpData
|
||||
{
|
||||
EekKey *key;
|
||||
gint x, y;
|
||||
};
|
||||
typedef struct _FbpData FbpData;
|
||||
|
||||
static gint
|
||||
compare_element_by_position (EekElement *element, gpointer user_data)
|
||||
{
|
||||
EekBounds bounds;
|
||||
FbpData *data = user_data;
|
||||
EekPoint *point = user_data;
|
||||
|
||||
eek_element_get_bounds (element, &bounds);
|
||||
if (bounds.x <= data->x && bounds.y <= data->y &&
|
||||
data->x <= (bounds.x + bounds.width) &&
|
||||
data->y <= (bounds.y + bounds.height))
|
||||
if (bounds.x <= point->x && bounds.y <= point->y &&
|
||||
point->x <= (bounds.x + bounds.width) &&
|
||||
point->y <= (bounds.y + bounds.height))
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
@ -258,13 +251,13 @@ eek_container_find_by_position (EekContainer *container,
|
||||
gdouble y)
|
||||
{
|
||||
EekBounds bounds;
|
||||
FbpData data;
|
||||
EekPoint point;
|
||||
|
||||
g_return_val_if_fail (EEK_IS_CONTAINER(container), NULL);
|
||||
eek_element_get_bounds (EEK_ELEMENT(container), &bounds);
|
||||
data.x = x - bounds.x;
|
||||
data.y = y - bounds.y;
|
||||
point.x = x - bounds.x;
|
||||
point.y = y - bounds.y;
|
||||
return eek_container_find (container,
|
||||
compare_element_by_position,
|
||||
&data);
|
||||
&point);
|
||||
}
|
||||
|
||||
@ -59,6 +59,8 @@ struct _EekGtkKeyboardPrivate
|
||||
PangoFontDescription *fonts[EEK_KEYSYM_CATEGORY_LAST];
|
||||
|
||||
gdouble scale;
|
||||
|
||||
EekKey *key;
|
||||
};
|
||||
|
||||
static void prepare_keyboard_pixmap (EekGtkKeyboard *keyboard);
|
||||
@ -155,6 +157,7 @@ eek_gtk_keyboard_init (EekGtkKeyboard *self)
|
||||
g_object_unref);
|
||||
memset (priv->fonts, 0, sizeof priv->fonts);
|
||||
priv->scale = 1.0;
|
||||
priv->key = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,6 +179,9 @@ struct _DrawingContext
|
||||
};
|
||||
typedef struct _DrawingContext DrawingContext;
|
||||
|
||||
static void on_key_pressed (EekKey *key, gpointer user_data);
|
||||
static void on_key_released (EekKey *key, gpointer user_data);
|
||||
|
||||
static void
|
||||
prepare_keyboard_pixmap_key_callback (EekElement *element,
|
||||
gpointer user_data)
|
||||
@ -190,6 +196,11 @@ prepare_keyboard_pixmap_key_callback (EekElement *element,
|
||||
|
||||
eek_element_get_bounds (element, &bounds);
|
||||
|
||||
g_signal_connect (key, "pressed", G_CALLBACK(on_key_pressed),
|
||||
context->keyboard);
|
||||
g_signal_connect (key, "released", G_CALLBACK(on_key_released),
|
||||
context->keyboard);
|
||||
|
||||
outline = eek_key_get_outline (key);
|
||||
texture = g_hash_table_lookup (priv->outline_textures, outline);
|
||||
if (!texture) {
|
||||
@ -411,42 +422,97 @@ key_shrink (EekGtkKeyboard *keyboard, EekKey *key)
|
||||
bounds.height * SCALE * priv->scale);
|
||||
}
|
||||
|
||||
static void
|
||||
on_key_pressed (EekKey *key, gpointer user_data)
|
||||
{
|
||||
EekGtkKeyboard *keyboard = user_data;
|
||||
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(keyboard);
|
||||
|
||||
key_enlarge (EEK_GTK_KEYBOARD(keyboard), key);
|
||||
priv->key = key;
|
||||
}
|
||||
|
||||
static void
|
||||
on_key_released (EekKey *key, gpointer user_data)
|
||||
{
|
||||
EekGtkKeyboard *keyboard = user_data;
|
||||
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(keyboard);
|
||||
|
||||
if (priv->key) {
|
||||
key_shrink (EEK_GTK_KEYBOARD(keyboard), EEK_KEY(priv->key));
|
||||
priv->key = NULL;
|
||||
}
|
||||
key_shrink (EEK_GTK_KEYBOARD(keyboard), key);
|
||||
}
|
||||
|
||||
static void
|
||||
press_key (EekGtkKeyboard *keyboard, EekKey *key)
|
||||
{
|
||||
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(keyboard);
|
||||
if (priv->key != key)
|
||||
g_signal_emit_by_name (key, "pressed", keyboard);
|
||||
}
|
||||
|
||||
static void
|
||||
release_key (EekGtkKeyboard *keyboard)
|
||||
{
|
||||
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(keyboard);
|
||||
|
||||
if (priv->key)
|
||||
g_signal_emit_by_name (priv->key, "released", keyboard);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_key_event (GtkWidget *widget,
|
||||
GdkEventKey *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
EekGtkKeyboard *keyboard = user_data;
|
||||
EekKey *key;
|
||||
|
||||
key = eek_keyboard_find_key_by_keycode (EEK_KEYBOARD(keyboard),
|
||||
event->hardware_keycode);
|
||||
if (!key)
|
||||
return FALSE;
|
||||
switch (event->type) {
|
||||
case GDK_KEY_PRESS:
|
||||
press_key (keyboard, key);
|
||||
return TRUE;
|
||||
case GDK_KEY_RELEASE:
|
||||
release_key (keyboard);
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_button_event (GtkWidget *widget,
|
||||
GdkEventButton *event,
|
||||
gpointer user_data)
|
||||
GdkEventButton *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
EekElement *keyboard = user_data, *section, *key;
|
||||
EekGtkKeyboard *keyboard = EEK_GTK_KEYBOARD(user_data);
|
||||
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(keyboard);
|
||||
EekBounds bounds;
|
||||
EekKey *key;
|
||||
gdouble x, y;
|
||||
|
||||
x = (gdouble)event->x / priv->scale;
|
||||
y = (gdouble)event->y / priv->scale;
|
||||
section = eek_container_find_by_position (EEK_CONTAINER(keyboard), x, y);
|
||||
if (section) {
|
||||
eek_element_get_bounds (keyboard, &bounds);
|
||||
x -= bounds.x;
|
||||
y -= bounds.y;
|
||||
key = eek_container_find_by_position (EEK_CONTAINER(section),
|
||||
x,
|
||||
y);
|
||||
if (key)
|
||||
switch (event->type) {
|
||||
case GDK_BUTTON_PRESS:
|
||||
key_enlarge (EEK_GTK_KEYBOARD(keyboard), EEK_KEY(key));
|
||||
g_signal_emit_by_name (keyboard, "key-pressed", key);
|
||||
return TRUE;
|
||||
case GDK_BUTTON_RELEASE:
|
||||
key_shrink (EEK_GTK_KEYBOARD(keyboard), EEK_KEY(key));
|
||||
g_signal_emit_by_name (keyboard, "key-released", key);
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
key = eek_keyboard_find_key_by_position (EEK_KEYBOARD(keyboard), x, y);
|
||||
if (key)
|
||||
switch (event->type) {
|
||||
case GDK_BUTTON_PRESS:
|
||||
press_key (EEK_GTK_KEYBOARD(keyboard), key);
|
||||
return TRUE;
|
||||
case GDK_BUTTON_RELEASE:
|
||||
release_key (EEK_GTK_KEYBOARD(keyboard));
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_size_allocate (GtkWidget *widget,
|
||||
GtkAllocation *allocation,
|
||||
@ -469,6 +535,7 @@ on_size_allocate (GtkWidget *widget,
|
||||
allocation->width / bounds.width :
|
||||
allocation->height / bounds.height;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
eek_gtk_keyboard_get_widget (EekGtkKeyboard *keyboard)
|
||||
{
|
||||
@ -483,12 +550,17 @@ eek_gtk_keyboard_get_widget (EekGtkKeyboard *keyboard)
|
||||
gtk_widget_set_events (priv->widget,
|
||||
GDK_EXPOSURE_MASK |
|
||||
GDK_KEY_PRESS_MASK |
|
||||
GDK_KEY_RELEASE_MASK |
|
||||
GDK_BUTTON_PRESS_MASK |
|
||||
GDK_BUTTON_RELEASE_MASK);
|
||||
g_signal_connect (priv->widget, "expose_event",
|
||||
G_CALLBACK (on_expose_event), keyboard);
|
||||
g_signal_connect (priv->widget, "size-allocate",
|
||||
G_CALLBACK (on_size_allocate), keyboard);
|
||||
g_signal_connect (priv->widget, "key-press-event",
|
||||
G_CALLBACK (on_key_event), keyboard);
|
||||
g_signal_connect (priv->widget, "key-release-event",
|
||||
G_CALLBACK (on_key_event), keyboard);
|
||||
g_signal_connect (priv->widget, "button-press-event",
|
||||
G_CALLBACK (on_button_event), keyboard);
|
||||
g_signal_connect (priv->widget, "button-release-event",
|
||||
|
||||
@ -484,3 +484,61 @@ eek_keyboard_find_key_by_keycode (EekKeyboard *keyboard,
|
||||
return EEK_KEYBOARD_GET_CLASS(keyboard)->find_key_by_keycode (keyboard,
|
||||
keycode);
|
||||
}
|
||||
|
||||
static gint
|
||||
compare_section_by_position (EekElement *element, gpointer user_data)
|
||||
{
|
||||
EekSection *section = EEK_SECTION(element);
|
||||
EekPoint *point = user_data;
|
||||
gint angle;
|
||||
EekBounds bounds;
|
||||
EekPoint rotated;
|
||||
|
||||
eek_element_get_bounds (element, &bounds);
|
||||
rotated.x = point->x - bounds.x;
|
||||
rotated.y = point->y - bounds.y;
|
||||
angle = eek_section_get_angle (section);
|
||||
eek_point_rotate (&rotated, -angle);
|
||||
|
||||
if (0 <= rotated.x && 0 <= rotated.y &&
|
||||
rotated.x <= bounds.width &&
|
||||
rotated.y <= bounds.height)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static EekSection *
|
||||
eek_keyboard_find_section_by_position (EekKeyboard *keyboard,
|
||||
gdouble x,
|
||||
gdouble y)
|
||||
{
|
||||
EekBounds bounds;
|
||||
EekPoint point;
|
||||
EekElement *element;
|
||||
|
||||
eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
|
||||
point.x = x - bounds.x;
|
||||
point.y = y - bounds.y;
|
||||
element = eek_container_find (EEK_CONTAINER(keyboard),
|
||||
compare_section_by_position,
|
||||
&point);
|
||||
return EEK_SECTION(element);
|
||||
}
|
||||
|
||||
EekKey *
|
||||
eek_keyboard_find_key_by_position (EekKeyboard *keyboard,
|
||||
gdouble x,
|
||||
gdouble y)
|
||||
{
|
||||
EekSection *section;
|
||||
EekBounds bounds;
|
||||
|
||||
section = eek_keyboard_find_section_by_position (keyboard, x, y);
|
||||
if (!section)
|
||||
return NULL;
|
||||
|
||||
eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
|
||||
x -= bounds.x;
|
||||
y -= bounds.y;
|
||||
return eek_section_find_key_by_position (section, x, y);
|
||||
}
|
||||
|
||||
@ -83,22 +83,25 @@ struct _EekKeyboardClass
|
||||
gpointer pdummy[24];
|
||||
};
|
||||
|
||||
GType eek_keyboard_get_type (void) G_GNUC_CONST;
|
||||
GType eek_keyboard_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void eek_keyboard_set_keysym_index (EekKeyboard *keyboard,
|
||||
gint group,
|
||||
gint level);
|
||||
void eek_keyboard_get_keysym_index (EekKeyboard *keyboard,
|
||||
gint *group,
|
||||
gint *level);
|
||||
void eek_keyboard_set_keysym_index (EekKeyboard *keyboard,
|
||||
gint group,
|
||||
gint level);
|
||||
void eek_keyboard_get_keysym_index (EekKeyboard *keyboard,
|
||||
gint *group,
|
||||
gint *level);
|
||||
|
||||
EekSection *eek_keyboard_create_section (EekKeyboard *keyboard);
|
||||
EekSection *eek_keyboard_create_section (EekKeyboard *keyboard);
|
||||
|
||||
void eek_keyboard_set_layout (EekKeyboard *keyboard,
|
||||
EekLayout *layout);
|
||||
void eek_keyboard_realize (EekKeyboard *keyboard);
|
||||
EekKey *eek_keyboard_find_key_by_keycode (EekKeyboard *keyboard,
|
||||
guint keycode);
|
||||
void eek_keyboard_set_layout (EekKeyboard *keyboard,
|
||||
EekLayout *layout);
|
||||
void eek_keyboard_realize (EekKeyboard *keyboard);
|
||||
EekKey *eek_keyboard_find_key_by_keycode (EekKeyboard *keyboard,
|
||||
guint keycode);
|
||||
EekKey *eek_keyboard_find_key_by_position (EekKeyboard *keyboard,
|
||||
gdouble x,
|
||||
gdouble y);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* EEK_KEYBOARD_H */
|
||||
|
||||
@ -438,3 +438,26 @@ eek_section_find_key_by_keycode (EekSection *section,
|
||||
return EEK_SECTION_GET_CLASS(section)->find_key_by_keycode (section,
|
||||
keycode);
|
||||
}
|
||||
|
||||
EekKey *
|
||||
eek_section_find_key_by_position (EekSection *section,
|
||||
gdouble x,
|
||||
gdouble y)
|
||||
{
|
||||
gint angle;
|
||||
EekBounds bounds;
|
||||
EekPoint point;
|
||||
EekElement *key;
|
||||
|
||||
eek_element_get_bounds (EEK_ELEMENT(section), &bounds);
|
||||
point.x = x - bounds.x;
|
||||
point.y = y - bounds.y;
|
||||
angle = eek_section_get_angle (section);
|
||||
eek_point_rotate (&point, -angle);
|
||||
key = eek_container_find_by_position (EEK_CONTAINER(section),
|
||||
point.x + bounds.x,
|
||||
point.y + bounds.y);
|
||||
if (!key)
|
||||
return NULL;
|
||||
return EEK_KEY(key);
|
||||
}
|
||||
|
||||
@ -86,27 +86,30 @@ struct _EekSectionClass
|
||||
gpointer pdummy[24];
|
||||
};
|
||||
|
||||
GType eek_section_get_type (void) G_GNUC_CONST;
|
||||
GType eek_section_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void eek_section_set_angle (EekSection *section,
|
||||
gint angle);
|
||||
gint eek_section_get_angle (EekSection *section);
|
||||
void eek_section_set_angle (EekSection *section,
|
||||
gint angle);
|
||||
gint eek_section_get_angle (EekSection *section);
|
||||
|
||||
gint eek_section_get_n_rows (EekSection *section);
|
||||
void eek_section_add_row (EekSection *section,
|
||||
gint num_columns,
|
||||
EekOrientation orientation);
|
||||
void eek_section_get_row (EekSection *section,
|
||||
gint index,
|
||||
gint *num_columns,
|
||||
EekOrientation *orientation);
|
||||
gint eek_section_get_n_rows (EekSection *section);
|
||||
void eek_section_add_row (EekSection *section,
|
||||
gint num_columns,
|
||||
EekOrientation orientation);
|
||||
void eek_section_get_row (EekSection *section,
|
||||
gint index,
|
||||
gint *num_columns,
|
||||
EekOrientation *orientation);
|
||||
|
||||
EekKey *eek_section_create_key (EekSection *section,
|
||||
gint column,
|
||||
gint row);
|
||||
EekKey *eek_section_create_key (EekSection *section,
|
||||
gint column,
|
||||
gint row);
|
||||
|
||||
EekKey *eek_section_find_key_by_keycode (EekSection *section,
|
||||
guint keycode);
|
||||
EekKey *eek_section_find_key_by_keycode (EekSection *section,
|
||||
guint keycode);
|
||||
EekKey *eek_section_find_key_by_position (EekSection *section,
|
||||
gdouble x,
|
||||
gdouble y);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* EEK_SECTION_H */
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include "eek-types.h"
|
||||
#include <math.h>
|
||||
|
||||
/* EekKeysymMatrix */
|
||||
static EekKeysymMatrix *
|
||||
@ -81,6 +82,18 @@ eek_point_get_type (void)
|
||||
return our_type;
|
||||
}
|
||||
|
||||
void
|
||||
eek_point_rotate (EekPoint *point, gint angle)
|
||||
{
|
||||
gdouble r, phi;
|
||||
|
||||
phi = atan2 (point->y, point->x);
|
||||
r = sqrt (point->x * point->x + point->y * point->y);
|
||||
phi += angle * M_PI / 180;
|
||||
point->x = r * cos (phi);
|
||||
point->y = r * sin (phi);
|
||||
}
|
||||
|
||||
/* EekBounds */
|
||||
static EekBounds *
|
||||
eek_bounds_copy (const EekBounds *bounds)
|
||||
|
||||
@ -80,6 +80,8 @@ typedef struct _EekPoint EekPoint;
|
||||
|
||||
#define EEK_TYPE_POINT (eek_point_get_type ())
|
||||
GType eek_point_get_type (void) G_GNUC_CONST;
|
||||
void eek_point_rotate (EekPoint *point,
|
||||
gint angle);
|
||||
|
||||
/**
|
||||
* EekBounds:
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
#include <X11/XKBlib.h>
|
||||
#include <X11/extensions/XKBgeom.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
@ -613,38 +614,64 @@ eek_xkb_layout_set_names (EekXkbLayout *layout, XkbComponentNamesRec *names)
|
||||
/**
|
||||
* eek_xkb_layout_set_names_full:
|
||||
* @layout: an #EekXkbLayout
|
||||
* @keymap: keymap component name
|
||||
* @keycodes: keycodes component name
|
||||
* @types: types component name
|
||||
* @compat: compat component name
|
||||
* @symbols: symbols component name
|
||||
* @geometry: geometry component name
|
||||
* @Varargs: pairs of component name and value, terminated by -1.
|
||||
*
|
||||
* Set the XKB component names to @layout. This function is merely a
|
||||
* wrapper around eek_xkb_layout_set_names() to avoid passing a
|
||||
* pointer of XkbComponentNamesRec, which is not currently available
|
||||
* in the gobject-introspection repository.
|
||||
*
|
||||
* Available component names are: keymap, keycodes, types, compat,
|
||||
* symbols, geometry.
|
||||
*
|
||||
* Returns: %TRUE if the component name is successfully set, %FALSE otherwise
|
||||
* Since: 0.0.2
|
||||
*/
|
||||
gboolean
|
||||
eek_xkb_layout_set_names_full (EekXkbLayout *layout,
|
||||
const gchar *keymap,
|
||||
const gchar *keycodes,
|
||||
const gchar *types,
|
||||
const gchar *compat,
|
||||
const gchar *symbols,
|
||||
const gchar *geometry)
|
||||
...)
|
||||
{
|
||||
va_list var_args;
|
||||
va_start (var_args, layout);
|
||||
eek_xkb_layout_set_names_full_valist (layout, var_args);
|
||||
va_end (var_args);
|
||||
}
|
||||
|
||||
/**
|
||||
* eek_xkb_layout_set_names_full_valist:
|
||||
* @layout: an #EekXkbLayout
|
||||
* @var_args: <type>va_list</type> of pairs of component name and value.
|
||||
*
|
||||
* See eek_xkb_layout_set_names_full(), this version takes a
|
||||
* <type>va_list</type> for language bindings to use.
|
||||
*
|
||||
* Since: 0.0.5
|
||||
*/
|
||||
gboolean
|
||||
eek_xkb_layout_set_names_full_valist (EekXkbLayout *layout,
|
||||
va_list var_args)
|
||||
{
|
||||
XkbComponentNamesRec names;
|
||||
gchar *name, *value;
|
||||
|
||||
names.keymap = (char *)keymap;
|
||||
names.keycodes = (char *)keycodes;
|
||||
names.types = (char *)types;
|
||||
names.compat = (char *)compat;
|
||||
names.symbols = (char *)symbols;
|
||||
names.geometry = (char *)geometry;
|
||||
memset (&names, 0, sizeof names);
|
||||
name = va_arg (var_args, gchar *);
|
||||
while (name != (gchar *)-1) {
|
||||
value = va_arg (var_args, gchar *);
|
||||
if (g_strcmp0 (name, "keymap") == 0)
|
||||
names.keymap = (char *)value;
|
||||
else if (g_strcmp0 (name, "keycodes") == 0)
|
||||
names.keycodes = (char *)value;
|
||||
else if (g_strcmp0 (name, "types") == 0)
|
||||
names.types = (char *)value;
|
||||
else if (g_strcmp0 (name, "compat") == 0)
|
||||
names.compat = (char *)value;
|
||||
else if (g_strcmp0 (name, "symbols") == 0)
|
||||
names.symbols = (char *)value;
|
||||
else if (g_strcmp0 (name, "geometry") == 0)
|
||||
names.geometry = (char *)value;
|
||||
name = va_arg (var_args, gchar *);
|
||||
}
|
||||
return eek_xkb_layout_set_names (layout, &names);
|
||||
}
|
||||
|
||||
|
||||
@ -63,12 +63,10 @@ gboolean eek_xkb_layout_set_names (EekXkbLayout *layout,
|
||||
|
||||
gboolean eek_xkb_layout_set_names_full
|
||||
(EekXkbLayout *layout,
|
||||
const gchar *keymap,
|
||||
const gchar *keycodes,
|
||||
const gchar *types,
|
||||
const gchar *compat,
|
||||
const gchar *symbols,
|
||||
const gchar *geometry);
|
||||
...);
|
||||
gboolean eek_xkb_layout_set_names_full_valist
|
||||
(EekXkbLayout *layout,
|
||||
va_list var_args);
|
||||
|
||||
gboolean eek_xkb_layout_set_keycodes
|
||||
(EekXkbLayout *layout,
|
||||
|
||||
@ -565,7 +565,7 @@ eek_xkl_layout_get_model (EekXklLayout *layout)
|
||||
EekXklLayoutPrivate *priv = EEK_XKL_LAYOUT_GET_PRIVATE (layout);
|
||||
|
||||
g_return_val_if_fail (priv, NULL);
|
||||
return priv->config->model;
|
||||
return g_strdup (priv->config->model);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -581,7 +581,7 @@ eek_xkl_layout_get_layouts (EekXklLayout *layout)
|
||||
EekXklLayoutPrivate *priv = EEK_XKL_LAYOUT_GET_PRIVATE (layout);
|
||||
|
||||
g_return_val_if_fail (priv, NULL);
|
||||
return priv->config->layouts;
|
||||
return g_strdupv (priv->config->layouts);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -597,7 +597,7 @@ eek_xkl_layout_get_variants (EekXklLayout *layout)
|
||||
EekXklLayoutPrivate *priv = EEK_XKL_LAYOUT_GET_PRIVATE (layout);
|
||||
|
||||
g_return_val_if_fail (priv, NULL);
|
||||
return priv->config->variants;
|
||||
return g_strdupv (priv->config->variants);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -613,7 +613,7 @@ eek_xkl_layout_get_options (EekXklLayout *layout)
|
||||
EekXklLayoutPrivate *priv = EEK_XKL_LAYOUT_GET_PRIVATE (layout);
|
||||
|
||||
g_return_val_if_fail (priv, NULL);
|
||||
return priv->config->options;
|
||||
return g_strdupv (priv->config->options);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
||||
23
eekboard-sample.conf
Normal file
23
eekboard-sample.conf
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<eekboard>
|
||||
<config>
|
||||
<name>Thai Kinesis</name>
|
||||
<model>kinesis</model>
|
||||
<layouts>pc+us+th(pat)</layouts>
|
||||
</config>
|
||||
<config>
|
||||
<name>Tifinagh Typematrix</name>
|
||||
<model>tm2030USB-106</model>
|
||||
<layouts>pc+us+ma(tifinagh-extended-phonetic)</layouts>
|
||||
</config>
|
||||
<config>
|
||||
<name>Indic Bengali Microsoft Natural</name>
|
||||
<model>microsoft</model>
|
||||
<layouts>pc+us+in(ben)</layouts>
|
||||
</config>
|
||||
<config>
|
||||
<name>US Generic 104-key PC</name>
|
||||
<model>pc104</model>
|
||||
<layouts>pc+us</layouts>
|
||||
</config>
|
||||
</eekboard>
|
||||
@ -22,19 +22,25 @@ eekboard_CFLAGS = \
|
||||
-I$(top_srcdir) \
|
||||
$(GOBJECT2_CFLAGS) \
|
||||
$(GTK2_CFLAGS) \
|
||||
$(GCONF2_CFLAGS) \
|
||||
$(XKB_CFLAGS) \
|
||||
$(LIBXKLAVIER_CFLAGS) \
|
||||
$(LIBFAKEKEY_CFLAGS)
|
||||
$(LIBFAKEKEY_CFLAGS) \
|
||||
$(CSPI_CFLAGS) \
|
||||
$(NOTIFY_CFLAGS)
|
||||
|
||||
eekboard_LDFLAGS = \
|
||||
$(top_builddir)/eek/libeek.la \
|
||||
$(top_builddir)/eek/libeek-xkl.la \
|
||||
$(top_builddir)/eek/libeek-gtk.la \
|
||||
$(GOBJECT2_LIBS) \
|
||||
$(GTK2_CFLAGS) \
|
||||
$(GTK2_LIBS) \
|
||||
$(GCONF2_LIBS) \
|
||||
$(XKB_LIBS) \
|
||||
$(LIBXKLAVIER_LIBS) \
|
||||
$(LIBFAKEKEY_LIBS)
|
||||
$(LIBFAKEKEY_LIBS) \
|
||||
$(CSPI_LIBS) \
|
||||
$(NOTIFY_LIBS)
|
||||
|
||||
if HAVE_CLUTTER
|
||||
eekboard_CFLAGS += $(CLUTTER_CFLAGS) $(CLUTTER_GTK_CFLAGS)
|
||||
|
||||
578
src/eekboard.c
578
src/eekboard.c
@ -30,11 +30,11 @@
|
||||
#include <glib/gi18n.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <gconf/gconf-client.h>
|
||||
#include <libxklavier/xklavier.h>
|
||||
#include <fakekey/fakekey.h>
|
||||
#if 0
|
||||
#include <atk/atk.h>
|
||||
#endif
|
||||
#include <cspi/spi.h>
|
||||
#include <libnotify/notify.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@ -76,17 +76,28 @@
|
||||
"You should have received a copy of the GNU General Public License " \
|
||||
"along with this program. If not, see <http://www.gnu.org/licenses/>. " \
|
||||
|
||||
struct _Config {
|
||||
gchar *name;
|
||||
XklConfigRec *rec;
|
||||
};
|
||||
typedef struct _Config Config;
|
||||
|
||||
struct _Eekboard {
|
||||
gboolean use_clutter;
|
||||
gboolean need_swap_event_workaround;
|
||||
gboolean accessibility_enabled;
|
||||
Config **config;
|
||||
gint active_config;
|
||||
Display *display;
|
||||
FakeKey *fakekey;
|
||||
GtkWidget *widget;
|
||||
GConfClient *gconfc;
|
||||
Accessible *acc;
|
||||
GtkWidget *widget, *window, *combo;
|
||||
gint width, height;
|
||||
guint key_event_listener;
|
||||
XklEngine *engine;
|
||||
XklConfigRegistry *registry;
|
||||
GtkUIManager *ui_manager;
|
||||
gulong on_key_pressed_id, on_key_released_id;
|
||||
|
||||
guint countries_merge_id;
|
||||
GtkActionGroup *countries_action_group;
|
||||
@ -142,11 +153,6 @@ static void on_about (GtkAction *action,
|
||||
GtkWidget *window);
|
||||
static void on_quit (GtkAction * action,
|
||||
GtkWidget *window);
|
||||
#if 0
|
||||
static void on_monitor_key_event_toggled
|
||||
(GtkToggleAction *action,
|
||||
GtkWidget *window);
|
||||
#endif
|
||||
static void eekboard_free (Eekboard *eekboard);
|
||||
static GtkWidget *create_widget (Eekboard *eekboard,
|
||||
gint initial_width,
|
||||
@ -166,9 +172,6 @@ static const char ui_description[] =
|
||||
" <menuitem action='Quit'/>"
|
||||
" </menu>"
|
||||
" <menu action='KeyboardMenu'>"
|
||||
#if 0
|
||||
" <menuitem action='MonitorKeyEvent'/>"
|
||||
#endif
|
||||
" <menu action='Country'>"
|
||||
" <placeholder name='CountriesPH'/>"
|
||||
" </menu>"
|
||||
@ -216,13 +219,6 @@ static const GtkActionEntry action_entry[] = {
|
||||
{"About", GTK_STOCK_ABOUT, NULL, NULL, NULL, G_CALLBACK (on_about)}
|
||||
};
|
||||
|
||||
#if 0
|
||||
static const GtkToggleActionEntry toggle_action_entry[] = {
|
||||
{"MonitorKeyEvent", NULL, N_("Monitor Key Typing"), NULL, NULL,
|
||||
G_CALLBACK(on_monitor_key_event_toggled), FALSE}
|
||||
};
|
||||
#endif
|
||||
|
||||
static gchar *opt_model = NULL;
|
||||
static gchar *opt_layouts = NULL;
|
||||
static gchar *opt_options = NULL;
|
||||
@ -230,6 +226,11 @@ static gboolean opt_list_models = FALSE;
|
||||
static gboolean opt_list_layouts = FALSE;
|
||||
static gboolean opt_list_options = FALSE;
|
||||
static gboolean opt_version = FALSE;
|
||||
#if HAVE_CLUTTER_GTK
|
||||
static gchar *opt_toolkit = NULL;
|
||||
#endif
|
||||
static gboolean opt_standalone = FALSE;
|
||||
static gchar *opt_config = NULL;
|
||||
|
||||
static const GOptionEntry options[] = {
|
||||
{"model", 'M', 0, G_OPTION_ARG_STRING, &opt_model,
|
||||
@ -244,6 +245,14 @@ static const GOptionEntry options[] = {
|
||||
N_("List all available keyboard layouts and variants")},
|
||||
{"list-options", 'O', 0, G_OPTION_ARG_NONE, &opt_list_options,
|
||||
N_("List all available keyboard layout options")},
|
||||
#if HAVE_CLUTTER_GTK
|
||||
{"toolkit", 't', 0, G_OPTION_ARG_STRING, &opt_toolkit,
|
||||
N_("Toolkit (\"clutter\" or \"gtk\")")},
|
||||
#endif
|
||||
{"standalone", 's', 0, G_OPTION_ARG_NONE, &opt_standalone,
|
||||
N_("Start as a standalone application")},
|
||||
{"config", 'c', 0, G_OPTION_ARG_STRING, &opt_config,
|
||||
N_("Specify configuration file")},
|
||||
{"version", 'v', 0, G_OPTION_ARG_NONE, &opt_version,
|
||||
N_("Display version")},
|
||||
{NULL}
|
||||
@ -280,32 +289,113 @@ on_quit (GtkAction * action, GtkWidget *window)
|
||||
gtk_main_quit ();
|
||||
}
|
||||
|
||||
#if 0
|
||||
static gint
|
||||
key_snoop (AtkKeyEventStruct *event, gpointer func_data)
|
||||
static void
|
||||
set_location (Eekboard *eekboard,
|
||||
Accessible *acc)
|
||||
{
|
||||
AccessibleComponent *component = Accessible_getComponent (acc);
|
||||
long int x, y, width, height;
|
||||
|
||||
AccessibleComponent_getExtents (component,
|
||||
&x, &y, &width, &height,
|
||||
SPI_COORD_TYPE_SCREEN);
|
||||
gtk_window_move (GTK_WINDOW(eekboard->window), x, y + height);
|
||||
}
|
||||
|
||||
static SPIBoolean
|
||||
a11y_focus_listener (const AccessibleEvent *event,
|
||||
void *user_data)
|
||||
{
|
||||
Eekboard *eekboard = user_data;
|
||||
Accessible *acc = event->source;
|
||||
AccessibleStateSet *state_set = Accessible_getStateSet (acc);
|
||||
AccessibleRole role = Accessible_getRole (acc);
|
||||
|
||||
/* Ignore focus on eekboard itself since eekboard itself has GTK+
|
||||
widgets. */
|
||||
if (gtk_widget_has_focus (eekboard->window))
|
||||
return FALSE;
|
||||
|
||||
/* The logic is borrowed from Caribou. */
|
||||
if (AccessibleStateSet_contains (state_set, SPI_STATE_EDITABLE) ||
|
||||
role == SPI_ROLE_TERMINAL) {
|
||||
switch (role) {
|
||||
case SPI_ROLE_TEXT:
|
||||
case SPI_ROLE_PARAGRAPH:
|
||||
case SPI_ROLE_PASSWORD_TEXT:
|
||||
case SPI_ROLE_TERMINAL:
|
||||
if (strncmp (event->type, "focus", 5) == 0 || event->detail1 == 1) {
|
||||
set_location (eekboard, acc);
|
||||
gtk_widget_show (eekboard->window);
|
||||
eekboard->acc = acc;
|
||||
} else if (event->detail1 == 0 && acc == eekboard->acc) {
|
||||
gtk_widget_hide (eekboard->window);
|
||||
eekboard->acc = NULL;
|
||||
}
|
||||
case SPI_ROLE_ENTRY:
|
||||
if (strncmp (event->type, "focus", 5) == 0 || event->detail1 == 1) {
|
||||
set_location (eekboard, acc);
|
||||
gtk_widget_show (eekboard->window);
|
||||
eekboard->acc = acc;
|
||||
} else if (event->detail1 == 0 && acc == eekboard->acc) {
|
||||
gtk_widget_hide (eekboard->window);
|
||||
eekboard->acc = NULL;
|
||||
}
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_monitor_key_event_toggled (GtkToggleAction *action,
|
||||
GtkWidget *window)
|
||||
static SPIBoolean
|
||||
a11y_keystroke_listener (const AccessibleKeystroke *stroke,
|
||||
void *user_data)
|
||||
{
|
||||
Eekboard *eekboard = user_data;
|
||||
EekKey *key;
|
||||
guint keysym;
|
||||
guint ignored_keysyms[] = {XK_Shift_L,
|
||||
XK_Shift_R,
|
||||
XK_Control_L,
|
||||
XK_Control_R,
|
||||
XK_Alt_L,
|
||||
XK_Alt_R};
|
||||
gint i;
|
||||
|
||||
key = eek_keyboard_find_key_by_keycode (eekboard->keyboard,
|
||||
stroke->keycode);
|
||||
if (!key)
|
||||
return FALSE;
|
||||
|
||||
Eekboard *eekboard = g_object_get_data (G_OBJECT(window), "eekboard");
|
||||
/* XXX: Ignore modifier keys since there is no way to receive
|
||||
SPI_KEY_RELEASED event for them. */
|
||||
keysym = eek_key_get_keysym (key);
|
||||
for (i = 0; i < G_N_ELEMENTS(ignored_keysyms) &&
|
||||
keysym != ignored_keysyms[i]; i++)
|
||||
;
|
||||
if (i != G_N_ELEMENTS(ignored_keysyms))
|
||||
return FALSE;
|
||||
|
||||
if (gtk_toggle_action_get_active (action)) {
|
||||
if (eekboard->key_event_listener == 0)
|
||||
eekboard->key_event_listener =
|
||||
atk_add_key_event_listener (key_snoop, eekboard);
|
||||
g_warning ("failed to enable ATK key event listener");
|
||||
} else
|
||||
if (eekboard->key_event_listener != 0) {
|
||||
atk_remove_key_event_listener (eekboard->key_event_listener);
|
||||
eekboard->key_event_listener = 0;
|
||||
}
|
||||
if (stroke->type == SPI_KEY_PRESSED) {
|
||||
g_signal_handler_block (eekboard->keyboard,
|
||||
eekboard->on_key_pressed_id);
|
||||
g_signal_emit_by_name (key, "pressed");
|
||||
g_signal_handler_unblock (eekboard->keyboard,
|
||||
eekboard->on_key_pressed_id);
|
||||
} else {
|
||||
g_signal_handler_block (eekboard->keyboard,
|
||||
eekboard->on_key_released_id);
|
||||
g_signal_emit_by_name (key, "released");
|
||||
g_signal_handler_unblock (eekboard->keyboard,
|
||||
eekboard->on_key_released_id);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static AccessibleEventListener* focusListener;
|
||||
static AccessibleEventListener* keystrokeListener;
|
||||
|
||||
static void
|
||||
on_key_pressed (EekKeyboard *keyboard,
|
||||
@ -317,6 +407,7 @@ on_key_pressed (EekKeyboard *keyboard,
|
||||
|
||||
keysym = eek_key_get_keysym (key);
|
||||
EEKBOARD_NOTE("%s %X", eek_keysym_to_string (keysym), eekboard->modifiers);
|
||||
|
||||
if (keysym == XK_Shift_L || keysym == XK_Shift_R) {
|
||||
gint group, level;
|
||||
|
||||
@ -861,11 +952,6 @@ create_menus (Eekboard *eekboard,
|
||||
|
||||
gtk_action_group_add_actions (action_group, action_entry,
|
||||
G_N_ELEMENTS (action_entry), window);
|
||||
#if 0
|
||||
gtk_action_group_add_toggle_actions (action_group, toggle_action_entry,
|
||||
G_N_ELEMENTS (toggle_action_entry),
|
||||
window);
|
||||
#endif
|
||||
|
||||
gtk_ui_manager_insert_action_group (eekboard->ui_manager, action_group, 0);
|
||||
gtk_ui_manager_add_ui_from_string (eekboard->ui_manager, ui_description, -1, NULL);
|
||||
@ -910,10 +996,12 @@ create_widget_gtk (Eekboard *eekboard,
|
||||
eekboard->keyboard = eek_gtk_keyboard_new ();
|
||||
eek_keyboard_set_layout (eekboard->keyboard, eekboard->layout);
|
||||
eek_element_set_bounds (EEK_ELEMENT(eekboard->keyboard), &bounds);
|
||||
g_signal_connect (eekboard->keyboard, "key-pressed",
|
||||
G_CALLBACK(on_key_pressed), eekboard);
|
||||
g_signal_connect (eekboard->keyboard, "key-released",
|
||||
G_CALLBACK(on_key_released), eekboard);
|
||||
eekboard->on_key_pressed_id =
|
||||
g_signal_connect (eekboard->keyboard, "key-pressed",
|
||||
G_CALLBACK(on_key_pressed), eekboard);
|
||||
eekboard->on_key_released_id =
|
||||
g_signal_connect (eekboard->keyboard, "key-released",
|
||||
G_CALLBACK(on_key_released), eekboard);
|
||||
|
||||
eekboard->widget =
|
||||
eek_gtk_keyboard_get_widget (EEK_GTK_KEYBOARD (eekboard->keyboard));
|
||||
@ -960,10 +1048,12 @@ create_widget_clutter (Eekboard *eekboard,
|
||||
eekboard->keyboard = eek_clutter_keyboard_new ();
|
||||
eek_keyboard_set_layout (eekboard->keyboard, eekboard->layout);
|
||||
eek_element_set_bounds (EEK_ELEMENT(eekboard->keyboard), &bounds);
|
||||
g_signal_connect (eekboard->keyboard, "key-pressed",
|
||||
G_CALLBACK(on_key_pressed), eekboard);
|
||||
g_signal_connect (eekboard->keyboard, "key-released",
|
||||
G_CALLBACK(on_key_released), eekboard);
|
||||
eekboard->on_key_pressed_id =
|
||||
g_signal_connect (eekboard->keyboard, "key-pressed",
|
||||
G_CALLBACK(on_key_pressed), eekboard);
|
||||
eekboard->on_key_released_id =
|
||||
g_signal_connect (eekboard->keyboard, "key-released",
|
||||
G_CALLBACK(on_key_released), eekboard);
|
||||
|
||||
eekboard->widget = gtk_clutter_embed_new ();
|
||||
#if NEED_SWAP_EVENT_WORKAROUND
|
||||
@ -997,14 +1087,43 @@ create_widget (Eekboard *eekboard,
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
parse_layouts (XklConfigRec *rec, const gchar *_layouts)
|
||||
{
|
||||
gchar **layouts, **variants;
|
||||
gint i;
|
||||
|
||||
layouts = g_strsplit (_layouts, ",", -1);
|
||||
variants = g_strdupv (layouts);
|
||||
for (i = 0; layouts[i]; i++) {
|
||||
gchar *layout = layouts[i], *variant = variants[i],
|
||||
*variant_start, *variant_end;
|
||||
|
||||
variant_start = strchr (layout, '(');
|
||||
variant_end = strrchr (layout, ')');
|
||||
if (variant_start && variant_end) {
|
||||
*variant_start++ = '\0';
|
||||
g_strlcpy (variant, variant_start,
|
||||
variant_end - variant_start + 1);
|
||||
} else
|
||||
*variant = '\0';
|
||||
}
|
||||
rec->layouts = layouts;
|
||||
rec->variants = variants;
|
||||
}
|
||||
|
||||
Eekboard *
|
||||
eekboard_new (gboolean use_clutter, gboolean need_swap_event_workaround)
|
||||
eekboard_new (gboolean use_clutter,
|
||||
gboolean need_swap_event_workaround,
|
||||
gboolean accessibility_enabled)
|
||||
{
|
||||
Eekboard *eekboard;
|
||||
|
||||
eekboard = g_slice_new0 (Eekboard);
|
||||
eekboard->use_clutter = use_clutter;
|
||||
eekboard->need_swap_event_workaround = need_swap_event_workaround;
|
||||
eekboard->accessibility_enabled = accessibility_enabled;
|
||||
eekboard->active_config = -1;
|
||||
eekboard->display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
||||
if (!eekboard->display) {
|
||||
g_slice_free (Eekboard, eekboard);
|
||||
@ -1028,26 +1147,14 @@ eekboard_new (gboolean use_clutter, gboolean need_swap_event_workaround)
|
||||
if (opt_model)
|
||||
eek_xkl_layout_set_model (EEK_XKL_LAYOUT(eekboard->layout), opt_model);
|
||||
if (opt_layouts) {
|
||||
gchar **layouts, **variants;
|
||||
gint i;
|
||||
layouts = g_strsplit (opt_layouts, ",", -1);
|
||||
variants = g_strdupv (layouts);
|
||||
for (i = 0; layouts[i]; i++) {
|
||||
gchar *layout = layouts[i], *variant = variants[i],
|
||||
*variant_start, *variant_end;
|
||||
XklConfigRec *rec = xkl_config_rec_new ();
|
||||
|
||||
variant_start = strchr (layout, '(');
|
||||
variant_end = strrchr (layout, ')');
|
||||
if (variant_start && variant_end) {
|
||||
*variant_start++ = '\0';
|
||||
g_strlcpy (variant, variant_start,
|
||||
variant_end - variant_start + 1);
|
||||
} else
|
||||
*variant = '\0';
|
||||
}
|
||||
eek_xkl_layout_set_layouts (EEK_XKL_LAYOUT(eekboard->layout), layouts);
|
||||
g_strfreev (layouts);
|
||||
g_strfreev (variants);
|
||||
parse_layouts (rec, opt_layouts);
|
||||
eek_xkl_layout_set_layouts (EEK_XKL_LAYOUT(eekboard->layout),
|
||||
rec->layouts);
|
||||
eek_xkl_layout_set_variants (EEK_XKL_LAYOUT(eekboard->layout),
|
||||
rec->variants);
|
||||
g_object_unref (rec);
|
||||
}
|
||||
if (opt_options) {
|
||||
gchar **options;
|
||||
@ -1129,15 +1236,156 @@ print_option_group (XklConfigRegistry *registry,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
on_notify_never_show (NotifyNotification *notification,
|
||||
char *action,
|
||||
gpointer user_data)
|
||||
{
|
||||
Eekboard *eekboard = user_data;
|
||||
GError *error;
|
||||
|
||||
gconf_client_set_bool (eekboard->gconfc,
|
||||
"/apps/eekboard/inhibit-startup-notify",
|
||||
TRUE,
|
||||
&error);
|
||||
}
|
||||
|
||||
static void
|
||||
on_layout_changed (GtkComboBox *combo,
|
||||
gpointer user_data)
|
||||
{
|
||||
Eekboard *eekboard = user_data;
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
gint active;
|
||||
|
||||
model = gtk_combo_box_get_model (combo);
|
||||
gtk_combo_box_get_active_iter (combo, &iter);
|
||||
gtk_tree_model_get (model, &iter, 1, &active, -1);
|
||||
|
||||
if (eekboard->active_config != active) {
|
||||
XklConfigRec *config, *config_base = eekboard->config[active]->rec;
|
||||
|
||||
config = xkl_config_rec_new ();
|
||||
if (config_base->model)
|
||||
config->model = g_strdup (config_base->model);
|
||||
else
|
||||
config->model =
|
||||
eek_xkl_layout_get_model (EEK_XKL_LAYOUT(eekboard->layout));
|
||||
|
||||
if (config_base->layouts)
|
||||
config->layouts = g_strdupv (config_base->layouts);
|
||||
else
|
||||
config->layouts =
|
||||
eek_xkl_layout_get_layouts (EEK_XKL_LAYOUT(eekboard->layout));
|
||||
|
||||
if (config_base->variants)
|
||||
config->variants = g_strdupv (config_base->variants);
|
||||
else
|
||||
config->variants =
|
||||
eek_xkl_layout_get_variants (EEK_XKL_LAYOUT(eekboard->layout));
|
||||
|
||||
if (config_base->options)
|
||||
config->options = g_strdupv (config_base->options);
|
||||
else
|
||||
config->options =
|
||||
eek_xkl_layout_get_options (EEK_XKL_LAYOUT(eekboard->layout));
|
||||
|
||||
eek_xkl_layout_set_config (EEK_XKL_LAYOUT(eekboard->layout), config);
|
||||
g_object_unref (config);
|
||||
|
||||
eekboard->active_config = active;
|
||||
}
|
||||
}
|
||||
|
||||
struct _ConfigContext {
|
||||
GSList *list;
|
||||
GString *text;
|
||||
};
|
||||
typedef struct _ConfigContext ConfigContext;
|
||||
|
||||
static void
|
||||
config_parser_start_element (GMarkupParseContext *pcontext,
|
||||
const gchar *element_name,
|
||||
const gchar **attribute_names,
|
||||
const gchar **attribute_values,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
ConfigContext *context = user_data;
|
||||
if (g_strcmp0 (element_name, "config") == 0) {
|
||||
Config *config = g_slice_new0 (Config);
|
||||
config->rec = xkl_config_rec_new ();
|
||||
context->list = g_slist_prepend (context->list, config);
|
||||
} else
|
||||
context->text = g_string_sized_new (100);
|
||||
}
|
||||
|
||||
static void
|
||||
config_parser_end_element (GMarkupParseContext *pcontext,
|
||||
const gchar *element_name,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
ConfigContext *context = user_data;
|
||||
Config *config = context->list->data;
|
||||
gchar *text;
|
||||
|
||||
if (g_strcmp0 (element_name, "config") == 0 &&
|
||||
!config->name) {
|
||||
if (error)
|
||||
*error = g_error_new (G_MARKUP_ERROR,
|
||||
G_MARKUP_ERROR_INVALID_CONTENT,
|
||||
"\"name\" is missing");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!context->text)
|
||||
return;
|
||||
|
||||
text = g_string_free (context->text, FALSE);
|
||||
context->text = NULL;
|
||||
|
||||
if (g_strcmp0 (element_name, "name") == 0)
|
||||
config->name = text;
|
||||
else if (g_strcmp0 (element_name, "model") == 0)
|
||||
config->rec->model = text;
|
||||
else if (g_strcmp0 (element_name, "layouts") == 0)
|
||||
parse_layouts (config->rec, text);
|
||||
else if (g_strcmp0 (element_name, "options") == 0)
|
||||
config->rec->options = g_strsplit (text, ",", -1);
|
||||
}
|
||||
|
||||
static void
|
||||
config_parser_text (GMarkupParseContext *pcontext,
|
||||
const gchar *text,
|
||||
gsize text_len,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
ConfigContext *context = user_data;
|
||||
if (context->text)
|
||||
context->text = g_string_append_len (context->text, text, text_len);
|
||||
}
|
||||
|
||||
GMarkupParser config_parser = {
|
||||
.start_element = config_parser_start_element,
|
||||
.end_element = config_parser_end_element,
|
||||
.text = config_parser_text
|
||||
};
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
const gchar *env;
|
||||
gboolean use_clutter = USE_CLUTTER;
|
||||
gboolean need_swap_event_workaround = FALSE;
|
||||
gboolean accessibility_enabled = FALSE;
|
||||
Eekboard *eekboard;
|
||||
GtkWidget *widget, *vbox, *menubar, *window;
|
||||
GtkWidget *widget, *vbox, *menubar, *window, *combo = NULL;
|
||||
GOptionContext *context;
|
||||
GConfClient *gconfc;
|
||||
GError *error;
|
||||
|
||||
context = g_option_context_new ("eekboard");
|
||||
g_option_context_add_main_entries (context, options, NULL);
|
||||
@ -1154,11 +1402,36 @@ main (int argc, char *argv[])
|
||||
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
||||
#endif
|
||||
|
||||
error = NULL;
|
||||
gconfc = gconf_client_get_default ();
|
||||
if (gconf_client_get_bool (gconfc,
|
||||
"/desktop/gnome/interface/accessibility",
|
||||
&error) ||
|
||||
gconf_client_get_bool (gconfc,
|
||||
"/desktop/gnome/interface/accessibility2",
|
||||
&error)) {
|
||||
if (SPI_init () == 0)
|
||||
accessibility_enabled = TRUE;
|
||||
else
|
||||
g_warning("AT-SPI initialization failed");
|
||||
}
|
||||
|
||||
env = g_getenv ("EEKBOARD_DISABLE_CLUTTER");
|
||||
if (env && g_strcmp0 (env, "1") == 0)
|
||||
use_clutter = FALSE;
|
||||
|
||||
#if HAVE_CLUTTER_GTK
|
||||
if (opt_toolkit) {
|
||||
if (g_strcmp0 (opt_toolkit, "clutter") == 0)
|
||||
use_clutter = TRUE;
|
||||
else if (g_strcmp0 (opt_toolkit, "gtk") == 0)
|
||||
use_clutter = FALSE;
|
||||
else {
|
||||
g_print ("Invalid toolkit \"%s\"\n", opt_toolkit);
|
||||
exit (0);
|
||||
}
|
||||
}
|
||||
|
||||
if (use_clutter &&
|
||||
gtk_clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) {
|
||||
g_warning ("Can't init Clutter-Gtk...fallback to GTK");
|
||||
@ -1178,7 +1451,9 @@ main (int argc, char *argv[])
|
||||
exit (1);
|
||||
}
|
||||
|
||||
eekboard = eekboard_new (use_clutter, need_swap_event_workaround);
|
||||
eekboard = eekboard_new (use_clutter,
|
||||
need_swap_event_workaround,
|
||||
accessibility_enabled);
|
||||
if (opt_list_models) {
|
||||
xkl_config_registry_foreach_model (eekboard->registry,
|
||||
print_item,
|
||||
@ -1201,7 +1476,64 @@ main (int argc, char *argv[])
|
||||
exit (0);
|
||||
}
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
if (opt_config) {
|
||||
ConfigContext context;
|
||||
GMarkupParseContext *pcontext;
|
||||
GFile *file;
|
||||
GError *error;
|
||||
GFileInputStream *stream;
|
||||
gchar buf[BUFSIZ];
|
||||
GSList *head;
|
||||
gint i;
|
||||
|
||||
memset (&context, 0, sizeof context);
|
||||
file = g_file_new_for_path (opt_config);
|
||||
|
||||
error = NULL;
|
||||
stream = g_file_read (file, NULL, &error);
|
||||
if (!stream) {
|
||||
eekboard_free (eekboard);
|
||||
g_print ("Can't read configuration file: %s\n", opt_config);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pcontext = g_markup_parse_context_new (&config_parser,
|
||||
0,
|
||||
&context,
|
||||
NULL);
|
||||
while (1) {
|
||||
gssize len;
|
||||
|
||||
error = NULL;
|
||||
len = g_input_stream_read (G_INPUT_STREAM(stream),
|
||||
buf, sizeof buf, NULL,
|
||||
&error);
|
||||
if (len <= 0)
|
||||
break;
|
||||
|
||||
error = NULL;
|
||||
if (!g_markup_parse_context_parse (pcontext, buf, len, &error))
|
||||
break;
|
||||
}
|
||||
g_object_unref (stream);
|
||||
|
||||
error = NULL;
|
||||
g_markup_parse_context_end_parse (pcontext, &error);
|
||||
g_markup_parse_context_free (pcontext);
|
||||
g_object_unref (file);
|
||||
|
||||
if (context.list) {
|
||||
eekboard->config =
|
||||
g_slice_alloc0 ((g_slist_length (context.list) + 1) *
|
||||
sizeof (*eekboard->config));
|
||||
for (i = 0, head = context.list; head; head = head->next)
|
||||
eekboard->config[i++] = head->data;
|
||||
}
|
||||
}
|
||||
|
||||
window = gtk_window_new (opt_standalone ?
|
||||
GTK_WINDOW_TOPLEVEL :
|
||||
GTK_WINDOW_POPUP);
|
||||
gtk_widget_set_can_focus (window, FALSE);
|
||||
g_object_set (G_OBJECT(window), "accept_focus", FALSE, NULL);
|
||||
gtk_window_set_title (GTK_WINDOW(window), "Keyboard");
|
||||
@ -1212,10 +1544,37 @@ main (int argc, char *argv[])
|
||||
|
||||
g_object_set_data (G_OBJECT(window), "eekboard", eekboard);
|
||||
widget = create_widget (eekboard, CSW, CSH);
|
||||
|
||||
create_menus (eekboard, window);
|
||||
menubar = gtk_ui_manager_get_widget (eekboard->ui_manager, "/MainMenu");
|
||||
gtk_box_pack_start (GTK_BOX (vbox), menubar, FALSE, FALSE, 0);
|
||||
|
||||
if (opt_standalone) {
|
||||
create_menus (eekboard, window);
|
||||
menubar = gtk_ui_manager_get_widget (eekboard->ui_manager, "/MainMenu");
|
||||
gtk_box_pack_start (GTK_BOX (vbox), menubar, FALSE, FALSE, 0);
|
||||
}
|
||||
|
||||
if (eekboard->config) {
|
||||
GtkListStore *store;
|
||||
GtkTreeIter iter;
|
||||
GtkCellRenderer *renderer;
|
||||
int i;
|
||||
|
||||
store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
|
||||
for (i = 0; eekboard->config[i]; i++) {
|
||||
gtk_list_store_append (store, &iter);
|
||||
gtk_list_store_set (store, &iter,
|
||||
0, eekboard->config[i]->name,
|
||||
1, i,
|
||||
-1);
|
||||
}
|
||||
combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL(store));
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT(combo),
|
||||
renderer, TRUE);
|
||||
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT(combo),
|
||||
renderer, "text", 0, NULL);
|
||||
gtk_box_pack_end (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
|
||||
g_signal_connect (combo, "changed", G_CALLBACK(on_layout_changed),
|
||||
eekboard);
|
||||
}
|
||||
|
||||
gtk_container_add (GTK_CONTAINER(vbox), widget);
|
||||
gtk_container_add (GTK_CONTAINER(window), vbox);
|
||||
@ -1224,6 +1583,69 @@ main (int argc, char *argv[])
|
||||
gtk_widget_show_all (window);
|
||||
gtk_widget_set_size_request (widget, -1, -1);
|
||||
|
||||
notify_init ("eekboard");
|
||||
eekboard->window = window;
|
||||
eekboard->gconfc = gconfc;
|
||||
if (eekboard->accessibility_enabled) {
|
||||
if (!opt_standalone) {
|
||||
NotifyNotification *notification;
|
||||
|
||||
error = NULL;
|
||||
if (!gconf_client_get_bool (eekboard->gconfc,
|
||||
"/apps/eekboard/inhibit-startup-notify",
|
||||
&error)) {
|
||||
notification = notify_notification_new
|
||||
("eekboard started in background",
|
||||
"As GNOME accessibility support enabled, "
|
||||
"eekboard is starting without a window.\n"
|
||||
"To make eekboard show up, click on some window with "
|
||||
"an editable widget.",
|
||||
"keyboard",
|
||||
NULL);
|
||||
notify_notification_add_action
|
||||
(notification,
|
||||
"dont-ask",
|
||||
"Don't show up",
|
||||
NOTIFY_ACTION_CALLBACK(on_notify_never_show),
|
||||
eekboard,
|
||||
NULL);
|
||||
error = NULL;
|
||||
notify_notification_show (notification, &error);
|
||||
}
|
||||
|
||||
gtk_widget_hide (window);
|
||||
|
||||
focusListener =
|
||||
SPI_createAccessibleEventListener (a11y_focus_listener,
|
||||
eekboard);
|
||||
SPI_registerGlobalEventListener (focusListener,
|
||||
"object:state-changed:focused");
|
||||
SPI_registerGlobalEventListener (focusListener,
|
||||
"focus:");
|
||||
}
|
||||
|
||||
/* monitor key events */
|
||||
if (!keystrokeListener) {
|
||||
keystrokeListener =
|
||||
SPI_createAccessibleKeystrokeListener (a11y_keystroke_listener,
|
||||
eekboard);
|
||||
}
|
||||
|
||||
if (!SPI_registerAccessibleKeystrokeListener
|
||||
(keystrokeListener,
|
||||
SPI_KEYSET_ALL_KEYS,
|
||||
0,
|
||||
SPI_KEY_PRESSED |
|
||||
SPI_KEY_RELEASED,
|
||||
SPI_KEYLISTENER_NOSYNC))
|
||||
g_warning ("failed to register keystroke listener");
|
||||
}
|
||||
|
||||
g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL);
|
||||
|
||||
if (combo)
|
||||
gtk_combo_box_set_active (GTK_COMBO_BOX(combo), 0);
|
||||
|
||||
gtk_main ();
|
||||
|
||||
return 0;
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*/
|
||||
#include "eek.h"
|
||||
#include "eek/eek.h"
|
||||
|
||||
static void
|
||||
test_create (void)
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*/
|
||||
#include "eek-xkb.h"
|
||||
#include "eek/eek-xkb.h"
|
||||
|
||||
/* For gdk_x11_display_get_xdisplay(). See main(). */
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
Reference in New Issue
Block a user