Make server responsible for loading keyboard files.

This commit is contained in:
Daiki Ueno
2011-08-17 18:11:28 +09:00
parent 84f614528f
commit 91ed49b65a
15 changed files with 905 additions and 1085 deletions

View File

@ -69,14 +69,19 @@ eekboard_server_CFLAGS = \
-I$(top_srcdir) \
$(GIO2_CFLAGS) \
$(GTK_CFLAGS) \
-DTHEMEDIR=\"$(pkgdatadir)/themes\"
$(LIBXKLAVIER_CFLAGS) \
-DTHEMEDIR=\"$(pkgdatadir)/themes\" \
-DKEYBOARDDIR=\"$(pkgdatadir)/keyboards\"
eekboard_server_LDADD = \
$(builddir)/libxklutil.la \
$(top_builddir)/eekboard/libeekboard.la \
$(top_builddir)/eek/libeek.la \
$(top_builddir)/eek/libeek-gtk.la \
$(top_builddir)/eek/libeek-xkl.la \
$(GIO2_LIBS) \
$(GTK_LIBS)
$(GTK_LIBS) \
$(LIBXKLAVIER_LIBS)
if ENABLE_CLUTTER_GTK
eekboard_server_CFLAGS += $(CLUTTER_GTK_CFLAGS)

View File

