Add keyboard selection dialog to preferences.

This commit is contained in:
Daiki Ueno
2012-03-28 11:24:46 +09:00
parent 1943749cb6
commit ee0505c100
20 changed files with 951 additions and 424 deletions

View File

@ -16,83 +16,120 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA
bin_PROGRAMS = \
eekboard \
eekboard-server
bin_PROGRAMS = \
eekboard \
eekboard-server \
$(NULL)
eekboard_CFLAGS = \
-I$(top_srcdir) \
$(GIO2_CFLAGS) \
$(GTK_CFLAGS) \
$(XKB_CFLAGS) \
$(LIBXKLAVIER_CFLAGS) \
-DKEYBOARDDIR=\"$(pkgdatadir)/keyboards\" \
-DPKGDATADIR=\"$(pkgdatadir)\"
libexec_PROGRAMS = \
eekboard-setup \
$(NULL)
eekboard_LDADD = \
$(top_builddir)/eekboard/libeekboard.la \
$(top_builddir)/eek/libeek.la \
$(top_builddir)/eek/libeek-xkl.la \
$(GIO2_LIBS) \
$(GTK_LIBS) \
$(XKB_LIBS) \
$(LIBXKLAVIER_LIBS)
eekboard_CFLAGS = \
-I$(top_srcdir) \
$(GIO2_CFLAGS) \
$(GTK_CFLAGS) \
$(XKB_CFLAGS) \
$(LIBXKLAVIER_CFLAGS) \
-DLIBEXECDIR=\"$(libexecdir)\" \
$(NULL)
eekboard_LDADD = \
$(top_builddir)/eekboard/libeekboard.la \
$(top_builddir)/eek/libeek.la \
$(top_builddir)/eek/libeek-xkl.la \
$(GIO2_LIBS) \
$(GTK_LIBS) \
$(XKB_LIBS) \
$(LIBXKLAVIER_LIBS) \
$(NULL)
if ENABLE_XTEST
eekboard_CFLAGS += \
$(XTEST_CFLAGS)
eekboard_LDADD += \
$(XTEST_LIBS)
eekboard_CFLAGS += $(XTEST_CFLAGS)
eekboard_LDADD += $(XTEST_LIBS)
endif
if ENABLE_ATSPI
eekboard_CFLAGS += \
$(ATSPI2_CFLAGS)
eekboard_LDADD += \
$(ATSPI2_LIBS)
eekboard_CFLAGS += $(ATSPI2_CFLAGS)
eekboard_LDADD += $(ATSPI2_LIBS)
endif
if ENABLE_IBUS
eekboard_CFLAGS += \
$(IBUS_CFLAGS)
eekboard_LDADD += \
$(IBUS_LIBS)
eekboard_CFLAGS += $(IBUS_CFLAGS)
eekboard_LDADD += $(IBUS_LIBS)
endif
eekboard_headers = client.h preferences-dialog.h
eekboard_SOURCES = client.c preferences-dialog.c client-main.c
eekboard_headers = \
client.h \
$(NULL)
eekboard_server_CFLAGS = \
-I$(top_srcdir) \
$(GIO2_CFLAGS) \
$(GTK_CFLAGS) \
$(LIBXKLAVIER_CFLAGS) \
-DTHEMEDIR=\"$(pkgdatadir)/themes\" \
-DKEYBOARDDIR=\"$(pkgdatadir)/keyboards\"
eekboard_SOURCES = \
client.c \
client-main.c \
$(NULL)
eekboard_server_LDADD = \
$(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) \
$(LIBXKLAVIER_LIBS)
eekboard_server_CFLAGS = \
-I$(top_srcdir) \
$(GIO2_CFLAGS) \
$(GTK_CFLAGS) \
$(LIBXKLAVIER_CFLAGS) \
-DTHEMESDIR=\"$(pkgdatadir)/themes\" \
$(NULL)
eekboard_server_LDADD = \
$(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) \
$(LIBXKLAVIER_LIBS) \
$(NULL)
if ENABLE_XDOCK
eekboard_server_CFLAGS += $(XDOCK_CFLAGS)
eekboard_server_LDADD += $(XDOCK_LIBS)
endif
eekboard_server_headers = server-service.h server-context-service.h
eekboard_server_SOURCES = server-service.c server-context-service.c server-main.c
eekboard_server_headers = \
server-service.h \
server-context-service.h \
$(NULL)
eekboarddir = $(includedir)/eekboard-$(EEK_API_VERSION)/eekboard
eekboard_HEADERS = \
$(libeekboard_headers)
eekboard_server_SOURCES = \
server-service.c \
server-context-service.c \
server-main.c \
$(NULL)
noinst_HEADERS = \
$(eekboard_headers) \
$(eekboard_server_headers)
eekboard_setup_CFLAGS = \
-I$(top_srcdir) \
$(GIO2_CFLAGS) \
$(GTK_CFLAGS) \
$(XKB_CFLAGS) \
$(LIBXKLAVIER_CFLAGS) \
-DPKGDATADIR=\"$(pkgdatadir)\" \
$(NULL)
eekboard_setup_headers = \
preferences-dialog.h \
$(NULL)
eekboard_setup_SOURCES = \
preferences-dialog.c \
setup-main.c \
$(NULL)
eekboard_setup_LDADD = \
$(top_builddir)/eek/libeek.la \
$(GIO2_LIBS) \
$(GTK_LIBS) \
$(NULL)
dist_pkgdata_DATA = preferences-dialog.ui
noinst_HEADERS = \
$(eekboard_headers) \
$(eekboard_server_headers) \
$(eekboard_setup_headers) \
$(NULL)

