Implement ibus xim agent.
This commit is contained in:
Родитель
90f1e606a7
Коммит
cb388f451b
|
@ -29,6 +29,7 @@ SUBDIRS = \
|
|||
gtk2 \
|
||||
qt4 \
|
||||
setup \
|
||||
x11 \
|
||||
icons \
|
||||
m4 \
|
||||
po \
|
||||
|
|
|
@ -152,6 +152,8 @@ gconf/ibus-gconf
|
|||
engine/Makefile
|
||||
gtk2/Makefile
|
||||
qt4/Makefile
|
||||
x11/Makefile
|
||||
x11/IMdkit/Makefile
|
||||
setup/Makefile
|
||||
setup/ibus-setup
|
||||
setup/ibus-setup.desktop
|
||||
|
|
|
@ -46,4 +46,4 @@ EXTRA_DIST = \
|
|||
$(NULL)
|
||||
|
||||
test:
|
||||
$(ENV) PYTHONPATH=$(top_srcdir) $(PYTHON) $(srcdir)/ibusdaemon.py
|
||||
$(ENV) DBUS_DEBUG=true PYTHONPATH=$(top_srcdir) $(PYTHON) $(srcdir)/ibusdaemon.py
|
||||
|
|
104
x11/Makefile.am
104
x11/Makefile.am
|
@ -1,97 +1,25 @@
|
|||
# vim:set noet ts=4:
|
||||
#
|
||||
# ibus - The Input Bus
|
||||
#
|
||||
# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com>
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this program; if not, write to the
|
||||
# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
# Boston, MA 02111-1307 USA
|
||||
bin_PROGRAMS = ibus-x11
|
||||
|
||||
SUBDIRS = \
|
||||
IMdkit \
|
||||
ibus_x11_SOURCES = \
|
||||
main.c \
|
||||
gdk-private.c \
|
||||
$(NULL)
|
||||
|
||||
xim_PYTHON = \
|
||||
engine.py \
|
||||
factory.py \
|
||||
main.py \
|
||||
tables.py \
|
||||
test.py \
|
||||
noinst_HEADERS = \
|
||||
gdk-private.h \
|
||||
$(NULL)
|
||||
|
||||
ximdir = $(datadir)/ibus/xim
|
||||
IMdkit = $(builddir)/IMdkit/libIMdkit.la
|
||||
|
||||
IMdkit_DATA = \
|
||||
IMdkit.py \
|
||||
$(NULL)
|
||||
|
||||
IMdkit_LTLIBRARIES = _IMdkit.la
|
||||
|
||||
IMdkitdir = @pyexecdir@
|
||||
|
||||
_IMdkit_la_SOURCES = \
|
||||
$(NULL)
|
||||
|
||||
nodist__IMdkit_la_SOURCES = \
|
||||
IMdkit_wrap.c \
|
||||
$(NULL)
|
||||
|
||||
_IMdkit_la_CFLAGS = \
|
||||
@X11_CFLAGS@ \
|
||||
@GDK2_CFLAGS@ \
|
||||
@PYGOBJECT2_CFLAGS@ \
|
||||
@PYGTK2_CFLAGS@ \
|
||||
@GTK2_CFLAGS@ \
|
||||
@PYTHON_CFLAGS@ \
|
||||
-IIMdkit \
|
||||
$(NULL)
|
||||
|
||||
_IMdkit_la_LDFLAGS = \
|
||||
@X11_LIBS@ \
|
||||
@GDK2_LIBS@ \
|
||||
@PYGOBJECT2_LIBS@ \
|
||||
@PYGTK2_LIBS@ \
|
||||
ibus_x11_LDADD = \
|
||||
@GTK2_LIBS@ \
|
||||
@PYTHON_LIBS@ \
|
||||
-rpath $(IMdkitdir) \
|
||||
-avoid-version \
|
||||
-module \
|
||||
IMdkit/libIMdkit.la \
|
||||
$(top_builddir)/gtk2/libibus-gtk.la \
|
||||
$(IMdkit) \
|
||||
$(NULL)
|
||||
ibus_x11_CFLAGS = \
|
||||
@GTK2_CFLAGS@ \
|
||||
-I$(srcdir)/IMdkit \
|
||||
-I$(top_srcdir)/gtk2 \
|
||||
$(NULL)
|
||||
|
||||
#libexec_SCRIPTS = ibus-xim
|
||||
|
||||
IMdkit.py IMdkit_wrap.c: IMdkit.i
|
||||
$(SWIG) -python -I/usr/include -o IMdkit_wrap.c $(srcdir)/IMdkit.i
|
||||
|
||||
test: all
|
||||
$(ENV) PYTHONPATH=$(builddir)/.libs python test.py
|
||||
|
||||
test-ipython: all
|
||||
$(ENV) PYTHONPATH=$(builddir)/.libs ipython
|
||||
|
||||
EXTRA_DIST = \
|
||||
IMdkit.i \
|
||||
ibus-xim.in \
|
||||
$(NULL)
|
||||
|
||||
CLEANFILES = \
|
||||
IMdkit.py \
|
||||
IMdkit_wrap.* \
|
||||
*.pyc \
|
||||
$(MULL)
|
||||
|
||||
DISTCLEANFILES = \
|
||||
$(MULL)
|
||||
SUBDIRS = IMdkit
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
/* xim-on-gtkim
|
||||
* Copyright (C) 2007 Huang Peng <phuang@redhat.com>
|
||||
*
|
||||
* gdk-private.c: Copied some code from gtk2
|
||||
*
|
||||
* This tool is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
|
||||
void
|
||||
translate_key_event (GdkDisplay *display,
|
||||
GdkEvent *event,
|
||||
XEvent *xevent)
|
||||
{
|
||||
GdkKeymap *keymap = gdk_keymap_get_for_display (display);
|
||||
gunichar c = 0;
|
||||
gchar buf[7];
|
||||
|
||||
event->key.type = xevent->xany.type == KeyPress ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
|
||||
event->key.time = xevent->xkey.time;
|
||||
|
||||
event->key.state = (GdkModifierType) xevent->xkey.state;
|
||||
//event->key.group = _gdk_x11_get_group_for_state (display, xevent->xkey.state);
|
||||
event->key.group = 0;
|
||||
event->key.hardware_keycode = xevent->xkey.keycode;
|
||||
|
||||
event->key.keyval = GDK_VoidSymbol;
|
||||
|
||||
gdk_keymap_translate_keyboard_state (keymap,
|
||||
event->key.hardware_keycode,
|
||||
event->key.state,
|
||||
event->key.group,
|
||||
&event->key.keyval,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
//_gdk_keymap_add_virtual_modifiers (keymap, &event->key.state);
|
||||
event->key.is_modifier =
|
||||
(event->key.state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) != 0;
|
||||
// event->key.is_modifier = _gdk_keymap_key_is_modifier (keymap, event->key.hardware_keycode);
|
||||
|
||||
/* Fill in event->string crudely, since various programs
|
||||
* depend on it.
|
||||
*/
|
||||
event->key.string = NULL;
|
||||
|
||||
if (event->key.keyval != GDK_VoidSymbol)
|
||||
c = gdk_keyval_to_unicode (event->key.keyval);
|
||||
|
||||
if (c)
|
||||
{
|
||||
gsize bytes_written;
|
||||
gint len;
|
||||
|
||||
/* Apply the control key - Taken from Xlib
|
||||
*/
|
||||
if (event->key.state & GDK_CONTROL_MASK)
|
||||
{
|
||||
if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
|
||||
else if (c == '2')
|
||||
{
|
||||
event->key.string = g_memdup ("\0\0", 2);
|
||||
event->key.length = 1;
|
||||
buf[0] = '\0';
|
||||
goto out;
|
||||
}
|
||||
else if (c >= '3' && c <= '7') c -= ('3' - '\033');
|
||||
else if (c == '8') c = '\177';
|
||||
else if (c == '/') c = '_' & 0x1F;
|
||||
}
|
||||
|
||||
len = g_unichar_to_utf8 (c, buf);
|
||||
buf[len] = '\0';
|
||||
|
||||
event->key.string = g_locale_from_utf8 (buf, len,
|
||||
NULL, &bytes_written,
|
||||
NULL);
|
||||
if (event->key.string)
|
||||
event->key.length = bytes_written;
|
||||
}
|
||||
else if (event->key.keyval == GDK_Escape)
|
||||
{
|
||||
event->key.length = 1;
|
||||
event->key.string = g_strdup ("\033");
|
||||
}
|
||||
else if (event->key.keyval == GDK_Return ||
|
||||
event->key.keyval == GDK_KP_Enter)
|
||||
{
|
||||
event->key.length = 1;
|
||||
event->key.string = g_strdup ("\r");
|
||||
}
|
||||
|
||||
if (!event->key.string)
|
||||
{
|
||||
event->key.length = 0;
|
||||
event->key.string = g_strdup ("");
|
||||
}
|
||||
|
||||
out:
|
||||
return;
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/* xim-on-gtkim
|
||||
* Copyright (C) 2007 Huang Peng <phuang@redhat.com>
|
||||
*
|
||||
* gdk-private.h:
|
||||
*
|
||||
* This tool is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __GTK_PRIVATE_H_
|
||||
#define __GTK_PRIVATE_H_
|
||||
|
||||
void
|
||||
translate_key_event (GdkDisplay *display,
|
||||
GdkEvent *event,
|
||||
XEvent *xevent);
|
||||
#endif
|
|
@ -0,0 +1,693 @@
|
|||
/* xim-on-gtkim
|
||||
* Copyright (C) 2007 Huang Peng <phuang@redhat.com>
|
||||
*
|
||||
* main.c:
|
||||
*
|
||||
* This tool is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include <X11/Xproto.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <XimProto.h>
|
||||
#include <IMdkit.h>
|
||||
#include <Xi18n.h>
|
||||
#include <stdio.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
#include <langinfo.h>
|
||||
#include <locale.h>
|
||||
#include <iconv.h>
|
||||
|
||||
#define _GNU_SOURCES
|
||||
#include <getopt.h>
|
||||
|
||||
#define LOG(level, fmt, args...) \
|
||||
if (g_debug_level >= (level)) { \
|
||||
fprintf (stderr, fmt, args); \
|
||||
}
|
||||
|
||||
#include <ibusimclient.h>
|
||||
#include "gdk-private.h"
|
||||
|
||||
struct _X11ICONN {
|
||||
GList *clients;
|
||||
};
|
||||
typedef struct _X11ICONN X11ICONN;
|
||||
|
||||
struct _X11IC {
|
||||
GtkIMContext *context;
|
||||
GdkWindow *client_window;
|
||||
GdkWindow *focus_window;
|
||||
gint32 input_style;
|
||||
X11ICONN *conn;
|
||||
gint icid;
|
||||
gint connect_id;
|
||||
gchar *lang;
|
||||
GdkRectangle preedit_area;
|
||||
};
|
||||
typedef struct _X11IC X11IC;
|
||||
|
||||
|
||||
|
||||
static void _xim_commit_cb (GtkIMContext *context, gchar *arg, gpointer data);
|
||||
|
||||
static GHashTable *g_clients = NULL;
|
||||
static GHashTable *g_connections = NULL;
|
||||
static XIMS g_xims = NULL;
|
||||
static gchar g_server_name[128] = "ibus";
|
||||
static gchar g_locale[1024] =
|
||||
"aa,af,am,an,ar,as,az,be,bg,bn,br,bs,"
|
||||
"ca,cs,cy,da,de,dz,el,en,es,et,eu,"
|
||||
"fa,fi,fo,fr,fy,ga,gd,gl,gu,gv,"
|
||||
"he,hi,hr,hu,hy,id,is,it,iw,ja,"
|
||||
"ka,kk,kl,km,kn,ko,ku,kw,ky,lg,lo,lt,lv,"
|
||||
"mg,mi,mk,ml,mn,mr,ms,mt,nb,ne,nl,nn,no,nr,"
|
||||
"oc,om,or,pa,pl,pt,ro,ru,rw,"
|
||||
"se,si,sk,sl,so,sq,sr,ss,st,sv,"
|
||||
"ta,te,tg,th,ti,tl,tn,tr,ts,tt,"
|
||||
"uk,ur,uz,ve,vi,wa,xh,yi,zh,zu";
|
||||
|
||||
static gint g_debug_level = 0;
|
||||
|
||||
IBusIMClient *_client = NULL;
|
||||
|
||||
|
||||
static void
|
||||
_xim_preedit_start (XIMS xims, int icid, int connect_id)
|
||||
{
|
||||
IMPreeditStateStruct ips;
|
||||
ips.major_code = 0;
|
||||
ips.minor_code = 0;
|
||||
ips.icid = icid;
|
||||
ips.connect_id = connect_id;
|
||||
IMPreeditStart (xims, (XPointer)&ips);
|
||||
}
|
||||
|
||||
static void
|
||||
_xim_preedit_end (XIMS xims, int icid, int connect_id)
|
||||
{
|
||||
IMPreeditStateStruct ips;
|
||||
ips.major_code = 0;
|
||||
ips.minor_code = 0;
|
||||
ips.icid = icid;
|
||||
ips.connect_id = connect_id;
|
||||
IMPreeditEnd (xims, (XPointer)&ips);
|
||||
}
|
||||
|
||||
int
|
||||
_xim_store_ic_values (X11IC *ic, IMChangeICStruct *call_data)
|
||||
{
|
||||
XICAttribute *ic_attr = call_data->ic_attr;
|
||||
XICAttribute *pre_attr = call_data->preedit_attr;
|
||||
XICAttribute *sts_attr = call_data->status_attr;
|
||||
|
||||
gint i;
|
||||
guint32 attrs = 1;
|
||||
|
||||
if (ic == NULL) {
|
||||
return 0;
|
||||
}
|
||||
#define _is_attr(a, b) (strcmp(a, b->name) == 0)
|
||||
for (i=0; i< (int) call_data->ic_attr_num; ++i, ++ic_attr) {
|
||||
if (_is_attr (XNInputStyle, ic_attr)) {
|
||||
ic->input_style = *(gint32 *) ic_attr->value;
|
||||
}
|
||||
else if (_is_attr (XNClientWindow, ic_attr)) {
|
||||
Window w;
|
||||
|
||||
if (ic->client_window != NULL) {
|
||||
g_object_unref (ic->client_window);
|
||||
}
|
||||
|
||||
w = *(Window *) call_data->ic_attr[i].value;
|
||||
ic->client_window = gdk_window_foreign_new (w);
|
||||
}
|
||||
else if (_is_attr (XNFocusWindow, ic_attr)) {
|
||||
Window w;
|
||||
|
||||
if (ic->focus_window != NULL) {
|
||||
g_object_unref (ic->focus_window);
|
||||
}
|
||||
|
||||
w = *(Window *) call_data->ic_attr[i].value;
|
||||
ic->focus_window = gdk_window_foreign_new (w);
|
||||
}
|
||||
else {
|
||||
// fprintf (stderr, "Unknown attr: %s\n", ic_attr->name);
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i< (int) call_data->preedit_attr_num; ++i, ++pre_attr) {
|
||||
if (_is_attr (XNSpotLocation, pre_attr)) {
|
||||
ic->preedit_area.x = ((XPoint *)pre_attr->value)->x;
|
||||
ic->preedit_area.y = ((XPoint *)pre_attr->value)->y;
|
||||
}
|
||||
else {
|
||||
// fprintf (stderr, "Unknown attr: %s\n", pre_attr->name);
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i< (int) call_data->status_attr_num; ++i, ++sts_attr) {
|
||||
// printf ("set status: %s\n", sts_attr->name);
|
||||
}
|
||||
|
||||
#undef _is_attr
|
||||
|
||||
return attrs;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_xim_commit_cb (GtkIMContext *context, gchar *arg, gpointer data)
|
||||
{
|
||||
char *clist[1];
|
||||
XTextProperty tp;
|
||||
IMCommitStruct cms;
|
||||
|
||||
X11IC *ic = (X11IC *)data;
|
||||
|
||||
clist[0] = arg;
|
||||
Xutf8TextListToTextProperty (GDK_DISPLAY (), clist, 1, XCompoundTextStyle, &tp);
|
||||
|
||||
memset (&cms, 0, sizeof (cms));
|
||||
cms.major_code = XIM_COMMIT;
|
||||
cms.icid = ic->icid;
|
||||
cms.connect_id = ic->connect_id;
|
||||
cms.flag = XimLookupChars;
|
||||
cms.commit_string = (char *)tp.value;
|
||||
IMCommitString (g_xims, (XPointer) & cms);
|
||||
|
||||
XFree (tp.value);
|
||||
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
xim_create_ic (XIMS xims, IMChangeICStruct *call_data)
|
||||
{
|
||||
static int base_icid = 1;
|
||||
X11IC *ic;
|
||||
int i;
|
||||
|
||||
LOG (1, "XIM_CREATE_IC ic=%d, connect_id=%d\n", call_data->icid, call_data->connect_id);
|
||||
|
||||
call_data->icid = base_icid ++;
|
||||
|
||||
ic = g_malloc0 (sizeof (X11IC));
|
||||
ic->icid = call_data->icid;
|
||||
ic->connect_id = call_data->connect_id;
|
||||
ic->conn = (X11ICONN *)g_hash_table_lookup (g_connections,
|
||||
(gconstpointer)(unsigned long)call_data->connect_id);
|
||||
|
||||
|
||||
i = _xim_store_ic_values (ic, call_data);
|
||||
|
||||
ic->context = (GtkIMContext *)ibus_im_client_create_im_context (_client);
|
||||
gtk_im_context_set_client_window (ic->context, ic->client_window);
|
||||
gtk_im_context_set_use_preedit (ic->context, FALSE);
|
||||
g_signal_connect (ic->context,
|
||||
"commit",
|
||||
G_CALLBACK (_xim_commit_cb),
|
||||
(gpointer)ic);
|
||||
|
||||
|
||||
g_hash_table_insert (g_clients, (gpointer)ic->icid, (gpointer) ic);
|
||||
ic->conn->clients = g_list_append (ic->conn->clients, (gpointer) ic);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
xim_destroy_ic (XIMS xims, IMChangeICStruct *call_data)
|
||||
{
|
||||
X11IC *ic;
|
||||
|
||||
LOG (1, "XIM_DESTROY_IC ic=%d, connect_id=%d\n", call_data->icid, call_data->connect_id);
|
||||
|
||||
ic = (X11IC *)g_hash_table_lookup (g_clients,
|
||||
(gconstpointer)(unsigned long)call_data->icid);
|
||||
g_object_unref (ic->context);
|
||||
ic->conn->clients = g_list_remove (ic->conn->clients, (gconstpointer)ic);
|
||||
g_hash_table_remove (g_clients,
|
||||
(gconstpointer)(unsigned long)call_data->icid);
|
||||
|
||||
g_free (ic);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
xim_set_ic_focus (XIMS xims, IMChangeFocusStruct *call_data)
|
||||
{
|
||||
X11IC *ic;
|
||||
|
||||
LOG (1, "XIM_SET_IC_FOCUS ic=%d, connect_id=%d\n", call_data->icid, call_data->connect_id);
|
||||
|
||||
ic = (X11IC *)g_hash_table_lookup (g_clients,
|
||||
(gconstpointer)(unsigned long)call_data->icid);
|
||||
|
||||
gtk_im_context_focus_in (ic->context);
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
xim_unset_ic_focus (XIMS xims, IMChangeFocusStruct *call_data)
|
||||
{
|
||||
X11IC *ic;
|
||||
|
||||
LOG (1, "XIM_UNSET_IC_FOCUS ic=%d, connect_id=%d\n", call_data->icid, call_data->connect_id);
|
||||
|
||||
ic = (X11IC *)g_hash_table_lookup (g_clients,
|
||||
(gconstpointer)(unsigned long)call_data->icid);
|
||||
|
||||
gtk_im_context_focus_out (ic->context);
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
xim_forward_event (XIMS xims, IMForwardEventStruct *call_data)
|
||||
{
|
||||
|
||||
X11IC *ic;
|
||||
XKeyEvent *xevent;
|
||||
GdkEventKey event;
|
||||
GdkWindow *window;
|
||||
|
||||
ic = (X11IC *)g_hash_table_lookup (g_clients,
|
||||
(gconstpointer)(unsigned long)call_data->icid);
|
||||
|
||||
g_return_val_if_fail (ic != NULL, 1);
|
||||
|
||||
window = ic->focus_window != NULL ? ic->focus_window : ic->client_window;
|
||||
|
||||
xevent = (XKeyEvent*) &(call_data->event);
|
||||
|
||||
translate_key_event (gdk_drawable_get_display (window),
|
||||
(GdkEvent *)&event, (XEvent *)xevent);
|
||||
|
||||
event.send_event = xevent->send_event;
|
||||
event.window = window;
|
||||
|
||||
if (gtk_im_context_filter_keypress (ic->context, &event)) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
IMForwardEventStruct fe;
|
||||
XEvent xkp;
|
||||
XKeyEvent *event = (XKeyEvent*) (&xkp);
|
||||
|
||||
memset (&fe, 0, sizeof (fe));
|
||||
fe.major_code = XIM_FORWARD_EVENT;
|
||||
fe.icid = ic->icid;
|
||||
fe.connect_id = ic->connect_id;
|
||||
fe.sync_bit = 0;
|
||||
fe.serial_number = 0L;
|
||||
fe.event = call_data->event;
|
||||
IMForwardEvent (g_xims, (XPointer) & fe);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
xim_open (XIMS xims, IMOpenStruct *call_data)
|
||||
{
|
||||
X11ICONN *conn;
|
||||
gchar *last;
|
||||
|
||||
LOG (1, "XIM_OPEN connect_id=%d\n", call_data->connect_id);
|
||||
|
||||
conn = (X11ICONN *)g_hash_table_lookup (g_connections,
|
||||
(gconstpointer)(unsigned long)call_data->connect_id);
|
||||
|
||||
g_return_val_if_fail (conn == NULL, 1);
|
||||
|
||||
conn = (X11ICONN *) g_malloc0(sizeof (X11ICONN));
|
||||
// conn->context = GTK_IM_CONTEXT (gtk_im_multicontext_new ());
|
||||
|
||||
g_hash_table_insert (g_connections,
|
||||
(gpointer)(unsigned long)call_data->connect_id,
|
||||
(gpointer) conn);
|
||||
|
||||
// g_signal_connect_after (conn->context,
|
||||
// "commit",
|
||||
// G_CALLBACK (_xim_commit_cb),
|
||||
// (gpointer)(unsigned long)call_data->connect_id);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
_free_ic (gpointer data, gpointer user_data)
|
||||
{
|
||||
X11IC *ic = (X11IC *) data;
|
||||
|
||||
g_return_if_fail (ic != NULL);
|
||||
|
||||
g_object_unref (ic->context);
|
||||
|
||||
/* Remove the IC from g_client dictionary */
|
||||
g_hash_table_remove (g_clients,
|
||||
(gconstpointer)(unsigned long)ic->icid);
|
||||
|
||||
g_free (ic);
|
||||
}
|
||||
|
||||
int
|
||||
xim_close (XIMS ims, IMCloseStruct *call_data)
|
||||
{
|
||||
X11ICONN *conn;
|
||||
|
||||
LOG (1, "XIM_CLOSE connect_id=%d\n", call_data->connect_id);
|
||||
|
||||
conn = (X11ICONN *)g_hash_table_lookup (g_connections,
|
||||
(gconstpointer)(unsigned long)call_data->connect_id);
|
||||
|
||||
g_return_val_if_fail (conn != NULL, 1);
|
||||
|
||||
g_list_foreach (conn->clients, _free_ic, NULL);
|
||||
|
||||
g_list_free (conn->clients);
|
||||
|
||||
// g_object_unref (conn->context);
|
||||
|
||||
g_hash_table_remove (g_connections, (gconstpointer)(unsigned long)call_data->connect_id);
|
||||
|
||||
g_free (conn);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
xim_set_ic_values (XIMS xims, IMChangeICStruct *call_data)
|
||||
{
|
||||
X11IC *ic;
|
||||
gint i;
|
||||
|
||||
LOG (1, "XIM_SET_IC_VALUES ic=%d connect_id=%d\n", call_data->icid, call_data->connect_id);
|
||||
|
||||
ic = (X11IC *)g_hash_table_lookup (g_clients,
|
||||
(gconstpointer)(unsigned long)call_data->icid);
|
||||
|
||||
g_return_val_if_fail (ic != NULL, 1);
|
||||
|
||||
i = _xim_store_ic_values (ic, call_data);
|
||||
|
||||
if (i) {
|
||||
gtk_im_context_set_cursor_location (ic->context, &ic->preedit_area);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
xim_reset_ic (XIMS xims, IMResetICStruct *call_data)
|
||||
{
|
||||
X11IC *ic;
|
||||
|
||||
LOG (1, "XIM_RESET_IC ic=%d connect_id=%d\n", call_data->icid, call_data->connect_id);
|
||||
|
||||
ic = (X11IC *)g_hash_table_lookup (g_clients,
|
||||
(gconstpointer)(unsigned long)call_data->icid);
|
||||
|
||||
g_return_val_if_fail (ic != NULL, 1);
|
||||
|
||||
gtk_im_context_reset (ic->context);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ims_protocol_handler (XIMS xims, IMProtocol *call_data)
|
||||
{
|
||||
g_return_val_if_fail (xims != NULL, 1);
|
||||
g_return_val_if_fail (call_data != NULL, 1);
|
||||
|
||||
switch (call_data->major_code) {
|
||||
case XIM_OPEN:
|
||||
return xim_open (xims, (IMOpenStruct *)call_data);
|
||||
case XIM_CLOSE:
|
||||
return xim_close (xims, (IMCloseStruct *)call_data);
|
||||
case XIM_CREATE_IC:
|
||||
return xim_create_ic (xims, (IMChangeICStruct *)call_data);
|
||||
case XIM_DESTROY_IC:
|
||||
return xim_destroy_ic (xims, (IMChangeICStruct *)call_data);
|
||||
case XIM_SET_IC_VALUES:
|
||||
return xim_set_ic_values (xims, (IMChangeICStruct *)call_data);
|
||||
case XIM_GET_IC_VALUES:
|
||||
return 1;
|
||||
case XIM_FORWARD_EVENT:
|
||||
return xim_forward_event (xims, (IMForwardEventStruct *)call_data);
|
||||
case XIM_SET_IC_FOCUS:
|
||||
return xim_set_ic_focus (xims, (IMChangeFocusStruct *)call_data);
|
||||
case XIM_UNSET_IC_FOCUS:
|
||||
return xim_unset_ic_focus (xims, (IMChangeFocusStruct *)call_data);
|
||||
case XIM_RESET_IC:
|
||||
return xim_reset_ic (xims, (IMResetICStruct *)call_data);
|
||||
case XIM_TRIGGER_NOTIFY:
|
||||
case XIM_PREEDIT_START_REPLY:
|
||||
case XIM_PREEDIT_CARET_REPLY:
|
||||
case XIM_SYNC_REPLY:
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static void
|
||||
_xim_forward_gdk_event (GdkEventKey *event)
|
||||
{
|
||||
IMForwardEventStruct fe;
|
||||
XEvent xkp;
|
||||
memset (&xkp, 0, sizeof (xkp));
|
||||
memset (&fe, 0, sizeof (fe));
|
||||
|
||||
xkp.xkey.type = (event->type == GDK_KEY_PRESS) ? KeyPress : KeyRelease;
|
||||
xkp.xkey.serial = 0L;
|
||||
xkp.xkey.send_event = False;
|
||||
xkp.xkey.same_screen = False;
|
||||
xkp.xkey.display = GDK_WINDOW_XDISPLAY (event->window);
|
||||
xkp.xkey.window = GDK_WINDOW_XWINDOW (event->window);
|
||||
xkp.xkey.subwindow = None;
|
||||
xkp.xkey.root = DefaultRootWindow (GDK_WINDOW_XDISPLAY (event->window));
|
||||
xkp.xkey.time = event->time;
|
||||
xkp.xkey.state = event->state;
|
||||
xkp.xkey.keycode = event->hardware_keycode;
|
||||
|
||||
fe.major_code = XIM_FORWARD_EVENT;
|
||||
fe.icid = g_focus_ic->icid;
|
||||
fe.connect_id = g_focus_ic->connect_id;
|
||||
fe.sync_bit = 0;
|
||||
fe.serial_number = 0L;
|
||||
fe.event = xkp;
|
||||
IMForwardEvent (g_xims, (XPointer) & fe);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
_xim_event_cb (GdkEvent *event, gpointer data)
|
||||
{
|
||||
switch (event->type) {
|
||||
case GDK_KEY_PRESS:
|
||||
case GDK_KEY_RELEASE:
|
||||
//_xim_forward_gdk_event ((GdkEventKey *)event);
|
||||
break;
|
||||
default:
|
||||
gtk_main_do_event (event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_xim_event_destroy_cb (gpointer data)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
_xim_init_IMdkit ()
|
||||
{
|
||||
XIMStyle ims_styles_overspot [] = {
|
||||
XIMPreeditPosition | XIMStatusNothing,
|
||||
XIMPreeditNothing | XIMStatusNothing,
|
||||
XIMPreeditPosition | XIMStatusCallbacks,
|
||||
XIMPreeditNothing | XIMStatusCallbacks,
|
||||
0
|
||||
};
|
||||
|
||||
XIMStyle ims_styles_onspot [] = {
|
||||
XIMPreeditPosition | XIMStatusNothing,
|
||||
XIMPreeditCallbacks | XIMStatusNothing,
|
||||
XIMPreeditNothing | XIMStatusNothing,
|
||||
XIMPreeditPosition | XIMStatusCallbacks,
|
||||
XIMPreeditCallbacks | XIMStatusCallbacks,
|
||||
XIMPreeditNothing | XIMStatusCallbacks,
|
||||
0
|
||||
};
|
||||
|
||||
XIMEncoding ims_encodings[] = {
|
||||
"COMPOUND_TEXT",
|
||||
0
|
||||
};
|
||||
|
||||
GdkWindowAttr window_attr = {
|
||||
title : "xim2gtkim",
|
||||
event_mask : GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK,
|
||||
wclass: GDK_INPUT_OUTPUT,
|
||||
window_type: GDK_WINDOW_TOPLEVEL,
|
||||
override_redirect: 1,
|
||||
};
|
||||
|
||||
XIMStyles styles;
|
||||
XIMEncodings encodings;
|
||||
|
||||
GdkWindow *win;
|
||||
|
||||
win = gdk_window_new (NULL, &window_attr, GDK_WA_TITLE);
|
||||
|
||||
styles.count_styles =
|
||||
sizeof (ims_styles_onspot)/sizeof (XIMStyle) - 1;
|
||||
styles.supported_styles = ims_styles_onspot;
|
||||
|
||||
encodings.count_encodings =
|
||||
sizeof (ims_encodings)/sizeof (XIMEncoding) - 1;
|
||||
encodings.supported_encodings = ims_encodings;
|
||||
|
||||
g_xims = IMOpenIM(GDK_DISPLAY(),
|
||||
IMModifiers, "Xi18n",
|
||||
IMServerWindow, GDK_WINDOW_XWINDOW(win),
|
||||
IMServerName, g_server_name,
|
||||
IMLocale, g_locale,
|
||||
IMServerTransport, "X/",
|
||||
IMInputStyles, &styles,
|
||||
IMEncodingList, &encodings,
|
||||
IMProtocolHandler, ims_protocol_handler,
|
||||
IMFilterEventMask, KeyPressMask | KeyReleaseMask,
|
||||
NULL);
|
||||
|
||||
gdk_event_handler_set (_xim_event_cb, NULL,
|
||||
_xim_event_destroy_cb);
|
||||
|
||||
ibus_im_client_register_type (NULL);
|
||||
ibus_im_context_register_type (NULL);
|
||||
_client = ibus_im_client_new ();
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
print_usage (FILE *fp, gchar *name)
|
||||
{
|
||||
fprintf (fp,
|
||||
"Usage:\n"
|
||||
" %s --help Show this message\n"
|
||||
" --server-name= -n Setup xim sevrer name\n"
|
||||
" --locale= -l Setup support locale\n"
|
||||
" --debug= -v Setup debug level\n",
|
||||
name);
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
GMainLoop *loop;
|
||||
gint option_index = 0;
|
||||
gint c;
|
||||
|
||||
gdk_init (&argc, &argv);
|
||||
|
||||
while (1) {
|
||||
static struct option long_options [] = {
|
||||
{"debug", 1, 0, 0},
|
||||
{"server-name", 1, 0, 0},
|
||||
{"locale", 1, 0, 0},
|
||||
{"help", 0, 0, 0},
|
||||
{0, 0, 0, 0},
|
||||
};
|
||||
|
||||
c = getopt_long (argc, argv, "v:n:l:",
|
||||
long_options, &option_index);
|
||||
|
||||
if (c == -1) break;
|
||||
|
||||
switch (c) {
|
||||
case 0:
|
||||
if (strcmp (long_options[option_index].name, "debug") == 0) {
|
||||
g_debug_level = atoi (optarg);
|
||||
}
|
||||
else if (strcmp (long_options[option_index].name, "server-name") == 0) {
|
||||
strncpy (g_server_name, optarg, sizeof (g_server_name));
|
||||
}
|
||||
else if (strcmp (long_options[option_index].name, "locale") == 0) {
|
||||
strncpy (g_locale, optarg, sizeof (g_locale));
|
||||
}
|
||||
else if (strcmp (long_options[option_index].name, "help") == 0) {
|
||||
print_usage (stdout, argv[0]);
|
||||
exit (EXIT_SUCCESS);
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
g_debug_level = atoi (optarg);
|
||||
break;
|
||||
case 'n':
|
||||
strncpy (g_server_name, optarg, sizeof (g_server_name));
|
||||
break;
|
||||
case 'l':
|
||||
strncpy (g_locale, optarg, sizeof (g_locale));
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
print_usage (stderr, argv[0]);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
g_clients = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
g_connections = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
|
||||
printf ("server-name = %s\n", g_server_name);
|
||||
printf ("locale = %s\n", g_locale);
|
||||
|
||||
_xim_init_IMdkit ();
|
||||
|
||||
|
||||
loop = g_main_loop_new (NULL, TRUE);
|
||||
|
||||
if (g_main_loop_is_running (loop)) {
|
||||
GDK_THREADS_LEAVE ();
|
||||
g_main_loop_run (loop);
|
||||
GDK_THREADS_ENTER ();
|
||||
gdk_flush ();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
Загрузка…
Ссылка в новой задаче