@ -32,7 +32,7 @@
#include "eekboard/eekboard.h"
#include "client.h"
#define DEFAULT_LAYOUT "us-qwerty"
#define DEFAULT_KEYBOARD "us"
static gboolean opt_system = FALSE;
static gboolean opt_session = FALSE;
@ -44,10 +44,6 @@ static gboolean opt_keystroke = FALSE;
static gchar *opt_keyboard = NULL;
static gchar *opt_model = NULL;
static gchar *opt_layouts = NULL;
static gchar *opt_options = NULL;
static gboolean opt_fullscreen = FALSE;
static const GOptionEntry options[] = {
@ -69,12 +65,6 @@ static const GOptionEntry options[] = {
#endif /* HAVE_ATSPI */
{"keyboard", 'k', 0, G_OPTION_ARG_STRING, &opt_keyboard,
N_("Specify keyboard")},
{"model", '\0', 0, G_OPTION_ARG_STRING, &opt_model,
N_("Specify model")},
{"layouts", '\0', 0, G_OPTION_ARG_STRING, &opt_layouts,
N_("Specify layouts")},
{"options", '\0', 0, G_OPTION_ARG_STRING, &opt_options,
N_("Specify options")},
{"fullscreen", 'F', 0, G_OPTION_ARG_NONE, &opt_fullscreen,
N_("Create window in fullscreen mode")},
{NULL}
@ -138,6 +128,13 @@ main (int argc, char **argv)
exit (1);
}
/* preload Eek* types for EekKeyboard deserialization */
g_type_class_ref (EEK_TYPE_KEYBOARD);
g_type_class_ref (EEK_TYPE_SECTION);
g_type_class_ref (EEK_TYPE_KEY);
g_type_class_ref (EEK_TYPE_SYMBOL);
g_type_class_ref (EEK_TYPE_KEYSYM);
option_context = g_option_context_new ("eekboard-desktop-client");
g_option_context_add_main_entries (option_context, options, NULL);
g_option_context_parse (option_context, &argc, &argv, NULL);
@ -254,7 +251,7 @@ main (int argc, char **argv)
}
#endif /* HAVE_IBUS */
if (opt_use_system_layout && (opt_keyboard || opt_model || opt_layouts || opt_options)) {
if (opt_use_system_layout && opt_keyboard) {
g_printerr ("Can't use --use-system-layout option with keyboard options\n");
g_object_unref (client);
exit (1);
@ -266,35 +263,6 @@ main (int argc, char **argv)
exit (1);
}
if (opt_use_system_layout || opt_model || opt_layouts || opt_options) {
if (!eekboard_client_load_keyboard_from_xkl (client,
opt_model,
opt_layouts,
opt_options)) {
g_printerr ("Can't load keyboard from xklavier config\n");
g_object_unref (client);
exit (1);
}
} else {
gchar *file;
gboolean success;
if (!opt_keyboard)
opt_keyboard = DEFAULT_LAYOUT;
if (g_str_has_suffix (opt_keyboard, ".xml"))
file = g_strdup (opt_keyboard);
else
file = g_strdup_printf ("%s/%s.xml", KEYBOARDDIR, opt_keyboard);
success = eekboard_client_load_keyboard_from_file (client, file);
g_free (file);
if (!success) {
g_printerr ("Can't load keyboard file %s\n", file);
g_object_unref (client);
exit (1);
}
}
#ifdef HAVE_XTEST
if (!eekboard_client_enable_xtest (client)) {
g_printerr ("Can't init xtest\n");
@ -303,6 +271,8 @@ main (int argc, char **argv)
}
#endif /* HAVE_XTEST */
eekboard_client_set_keyboard (client, opt_keyboard ? opt_keyboard : DEFAULT_KEYBOARD);
loop = g_main_loop_new (NULL, FALSE);
if (!opt_focus) {
g_object_get (client, "context", &context, NULL);

View File

@ -68,7 +68,6 @@ struct _EekboardClient {
XklEngine *xkl_engine;
XklConfigRegistry *xkl_config_registry;
gboolean use_xkl_layout;
gint group;
gulong xkl_config_changed_handler;
gulong xkl_state_changed_handler;
@ -123,13 +122,7 @@ static gboolean keystroke_listener_cb (const AtspiDeviceEvent *stroke,
void *user_data);
#endif /* HAVE_ATSPI */
static gboolean set_keyboard (EekboardClient *client,
gboolean show,
EekLayout *layout);
static gboolean set_keyboard_from_xkl (EekboardClient *client,
gboolean show,
const gchar *model,
const gchar *layouts,
const gchar *options);
const gchar *keyboard);
#ifdef HAVE_XTEST
static void update_modifier_keycodes
(EekboardClient *client);
@ -232,11 +225,6 @@ eekboard_client_dispose (GObject *object)
client->eekboard = NULL;
}
if (client->keyboard) {
g_object_unref (client->keyboard);
client->keyboard = NULL;
}
if (client->settings) {
g_object_unref (client->settings);
client->settings = NULL;
@ -286,50 +274,25 @@ eekboard_client_class_init (EekboardClientClass *klass)
static void
eekboard_client_init (EekboardClient *client)
{
client->eekboard = NULL;
client->context = NULL;
client->xkl_engine = NULL;
client->xkl_config_registry = NULL;
client->keyboard = NULL;
client->key_pressed_handler = 0;
client->key_released_handler = 0;
client->xkl_config_changed_handler = 0;
client->xkl_state_changed_handler = 0;
#if ENABLE_FOCUS_LISTENER
client->follows_focus = FALSE;
client->hide_keyboard_timeout_id = 0;
#endif /* ENABLE_FOCUS_LISTENER */
#ifdef HAVE_ATSPI
client->keystroke_listener = NULL;
#endif /* HAVE_ATSPI */
#ifdef HAVE_IBUS
client->ibus_bus = NULL;
client->ibus_focus_message_filter = 0;
#endif /* HAVE_IBUS */
client->settings = g_settings_new ("org.fedorahosted.eekboard");
}
gboolean
eekboard_client_load_keyboard_from_xkl (EekboardClient *client,
const gchar *model,
const gchar *layouts,
const gchar *options)
{
client->use_xkl_layout = TRUE;
#if ENABLE_FOCUS_LISTENER
return set_keyboard_from_xkl (client,
!client->follows_focus,
model,
layouts,
options);
#define IS_KEYBOARD_VISIBLE(client) (!client->follows_focus)
#else /* ENABLE_FOCUS_LISTENER */
return set_keyboard_from_xkl (client,
TRUE,
model,
layouts,
options);
#define IS_KEYBOARD_VISIBLE(client) TRUE
#endif /* !ENABLE_FOCUS_LISTENER */
gboolean
eekboard_client_set_keyboard (EekboardClient *client,
const gchar *keyboard)
{
gboolean retval;
retval = set_keyboard (client, keyboard);
if (IS_KEYBOARD_VISIBLE (client))
eekboard_context_show_keyboard (client->context, NULL);
return retval;
}
gboolean
@ -550,24 +513,17 @@ keystroke_listener_cb (const AtspiDeviceEvent *stroke,
void *user_data)
{
EekboardClient *client = user_data;
EekKey *key;
/* Ignore modifiers since the keystroke listener does not called
when a modifier key is released. */
key = eek_keyboard_find_key_by_keycode (client->keyboard,
stroke->hw_code);
if (key) {
EekSymbol *symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
if (symbol && eek_symbol_is_modifier (symbol))
return FALSE;
}
if (stroke->type == ATSPI_KEY_PRESSED) {
switch (stroke->type) {
case ATSPI_KEY_PRESSED:
eekboard_context_press_key (client->context, stroke->hw_code, NULL);
} else {
break;
case ATSPI_KEY_RELEASED:
eekboard_context_release_key (client->context, stroke->hw_code, NULL);
break;
default:
g_return_val_if_reached (FALSE);
}
return TRUE;
}
#endif /* HAVE_ATSPI */
@ -725,7 +681,19 @@ on_xkl_config_changed (XklEngine *xklengine,
gboolean retval;
if (client->use_xkl_layout) {
retval = set_keyboard_from_xkl (client, FALSE, NULL, NULL, NULL);
XklConfigRec *rec;
gchar *layout, *keyboard;
rec = xkl_config_rec_new ();
xkl_config_rec_get_from_server (rec, client->xkl_engine);
layout = eekboard_xkl_config_rec_to_string (rec);
g_object_unref (rec);
keyboard = g_strdup_printf ("xkl:%s", layout);
g_free (layout);
retval = set_keyboard (client, keyboard);
g_free (keyboard);
g_return_if_fail (retval);
}
@ -736,88 +704,17 @@ on_xkl_config_changed (XklEngine *xklengine,
static gboolean
set_keyboard (EekboardClient *client,
gboolean show,
EekLayout *layout)
const gchar *keyboard)
{
gchar *keyboard_name;
static gint keyboard_serial = 0;
guint keyboard_id;
client->keyboard = eek_keyboard_new (layout, CSW, CSH);
eek_keyboard_set_modifier_behavior (client->keyboard,
EEK_MODIFIER_BEHAVIOR_LATCH);
keyboard_name = g_strdup_printf ("keyboard%d", keyboard_serial++);
eek_element_set_name (EEK_ELEMENT(client->keyboard), keyboard_name);
g_free (keyboard_name);
keyboard_id = eekboard_context_add_keyboard (client->context,
client->keyboard,
keyboard,
NULL);
eekboard_context_set_keyboard (client->context, keyboard_id, NULL);
if (show)
eekboard_context_show_keyboard (client->context, NULL);
return TRUE;
}
static gboolean
set_keyboard_from_xkl (EekboardClient *client,
gboolean show,
const gchar *model,
const gchar *layouts,
const gchar *options)
{
EekLayout *layout;
gboolean retval;
if (client->keyboard)
g_object_unref (client->keyboard);
layout = eek_xkl_layout_new ();
if (model) {
if (!eek_xkl_layout_set_model (EEK_XKL_LAYOUT(layout), model)) {
g_object_unref (layout);
return FALSE;
}
}
if (layouts) {
XklConfigRec *rec;
rec = eekboard_xkl_config_rec_new_from_string (layouts);
if (!eek_xkl_layout_set_layouts (EEK_XKL_LAYOUT(layout),
rec->layouts)) {
g_object_unref (rec);
g_object_unref (layout);
return FALSE;
}
if (!eek_xkl_layout_set_variants (EEK_XKL_LAYOUT(layout),
rec->variants)) {
g_object_unref (rec);
g_object_unref (layout);
return FALSE;
}
g_object_unref (rec);
}
if (options) {
gchar **_options;
_options = g_strsplit (options, ",", -1);
if (!eek_xkl_layout_set_options (EEK_XKL_LAYOUT(layout), _options)) {
g_strfreev (_options);
g_object_unref (layout);
return FALSE;
}
}
retval = set_keyboard (client, show, layout);
g_object_unref (layout);
return retval;
}
static void
on_xkl_state_changed (XklEngine *xklengine,
XklEngineStateChange type,
@ -827,14 +724,9 @@ on_xkl_state_changed (XklEngine *xklengine,
{
EekboardClient *client = user_data;
if (type == GROUP_CHANGED && client->keyboard) {
if (client->use_xkl_layout) {
gint group = eek_element_get_group (EEK_ELEMENT(client->keyboard));
if (group != value) {
eekboard_context_set_group (client->context, value, NULL);
}
}
client->group = value;
if (type == GROUP_CHANGED) {
if (client->use_xkl_layout)
eekboard_context_set_group (client->context, value, NULL);
}
}
@ -918,7 +810,7 @@ get_keycode_from_gdk_keymap (EekboardClient *client,
return FALSE;
for (i = 0; i < n_keys; i++)
if (keys[i].group == client->group)
if (keys[i].group == eekboard_context_get_group (client->context))
best_match = &keys[i];
*keycode = best_match->keycode;
@ -953,17 +845,15 @@ send_fake_modifier_key_event (EekboardClient *client,
static void
send_fake_key_event (EekboardClient *client,
EekKey *key,
EekSymbol *symbol,
guint keyboard_modifiers,
gboolean is_pressed)
{
GdkDisplay *display = gdk_display_get_default ();
EekSymbol *symbol;
EekModifierType keyboard_modifiers, modifiers;
EekModifierType modifiers;
guint xkeysym;
guint keycode, replaced_keysym = 0;
symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
/* Ignore special keys and modifiers */
if (!EEK_IS_KEYSYM(symbol) || eek_symbol_is_modifier (symbol))
return;
@ -982,10 +872,9 @@ send_fake_key_event (EekboardClient *client,
}
/* Clear level shift modifiers */
keyboard_modifiers = eek_keyboard_get_modifiers (client->keyboard);
keyboard_modifiers &= ~EEK_SHIFT_MASK;
keyboard_modifiers &= ~EEK_LOCK_MASK;
keyboard_modifiers &= ~eek_keyboard_get_alt_gr_mask (client->keyboard);
//keyboard_modifiers &= ~eek_keyboard_get_alt_gr_mask (client->keyboard);
modifiers |= keyboard_modifiers;
@ -1007,20 +896,15 @@ send_fake_key_event (EekboardClient *client,
}
static void
on_key_pressed (EekKeyboard *keyboard,
EekKey *key,
gpointer user_data)
on_key_pressed (EekboardContext *context,
guint keycode,
EekSymbol *symbol,
guint modifiers,
gpointer user_data)
{
EekboardClient *client = user_data;
send_fake_key_event (client, key, TRUE);
send_fake_key_event (client, key, FALSE);
}
static void
on_key_released (EekKeyboard *keyboard,
EekKey *key,
gpointer user_data)
{
send_fake_key_event (client, symbol, modifiers, TRUE);
send_fake_key_event (client, symbol, modifiers, FALSE);
}
static void
@ -1074,11 +958,8 @@ eekboard_client_enable_xtest (EekboardClient *client)
update_modifier_keycodes (client);
client->key_pressed_handler =
g_signal_connect (client->keyboard, "key-pressed",
g_signal_connect (client->context, "key-pressed",
G_CALLBACK(on_key_pressed), client);
client->key_released_handler =
g_signal_connect (client->keyboard, "key-released",
G_CALLBACK(on_key_released), client);
return TRUE;
}
@ -1090,43 +971,5 @@ eekboard_client_disable_xtest (EekboardClient *client)
XkbFreeKeyboard (client->xkb, 0, TRUE); /* free_all = TRUE */
client->xkb = NULL;
}
if (g_signal_handler_is_connected (client->keyboard,
client->key_pressed_handler))
g_signal_handler_disconnect (client->keyboard,
client->key_pressed_handler);
if (g_signal_handler_is_connected (client->keyboard,
client->key_released_handler))
g_signal_handler_disconnect (client->keyboard,
client->key_released_handler);
}
gboolean
eekboard_client_load_keyboard_from_file (EekboardClient *client,
const gchar *keyboard_file)
{
GFile *file;
GFileInputStream *input;
GError *error;
EekLayout *layout;
gboolean retval;
file = g_file_new_for_path (keyboard_file);
error = NULL;
input = g_file_read (file, NULL, &error);
if (input == NULL)
return FALSE;
layout = eek_xml_layout_new (G_INPUT_STREAM(input));
g_object_unref (input);
#if ENABLE_FOCUS_LISTENER
retval = set_keyboard (client, !client->follows_focus, layout);
#else /* ENABLE_FOCUS_LISTENER */
retval = set_keyboard (client, TRUE, layout);
#endif /* !ENABLE_FOCUS_LISTENER */
g_object_unref (layout);
return retval;
}
#endif /* HAVE_XTEST */

View File

@ -33,15 +33,9 @@ typedef struct _EekboardClient EekboardClient;
EekboardClient * eekboard_client_new (GDBusConnection *connection);
gboolean eekboard_client_load_keyboard_from_file
gboolean eekboard_client_set_keyboard
(EekboardClient *client,
const gchar *file);
gboolean eekboard_client_load_keyboard_from_xkl
(EekboardClient *client,
const gchar *model,
const gchar *layouts,
const gchar *options);
const gchar *keyboard);
gboolean eekboard_client_enable_xkl (EekboardClient *client);
void eekboard_client_disable_xkl (EekboardClient *client);

View File

@ -32,8 +32,10 @@
#include "eek/eek-clutter.h"
#endif
#include "eek/eek-gtk.h"
#include "eek/eek-xkl.h"
#include "server-context.h"
#include "xklutil.h"
#define CSW 640
#define CSH 480
@ -51,7 +53,7 @@ static const gchar introspection_xml[] =
"<node>"
" <interface name='org.fedorahosted.Eekboard.Context'>"
" <method name='AddKeyboard'>"
" <arg direction='in' type='v' name='keyboard'/>"
" <arg direction='in' type='s' name='keyboard'/>"
" <arg direction='out' type='u' name='keyboard_id'/>"
" </method>"
" <method name='RemoveKeyboard'>"
@ -79,13 +81,18 @@ static const gchar introspection_xml[] =
" <signal name='Disabled'/>"
" <signal name='KeyPressed'>"
" <arg type='u' name='keycode'/>"
" </signal>"
" <signal name='KeyReleased'>"
" <arg type='u' name='keycode'/>"
" <arg type='v' name='symbol'/>"
" <arg type='u' name='modifiers'/>"
" </signal>"
" <signal name='KeyboardVisibilityChanged'>"
" <arg type='b' name='visible'/>"
" </signal>"
" <signal name='KeyboardChanged'>"
" <arg type='u' name='keyboard_id'/>"
" </signal>"
" <signal name='GroupChanged'>"
" <arg type='i' name='group'/>"
" </signal>"
" </interface>"
"</node>";
@ -206,8 +213,7 @@ on_realize_set_dock (GtkWidget *widget,
{
#ifdef HAVE_XDOCK
GdkWindow *window = gtk_widget_get_window (widget);
Atom atoms[2] = { None, None };
gint x, y, width, height, depth;
gint x, y, width, height;
long vals[12];
/* set window type to dock */
@ -599,30 +605,29 @@ server_context_init (ServerContext *context)
static gboolean on_repeat_timeout (ServerContext *context);
static void
emit_press_release_dbus_signal (ServerContext *context)
emit_key_pressed_dbus_signal (ServerContext *context, EekKey *key)
{
if (context->connection && context->enabled) {
guint keycode = eek_key_get_keycode (context->repeat_key);
guint keycode = eek_key_get_keycode (key);
EekSymbol *symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
guint modifiers = eek_keyboard_get_modifiers (context->keyboard);
GVariant *variant;
GError *error;
variant = eek_serializable_serialize (EEK_SERIALIZABLE(symbol));
error = NULL;
g_dbus_connection_emit_signal (context->connection,
NULL,
context->object_path,
SERVER_CONTEXT_INTERFACE,
"KeyPressed",
g_variant_new ("(u)", keycode),
&error);
g_assert_no_error (error);
error = NULL;
g_dbus_connection_emit_signal (context->connection,
NULL,
context->object_path,
SERVER_CONTEXT_INTERFACE,
"KeyReleased",
g_variant_new ("(u)", keycode),
g_variant_new ("(uvu)",
keycode,
variant,
modifiers),
&error);
g_variant_unref (variant);
g_assert_no_error (error);
}
}
@ -632,7 +637,7 @@ on_repeat_timeout (ServerContext *context)
{
gint delay = g_settings_get_int (context->settings, "repeat-interval");
emit_press_release_dbus_signal (context);
emit_key_pressed_dbus_signal (context, context->repeat_key);
context->repeat_timeout_id =
g_timeout_add (delay,
@ -645,7 +650,7 @@ on_repeat_timeout (ServerContext *context)
static gboolean
on_repeat_timeout_init (ServerContext *context)
{
emit_press_release_dbus_signal (context);
emit_key_pressed_dbus_signal (context, context->repeat_key);
/* FIXME: clear modifiers for further key repeat; better not
depend on modifier behavior is LATCH */
@ -690,39 +695,13 @@ on_key_released (EekKeyboard *keyboard,
gpointer user_data)
{
ServerContext *context = user_data;
gboolean need_key_press = FALSE;
if (context->repeat_timeout_id > 0) {
g_source_remove (context->repeat_timeout_id);
context->repeat_timeout_id = 0;
need_key_press = TRUE;
}
if (context->connection && context->enabled) {
guint keycode = eek_key_get_keycode (key);
GError *error;
if (need_key_press) {
error = NULL;
g_dbus_connection_emit_signal (context->connection,
NULL,
context->object_path,
SERVER_CONTEXT_INTERFACE,
"KeyPressed",
g_variant_new ("(u)", keycode),
&error);
g_assert_no_error (error);
}
error = NULL;
g_dbus_connection_emit_signal (context->connection,
NULL,
context->object_path,
SERVER_CONTEXT_INTERFACE,
"KeyReleased",
g_variant_new ("(u)", keycode),
&error);
g_assert_no_error (error);
/* KeyPressed signal has not been emitted in repeat handler */
emit_key_pressed_dbus_signal (context, context->repeat_key);
}
}
@ -739,6 +718,60 @@ disconnect_keyboard_signals (ServerContext *context)
context->key_released_handler);
}
static EekKeyboard *
create_keyboard_from_string (const gchar *string)
{
EekKeyboard *keyboard;
EekLayout *layout;
if (g_str_has_prefix (string, "xkl:")) {
XklConfigRec *rec = eekboard_xkl_config_rec_from_string (&string[4]);
layout = eek_xkl_layout_new ();
if (!eek_xkl_layout_set_config (EEK_XKL_LAYOUT(layout), rec)) {
g_object_unref (layout);
return NULL;
}
} else {
gchar *path;
GFile *file;
GFileInputStream *input;
GError *error;
path = g_strdup_printf ("%s/%s.xml", KEYBOARDDIR, string);
file = g_file_new_for_path (path);
g_free (path);
error = NULL;
input = g_file_read (file, NULL, &error);
if (input == NULL) {
g_object_unref (file);
return NULL;
}
layout = eek_xml_layout_new (G_INPUT_STREAM(input));
}
keyboard = eek_keyboard_new (layout, CSW, CSH);
g_object_unref (layout);
return keyboard;
}
static void
emit_group_changed_signal (ServerContext *context, int group)
{
GError *error;
error = NULL;
g_dbus_connection_emit_signal (context->connection,
NULL,
context->object_path,
SERVER_CONTEXT_INTERFACE,
"GroupChanged",
g_variant_new ("(i)", group),
&error);
g_assert_no_error (error);
}
static void
handle_method_call (GDBusConnection *connection,
const gchar *sender,
@ -752,26 +785,27 @@ handle_method_call (GDBusConnection *connection,
ServerContext *context = user_data;
if (g_strcmp0 (method_name, "AddKeyboard") == 0) {
GVariant *variant;
EekSerializable *serializable;
const gchar *name;
static guint keyboard_id = 0;
EekKeyboard *keyboard;
g_variant_get (parameters, "(v)", &variant);
g_variant_get (parameters, "(&s)", &name);
keyboard = create_keyboard_from_string (name);
serializable = eek_serializable_deserialize (variant);
if (!EEK_IS_KEYBOARD(serializable)) {
if (keyboard == NULL) {
g_dbus_method_invocation_return_error (invocation,
G_IO_ERROR,
G_IO_ERROR_FAILED_HANDLED,
"not a keyboard");
"can't create a keyboard");
return;
}
eek_keyboard_set_modifier_behavior (EEK_KEYBOARD(serializable),
eek_keyboard_set_modifier_behavior (keyboard,
EEK_MODIFIER_BEHAVIOR_LATCH);
g_hash_table_insert (context->keyboard_hash,
GUINT_TO_POINTER(++keyboard_id),
serializable);
keyboard);
g_dbus_method_invocation_return_value (invocation,
g_variant_new ("(u)",
keyboard_id));
@ -802,6 +836,7 @@ handle_method_call (GDBusConnection *connection,
if (g_strcmp0 (method_name, "SetKeyboard") == 0) {
EekKeyboard *keyboard;
guint keyboard_id;
gint group;
g_variant_get (parameters, "(u)", &keyboard_id);
@ -847,6 +882,10 @@ handle_method_call (GDBusConnection *connection,
}
g_dbus_method_invocation_return_value (invocation, NULL);
eek_element_get_group (EEK_ELEMENT(context->keyboard));
emit_group_changed_signal (context, group);
return;
}
@ -895,6 +934,9 @@ handle_method_call (GDBusConnection *connection,
}
g_dbus_method_invocation_return_value (invocation, NULL);
emit_group_changed_signal (context, group);
return;
}

View File

@ -21,13 +21,13 @@
#include "xklutil.h"
XklConfigRec *
eekboard_xkl_config_rec_new_from_string (const gchar *layouts)
eekboard_xkl_config_rec_from_string (const gchar *layouts)
{
XklConfigRec *rec;
gchar **l, **v;
gint i;
l = g_strsplit (layouts, ",", -1);
l = g_strsplit (layouts, ":", -1);
v = g_strdupv (l);
for (i = 0; l[i]; i++) {
gchar *layout = l[i], *variant = v[i],
@ -50,6 +50,36 @@ eekboard_xkl_config_rec_new_from_string (const gchar *layouts)
return rec;
}
gchar *
eekboard_xkl_config_rec_to_string (XklConfigRec *rec)
{
gchar **strv, **sp, **lp, **vp, *p;
gint n_layouts;
GString *str;
n_layouts = g_strv_length (rec->layouts);
strv = g_malloc0_n (n_layouts + 2, sizeof (gchar *));
for (sp = strv, lp = rec->layouts, vp = rec->variants; *lp; sp++, lp++) {
if (*vp != NULL)
*sp = g_strdup_printf ("%s(%s)", *lp, *vp++);
else
*sp = g_strdup_printf ("%s", *lp);
}
str = g_string_new ("");
p = g_strjoinv (":", strv);
g_strfreev (strv);
g_string_append (str, p);
g_free (p);
g_string_append_c (str, ':');
p = g_strjoinv ("+", rec->options);
g_string_append (str, p);
g_free (p);
return g_string_free (str,FALSE);
}
static XklConfigItem *
xkl_config_item_copy (const XklConfigItem *item)
{

View File

@ -24,16 +24,16 @@
G_BEGIN_DECLS
XklConfigRec *eekboard_xkl_config_rec_new_from_string
(const gchar *layouts);
XklConfigRec *eekboard_xkl_config_rec_from_string (const gchar *layouts);
gchar *eekboard_xkl_config_rec_to_string (XklConfigRec *rec);
GSList *eekboard_xkl_list_models (XklConfigRegistry *registry);
GSList *eekboard_xkl_list_layouts (XklConfigRegistry *registry);
GSList *eekboard_xkl_list_option_groups (XklConfigRegistry *registry);
GSList *eekboard_xkl_list_layout_variants (XklConfigRegistry *registry,
const gchar *layout);
GSList *eekboard_xkl_list_options (XklConfigRegistry *registry,
const gchar *group);
GSList *eekboard_xkl_list_models (XklConfigRegistry *registry);
GSList *eekboard_xkl_list_layouts (XklConfigRegistry *registry);
GSList *eekboard_xkl_list_option_groups (XklConfigRegistry *registry);
GSList *eekboard_xkl_list_layout_variants (XklConfigRegistry *registry,
const gchar *layout);
GSList *eekboard_xkl_list_options (XklConfigRegistry *registry,
const gchar *group);
G_END_DECLS
#endif /* EEKBOARD_XKLUTIL_H */

View File

@ -201,7 +201,7 @@ main (int argc, char **argv)
if (opt_layouts) {
XklConfigRec *rec;
rec = eekboard_xkl_config_rec_new_from_string (opt_layouts);
rec = eekboard_xkl_config_rec_from_string (opt_layouts);
eek_xkl_layout_set_layouts (EEK_XKL_LAYOUT(layout), rec->layouts);
eek_xkl_layout_set_variants (EEK_XKL_LAYOUT(layout), rec->variants);
g_object_unref (rec);