View File

@ -67,21 +67,6 @@ static const GOptionEntry options[] = {
{NULL}
};
static void
on_notify_visible (GObject *object,
GParamSpec *spec,
gpointer user_data)
{
GMainLoop *loop = user_data;
gboolean visible;
g_object_get (object, "visible", &visible, NULL);
/* user explicitly closed the window */
if (!visible && eekboard_context_is_enabled (EEKBOARD_CONTEXT(object)))
g_main_loop_quit (loop);
}
static void
on_context_destroyed (EekboardContext *context,
gpointer user_data)
@ -139,7 +124,7 @@ main (int argc, char **argv)
GMainLoop *loop = NULL;
gint focus;
GSettings *settings = NULL;
gchar **keyboards;
gchar **keyboards = NULL;
gint retval = 0;
if (!gtk_init_check (&argc, &argv)) {
@ -302,8 +287,6 @@ main (int argc, char **argv)
if (!opt_focus) {
g_object_get (client, "context", &context, NULL);
g_signal_connect (context, "notify::visible",
G_CALLBACK(on_notify_visible), loop);
g_signal_connect (context, "destroyed",
G_CALLBACK(on_context_destroyed), loop);
g_object_unref (context);
@ -321,16 +304,16 @@ main (int argc, char **argv)
G_CALLBACK(on_destroyed), loop);
g_object_unref (eekboard);
if (opt_keyboards != NULL)
if (opt_keyboards != NULL) {
keyboards = g_strsplit (opt_keyboards, ",", -1);
else
keyboards = g_settings_get_strv (settings, "keyboards");
if (!set_keyboards (client, (const gchar * const *)keyboards)) {
if (!set_keyboards (client, (const gchar * const *)keyboards)) {
g_strfreev (keyboards);
retval = 1;
goto out;
}
g_strfreev (keyboards);
retval = 1;
goto out;
}
g_strfreev (keyboards);
g_main_loop_run (loop);

View File

@ -42,7 +42,6 @@
#include "eekboard/eekboard-client.h"
#include "eekboard/eekboard-xklutil.h"
#include "client.h"
#include "preferences-dialog.h"
#include <string.h>
@ -54,6 +53,7 @@ enum {
PROP_CONNECTION,
PROP_EEKBOARD,
PROP_CONTEXT,
PROP_KEYBOARDS,
PROP_LAST
};
@ -66,14 +66,15 @@ struct _Client {
EekboardContext *context;
GSList *keyboards;
GSList *keyboards_head;
XklEngine *xkl_engine;
XklConfigRegistry *xkl_config_registry;
gulong xkl_config_changed_handler;
gulong xkl_state_changed_handler;
gulong key_pressed_handler;
gulong key_released_handler;
gulong key_activated_handler;
gboolean follows_focus;
guint hide_keyboard_timeout_id;
@ -158,16 +159,21 @@ client_set_property (GObject *object,
if (client->context == NULL) {
g_object_unref (client->eekboard);
client->eekboard = NULL;
} else
} else {
eekboard_client_push_context (client->eekboard,
client->context,
NULL);
g_settings_bind (client->settings, "keyboards",
client, "keyboards",
G_SETTINGS_BIND_GET);
}
}
break;
case PROP_KEYBOARDS:
client_set_keyboards (client, g_value_get_boxed (value));
break;
default:
g_object_set_property (object,
g_param_spec_get_name (pspec),
value);
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
@ -188,9 +194,7 @@ client_get_property (GObject *object,
g_value_set_object (value, client->context);
break;
default:
g_object_get_property (object,
g_param_spec_get_name (pspec),
value);
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
@ -289,6 +293,15 @@ client_class_init (ClientClass *klass)
g_object_class_install_property (gobject_class,
PROP_CONTEXT,
pspec);
pspec = g_param_spec_boxed ("keyboards",
"Keyboards",
"Keyboards",
G_TYPE_STRV,
G_PARAM_WRITABLE);
g_object_class_install_property (gobject_class,
PROP_KEYBOARDS,
pspec);
}
static void
@ -753,10 +766,20 @@ set_keyboards (Client *client,
{
guint keyboard_id;
const gchar * const *p;
GSList *head = NULL;
GSList *head;
if (client->keyboards)
g_return_val_if_fail (keyboards != NULL, FALSE);
g_return_val_if_fail (client->context, FALSE);
if (client->keyboards) {
for (head = client->keyboards; head; head = head->next) {
eekboard_context_remove_keyboard (client->context,
GPOINTER_TO_UINT(head->data),
NULL);
}
g_slist_free (client->keyboards);
client->keyboards = NULL;
}
for (p = keyboards; *p != NULL; p++) {
keyboard_id = eekboard_context_add_keyboard (client->context, *p, NULL);
@ -764,17 +787,16 @@ set_keyboards (Client *client,
g_slist_free (head);
return FALSE;
}
head = g_slist_prepend (head, GUINT_TO_POINTER(keyboard_id));
client->keyboards = g_slist_prepend (client->keyboards,
GUINT_TO_POINTER(keyboard_id));
}
/* make a cycle */
head = g_slist_reverse (head);
g_slist_last (head)->next = head;
client->keyboards = head;
client->keyboards = g_slist_reverse (client->keyboards);
client->keyboards_head = client->keyboards;
/* select the first keyboard */
eekboard_context_set_keyboard (client->context,
GPOINTER_TO_UINT(head->data),
GPOINTER_TO_UINT(client->keyboards_head->data),
NULL);
return TRUE;
}
@ -1028,25 +1050,37 @@ send_fake_key_events (Client *client,
}
static void
on_key_pressed (EekboardContext *context,
const gchar *keyname,
EekSymbol *symbol,
guint modifiers,
gpointer user_data)
on_key_activated (EekboardContext *context,
guint keycode,
EekSymbol *symbol,
guint modifiers,
gpointer user_data)
{
Client *client = user_data;
if (g_strcmp0 (eek_symbol_get_name (symbol), "cycle-keyboard") == 0) {
client->keyboards = g_slist_next (client->keyboards);
client->keyboards_head = g_slist_next (client->keyboards_head);
if (client->keyboards_head == NULL)
client->keyboards_head = client->keyboards;
eekboard_context_set_keyboard (client->context,
GPOINTER_TO_UINT(client->keyboards->data),
GPOINTER_TO_UINT(client->keyboards_head->data),
NULL);
return;
}
if (g_strcmp0 (eek_symbol_get_name (symbol), "preferences") == 0) {
PreferencesDialog *dialog = preferences_dialog_new ();
preferences_dialog_run (dialog);
gchar *argv[2];
GError *error;
argv[0] = g_build_filename (LIBEXECDIR, "eekboard-setup", NULL);
argv[1] = NULL;
error = NULL;
if (!g_spawn_async (NULL, argv, NULL, 0, NULL, NULL, NULL, &error)) {
g_warning ("can't spawn %s: %s", argv[0], error->message);
g_error_free (error);
}
g_free (argv[0]);
return;
}
@ -1104,9 +1138,9 @@ client_enable_xtest (Client *client)
update_modifier_keycodes (client);
client->key_pressed_handler =
g_signal_connect (client->context, "key-pressed",
G_CALLBACK(on_key_pressed), client);
client->key_activated_handler =
g_signal_connect (client->context, "key-activated",
G_CALLBACK(on_key_activated), client);
return TRUE;
}

View File

@ -21,6 +21,7 @@
#include <gtk/gtk.h>
#include "preferences-dialog.h"
#include <eek/eek.h>
struct _PreferencesDialog {
GtkWidget *dialog;
@ -29,9 +30,16 @@ struct _PreferencesDialog {
GtkWidget *repeat_speed_scale;
GtkWidget *auto_hide_toggle;
GtkWidget *auto_hide_delay_scale;
GtkWidget *start_fullscreen_toggle;
GtkWidget *keyboard_entry;
GtkWidget *selected_keyboards_treeview;
GtkWidget *up_button;
GtkWidget *down_button;
GtkWidget *add_button;
GtkWidget *remove_button;
GtkWidget *new_keyboard_dialog;
GtkWidget *available_keyboards_treeview;
GList *available_keyboards;
GSettings *settings;
};
@ -62,33 +70,191 @@ set_rate (const GValue *value,
return g_variant_new_uint32 (msecs);
}
static gboolean
get_strv (GValue *value,
GVariant *variant,
gpointer user_data)
static void
add_keyboard_to_treeview (GtkTreeView *treeview,
const gchar *id,
const gchar *longname)
{
const gchar **strv = g_variant_get_strv (variant, NULL);
gchar *text = g_strjoinv (", ", (gchar **)strv);
g_free (strv);
g_value_set_string (value, text);
return TRUE;
GtkTreeModel *model = gtk_tree_view_get_model (treeview);
GtkTreeIter iter;
if (gtk_tree_model_get_iter_first (model, &iter)) {
do {
gchar *_id;
gtk_tree_model_get (model, &iter, 0, &_id, -1);
if (g_strcmp0 (id, _id) == 0) {
g_free (_id);
return;
}
g_free (_id);
} while (gtk_tree_model_iter_next (model, &iter));
}
gtk_list_store_append (GTK_LIST_STORE(model),
&iter);
gtk_list_store_set (GTK_LIST_STORE(model),
&iter,
0, id,
1, longname,
-1);
}
static GVariant *
set_strv (const GValue *value,
const GVariantType *expected_type,
gpointer user_data)
static void
add_keyboard (GtkWidget *button, PreferencesDialog *dialog)
{
const gchar *text = g_value_get_string (value);
gchar **strv = g_strsplit (text, ",", -1), **p;
GVariant *variant;
gint retval = gtk_dialog_run (GTK_DIALOG(dialog->new_keyboard_dialog));
if (retval == GTK_RESPONSE_OK) {
GtkTreeSelection *selection;
GtkTreeModel *model;
GList *rows, *p;
for (p = strv; *p != NULL; p++)
g_strstrip (*p);
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(dialog->available_keyboards_treeview));
rows = gtk_tree_selection_get_selected_rows (selection, &model);
for (p = rows; p; p = p->next) {
GtkTreeIter iter;
if (gtk_tree_model_get_iter (model, &iter, p->data)) {
gchar *id, *longname;
gtk_tree_model_get (model, &iter, 0, &id, 1, &longname, -1);
add_keyboard_to_treeview (GTK_TREE_VIEW(dialog->selected_keyboards_treeview),
id,
longname);
g_free (id);
g_free (longname);
}
}
}
gtk_widget_hide (dialog->new_keyboard_dialog);
}
variant = g_variant_new_strv ((const gchar * const *)strv, -1);
static void
remove_keyboard (GtkWidget *button, PreferencesDialog *dialog)
{
GtkTreeSelection *selection;
GtkTreeModel *model;
GList *rows, *p;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(dialog->selected_keyboards_treeview));
rows = gtk_tree_selection_get_selected_rows (selection, &model);
for (p = rows; p; p = p->next) {
GtkTreeIter iter;
if (gtk_tree_model_get_iter (model, &iter, p->data))
gtk_list_store_remove (GTK_LIST_STORE(model), &iter);
}
}
static void
up_keyboard (GtkWidget *button, PreferencesDialog *dialog)
{
GtkTreeSelection *selection;
GtkTreeModel *model;
GtkTreeIter iter;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(dialog->selected_keyboards_treeview));
if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
GtkTreeIter prev = iter;
if (gtk_tree_model_iter_previous (model, &prev))
gtk_list_store_swap (GTK_LIST_STORE(model), &iter, &prev);
}
}
static void
down_keyboard (GtkWidget *button, PreferencesDialog *dialog)
{
GtkTreeSelection *selection;
GtkTreeModel *model;
GtkTreeIter iter;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(dialog->selected_keyboards_treeview));
if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
GtkTreeIter next = iter;
if (gtk_tree_model_iter_next (model, &next))
gtk_list_store_swap (GTK_LIST_STORE(model), &iter, &next);
}
}
static void
selection_changed_cb (GtkTreeSelection *selection, PreferencesDialog *dialog)
{
gint count = gtk_tree_selection_count_selected_rows (selection);
if (count > 0) {
gtk_widget_set_sensitive (dialog->remove_button, TRUE);
gtk_widget_set_sensitive (dialog->up_button, TRUE);
gtk_widget_set_sensitive (dialog->down_button, TRUE);
} else {
gtk_widget_set_sensitive (dialog->remove_button, FALSE);
gtk_widget_set_sensitive (dialog->up_button, FALSE);
gtk_widget_set_sensitive (dialog->down_button, FALSE);
}
}
static gint
compare_keyboard_id (const EekXmlKeyboardDesc *desc, const char *id)
{
return g_strcmp0 (desc->id, id);
}
static void
populate_selected_keyboards (PreferencesDialog *dialog)
{
gchar **strv, **p;
strv = g_settings_get_strv (dialog->settings, "keyboards");
for (p = strv; *p != NULL; p++) {
GList *head = g_list_find_custom (dialog->available_keyboards,
*p,
(GCompareFunc) compare_keyboard_id);
if (head == NULL) {
g_warning ("unknown keyboard %s", *p);
} else {
EekXmlKeyboardDesc *desc = head->data;
add_keyboard_to_treeview (GTK_TREE_VIEW(dialog->selected_keyboards_treeview),
desc->id,
desc->longname);
}
}
g_strfreev (strv);
return variant;
}
static void
populate_available_keyboards (PreferencesDialog *dialog)
{
GList *p;
for (p = dialog->available_keyboards; p; p = p->next) {
EekXmlKeyboardDesc *desc = p->data;
add_keyboard_to_treeview (GTK_TREE_VIEW(dialog->available_keyboards_treeview),
desc->id,
desc->longname);
}
}
static void
save_keyboards (PreferencesDialog *dialog)
{
GtkTreeModel *model;
GtkTreeIter iter;
GList *list = NULL, *head;
gchar **strv, **p;
model = gtk_tree_view_get_model (GTK_TREE_VIEW(dialog->selected_keyboards_treeview));
if (gtk_tree_model_get_iter_first (model, &iter)) {
do {
gchar *id;
gtk_tree_model_get (model, &iter, 0, &id, -1);
list = g_list_prepend (list, id);
} while (gtk_tree_model_iter_next (model, &iter));
}
list = g_list_reverse (list);
strv = g_new0 (gchar *, g_list_length (list) + 1);
for (head = list, p = strv; head; head = head->next, p++) {
*p = head->data;
}
g_settings_set_strv (dialog->settings,
"keyboards",
(const gchar * const *)strv);
g_strfreev (strv);
g_list_free (list);
}
PreferencesDialog *
@ -99,13 +265,19 @@ preferences_dialog_new (void)
GtkBuilder *builder;
GObject *object;
GError *error;
GtkListStore *store;
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
GtkTreeSelection *selection;
dialog = g_slice_new0 (PreferencesDialog);
dialog->settings = g_settings_new ("org.fedorahosted.eekboard");
builder = gtk_builder_new ();
gtk_builder_set_translation_domain (builder, "eekboard");
ui_path = g_strdup_printf ("%s/%s", PKGDATADIR, "preferences-dialog.ui");
ui_path = g_build_filename (PKGDATADIR,
"preferences-dialog.ui",
NULL);
error = NULL;
if (gtk_builder_add_from_file (builder, ui_path, &error) == 0) {
g_warning ("can't load %s: %s", ui_path, error->message);
@ -113,28 +285,24 @@ preferences_dialog_new (void)
}
g_free (ui_path);
object =
gtk_builder_get_object (builder, "dialog");
object = gtk_builder_get_object (builder, "dialog");
dialog->dialog = GTK_WIDGET(object);
object =
gtk_builder_get_object (builder, "repeat_toggle");
object = gtk_builder_get_object (builder, "repeat_toggle");
dialog->repeat_toggle = GTK_WIDGET(object);
g_settings_bind (dialog->settings, "repeat",
dialog->repeat_toggle, "active",
G_SETTINGS_BIND_DEFAULT);
object =
gtk_builder_get_object (builder, "repeat_delay_scale");
object = gtk_builder_get_object (builder, "repeat_delay_scale");
dialog->repeat_delay_scale = GTK_WIDGET(object);
g_settings_bind (dialog->settings, "repeat-delay",
gtk_range_get_adjustment (GTK_RANGE (dialog->repeat_delay_scale)), "value",
G_SETTINGS_BIND_DEFAULT);
object =
gtk_builder_get_object (builder, "repeat_speed_scale");
object = gtk_builder_get_object (builder, "repeat_speed_scale");
dialog->repeat_speed_scale = GTK_WIDGET(object);
g_settings_bind_with_mapping (dialog->settings, "repeat-interval",
@ -142,38 +310,85 @@ preferences_dialog_new (void)
G_SETTINGS_BIND_DEFAULT,
get_rate, set_rate, NULL, NULL);
object =
gtk_builder_get_object (builder, "auto_hide_toggle");
object = gtk_builder_get_object (builder, "auto_hide_toggle");
dialog->auto_hide_toggle = GTK_WIDGET(object);
g_settings_bind (dialog->settings, "auto-hide",
dialog->auto_hide_toggle, "active",
G_SETTINGS_BIND_DEFAULT);
object =
gtk_builder_get_object (builder, "auto_hide_delay_scale");
object = gtk_builder_get_object (builder, "auto_hide_delay_scale");
dialog->auto_hide_delay_scale = GTK_WIDGET(object);
g_settings_bind (dialog->settings, "auto-hide-delay",
gtk_range_get_adjustment (GTK_RANGE (dialog->auto_hide_delay_scale)), "value",
G_SETTINGS_BIND_DEFAULT);
object =
gtk_builder_get_object (builder, "start_fullscreen_toggle");
dialog->start_fullscreen_toggle = GTK_WIDGET(object);
object = gtk_builder_get_object (builder,
"selected_keyboards_treeview");
dialog->selected_keyboards_treeview = GTK_WIDGET(object);
g_settings_bind (dialog->settings, "start-fullscreen",
dialog->start_fullscreen_toggle, "active",
G_SETTINGS_BIND_DEFAULT);
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (object));
g_signal_connect (G_OBJECT(selection), "changed",
G_CALLBACK(selection_changed_cb), dialog);
object =
gtk_builder_get_object (builder, "keyboard_entry");
dialog->keyboard_entry = GTK_WIDGET(object);
renderer = GTK_CELL_RENDERER(gtk_cell_renderer_text_new ());
column = gtk_tree_view_column_new_with_attributes ("Keyboard",
renderer,
"text",
1,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (object), column);
g_settings_bind_with_mapping (dialog->settings, "keyboards",
GTK_ENTRY(dialog->keyboard_entry), "text",
G_SETTINGS_BIND_DEFAULT,
get_strv, set_strv, NULL, NULL);
object = gtk_builder_get_object (builder, "up_button");
dialog->up_button = GTK_WIDGET(object);
g_signal_connect (object, "clicked",
G_CALLBACK(up_keyboard), dialog);
object = gtk_builder_get_object (builder, "down_button");
dialog->down_button = GTK_WIDGET(object);
g_signal_connect (object, "clicked",
G_CALLBACK(down_keyboard), dialog);
object = gtk_builder_get_object (builder, "add_button");
dialog->add_button = GTK_WIDGET(object);
g_signal_connect (object, "clicked",
G_CALLBACK(add_keyboard), dialog);
object = gtk_builder_get_object (builder, "remove_button");
dialog->remove_button = GTK_WIDGET(object);
g_signal_connect (object, "clicked",
G_CALLBACK(remove_keyboard), dialog);
object = gtk_builder_get_object (builder, "new_keyboard_dialog");
dialog->new_keyboard_dialog = GTK_WIDGET(object);
object = gtk_builder_get_object (builder,
"available_keyboards_treeview");
dialog->available_keyboards_treeview = GTK_WIDGET(object);
renderer = GTK_CELL_RENDERER(gtk_cell_renderer_text_new ());
column = gtk_tree_view_column_new_with_attributes ("Keyboard",
renderer,
"text",
1,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (object), column);
object = gtk_builder_get_object (builder,
"available_keyboards_liststore");
store = GTK_LIST_STORE(object);
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(store),
1,
GTK_SORT_ASCENDING);
dialog->available_keyboards = eek_xml_list_keyboards ();
populate_selected_keyboards (dialog);
populate_available_keyboards (dialog);
g_object_unref (builder);
return dialog;
}
@ -183,5 +398,18 @@ preferences_dialog_run (PreferencesDialog *dialog)
{
gtk_window_present (GTK_WINDOW(dialog->dialog));
gtk_dialog_run (GTK_DIALOG(dialog->dialog));
gtk_widget_destroy (dialog->dialog);
save_keyboards (dialog);
}
void
preferences_dialog_free (PreferencesDialog *dialog)
{
gtk_widget_destroy (dialog->dialog);
// gtk_widget_destroy (dialog->new_keyboard_dialog);
g_object_unref (dialog->settings);
g_list_free_full (dialog->available_keyboards,
(GDestroyNotify) eek_xml_keyboard_desc_free);
g_slice_free (PreferencesDialog, dialog);
}

