Reimplement eekboard as a D-Bus server.
This commit is contained in:
		
							
								
								
									
										25
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								README
									
									
									
									
									
								
							@ -6,7 +6,7 @@ create keyboard-like UI ("libeek").
 | 
			
		||||
 | 
			
		||||
* Requirements
 | 
			
		||||
 | 
			
		||||
  * GLib2, GTK, GConf2, PangoCairo, libxklavier, libfakekey, libnotify, CSPI
 | 
			
		||||
  * GLib2, GTK, GConf2, PangoCairo, libxklavier, libfakekey, CSPI
 | 
			
		||||
  * Clutter (optional)
 | 
			
		||||
  * Clutter-Gtk (optional)
 | 
			
		||||
  * Vala (optional)
 | 
			
		||||
@ -19,15 +19,26 @@ Build from git repo:
 | 
			
		||||
  $ git clone git://github.com/ueno/eekboard.git
 | 
			
		||||
  $ cd eekboard
 | 
			
		||||
  $ ./autogen.sh --prefix=/usr --enable-gtk-doc
 | 
			
		||||
 | 
			
		||||
Build from tarball:
 | 
			
		||||
 | 
			
		||||
  $ ./configure
 | 
			
		||||
  $ make
 | 
			
		||||
  $ sudo make install
 | 
			
		||||
  $ eekboard
 | 
			
		||||
 | 
			
		||||
How to test (dump/load the current layout):
 | 
			
		||||
 | 
			
		||||
  $ ./tests/eek-example-xml -d > keyboard.xml
 | 
			
		||||
  $ ./tests/eek-example-xml -l keyboard.xml
 | 
			
		||||
 | 
			
		||||
NOTE: eekboard is now being heavily rewritten and it may behave
 | 
			
		||||
wrongly.  Make sure to close windows where you are doing any important
 | 
			
		||||
work, before running eekboard.
 | 
			
		||||
 | 
			
		||||
  $ ./src/eekboard-server &
 | 
			
		||||
  $ ./src/eekboard-system-client --xklavier --accessibility --fakekey
 | 
			
		||||
 | 
			
		||||
Where --xklavier is to monitor system keyboard layout change,
 | 
			
		||||
--accessibility is to track focus/key events via AT-SPI, and --fakekey
 | 
			
		||||
generates X key events when eekboard-server signals virtual
 | 
			
		||||
key-press/key-release events.
 | 
			
		||||
 | 
			
		||||
* Documentation
 | 
			
		||||
 | 
			
		||||
<file:docs/reference/eek/html/index.html>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -17,8 +17,18 @@
 | 
			
		||||
# 02110-1301 USA
 | 
			
		||||
 | 
			
		||||
if ENABLE_EEKBOARD
 | 
			
		||||
bin_PROGRAMS = eekboard
 | 
			
		||||
eekboard_CFLAGS = \
 | 
			
		||||
bin_PROGRAMS = eekboard-system-client eekboard-server
 | 
			
		||||
noinst_LIBRARIES = libeekboard.a
 | 
			
		||||
 | 
			
		||||
libeekboard_a_headers = proxy.h
 | 
			
		||||
 | 
			
		||||
libeekboard_a_CFLAGS = \
 | 
			
		||||
	-I$(top_srcdir) \
 | 
			
		||||
	$(GIO2_CFLAGS)
 | 
			
		||||
 | 
			
		||||
libeekboard_a_SOURCES = proxy.c
 | 
			
		||||
 | 
			
		||||
eekboard_system_client_CFLAGS = \
 | 
			
		||||
	-I$(top_srcdir) \
 | 
			
		||||
	$(GIO2_CFLAGS) \
 | 
			
		||||
	$(GTK_CFLAGS) \
 | 
			
		||||
@ -26,24 +36,45 @@ eekboard_CFLAGS = \
 | 
			
		||||
	$(XKB_CFLAGS) \
 | 
			
		||||
	$(LIBXKLAVIER_CFLAGS) \
 | 
			
		||||
	$(LIBFAKEKEY_CFLAGS) \
 | 
			
		||||
	$(CSPI_CFLAGS) \
 | 
			
		||||
	$(NOTIFY_CFLAGS)
 | 
			
		||||
	$(CSPI_CFLAGS)
 | 
			
		||||
 | 
			
		||||
eekboard_LDFLAGS = \
 | 
			
		||||
eekboard_system_client_LDADD = \
 | 
			
		||||
	libeekboard.a \
 | 
			
		||||
	$(top_builddir)/eek/libeek.la \
 | 
			
		||||
	$(top_builddir)/eek/libeek-xkl.la \
 | 
			
		||||
	$(top_builddir)/eek/libeek-gtk.la \
 | 
			
		||||
	$(GIO2_LIBS) \
 | 
			
		||||
	$(GTK_LIBS) \
 | 
			
		||||
	$(GCONF2_LIBS) \
 | 
			
		||||
	$(XKB_LIBS) \
 | 
			
		||||
	$(LIBXKLAVIER_LIBS) \
 | 
			
		||||
	$(LIBFAKEKEY_LIBS) \
 | 
			
		||||
	$(CSPI_LIBS) \
 | 
			
		||||
	$(NOTIFY_LIBS)
 | 
			
		||||
	$(CSPI_LIBS)
 | 
			
		||||
 | 
			
		||||
eekboard_system_client_headers = system-client.h
 | 
			
		||||
eekboard_system_client_SOURCES = system-client.c system-client-main.c
 | 
			
		||||
 | 
			
		||||
eekboard_server_CFLAGS = \
 | 
			
		||||
	-I$(top_srcdir) \
 | 
			
		||||
	$(GIO2_CFLAGS) \
 | 
			
		||||
	$(GTK_CFLAGS)
 | 
			
		||||
 | 
			
		||||
eekboard_server_LDADD = \
 | 
			
		||||
	libeekboard.a \
 | 
			
		||||
	$(top_builddir)/eek/libeek.la \
 | 
			
		||||
	$(top_builddir)/eek/libeek-gtk.la \
 | 
			
		||||
	$(GIO2_LIBS) \
 | 
			
		||||
	$(GTK_LIBS)
 | 
			
		||||
 | 
			
		||||
eekboard_server_headers = server.h
 | 
			
		||||
eekboard_server_SOURCES = server.c server-main.c
 | 
			
		||||
 | 
			
		||||
if HAVE_CLUTTER
 | 
			
		||||
eekboard_CFLAGS += $(CLUTTER_CFLAGS) $(CLUTTER_GTK_CFLAGS)
 | 
			
		||||
eekboard_LDFLAGS += $(CLUTTER_LIBS) $(top_builddir)/eek/libeek-clutter.la $(CLUTTER_GTK_LIBS)
 | 
			
		||||
eekboard_server_CFLAGS += $(CLUTTER_CFLAGS) $(CLUTTER_GTK_CFLAGS)
 | 
			
		||||
eekboard_server_LDADD += $(CLUTTER_LIBS) $(top_builddir)/eek/libeek-clutter.la $(CLUTTER_GTK_LIBS)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
noinst_HEADERS = \
 | 
			
		||||
	$(libeekboard_a_headers) \
 | 
			
		||||
	$(eekboard_system_client_headers) \
 | 
			
		||||
	$(eekboard_server_headers)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										213
									
								
								src/proxy.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										213
									
								
								src/proxy.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,213 @@
 | 
			
		||||
/* 
 | 
			
		||||
 * Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
 | 
			
		||||
 * Copyright (C) 2010-2011 Red Hat, Inc.
 | 
			
		||||
 * 
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program 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 General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
#ifdef HAVE_CONFIG_H
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#endif  /* HAVE_CONFIG_H */
 | 
			
		||||
 | 
			
		||||
#include "proxy.h"
 | 
			
		||||
 | 
			
		||||
#define BUFSIZE 8192
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    KEY_PRESSED,
 | 
			
		||||
    KEY_RELEASED,
 | 
			
		||||
    LAST_SIGNAL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static guint signals[LAST_SIGNAL] = { 0, };
 | 
			
		||||
 | 
			
		||||
struct _EekboardProxy {
 | 
			
