summaryrefslogtreecommitdiff
path: root/rcm-client-advanced.c
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2015-08-19 20:56:38 +0200
committerDavid Härdeman <david@hardeman.nu>2015-08-19 20:56:38 +0200
commit09c3b53ad8795e050b72277968fd50591bbb3a7f (patch)
treed83bcf26ec55ce585de3a86dd95bd17fe9861e4a /rcm-client-advanced.c
parentf3f7d5445e6f64a7c946f6e0144452952f0809e8 (diff)
Add support for editing in-kernel keymap
Diffstat (limited to 'rcm-client-advanced.c')
-rw-r--r--rcm-client-advanced.c201
1 files changed, 185 insertions, 16 deletions
diff --git a/rcm-client-advanced.c b/rcm-client-advanced.c
index 3374ba3..31ac86b 100644
--- a/rcm-client-advanced.c
+++ b/rcm-client-advanced.c
@@ -1,6 +1,8 @@
#include <stdint.h>
#include <string.h>
#include <gtk/gtk.h>
+#include <inttypes.h>
+#include <stdint.h>
#include "generated.h"
#include "shared.h"
@@ -58,8 +60,8 @@ advanced_transmit_cb(GtkButton *button, gpointer user_data)
GError *error = NULL;
gboolean r;
- protocolw = GTK_COMBO_BOX_TEXT(gtk_builder_get_object(global->builder, "advanced_transmit_protocol"));
- scancodew = GTK_ENTRY(gtk_builder_get_object(global->builder, "advanced_transmit_scancode"));
+ protocolw = GTK_COMBO_BOX_TEXT(get_object("advanced_transmit_protocol"));
+ scancodew = GTK_ENTRY(get_object("advanced_transmit_scancode"));
protocol = gtk_combo_box_text_get_active_text(protocolw);
scancode = gtk_entry_get_text(scancodew);
@@ -89,7 +91,7 @@ local_create_header_button(const gchar *tooltip,
const gchar *icon_name, gboolean end,
GCallback callback, gpointer user_data)
{
- GtkHeaderBar *header = GTK_HEADER_BAR(gtk_builder_get_object(global->builder, "advanced_headerbar"));
+ GtkHeaderBar *header = GTK_HEADER_BAR(get_object("advanced_headerbar"));
GtkWidget *button;
button = create_header_button(header, tooltip, icon_name, end, callback, user_data);
@@ -114,7 +116,7 @@ advanced_show_main_cb(GtkButton *button, gpointer user_data)
GtkStack *stack;
remove_header_buttons();
- stack = GTK_STACK(gtk_builder_get_object(global->builder, "advanced_stack"));
+ stack = GTK_STACK(get_object("advanced_stack"));
gtk_stack_set_visible_child_name(stack, "advanced_main_page");
}
@@ -123,35 +125,202 @@ advanced_show_transmit_cb(GtkButton *button, gpointer user_data)
{
RCDevice *object = user_data;
GtkStack *stack;
- GtkWidget *transmit_button;
- stack = GTK_STACK(gtk_builder_get_object(global->builder, "advanced_stack"));
+ stack = GTK_STACK(get_object("advanced_stack"));
gtk_stack_set_visible_child_name(stack, "advanced_transmit_page");
- transmit_button = GTK_WIDGET(gtk_builder_get_object(global->builder, "advanced_transmit_button"));
- g_signal_connect(transmit_button, "clicked", G_CALLBACK(advanced_transmit_cb), object);
+ g_signal_replace_id("advanced_transmit_button", "clicked", G_CALLBACK(advanced_transmit_cb), object);
+ local_create_header_button("Return to advanced menu", "go-previous-symbolic", false, G_CALLBACK(advanced_show_main_cb), NULL);
+}
+
+static void advanced_show_keymap_cb(GtkButton *button, gpointer user_data);
+
+static void
+advanced_keymap_remove_cb(GtkButton *button, gpointer user_data)
+{
+ RCDevice *object = user_data;
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gchar *protocol;
+ guint64 scancode;
+ gchar *keycode;
+ GVariantBuilder builder;
+
+ selection = GTK_TREE_SELECTION(get_object("advanced_keymap_treeselection"));
+ if (!gtk_tree_selection_get_selected(selection, &model, &iter))
+ return;
+
+ gtk_tree_model_get(model, &iter, 0, &protocol, 1, &scancode, 2, &keycode, -1);
+ printf("Row to be deleted: %s:%lux:%s\n", protocol, scancode, keycode);
+
+ g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
+ g_variant_builder_open(&builder, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add(&builder, "{sv}", "protocol",
+ g_variant_new_string(protocol));
+ g_variant_builder_add(&builder, "{sv}", "scancode",
+ g_variant_new_uint64(scancode));
+ g_variant_builder_add(&builder, "{sv}", "keycode",
+ g_variant_new_string("KEY_RESERVED"));
+ g_variant_builder_close(&builder);
+
+ if (!rcdevice_call_set_kernel_mappings_sync(object,
+ g_variant_builder_end(&builder),
+ NULL, NULL))
+ return;
+
+ advanced_show_keymap_cb(NULL, object);
+}
+
+static void
+advanced_keymap_row_selected_cb(GtkTreeSelection *selection, gpointer user_data)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkWidget *remove;
+
+ remove = GTK_WIDGET(get_object("advanced_keymap_remove"));
+ if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
+ g_signal_replace(remove, "clicked", G_CALLBACK(advanced_keymap_remove_cb), user_data);
+ gtk_widget_set_sensitive(remove, true);
+ } else
+ gtk_widget_set_sensitive(remove, false);
+}
+
+static void
+advanced_keymap_add_cb(GtkButton *button, gpointer user_data)
+{
+ RCDevice *object = user_data;
+ GtkWidget *dialog;
+ gchar *protocol;
+ const char *scanstr;
+ guint64 scancode;
+ gchar *keycode;
+ GVariantBuilder builder;
+ int r;
+
+ dialog = GTK_WIDGET(get_object("advanced_add"));
+ gtk_widget_show_all(dialog);
+ r = gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_hide(dialog);
+
+ if (r != 1)
+ return;
+
+ scanstr = gtk_entry_get_text(GTK_ENTRY(get_object("advanced_add_scancode")));
+ r = strtoull_strict(scanstr, &scancode);
+ if (r < 0)
+ return;
+
+ protocol = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(get_object("advanced_add_protocol")));
+ keycode = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(get_object("advanced_add_keycode")));
+
+ g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
+ g_variant_builder_open(&builder, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add(&builder, "{sv}", "protocol",
+ g_variant_new_string(protocol));
+ g_variant_builder_add(&builder, "{sv}", "scancode",
+ g_variant_new_uint64(scancode));
+ g_variant_builder_add(&builder, "{sv}", "keycode",
+ g_variant_new_string(keycode));
+ g_variant_builder_close(&builder);
+
+ g_free(protocol);
+ g_free(keycode);
+
+ if (!rcdevice_call_set_kernel_mappings_sync(object,
+ g_variant_builder_end(&builder),
+ NULL, NULL))
+ return;
+
+ advanced_show_keymap_cb(NULL, object);
+}
+
+static void
+advanced_show_keymap_cb(GtkButton *button, gpointer user_data)
+{
+ RCDevice *object = user_data;
+ GtkListStore *store;
+ GVariant *keymap_entries = NULL;
+ GtkStack *stack;
+
+ g_signal_replace_id("advanced_keymap_treeselection", "changed", G_CALLBACK(advanced_keymap_row_selected_cb), object);
+ g_signal_replace_id("advanced_keymap_add", "clicked", G_CALLBACK(advanced_keymap_add_cb), object);
+ g_signal_replace_id("advanced_keymap_refresh", "clicked", G_CALLBACK(advanced_show_keymap_cb), object);
+ store = GTK_LIST_STORE(get_object("advanced_keymap_liststore"));
+ gtk_list_store_clear(store);
+
+ rcdevice_call_get_kernel_mappings_sync(object, &keymap_entries, NULL, NULL);
+
+ g_assert(g_variant_is_of_type(keymap_entries, G_VARIANT_TYPE("aa{sv}")));
+
+ GVariantIter iter;
+ gsize n_items;
+ GVariant *item;
+
+ n_items = g_variant_iter_init(&iter, keymap_entries);
+ g_print("Keymap items: %zu\n", n_items);
+ while (g_variant_iter_loop (&iter, "@a{sv}", &item)) {
+ gchar *protocol;
+ guint64 scancode;
+ gchar *keycode;
+ GtkTreeIter iter;
+
+ g_variant_lookup(item, "protocol", "s", &protocol);
+ g_variant_lookup(item, "scancode", "t", &scancode);
+ g_variant_lookup(item, "keycode", "s", &keycode);
+
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter, 0, protocol, 1, scancode, 2, keycode, -1);
+ }
+ g_variant_unref(keymap_entries);
+
+ stack = GTK_STACK(get_object("advanced_stack"));
+ gtk_stack_set_visible_child_name(stack, "advanced_keymap_page");
+ remove_header_buttons();
local_create_header_button("Return to advanced menu", "go-previous-symbolic", false, G_CALLBACK(advanced_show_main_cb), NULL);
}
+static void
+render_cell_as_hexadecimal(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
+ GtkTreeModel *tree_model, GtkTreeIter *iter,
+ gpointer user_data)
+{
+ guint64 val;
+ gchar *text;
+
+ gtk_tree_model_get(tree_model, iter, 1, &val, -1);
+ if (val > UINT32_MAX)
+ text = g_strdup_printf("0x%016" PRIX64, val);
+ else
+ text = g_strdup_printf("0x%08" PRIX64, val);
+ g_object_set(cell, "text", text, NULL);
+ g_free (text);
+}
+
void
advanced_init_ui(RCDevice *object)
{
- GtkWidget *dialog;
GtkWidget *title;
- GtkWidget *transmit;
gchar *titlestr;
+ GtkWidget *dialog;
- dialog = GTK_WIDGET(gtk_builder_get_object(global->builder, "advanced"));
-
- title = GTK_WIDGET(gtk_builder_get_object(global->builder, "advanced_main_title_label"));
+ title = GTK_WIDGET(get_object("advanced_main_title_label"));
titlestr = g_markup_printf_escaped("<b><big>Advanced Actions</big></b>\nFor device %s",
rcdevice_get_sys_name(object));
gtk_label_set_markup(GTK_LABEL(title), titlestr);
g_free(titlestr);
- transmit = GTK_WIDGET(gtk_builder_get_object(global->builder, "advanced_main_transmit"));
- g_signal_connect(transmit, "clicked", G_CALLBACK(advanced_show_transmit_cb), object);
+ g_signal_replace_id("advanced_main_transmit", "clicked", G_CALLBACK(advanced_show_transmit_cb), object);
+ g_signal_replace_id("advanced_main_keymap", "clicked", G_CALLBACK(advanced_show_keymap_cb), object);
+
+ gtk_tree_view_column_set_cell_data_func(GTK_TREE_VIEW_COLUMN(get_object("advanced_keymap_treecol_scancode")),
+ GTK_CELL_RENDERER(get_object("advanced_keymap_treecell_scancode")),
+ render_cell_as_hexadecimal,
+ NULL, NULL);
- g_signal_connect_swapped(dialog, "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), dialog);
+ dialog = GTK_WIDGET(get_object("advanced"));
+ g_signal_replace_swapped(dialog, "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), dialog);
+ advanced_show_main_cb(NULL, NULL);
gtk_widget_show(dialog);
}