View File

@ -18,12 +18,15 @@
#ifndef PREFERENCES_DIALOG_H
#define PREFERENCES_DIALOG_H 1
#include <glib-object.h>
G_BEGIN_DECLS
typedef struct _PreferencesDialog PreferencesDialog;
PreferencesDialog *preferences_dialog_new (void);
void preferences_dialog_run (PreferencesDialog *dialog);
void preferences_dialog_free (PreferencesDialog *dialog);
G_END_DECLS
#endif /* PREFERENCES_DIALOG_H */

View File

@ -1,6 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkAction" id="action1">
<property name="stock_id">gtk-close</property>
</object>
<object class="GtkAction" id="action2">
<property name="stock_id">gtk-cancel</property>
</object>
<object class="GtkAction" id="action3">
<property name="label" translatable="yes">Select</property>
<property name="stock_id">gtk-ok</property>
</object>
<object class="GtkAdjustment" id="auto_hide_delay_adjustment">
<property name="lower">100</property>
<property name="upper">2000</property>
<property name="value">500</property>
<property name="step_increment">10</property>
<property name="page_increment">10</property>
</object>
<object class="GtkListStore" id="available_keyboards_liststore">
<columns>
<!-- column-name id -->
<column type="gchararray"/>
<!-- column-name gchararray1 -->
<column type="gchararray"/>
</columns>
</object>
<object class="GtkDialog" id="dialog">
<property name="can_focus">False</property>
<property name="border_width">5</property>
@ -452,116 +477,6 @@
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Keyboard</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label"> </property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="appearances_vbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">6</property>
<child>
<object class="GtkCheckButton" id="start_fullscreen_toggle">
<property name="label" translatable="yes">Start in fullscreen mode</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkTable" id="table2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="n_columns">4</property>
<child>
<object class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Keyboard type: </property>
</object>
</child>
<child>
<object class="GtkEntry" id="keyboard_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">4</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
<child type="tab">
@ -575,10 +490,119 @@
</packing>
</child>
<child>
<placeholder/>
<object class="GtkVBox" id="keyboards_page">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">12</property>
<property name="spacing">18</property>
<child>
<object class="GtkTreeView" id="selected_keyboards_treeview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">selected_keyboards_liststore</property>
<property name="headers_visible">False</property>
<property name="headers_clickable">False</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="treeview-selection2"/>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButtonBox" id="buttonbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">2</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="up_button">
<property name="label">gtk-go-up</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="down_button">
<property name="label">gtk-go-down</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="add_button">
<property name="label">gtk-add</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="remove_button">
<property name="label">gtk-remove</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child type="tab">
<placeholder/>
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Keyboards</property>
</object>
<packing>
<property name="position">1</property>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<placeholder/>
@ -599,8 +623,86 @@
<action-widget response="0">button1</action-widget>
</action-widgets>
</object>
<object class="GtkAction" id="action1">
<property name="stock_id">gtk-close</property>
<object class="GtkDialog" id="new_keyboard_dialog">
<property name="can_focus">False</property>
<property name="border_width">5</property>
<property name="default_height">430</property>
<property name="destroy_with_parent">True</property>
<property name="type_hint">dialog</property>
<property name="transient_for">dialog</property>
<child internal-child="vbox">
<object class="GtkBox" id="dialog-vbox2">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox" id="dialog-action_area2">
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="button2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="related_action">action2</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button3">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="related_action">action3</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="available_keyboards_treeview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">available_keyboards_liststore</property>
<property name="headers_visible">False</property>
<property name="headers_clickable">False</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="treeview-selection3"/>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="0">button2</action-widget>
<action-widget response="-5">button3</action-widget>
</action-widgets>
</object>
<object class="GtkAdjustment" id="repeat_delay_adjustment">
<property name="lower">100</property>
@ -616,11 +718,12 @@
<property name="step_increment">1</property>
<property name="page_increment">1</property>
</object>
<object class="GtkAdjustment" id="auto_hide_delay_adjustment">
<property name="lower">100</property>
<property name="upper">2000</property>
<property name="value">500</property>
<property name="step_increment">10</property>
<property name="page_increment">10</property>
<object class="GtkListStore" id="selected_keyboards_liststore">
<columns>
<!-- column-name id -->
<column type="gchararray"/>
<!-- column-name gchararray1 -->
<column type="gchararray"/>
</columns>
</object>
</interface>