		||||
    GDBusProxy parent;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _EekboardProxyClass {
 | 
			
		||||
    GDBusProxyClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (EekboardProxy, eekboard_proxy, G_TYPE_DBUS_PROXY);
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eekboard_proxy_real_g_signal (GDBusProxy  *self,
 | 
			
		||||
                              const gchar *sender_name,
 | 
			
		||||
                              const gchar *signal_name,
 | 
			
		||||
                              GVariant    *parameters)
 | 
			
		||||
{
 | 
			
		||||
    EekboardProxy *proxy = EEKBOARD_PROXY (self);
 | 
			
		||||
    guint *keycode;
 | 
			
		||||
 | 
			
		||||
    g_debug ("%s %s", sender_name, signal_name);
 | 
			
		||||
    if (g_strcmp0 (signal_name, "KeyPressed") == 0) {
 | 
			
		||||
 | 
			
		||||
        g_variant_get (parameters, "(u)", &keycode);
 | 
			
		||||
        g_signal_emit_by_name (proxy, "key-pressed", keycode);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (g_strcmp0 (signal_name, "KeyReleased") == 0) {
 | 
			
		||||
        g_variant_get (parameters, "(u)", &keycode);
 | 
			
		||||
        g_signal_emit_by_name (proxy, "key-released", keycode);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    g_return_if_reached ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eekboard_proxy_class_init (EekboardProxyClass *klass)
 | 
			
		||||
{
 | 
			
		||||
    GDBusProxyClass *proxy_class = G_DBUS_PROXY_CLASS (klass);
 | 
			
		||||
    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
    proxy_class->g_signal = eekboard_proxy_real_g_signal;
 | 
			
		||||
 | 
			
		||||
    signals[KEY_PRESSED] =
 | 
			
		||||
        g_signal_new ("key-pressed",
 | 
			
		||||
                      G_TYPE_FROM_CLASS(gobject_class),
 | 
			
		||||
                      G_SIGNAL_RUN_LAST,
 | 
			
		||||
                      0,
 | 
			
		||||
                      NULL,
 | 
			
		||||
                      NULL,
 | 
			
		||||
                      g_cclosure_marshal_VOID__UINT,
 | 
			
		||||
                      G_TYPE_NONE,
 | 
			
		||||
                      1,
 | 
			
		||||
                      G_TYPE_UINT);
 | 
			
		||||
 | 
			
		||||
    signals[KEY_RELEASED] =
 | 
			
		||||
        g_signal_new ("key-released",
 | 
			
		||||
                      G_TYPE_FROM_CLASS(gobject_class),
 | 
			
		||||
                      G_SIGNAL_RUN_LAST,
 | 
			
		||||
                      0,
 | 
			
		||||
                      NULL,
 | 
			
		||||
                      NULL,
 | 
			
		||||
                      g_cclosure_marshal_VOID__UINT,
 | 
			
		||||
                      G_TYPE_NONE,
 | 
			
		||||
                      1,
 | 
			
		||||
                      G_TYPE_UINT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eekboard_proxy_init (EekboardProxy *proxy)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EekboardProxy *
 | 
			
		||||
eekboard_proxy_new (const gchar     *path,
 | 
			
		||||
                    GDBusConnection *connection,
 | 
			
		||||
                    GCancellable    *cancellable,
 | 
			
		||||
                    GError         **error)
 | 
			
		||||
{
 | 
			
		||||
    GInitable *initable;
 | 
			
		||||
 | 
			
		||||
    g_assert (path != NULL);
 | 
			
		||||
    g_assert (G_IS_DBUS_CONNECTION(connection));
 | 
			
		||||
 | 
			
		||||
    initable =
 | 
			
		||||
        g_initable_new (EEKBOARD_TYPE_PROXY,
 | 
			
		||||
                        cancellable,
 | 
			
		||||
                        error,
 | 
			
		||||
                        "g-connection", connection,
 | 
			
		||||
                        "g-name", "com.redhat.eekboard.Keyboard",
 | 
			
		||||
                        "g-flags", G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START |
 | 
			
		||||
                        G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
 | 
			
		||||
                        "g-interface-name", "com.redhat.eekboard.Keyboard",
 | 
			
		||||
                        "g-object-path", path,
 | 
			
		||||
                        NULL);
 | 
			
		||||
    if (initable != NULL)
 | 
			
		||||
        return EEKBOARD_PROXY (initable);
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
proxy_call_async_ready_cb (GObject      *source_object,
 | 
			
		||||
                           GAsyncResult *res,
 | 
			
		||||
                           gpointer      user_data)
 | 
			
		||||
{
 | 
			
		||||
    GError *error = NULL;
 | 
			
		||||
    GVariant *result;
 | 
			
		||||
 | 
			
		||||
    result = g_dbus_proxy_call_finish (G_DBUS_PROXY(source_object),
 | 
			
		||||
                                       res,
 | 
			
		||||
                                       &error);
 | 
			
		||||
    g_assert_no_error (error);
 | 
			
		||||
    g_assert (result != NULL);
 | 
			
		||||
    g_variant_unref (result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
eekboard_proxy_set_keyboard (EekboardProxy *proxy, EekKeyboard *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    GString *output;
 | 
			
		||||
    GVariant *variant;
 | 
			
		||||
    gchar *data;
 | 
			
		||||
 | 
			
		||||
    output = g_string_sized_new (BUFSIZE);
 | 
			
		||||
    eek_keyboard_output (keyboard, output, 0);
 | 
			
		||||
 | 
			
		||||
    data = g_string_free (output, FALSE);
 | 
			
		||||
    variant = g_variant_new ("(s)", data);
 | 
			
		||||
    g_free (data);
 | 
			
		||||
 | 
			
		||||
    g_dbus_proxy_call (G_DBUS_PROXY(proxy),
 | 
			
		||||
                       "SetKeyboard",
 | 
			
		||||
                       g_variant_new ("(v)", variant),
 | 
			
		||||
                       G_DBUS_CALL_FLAGS_NONE,
 | 
			
		||||
                       -1,
 | 
			
		||||
                       NULL,
 | 
			
		||||
                       proxy_call_async_ready_cb,
 | 
			
		||||
                       NULL);
 | 
			
		||||
    g_variant_unref (variant);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
eekboard_proxy_set_group (EekboardProxy *proxy, gint group)
 | 
			
		||||
{
 | 
			
		||||
    g_dbus_proxy_call (G_DBUS_PROXY(proxy),
 | 
			
		||||
                       "SetGroup",
 | 
			
		||||
                       g_variant_new ("(i)", group),
 | 
			
		||||
                       G_DBUS_CALL_FLAGS_NONE,
 | 
			
		||||
                       -1,
 | 
			
		||||
                       NULL,
 | 
			
		||||
                       proxy_call_async_ready_cb,
 | 
			
		||||
                       NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
eekboard_proxy_show (EekboardProxy *proxy)
 | 
			
		||||
{
 | 
			
		||||
    g_dbus_proxy_call (G_DBUS_PROXY(proxy),
 | 
			
		||||
                       "Show",
 | 
			
		||||
                       NULL,
 | 
			
		||||
                       G_DBUS_CALL_FLAGS_NONE,
 | 
			
		||||
                       -1,
 | 
			
		||||
                       NULL,
 | 
			
		||||
                       proxy_call_async_ready_cb,
 | 
			
		||||
                       NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
eekboard_proxy_hide (EekboardProxy *proxy)
 | 
			
		||||
{
 | 
			
		||||
    g_dbus_proxy_call (G_DBUS_PROXY(proxy),
 | 
			
		||||
                       "Hide",
 | 
			
		||||
                       NULL,
 | 
			
		||||
                       G_DBUS_CALL_FLAGS_NONE,
 | 
			
		||||
                       -1,
 | 
			
		||||
                       NULL,
 | 
			
		||||
                       proxy_call_async_ready_cb,
 | 
			
		||||
                       NULL);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										48
									
								
								src/proxy.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/proxy.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
			
		||||
/* 
 | 
			
		||||
 * Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
 | 
			
		||||
 * Copyright (C) 2010-2011 Red Hat, Inc.
 | 
			
		||||
 * 
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program 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 General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef EEKBOARD_PROXY_H
 | 
			
		||||
#define EEKBOARD_PROXY_H 1
 | 
			
		||||
 | 
			
		||||
#include <gio/gio.h>
 | 
			
		||||
#include "eek/eek.h"
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
#define EEKBOARD_TYPE_PROXY (eekboard_proxy_get_type())
 | 
			
		||||
#define EEKBOARD_PROXY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEKBOARD_TYPE_PROXY, EekboardProxy))
 | 
			
		||||
#define EEKBOARD_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEKBOARD_TYPE_PROXY, EekboardProxyClass))
 | 
			
		||||
#define EEKBOARD_IS_PROXY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEKBOARD_TYPE_PROXY))
 | 
			
		||||
#define EEKBOARD_IS_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEKBOARD_TYPE_PROXY))
 | 
			
		||||
#define EEKBOARD_PROXY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEKBOARD_TYPE_PROXY, EekboardProxyClass))
 | 
			
		||||
 | 
			
		||||
typedef struct _EekboardProxy EekboardProxy;
 | 
			
		||||
typedef struct _EekboardProxyClass EekboardProxyClass;
 | 
			
		||||
 | 
			
		||||
EekboardProxy *eekboard_proxy_new          (const gchar     *path,
 | 
			
		||||
                                            GDBusConnection *connection,
 | 
			
		||||
                                            GCancellable    *cancellable,
 | 
			
		||||
                                            GError         **error);
 | 
			
		||||
void           eekboard_proxy_set_keyboard (EekboardProxy   *proxy,
 | 
			
		||||
                                            EekKeyboard     *keyboard);
 | 
			
		||||
void           eekboard_proxy_set_group    (EekboardProxy   *proxy,
 | 
			
		||||
                                            gint             group);
 | 
			
		||||
void           eekboard_proxy_show         (EekboardProxy   *proxy);
 | 
			
		||||
void           eekboard_proxy_hide         (EekboardProxy   *proxy);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
#endif  /* EEKBOARD_PROXY_H */
 | 
			
		||||
							
								
								
									
										65
									
								
								src/server-main.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/server-main.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,65 @@
 | 
			
		||||
/* 
 | 
			
		||||
 * Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
 | 
			
		||||
 * Copyright (C) 2010-2011 Red Hat, Inc.
 | 
			
		||||
 * 
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program 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 General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <gio/gio.h>
 | 
			
		||||
#include <gtk/gtk.h>
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_CONFIG_H
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#endif  /* HAVE_CONFIG_H */
 | 
			
		||||
 | 
			
		||||
#include "server.h"
 | 
			
		||||
#include "eek/eek.h"
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main (int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
    EekboardServer *server;
 | 
			
		||||
    GDBusConnection *connection;
 | 
			
		||||
    GError *error;
 | 
			
		||||
    GMainLoop *loop;
 | 
			
		||||
 | 
			
		||||
    if (!gtk_init_check (&argc, &argv)) {
 | 
			
		||||
        g_warning ("Can't init GTK");
 | 
			
		||||
        exit (1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    error = NULL;
 | 
			
		||||
    connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
 | 
			
		||||
    if (error) {
 | 
			
		||||
        g_printerr ("%s\n", error->message);
 | 
			
		||||
        exit (1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    server = eekboard_server_new (connection);
 | 
			
		||||
 | 
			
		||||
    loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
 | 
			
		||||
    if (!eekboard_server_start (server)) {
 | 
			
		||||
        g_printerr ("Can't start server\n");
 | 
			
		||||
        exit (1);
 | 
			
		||||
    }
 | 
			
		||||
    g_main_loop_run(loop);
 | 
			
		||||
    eekboard_server_stop (server);
 | 
			
		||||
 | 
			
		||||
    g_object_unref(server);
 | 
			
		||||
    g_object_unref(connection);
 | 
			
		||||
    g_main_loop_unref(loop);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										365
									
								
								src/server.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										365
									
								
								src/server.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,365 @@
 | 
			
		||||
/* 
 | 
			
		||||
 * Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
 | 
			
		||||
 * Copyright (C) 2010-2011 Red Hat, Inc.
 | 
			
		||||
 * 
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program 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 General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
#include <gtk/gtk.h>
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_CONFIG_H
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#endif  /* HAVE_CONFIG_H */
 | 
			
		||||
 | 
			
		||||
#include "eek/eek.h"
 | 
			
		||||
#include "eek/eek-gtk.h"
 | 
			
		||||
#include "server.h"
 | 
			
		||||
 | 
			
		||||
#define CSW 640
 | 
			
		||||
#define CSH 480
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    PROP_0,
 | 
			
		||||
    PROP_CONNECTION,
 | 
			
		||||
    PROP_LAST
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const gchar introspection_xml[] =
 | 
			
		||||
    "<node>"
 | 
			
		||||
    "  <interface name='com.redhat.eekboard.Keyboard'>"
 | 
			
		||||
    "    <method name='SetKeyboard'>"
 | 
			
		||||
    "      <arg type='v' name='keyboard'/>"
 | 
			
		||||
    "    </method>"
 | 
			
		||||
    "    <method name='SetGroup'>"
 | 
			
		||||
    "      <arg type='i' name='group'/>"
 | 
			
		||||
    "    </method>"
 | 
			
		||||
    "    <method name='Show'/>"
 | 
			
		||||
    "    <method name='Hide'/>"
 | 
			
		||||
    "    <method name='PressKey'>"
 | 
			
		||||
    "      <arg type='s' name='key_id' direction='in'/>"
 | 
			
		||||
    "    </method>"
 | 
			
		||||
    "    <method name='ReleaseKey'>"
 | 
			
		||||
    "      <arg type='s' name='key_id' direction='in'/>"
 | 
			
		||||
    "    </method>"
 | 
			
		||||
    "    <signal name='KeyPressed'>"
 | 
			
		||||
    "      <arg type='u' name='keycode'/>"
 | 
			
		||||
    "    </signal>"
 | 
			
		||||
    "    <signal name='KeyReleased'>"
 | 
			
		||||
    "      <arg type='u' name='keycode'/>"
 | 
			
		||||
    "    </signal>"
 | 
			
		||||
    "  </interface>"
 | 
			
		||||
    "</node>";
 | 
			
		||||
 | 
			
		||||
typedef struct _EekboardServerClass EekboardServerClass;
 | 
			
		||||
 | 
			
		||||
struct _EekboardServer {
 | 
			
		||||
    GObject parent;
 | 
			
		||||
    GDBusConnection *connection;
 | 
			
		||||
    guint owner_id;
 | 
			
		||||
    GDBusNodeInfo *introspection_data;
 | 
			
		||||
 | 
			
		||||
    GtkWidget *window;
 | 
			
		||||
    GtkWidget *widget;
 | 
			
		||||
    EekKeyboard *keyboard;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _EekboardServerClass {
 | 
			
		||||
    GObjectClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (EekboardServer, eekboard_server, G_TYPE_OBJECT);
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
update_widget (EekboardServer *server)
 | 
			
		||||
{
 | 
			
		||||
    GdkScreen *screen;
 | 
			
		||||
    GdkWindow *root;
 | 
			
		||||
    gint monitor;
 | 
			
		||||
    GdkRectangle rect;
 | 
			
		||||
    EekBounds bounds;
 | 
			
		||||
 | 
			
		||||
    if (server->widget)
 | 
			
		||||
        gtk_widget_destroy (server->widget);
 | 
			
		||||
 | 
			
		||||
    if (server->window)
 | 
			
		||||
        gtk_widget_destroy (server->window);
 | 
			
		||||
 | 
			
		||||
    server->widget = eek_gtk_keyboard_new (server->keyboard);
 | 
			
		||||
 | 
			
		||||
    eek_element_get_bounds (EEK_ELEMENT(server->keyboard), &bounds);
 | 
			
		||||
    gtk_widget_set_size_request (server->widget, bounds.width, bounds.height);
 | 
			
		||||
 | 
			
		||||
    server->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 | 
			
		||||
    gtk_container_add (GTK_CONTAINER(server->window), server->widget);
 | 
			
		||||
 | 
			
		||||
    gtk_widget_set_can_focus (server->window, FALSE);
 | 
			
		||||
    g_object_set (G_OBJECT(server->window), "accept_focus", FALSE, NULL);
 | 
			
		||||
    gtk_window_set_title (GTK_WINDOW(server->window), "Keyboard");
 | 
			
		||||
 | 
			
		||||
    screen = gdk_screen_get_default ();
 | 
			
		||||
    root = gtk_widget_get_root_window (server->window);
 | 
			
		||||
    monitor = gdk_screen_get_monitor_at_window (screen, root);
 | 
			
		||||
    gdk_screen_get_monitor_geometry (screen, monitor, &rect);
 | 
			
		||||
    gtk_window_move (GTK_WINDOW(server->window),
 | 
			
		||||
                     MAX(rect.width - 20 - bounds.width, 0),
 | 
			
		||||
                     MAX(rect.height - 40 - bounds.height, 0));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eekboard_server_set_property (GObject      *object,
 | 
			
		||||
                              guint         prop_id,
 | 
			
		||||
                              const GValue *value,
 | 
			
		||||
                              GParamSpec   *pspec)
 | 
			
		||||
{
 | 
			
		||||
    EekboardServer *server = EEKBOARD_SERVER(object);
 | 
			
		||||
    GDBusConnection *connection;
 | 
			
		||||
 | 
			
		||||
    switch (prop_id) {
 | 
			
		||||
    case PROP_CONNECTION:
 | 
			
		||||
        connection = g_value_get_object (value);
 | 
			
		||||
        if (server->connection)
 | 
			
		||||
            g_object_unref (server->connection);
 | 
			
		||||
        server->connection = g_object_ref (connection);
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        g_object_set_property (object,
 | 
			
		||||
                               g_param_spec_get_name (pspec),
 | 
			
		||||
                               value);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eekboard_server_dispose (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
    EekboardServer *server = EEKBOARD_SERVER(object);
 | 
			
		||||
    if (server->connection) {
 | 
			
		||||
        g_object_unref (server->connection);
 | 
			
		||||
        server->connection = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    G_OBJECT_CLASS (eekboard_server_parent_class)->dispose (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eekboard_server_class_init (EekboardServerClass *klass)
 | 
			
		||||
{
 | 
			
		||||
    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
    GParamSpec *pspec;
 | 
			
		||||
 | 
			
		||||
    gobject_class->set_property = eekboard_server_set_property;
 | 
			
		||||
    gobject_class->dispose = eekboard_server_dispose;
 | 
			
		||||
 | 
			
		||||
    pspec = g_param_spec_object ("connection",
 | 
			
		||||
                                 "Connection",
 | 
			
		||||
                                 "Connection",
 | 
			
		||||
                                 G_TYPE_DBUS_CONNECTION,
 | 
			
		||||
                                 G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE);
 | 
			
		||||
    g_object_class_install_property (gobject_class,
 | 
			
		||||
                                     PROP_CONNECTION,
 | 
			
		||||
                                     pspec);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eekboard_server_init (EekboardServer *server)
 | 
			
		||||
{
 | 
			
		||||
    GError *error;
 | 
			
		||||
 | 
			
		||||
    error = NULL;
 | 
			
		||||
    server->introspection_data =
 | 
			
		||||
        g_dbus_node_info_new_for_xml (introspection_xml, &error);
 | 
			
		||||
    g_assert (server->introspection_data != NULL);
 | 
			
		||||
    server->owner_id = 0;
 | 
			
		||||
    server->keyboard = NULL;
 | 
			
		||||
    server->widget = NULL;
 | 
			
		||||
    server->window = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_key_pressed (EekKeyboard *keyboard,
 | 
			
		||||
                EekKey      *key,
 | 
			
		||||
                gpointer     user_data)
 | 
			
		||||
{
 | 
			
		||||
    EekboardServer *server = user_data;
 | 
			
		||||
    GError *error;
 | 
			
		||||
 | 
			
		||||
    error = NULL;
 | 
			
		||||
    g_dbus_connection_emit_signal (server->connection,
 | 
			
		||||
                                   "com.redhat.eekboard.Keyboard",
 | 
			
		||||
                                   "/com/redhat/eekboard/Keyboard",
 | 
			
		||||
                                   "com.redhat.eekboard.Keyboard",
 | 
			
		||||
                                   "KeyPressed",
 | 
			
		||||
                                   g_variant_new ("(u)",
 | 
			
		||||
                                                  eek_key_get_keycode (key)),
 | 
			
		||||
                                   &error);
 | 
			
		||||
    g_assert_no_error (error);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_key_released (EekKeyboard *keyboard,
 | 
			
		||||
                EekKey      *key,
 | 
			
		||||
                gpointer     user_data)
 | 
			
		||||
{
 | 
			
		||||
    EekboardServer *server = user_data;
 | 
			
		||||
    GError *error;
 | 
			
		||||
 | 
			
		||||
    error = NULL;
 | 
			
		||||
    g_dbus_connection_emit_signal (server->connection,
 | 
			
		||||
                                   "com.redhat.eekboard.Keyboard",
 | 
			
		||||
                                   "/com/redhat/eekboard/Keyboard",
 | 
			
		||||
                                   "com.redhat.eekboard.Keyboard",
 | 
			
		||||
                                   "KeyReleased",
 | 
			
		||||
                                   g_variant_new ("(u)",
 | 
			
		||||
                                                  eek_key_get_keycode (key)),
 | 
			
		||||
                                   &error);
 | 
			
		||||
    g_assert_no_error (error);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
handle_method_call (GDBusConnection       *connection,
 | 
			
		||||
                    const gchar           *sender,
 | 
			
		||||
                    const gchar           *object_path,
 | 
			
		||||
                    const gchar           *interface_name,
 | 
			
		||||
                    const gchar           *method_name,
 | 
			
		||||
                    GVariant              *parameters,
 | 
			
		||||
                    GDBusMethodInvocation *invocation,
 | 
			
		||||
                    gpointer               user_data)
 | 
			
		||||
{
 | 
			
		||||
    EekboardServer *server = user_data;
 | 
			
		||||
 | 
			
		||||
    g_debug ("%s", method_name);
 | 
			
		||||
    if (g_strcmp0 (method_name, "SetKeyboard") == 0) {
 | 
			
		||||
        GVariant *variant;
 | 
			
		||||
        gchar *data;
 | 
			
		||||
        GInputStream *input;
 | 
			
		||||
        EekLayout *layout;
 | 
			
		||||
 | 
			
		||||
        g_variant_get (parameters, "(v)", &variant);
 | 
			
		||||
        g_variant_get (variant, "(&s)", &data);
 | 
			
		||||
        input = g_memory_input_stream_new_from_data (data, -1, NULL);
 | 
			
		||||
        g_variant_unref (variant);
 | 
			
		||||
 | 
			
		||||
        layout = eek_xml_layout_new (input);
 | 
			
		||||
        if (!layout) {
 | 
			
		||||
            g_dbus_method_invocation_return_error (invocation,
 | 
			
		||||
                                                   G_IO_ERROR,
 | 
			
		||||
                                                   G_IO_ERROR_FAILED_HANDLED,
 | 
			
		||||
                                                   "can't create layout");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        server->keyboard = eek_keyboard_new (layout, CSW, CSH);
 | 
			
		||||
        g_signal_connect (server->keyboard, "key-pressed",
 | 
			
		||||
                          G_CALLBACK(on_key_pressed),
 | 
			
		||||
                          server);
 | 
			
		||||
        g_signal_connect (server->keyboard, "key-released",
 | 
			
		||||
                          G_CALLBACK(on_key_released),
 | 
			
		||||
                          server);
 | 
			
		||||
        eek_keyboard_set_modifier_behavior (server->keyboard,
 | 
			
		||||
                                            EEK_MODIFIER_BEHAVIOR_LATCH);
 | 
			
		||||
        
 | 
			
		||||
        update_widget (server);
 | 
			
		||||
        g_dbus_method_invocation_return_value (invocation, NULL);
 | 
			
		||||
    } else if (g_strcmp0 (method_name, "SetGroup") == 0) {
 | 
			
		||||
        gint group;
 | 
			
		||||
 | 
			
		||||
        if (!server->keyboard)
 | 
			
		||||
            g_dbus_method_invocation_return_error (invocation,
 | 
			
		||||
                                                   G_IO_ERROR,
 | 
			
		||||
                                                   G_IO_ERROR_FAILED_HANDLED,
 | 
			
		||||
                                                   "keyboard is not set");
 | 
			
		||||
        g_variant_get (parameters, "(i)", &group);
 | 
			
		||||
        eek_keyboard_set_group (server->keyboard, group);
 | 
			
		||||
        g_dbus_method_invocation_return_value (invocation, NULL);
 | 
			
		||||
    } else if (g_strcmp0 (method_name, "Show") == 0) {
 | 
			
		||||
        if (!server->keyboard)
 | 
			
		||||
            g_dbus_method_invocation_return_error (invocation,
 | 
			
		||||
                                                   G_IO_ERROR,
 | 
			
		||||
                                                   G_IO_ERROR_FAILED_HANDLED,
 | 
			
		||||
                                                   "keyboard is not set");
 | 
			
		||||
        if (server->window)
 | 
			
		||||
            gtk_widget_show_all (server->window);
 | 
			
		||||
        g_dbus_method_invocation_return_value (invocation, NULL);
 | 
			
		||||
    } else if (g_strcmp0 (method_name, "Hide") == 0) {
 | 
			
		||||
        if (server->window)
 | 
			
		||||
            gtk_widget_hide (server->window);
 | 
			
		||||
        g_dbus_method_invocation_return_value (invocation, NULL);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const GDBusInterfaceVTable interface_vtable =
 | 
			
		||||
{
 | 
			
		||||
  handle_method_call,
 | 
			
		||||
  NULL,
 | 
			
		||||
  NULL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_name_acquired (GDBusConnection *connection,
 | 
			
		||||
                  const gchar     *name,
 | 
			
		||||
                  gpointer         user_data)
 | 
			
		||||
{
 | 
			
		||||
    //g_debug ("name acquired %s", name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_name_lost (GDBusConnection *connection,
 | 
			
		||||
              const gchar     *name,
 | 
			
		||||
              gpointer         user_data)
 | 
			
		||||
{
 | 
			
		||||
    //g_debug ("name lost %s", name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EekboardServer *
 | 
			
		||||
eekboard_server_new (GDBusConnection *connection)
 | 
			
		||||
{
 | 
			
		||||
    return g_object_new (EEKBOARD_TYPE_SERVER, "connection", connection, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
eekboard_server_start (EekboardServer *server)
 | 
			
		||||
{
 | 
			
		||||
    guint registration_id;
 | 
			
		||||
    GError *error;
 | 
			
		||||
 | 
			
		||||
    error = NULL;
 | 
			
		||||
    registration_id = g_dbus_connection_register_object
 | 
			
		||||
        (server->connection,
 | 
			
		||||
         "/com/redhat/eekboard/Keyboard",
 | 
			
		||||
         server->introspection_data->interfaces[0],
 | 
			
		||||
         &interface_vtable,
 | 
			
		||||
         server,
 | 
			
		||||
         NULL,
 | 
			
		||||
         &error);
 | 
			
		||||
    if (error)
 | 
			
		||||
        g_printerr ("%s\n", error->message);
 | 
			
		||||
    g_assert (registration_id > 0);
 | 
			
		||||
 | 
			
		||||
    server->owner_id =
 | 
			
		||||
        g_bus_own_name_on_connection (server->connection,
 | 
			
		||||
                                      "com.redhat.eekboard.Keyboard",
 | 
			
		||||
                                      G_BUS_NAME_OWNER_FLAGS_NONE,
 | 
			
		||||
                                      on_name_acquired,
 | 
			
		||||
                                      on_name_lost,
 | 
			
		||||
                                      NULL,
 | 
			
		||||
                                      NULL);
 | 
			
		||||
    return server->owner_id > 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
eekboard_server_stop (EekboardServer *server)
 | 
			
		||||
{
 | 
			
		||||
    if (server->owner_id > 0)
 | 
			
		||||
        g_bus_unown_name (server->owner_id);
 | 
			
		||||
    if (server->introspection_data)
 | 
			
		||||
        g_dbus_node_info_unref (server->introspection_data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										40
									
								
								src/server.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/server.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,40 @@
 | 
			
		||||
/* 
 | 
			
		||||
 * Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
 | 
			
		||||
 * Copyright (C) 2010-2011 Red Hat, Inc.
 | 
			
		||||
 * 
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program 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 General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef EEKBOARD_SERVER_H
 | 
			
		||||
#define EEKBOARD_SERVER_H 1
 | 
			
		||||
 | 
			
		||||
#include <gio/gio.h>
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
#define EEKBOARD_TYPE_SERVER (eekboard_server_get_type())
 | 
			
		||||
#define EEKBOARD_SERVER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEKBOARD_TYPE_SERVER, EekboardServer))
 | 
			
		||||
#define EEKBOARD_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEKBOARD_TYPE_SERVER, EekboardServerClass))
 | 
			
		||||
#define EEKBOARD_IS_SERVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEKBOARD_TYPE_SERVER))
 | 
			
		||||
#define EEKBOARD_IS_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEKBOARD_TYPE_SERVER))
 | 
			
		||||
#define EEKBOARD_SERVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEKBOARD_TYPE_SERVER, EekboardServerClass))
 | 
			
		||||
 | 
			
		||||
typedef struct _EekboardServer EekboardServer;
 | 
			
		||||
 | 
			
		||||
EekboardServer *eekboard_server_new   (GDBusConnection *connection);
 | 
			
		||||
 | 
			
		||||
gboolean        eekboard_server_start (EekboardServer  *server);
 | 
			
		||||
void            eekboard_server_stop  (EekboardServer  *server);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
#endif  /* EEKBOARD_SERVER_H */
 | 
			
		||||
							
								
								
									
										86
									
								
								src/system-client-main.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/system-client-main.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,86 @@
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <cspi/spi.h>
 | 
			
		||||
#include <gtk/gtk.h>
 | 
			
		||||
#include <gconf/gconf-client.h>
 | 
			
		||||
#include "system-client.h"
 | 
			
		||||
 | 
			
		||||
gboolean opt_xkl = FALSE;
 | 
			
		||||
gboolean opt_cspi = FALSE;
 | 
			
		||||
gboolean opt_fakekey = FALSE;
 | 
			
		||||
 | 
			
		||||
static const GOptionEntry options[] = {
 | 
			
		||||
    {"xklavier", 'x', 0, G_OPTION_ARG_NONE, &opt_xkl,
 | 
			
		||||
     "Listen xklavier events"},
 | 
			
		||||
    {"accessibility", 'a', 0, G_OPTION_ARG_NONE, &opt_cspi,
 | 
			
		||||
     "Listen accessibility events"},
 | 
			
		||||
    {"fakekey", 'k', 0, G_OPTION_ARG_NONE, &opt_fakekey,
 | 
			
		||||
     "Generate X key events via libfakekey"},
 | 
			
		||||
    {NULL}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main (int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
    EekboardSystemClient *client;
 | 
			
		||||
    GDBusConnection *connection;
 | 
			
		||||
    GError *error;
 | 
			
		||||
    GConfClient *gconfc;
 | 
			
		||||
    GOptionContext *context;
 | 
			
		||||
 | 
			
		||||
    if (!gtk_init_check (&argc, &argv)) {
 | 
			
		||||
        g_printerr ("Can't init GTK\n");
 | 
			
		||||
        exit (1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    context = g_option_context_new ("eekboard-system-client");
 | 
			
		||||
    g_option_context_add_main_entries (context, options, NULL);
 | 
			
		||||
    g_option_context_parse (context, &argc, &argv, NULL);
 | 
			
		||||
    g_option_context_free (context);
 | 
			
		||||
 | 
			
		||||
    error = NULL;
 | 
			
		||||
    connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
 | 
			
		||||
    if (error) {
 | 
			
		||||
        g_printerr ("%s\n", error->message);
 | 
			
		||||
        exit (1);
 | 
			
		||||
    }
 | 
			
		||||
    client = eekboard_system_client_new (connection);
 | 
			
		||||
 | 
			
		||||
    gconfc = gconf_client_get_default ();
 | 
			
		||||
    error = NULL;
 | 
			
		||||
    if (opt_cspi) {
 | 
			
		||||
        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) {
 | 
			
		||||
                g_printerr ("Can't init CSPI\n");
 | 
			
		||||
                exit (1);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!eekboard_system_client_enable_cspi (client)) {
 | 
			
		||||
                g_printerr ("Can't register accessibility event listeners\n");
 | 
			
		||||
                exit (1);
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            g_printerr ("System accessibility support is disabled");
 | 
			
		||||
            exit (1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (opt_xkl &&
 | 
			
		||||
        !eekboard_system_client_enable_xkl (client)) {
 | 
			
		||||
        g_printerr ("Can't register xklavier event listeners\n"); 
 | 
			
		||||
        exit (1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (opt_fakekey &&
 | 
			
		||||
        !eekboard_system_client_enable_fakekey (client)) {
 | 
			
		||||
        g_printerr ("Can't init fakekey\n"); 
 | 
			
		||||
        exit (1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    gtk_main ();
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										477
									
								
								src/system-client.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										477
									
								
								src/system-client.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,477 @@
 | 
			
		||||
/* 
 | 
			
		||||
 * Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
 | 
			
		||||
 * Copyright (C) 2010-2011 Red Hat, Inc.
 | 
			
		||||
 * 
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program 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 General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
#include <libxklavier/xklavier.h>
 | 
			
		||||
#include <cspi/spi.h>
 | 
			
		||||
#include <gdk/gdkx.h>
 | 
			
		||||
#include <fakekey/fakekey.h>
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_CONFIG_H
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#endif  /* HAVE_CONFIG_H */
 | 
			
		||||
 | 
			
		||||
#include "eek/eek.h"
 | 
			
		||||
#include "eek/eek-xkl.h"
 | 
			
		||||
#include "system-client.h"
 | 
			
		||||
#include "proxy.h"
 | 
			
		||||
 | 
			
		||||
#define CSW 640
 | 
			
		||||
#define CSH 480
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    PROP_0,
 | 
			
		||||
    PROP_CONNECTION,
 | 
			
		||||
    PROP_LAST
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct _EekboardSystemClientClass EekboardSystemClientClass;
 | 
			
		||||
 | 
			
		||||
struct _EekboardSystemClient {
 | 
			
		||||
    GObject parent;
 | 
			
		||||
 | 
			
		||||
    EekboardProxy *proxy;
 | 
			
		||||
 | 
			
		||||
    EekKeyboard *keyboard;
 | 
			
		||||
    Accessible *accessible;
 | 
			
		||||
    XklEngine *xkl_engine;
 | 
			
		||||
    XklConfigRegistry *xkl_config_registry;
 | 
			
		||||
    FakeKey *fakekey;
 | 
			
		||||
 | 
			
		||||
    gulong xkl_config_changed_handler_id;
 | 
			
		||||
    gulong xkl_state_changed_handler_id;
 | 
			
		||||
 | 
			
		||||
    gulong key_pressed_handler_id;
 | 
			
		||||
    gulong key_released_handler_id;
 | 
			
		||||
 | 
			
		||||
    AccessibleEventListener *focus_listener;
 | 
			
		||||
    AccessibleEventListener *keystroke_listener;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _EekboardSystemClientClass {
 | 
			
		||||
    GObjectClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (EekboardSystemClient, eekboard_system_client, G_TYPE_OBJECT);
 | 
			
		||||
 | 
			
		||||
static GdkFilterReturn filter_xkl_event  (GdkXEvent                 *xev,
 | 
			
		||||
                                          GdkEvent                  *event,
 | 
			
		||||
                                          gpointer                   user_data);
 | 
			
		||||
static void            on_xkl_config_changed
 | 
			
		||||
                                         (XklEngine                 *xklengine,
 | 
			
		||||
                                          gpointer                   user_data);
 | 
			
		||||
 | 
			
		||||
static void            on_xkl_state_changed
 | 
			
		||||
                                         (XklEngine                 *xklengine,
 | 
			
		||||
                                          XklEngineStateChange       type,
 | 
			
		||||
                                          gint                       value,
 | 
			
		||||
                                          gboolean                   restore,
 | 
			
		||||
                                          gpointer                   user_data);
 | 
			
		||||
 | 
			
		||||
static SPIBoolean      focus_listener_cb (const AccessibleEvent     *event,
 | 
			
		||||
                                          void                      *user_data);
 | 
			
		||||
 | 
			
		||||
static SPIBoolean      keystroke_listener_cb
 | 
			
		||||
                                         (const AccessibleKeystroke *stroke,
 | 
			
		||||
                                          void                      *user_data);
 | 
			
		||||
static void            set_keyboard      (EekboardSystemClient     *client);
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eekboard_system_client_set_property (GObject      *object,
 | 
			
		||||
                                      guint         prop_id,
 | 
			
		||||
                                      const GValue *value,
 | 
			
		||||
                                      GParamSpec   *pspec)
 | 
			
		||||
{
 | 
			
		||||
    EekboardSystemClient *client = EEKBOARD_SYSTEM_CLIENT(object);
 | 
			
		||||
    GDBusConnection *connection;
 | 
			
		||||
    GError *error;
 | 
			
		||||
 | 
			
		||||
    switch (prop_id) {
 | 
			
		||||
    case PROP_CONNECTION:
 | 
			
		||||
        connection = g_value_get_object (value);
 | 
			
		||||
        error = NULL;
 | 
			
		||||
        client->proxy = eekboard_proxy_new ("/com/redhat/eekboard/Keyboard",
 | 
			
		||||
                                             connection,
 | 
			
		||||
                                             NULL,
 | 
			
		||||
                                             &error);
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        g_object_set_property (object,
 | 
			
		||||
                               g_param_spec_get_name (pspec),
 | 
			
		||||
                               value);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eekboard_system_client_dispose (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
    EekboardSystemClient *client = EEKBOARD_SYSTEM_CLIENT(object);
 | 
			
		||||
 | 
			
		||||
    eekboard_system_client_disable_xkl (client);
 | 
			
		||||
    eekboard_system_client_disable_cspi (client);
 | 
			
		||||
    eekboard_system_client_disable_fakekey (client);
 | 
			
		||||
 | 
			
		||||
    if (client->proxy) {
 | 
			
		||||
        g_object_unref (client->proxy);
 | 
			
		||||
        client->proxy = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (client->fakekey) {
 | 
			
		||||
        client->fakekey = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    G_OBJECT_CLASS (eekboard_system_client_parent_class)->dispose (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eekboard_system_client_class_init (EekboardSystemClientClass *klass)
 | 
			
		||||
{
 | 
			
		||||
    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
    GParamSpec *pspec;
 | 
			
		||||
 | 
			
		||||
    gobject_class->set_property = eekboard_system_client_set_property;
 | 
			
		||||
    gobject_class->dispose = eekboard_system_client_dispose;
 | 
			
		||||
 | 
			
		||||
    pspec = g_param_spec_object ("connection",
 | 
			
		||||
                                 "Connection",
 | 
			
		||||
                                 "Connection",
 | 
			
		||||
                                 G_TYPE_DBUS_CONNECTION,
 | 
			
		||||
                                 G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE);
 | 
			
		||||
    g_object_class_install_property (gobject_class,
 | 
			
		||||
                                     PROP_CONNECTION,
 | 
			
		||||
                                     pspec);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eekboard_system_client_init (EekboardSystemClient *client)
 | 
			
		||||
{
 | 
			
		||||
    client->keyboard = NULL;
 | 
			
		||||
    client->accessible = NULL;
 | 
			
		||||
    client->xkl_engine = NULL;
 | 
			
		||||
    client->xkl_config_registry = NULL;
 | 
			
		||||
    client->focus_listener = NULL;
 | 
			
		||||
    client->keystroke_listener = NULL;
 | 
			
		||||
    client->proxy = NULL;
 | 
			
		||||
    client->fakekey = NULL;
 | 
			
		||||
    client->key_pressed_handler_id = 0;
 | 
			
		||||
    client->key_released_handler_id = 0;
 | 
			
		||||
    client->xkl_config_changed_handler_id = 0;
 | 
			
		||||
    client->xkl_state_changed_handler_id = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
eekboard_system_client_enable_xkl (EekboardSystemClient *client)
 | 
			
		||||
{
 | 
			
		||||
    if (!client->xkl_engine) {
 | 
			
		||||
        Display *display;
 | 
			
		||||
 | 
			
		||||
        display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 | 
			
		||||
        client->xkl_engine = xkl_engine_get_instance (display);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!client->xkl_config_registry) {
 | 
			
		||||
        client->xkl_config_registry =
 | 
			
		||||
            xkl_config_registry_get_instance (client->xkl_engine);
 | 
			
		||||
        xkl_config_registry_load (client->xkl_config_registry, FALSE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    client->xkl_config_changed_handler_id =
 | 
			
		||||
        g_signal_connect (client->xkl_engine, "X-config-changed",
 | 
			
		||||
                          G_CALLBACK(on_xkl_config_changed), client);
 | 
			
		||||
    client->xkl_state_changed_handler_id =
 | 
			
		||||
        g_signal_connect (client->xkl_engine, "X-state-changed",
 | 
			
		||||
                          G_CALLBACK(on_xkl_state_changed), client);
 | 
			
		||||
 | 
			
		||||
    gdk_window_add_filter (NULL,
 | 
			
		||||
                           (GdkFilterFunc) filter_xkl_event,
 | 
			
		||||
                           client);
 | 
			
		||||
    gdk_window_add_filter (gdk_get_default_root_window (),
 | 
			
		||||
                           (GdkFilterFunc) filter_xkl_event,
 | 
			
		||||
                           client);
 | 
			
		||||
 | 
			
		||||
    xkl_engine_start_listen (client->xkl_engine, XKLL_TRACK_KEYBOARD_STATE);
 | 
			
		||||
 | 
			
		||||
    set_keyboard (client);
 | 
			
		||||
 | 
			
		||||
    return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
eekboard_system_client_disable_xkl (EekboardSystemClient *client)
 | 
			
		||||
{
 | 
			
		||||
    if (client->xkl_engine)
 | 
			
		||||
        xkl_engine_stop_listen (client->xkl_engine, XKLL_TRACK_KEYBOARD_STATE);
 | 
			
		||||
    if (g_signal_handler_is_connected (client->xkl_engine,
 | 
			
		||||
                                       client->xkl_config_changed_handler_id))
 | 
			
		||||
        g_signal_handler_disconnect (client->xkl_engine,
 | 
			
		||||
                                     client->xkl_config_changed_handler_id);
 | 
			
		||||
    if (g_signal_handler_is_connected (client->xkl_engine,
 | 
			
		||||
                                       client->xkl_state_changed_handler_id))
 | 
			
		||||
        g_signal_handler_disconnect (client->xkl_engine,
 | 
			
		||||
                                     client->xkl_state_changed_handler_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
eekboard_system_client_enable_cspi (EekboardSystemClient *client)
 | 
			
		||||
{
 | 
			
		||||
    client->focus_listener = SPI_createAccessibleEventListener
 | 
			
		||||
        ((AccessibleEventListenerCB)focus_listener_cb,
 | 
			
		||||
         client);
 | 
			
		||||
 | 
			
		||||
    if (!SPI_registerGlobalEventListener (client->focus_listener,
 | 
			
		||||
                                          "object:state-changed:focused"))
 | 
			
		||||
        return FALSE;
 | 
			
		||||
 | 
			
		||||
    if (!SPI_registerGlobalEventListener (client->focus_listener,
 | 
			
		||||
                                          "focus:"))
 | 
			
		||||
        return FALSE;
 | 
			
		||||
 | 
			
		||||
    client->keystroke_listener =
 | 
			
		||||
        SPI_createAccessibleKeystrokeListener (keystroke_listener_cb,
 | 
			
		||||
                                               client);
 | 
			
		||||
 | 
			
		||||
    if (!SPI_registerAccessibleKeystrokeListener
 | 
			
		||||
        (client->keystroke_listener,
 | 
			
		||||
         SPI_KEYSET_ALL_KEYS,
 | 
			
		||||
         0,
 | 
			
		||||
         SPI_KEY_PRESSED |
 | 
			
		||||
         SPI_KEY_RELEASED,
 | 
			
		||||
         SPI_KEYLISTENER_NOSYNC))
 | 
			
		||||
        return FALSE;
 | 
			
		||||
    return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
eekboard_system_client_disable_cspi (EekboardSystemClient *client)
 | 
			
		||||
{
 | 
			
		||||
    if (client->focus_listener) {
 | 
			
		||||
        SPI_deregisterGlobalEventListenerAll (client->focus_listener);
 | 
			
		||||
        AccessibleEventListener_unref (client->focus_listener);
 | 
			
		||||
        client->focus_listener = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    if (client->keystroke_listener) {
 | 
			
		||||
        SPI_deregisterAccessibleKeystrokeListener (client->keystroke_listener,
 | 
			
		||||
                                                   0);
 | 
			
		||||
        AccessibleKeystrokeListener_unref (client->keystroke_listener);
 | 
			
		||||
        client->keystroke_listener = NULL;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EekboardSystemClient *
 | 
			
		||||
eekboard_system_client_new (GDBusConnection *connection)
 | 
			
		||||
{
 | 
			
		||||
    return g_object_new (EEKBOARD_TYPE_SYSTEM_CLIENT,
 | 
			
		||||
                         "connection", connection,
 | 
			
		||||
                         NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static SPIBoolean
 | 
			
		||||
focus_listener_cb (const AccessibleEvent *event,
 | 
			
		||||
                   void                  *user_data)
 | 
			
		||||
{
 | 
			
		||||
    EekboardSystemClient *client = user_data;
 | 
			
		||||
    Accessible *accessible = event->source;
 | 
			
		||||
    AccessibleStateSet *state_set = Accessible_getStateSet (accessible);
 | 
			
		||||
    AccessibleRole role = Accessible_getRole (accessible);
 | 
			
		||||
 | 
			
		||||
    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 (g_strcmp0 (event->type, "focus") == 0 ||
 | 
			
		||||
                event->detail1 == 1) {
 | 
			
		||||
                client->accessible = accessible;
 | 
			
		||||
                eekboard_proxy_show (client->proxy);
 | 
			
		||||
            } else if (event->detail1 == 0 &&
 | 
			
		||||
                       accessible == client->accessible) {
 | 
			
		||||
                client->accessible = NULL;
 | 
			
		||||
                eekboard_proxy_hide (client->proxy);
 | 
			
		||||
            }
 | 
			
		||||
        case SPI_ROLE_ENTRY:
 | 
			
		||||
            if (g_strcmp0 (event->type, "focus") == 0 ||
 | 
			
		||||
                event->detail1 == 1) {
 | 
			
		||||
                client->accessible = accessible;
 | 
			
		||||
                eekboard_proxy_show (client->proxy);
 | 
			
		||||
            } else if (event->detail1 == 0 &&
 | 
			
		||||
                       accessible == client->accessible) {
 | 
			
		||||
                client->accessible = NULL;
 | 
			
		||||
                eekboard_proxy_hide (client->proxy);
 | 
			
		||||
            }
 | 
			
		||||
        default:
 | 
			
		||||
            ;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static SPIBoolean
 | 
			
		||||
keystroke_listener_cb (const AccessibleKeystroke *stroke,
 | 
			
		||||
                       void                      *user_data)
 | 
			
		||||
{
 | 
			
		||||
    EekboardSystemClient *client = user_data;
 | 
			
		||||
    EekKey *key;
 | 
			
		||||
    EekSymbol *symbol;
 | 
			
		||||
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
    key = eek_keyboard_find_key_by_keycode (client->keyboard,
 | 
			
		||||
                                            stroke->keycode);
 | 
			
		||||
    if (!key)
 | 
			
		||||
        return FALSE;
 | 
			
		||||
 | 
			
		||||
    symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
 | 
			
		||||
    if (!symbol)
 | 
			
		||||
        return FALSE;
 | 
			
		||||
 | 
			
		||||
    /* XXX: Ignore modifier keys since there is no way to receive
 | 
			
		||||
       SPI_KEY_RELEASED event for them. */
 | 
			
		||||
    if (eek_symbol_is_modifier (symbol))
 | 
			
		||||
        return FALSE;
 | 
			
		||||
 | 
			
		||||
    if (stroke->type == SPI_KEY_PRESSED)
 | 
			
		||||
        g_signal_emit_by_name (key, "pressed");
 | 
			
		||||
    else
 | 
			
		||||
        g_signal_emit_by_name (key, "released");
 | 
			
		||||
    return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GdkFilterReturn
 | 
			
		||||
filter_xkl_event (GdkXEvent *xev,
 | 
			
		||||
                  GdkEvent  *event,
 | 
			
		||||
                  gpointer   user_data)
 | 
			
		||||
{
 | 
			
		||||
    EekboardSystemClient *client = user_data;
 | 
			
		||||
    XEvent *xevent = (XEvent *)xev;
 | 
			
		||||
 | 
			
		||||
    xkl_engine_filter_events (client->xkl_engine, xevent);
 | 
			
		||||
    return GDK_FILTER_CONTINUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_xkl_config_changed (XklEngine *xklengine,
 | 
			
		||||
                       gpointer   user_data)
 | 
			
		||||
{
 | 
			
		||||
    EekboardSystemClient *client = user_data;
 | 
			
		||||
 | 
			
		||||
    set_keyboard (client);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
set_keyboard (EekboardSystemClient *client)
 | 
			
		||||
{
 | 
			
		||||
    EekLayout *layout;
 | 
			
		||||
    gchar *keyboard_name;
 | 
			
		||||
    static gint keyboard_serial = 0;
 | 
			
		||||
 | 
			
		||||
    if (client->keyboard)
 | 
			
		||||
        g_object_unref (client->keyboard);
 | 
			
		||||
    layout = eek_xkl_layout_new ();
 | 
			
		||||
    client->keyboard = eek_keyboard_new (layout, CSW, CSH);
 | 
			
		||||
 | 
			
		||||
    keyboard_name = g_strdup_printf ("keyboard%d", keyboard_serial++);
 | 
			
		||||
    eek_element_set_name (EEK_ELEMENT(client->keyboard), keyboard_name);
 | 
			
		||||
 | 
			
		||||
    eekboard_proxy_set_keyboard (client->proxy, client->keyboard);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_xkl_state_changed (XklEngine           *xklengine,
 | 
			
		||||
                      XklEngineStateChange type,
 | 
			
		||||
                      gint                 value,
 | 
			
		||||
                      gboolean             restore,
 | 
			
		||||
                      gpointer             user_data)
 | 
			
		||||
{
 | 
			
		||||
    EekboardSystemClient *client = user_data;
 | 
			
		||||
 | 
			
		||||
    if (type == GROUP_CHANGED && client->keyboard) {
 | 
			
		||||
        gint group = eek_keyboard_get_group (client->keyboard);
 | 
			
		||||
        if (group != value) {
 | 
			
		||||
            eek_keyboard_set_group (client->keyboard, value);
 | 
			
		||||
            eekboard_proxy_set_group (client->proxy, value);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_key_pressed (EekboardProxy *proxy,
 | 
			
		||||
                guint          keycode,
 | 
			
		||||
                gpointer       user_data)
 | 
			
		||||
{
 | 
			
		||||
    EekboardSystemClient *client = user_data;
 | 
			
		||||
    EekKey *key;
 | 
			
		||||
    EekSymbol *symbol;
 | 
			
		||||
 | 
			
		||||
    g_assert (client->fakekey);
 | 
			
		||||
    key = eek_keyboard_find_key_by_keycode (client->keyboard, keycode);
 | 
			
		||||
    symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
 | 
			
		||||
    if (EEK_IS_KEYSYM(symbol) && !eek_symbol_is_modifier (symbol))
 | 
			
		||||
        fakekey_press_keysym (client->fakekey,
 | 
			
		||||
                              eek_keysym_get_xkeysym (EEK_KEYSYM(symbol)),
 | 
			
		||||
                              eek_keyboard_get_modifiers (client->keyboard));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_key_released (EekboardProxy *proxy,
 | 
			
		||||
                 guint          keycode,
 | 
			
		||||
                 gpointer       user_data)
 | 
			
		||||
{
 | 
			
		||||
    EekboardSystemClient *client = user_data;
 | 
			
		||||
 | 
			
		||||
    g_assert (client->fakekey);
 | 
			
		||||
    fakekey_release (client->fakekey);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
eekboard_system_client_enable_fakekey (EekboardSystemClient *client)
 | 
			
		||||
{
 | 
			
		||||
    if (!client->fakekey) {
 | 
			
		||||
        Display *display;
 | 
			
		||||
 | 
			
		||||
        display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 | 
			
		||||
        client->fakekey = fakekey_init (display);
 | 
			
		||||
    }
 | 
			
		||||
    g_assert (client->fakekey);
 | 
			
		||||
 | 
			
		||||
    client->key_pressed_handler_id =
 | 
			
		||||
        g_signal_connect (client->proxy, "key-pressed",
 | 
			
		||||
                          G_CALLBACK(on_key_pressed), client);
 | 
			
		||||
    client->key_released_handler_id =
 | 
			
		||||
        g_signal_connect (client->proxy, "key-pressed",
 | 
			
		||||
                          G_CALLBACK(on_key_released), client);
 | 
			
		||||
 | 
			
		||||
    return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
eekboard_system_client_disable_fakekey (EekboardSystemClient *client)
 | 
			
		||||
{
 | 
			
		||||
    if (client->fakekey)
 | 
			
		||||
        fakekey_release (client->fakekey);
 | 
			
		||||
 | 
			
		||||
    if (g_signal_handler_is_connected (client->proxy,
 | 
			
		||||
                                       client->key_pressed_handler_id))
 | 
			
		||||
        g_signal_handler_disconnect (client->proxy,
 | 
			
		||||
                                     client->key_pressed_handler_id);
 | 
			
		||||
    if (g_signal_handler_is_connected (client->proxy,
 | 
			
		||||
                                       client->key_released_handler_id))
 | 
			
		||||
        g_signal_handler_disconnect (client->proxy,
 | 
			
		||||
                                     client->key_released_handler_id);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										53
									
								
								src/system-client.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/system-client.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,53 @@
 | 
			
		||||
/* 
 | 
			
		||||
 * Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
 | 
			
		||||
 * Copyright (C) 2010-2011 Red Hat, Inc.
 | 
			
		||||
 * 
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program 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 General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef EEKBOARD_SYSTEM_CLIENT_H
 | 
			
		||||
#define EEKBOARD_SYSTEM_CLIENT_H 1
 | 
			
		||||
 | 
			
		||||
#include <gio/gio.h>
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
#define EEKBOARD_TYPE_SYSTEM_CLIENT (eekboard_system_client_get_type())
 | 
			
		||||
#define EEKBOARD_SYSTEM_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEKBOARD_TYPE_SYSTEM_CLIENT, EekboardSystemClient))
 | 
			
		||||
#define EEKBOARD_SYSTEM_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEKBOARD_TYPE_SYSTEM_CLIENT, EekboardSystemClientClass))
 | 
			
		||||
#define EEKBOARD_IS_SYSTEM_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEKBOARD_TYPE_SYSTEM_CLIENT))
 | 
			
		||||
#define EEKBOARD_IS_SYSTEM_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEKBOARD_TYPE_SYSTEM_CLIENT))
 | 
			
		||||
#define EEKBOARD_SYSTEM_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEKBOARD_TYPE_SYSTEM_CLIENT, EekboardSystemClientClass))
 | 
			
		||||
 | 
			
		||||
typedef struct _EekboardSystemClient EekboardSystemClient;
 | 
			
		||||
 | 
			
		||||
EekboardSystemClient * eekboard_system_client_new
 | 
			
		||||
                       (GDBusConnection      *connection);
 | 
			
		||||
 | 
			
		||||
gboolean               eekboard_system_client_enable_xkl
 | 
			
		||||
                       (EekboardSystemClient *client);
 | 
			
		||||
void                   eekboard_system_client_disable_xkl
 | 
			
		||||
                       (EekboardSystemClient *client);
 | 
			
		||||
 | 
			
		||||
gboolean               eekboard_system_client_enable_cspi
 | 
			
		||||
                       (EekboardSystemClient *client);
 | 
			
		||||
void                   eekboard_system_client_disable_cspi
 | 
			
		||||
                       (EekboardSystemClient *client);
 | 
			
		||||
 | 
			
		||||
gboolean               eekboard_system_client_enable_fakekey
 | 
			
		||||
                       (EekboardSystemClient *client);
 | 
			
		||||
void                   eekboard_system_client_disable_fakekey
 | 
			
		||||
                       (EekboardSystemClient *client);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
#endif  /* EEKBOARD_SYSTEM_CLIENT_H */
 | 
			
		||||
		Reference in New Issue
	
	Block a user