View File

@ -79,8 +79,11 @@ on_destroy (GtkWidget *widget, gpointer user_data)
ServerContextService *context = user_data;
g_assert (widget == context->window);
context->window = NULL;
context->widget = NULL;
eekboard_context_service_destroy (EEKBOARD_CONTEXT_SERVICE (context));
}
static void
@ -96,6 +99,7 @@ on_notify_keyboard (GObject *object,
if (keyboard == NULL) {
gtk_widget_hide (context->window);
gtk_widget_destroy (context->widget);
context->widget = NULL;
} else {
gboolean was_visible = gtk_widget_get_visible (context->window);
/* avoid to send KeyboardVisibilityChanged */
@ -273,16 +277,21 @@ update_widget (ServerContextService *context)
EekKeyboard *keyboard;
const gchar *client_name;
EekBounds bounds;
gchar *theme_name, *theme_path;
gchar *theme_name, *theme_filename, *theme_path;
EekTheme *theme;
if (context->widget)
if (context->widget) {
gtk_widget_destroy (context->widget);
context->widget = NULL;
}
theme_name = g_settings_get_string (context->settings, "theme");
theme_path = g_strdup_printf ("%s/%s.css", THEMEDIR, theme_name);
theme_filename = g_strdup_printf ("%s.css", theme_name);
g_free (theme_name);
theme_path = g_build_filename (THEMESDIR, theme_filename, NULL);
g_free (theme_filename);
theme = eek_theme_new (theme_path, NULL, NULL);
g_free (theme_path);
@ -353,6 +362,11 @@ server_context_service_real_disabled (EekboardContextService *_context)
}
}
static void
server_context_service_real_destroyed (EekboardContextService *_context)
{
}
static void
server_context_service_set_property (GObject *object,
guint prop_id,
@ -377,9 +391,7 @@ server_context_service_set_property (GObject *object,
break;
default:
g_object_set_property (object,
g_param_spec_get_name (pspec),
value);
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
@ -408,6 +420,7 @@ server_context_service_class_init (ServerContextServiceClass *klass)
context_class->hide_keyboard = server_context_service_real_hide_keyboard;
context_class->enabled = server_context_service_real_enabled;
context_class->disabled = server_context_service_real_disabled;
context_class->destroyed = server_context_service_real_destroyed;
gobject_class->set_property = server_context_service_set_property;
gobject_class->dispose = server_context_service_dispose;

41
src/setup-main.c Normal file
View File

@ -0,0 +1,41 @@
/*
* Copyright (C) 2012 Daiki Ueno <ueno@unixuser.org>
* Copyright (C) 2012 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
#include "preferences-dialog.h"
#include <gtk/gtk.h>
#include <stdlib.h>
int
main (int argc, char **argv)
{
PreferencesDialog *dialog;
if (!gtk_init_check (&argc, &argv)) {
g_printerr ("Can't init GTK\n");
return EXIT_FAILURE;
}
dialog = preferences_dialog_new ();
preferences_dialog_run (dialog);
preferences_dialog_free (dialog);
return EXIT_SUCCESS;
}