#include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include "e16keyedit.h" #if USE_GTK == 3 #define USE_GTK_TREEVIEW 1 #else #define USE_GTK_TREEVIEW 1 #endif #if !USE_GTK_TREEVIEW #define ENABLE_SORTING 1 #endif #define DEBUG 0 #define VER(maj, min, mic) (10000 * (maj) + 100 * (min) + (mic)) GtkAccelGroup *accel_group; static GtkWidget *clist; static GtkWidget *act_key; static GtkWidget *act_params; static GtkWidget *act_mod; static GtkWidget *act_clist; static gchar *e_ipc_msg = NULL; static char dont_update = 0; static int last_row = 0; static int real_rows = 0; typedef struct { const char *name_short; const char *name_long; } Modifier; typedef struct { const char *text; gchar param_tpe; const char *params; const char *command; } ActionOpt; /* *INDENT-OFF* */ static const Modifier modifiers[] = { {"-", ""}, {"C", "CTRL"}, {"S", "SHIFT"}, {"A", "ALT"}, {"CS", "CTRL+SHIFT"}, {"CA", "CTRL+ALT"}, {"SA", "ALT+SHIFT"}, {"CSA", "CTRL+ALT+SHIFT"}, {"2", "MOD2"}, {"3", "MOD3"}, {"4", "MOD4"}, {"5", "MOD5"}, {"C2", "MOD2+CTRL"}, {"S2", "MOD2+SHIFT"}, {"A2", "MOD2+ALT"}, {"C4", "MOD4+CTRL"}, {"S4", "MOD4+SHIFT"}, {"A4", "MOD4+ALT"}, {"CS4", "MOD4+CTRL+SHIFT"}, {"C5", "MOD5+CTRL"}, {"S5", "MOD5+SHIFT"}, {"A5", "MOD5+ALT"}, {"CS5", "MOD5+CTRL+SHIFT"}, }; #define N_MODIFIERS (sizeof(modifiers)/sizeof(Modifier)) #define MOD_TEXT(mod) modifiers[mod].name_long static const ActionOpt actions_default[] = { {"Run command", 1, NULL, "exec "}, {"Restart Enlightenment", 0, "restart", "restart"}, {"Exit Enlightenment", 0, NULL, "exit"}, {"Goto Next Desktop", 0, NULL, "desk next"}, {"Goto Previous Deskop", 0, NULL, "desk prev"}, {"Goto Desktop", 2, NULL, "desk goto "}, {"Raise Desktop", 0, NULL, "desk raise"}, {"Lower Desktop", 0, NULL, "desk lower"}, {"Reset Desktop In Place", 0, NULL, "desk this"}, {"Cleanup Windows", 0, NULL, "misc arrange size"}, {"Move mouse pointer to next screen", 0, NULL, "warp screen"}, {"Move mouse pointer to left", 0, "-1 0", "warp rel -1 0"}, {"Move mouse pointer to right", 0, "1 0", "warp rel 1 0"}, {"Move mouse pointer up", 0, "0 -1", "warp rel 0 -1"}, {"Move mouse pointer down", 0, "0 1", "warp rel 0 1"}, {"Move mouse pointer by [X Y]", 3, NULL, "warp rel "}, {"Goto Desktop area [X Y]", 3, NULL, "area goto"}, {"Move to Desktop area on the left", 0, "-1 0", "area move -1 0"}, {"Move to Desktop area on the right", 0, "1 0", "area move 1 0"}, {"Move to Desktop area above", 0, "0 -1", "area move 0 -1"}, {"Move to Desktop area below", 0, "0 1", "area move 0 1"}, {"Raise Window", 0, NULL, "wop * raise"}, {"Lower Window", 0, NULL, "wop * lower"}, {"Close Window", 0, NULL, "wop * close"}, {"Annihilate Window", 0, NULL, "wop * kill"}, {"Stick / Unstick Window", 0, NULL, "wop * stick"}, {"Iconify Window", 0, NULL, "wop * iconify"}, {"Shade / Unshade Window", 0, NULL, "wop * shade"}, {"Maximise Height of Window", 0, "conservative", "wop * th conservative"}, {"Maximise Height of Window to available space", 0, "available", "wop * th available"}, {"Maximise Height of Window to whole screen", 0, NULL, "wop * th"}, {"Maximise Width of Window", 0, "conservative", "wop * tw conservative"}, {"Maximise Width of Window to available space", 0, "available", "wop * tw available"}, {"Maximise Width of Window to whole screen", 0, NULL, "wop * tw"}, {"Maximise Size of Window", 0, "conservative", "wop * ts conservative"}, {"Maximise Size of Window to available space", 0, "available", "wop * ts available"}, {"Maximise Size of Window to whole screen", 0, NULL, "wop * ts"}, {"Toggle Window fullscreen state", 0, NULL, "wop * fullscreen"}, {"Toggle Window zoom state", 0, NULL, "wop * zoom"}, {"Send window to next desktop", 0, NULL, "wop * desk next"}, {"Send window to previous desktop", 0, NULL, "wop * desk prev"}, {"Switch focus to next window", 0, NULL, "focus next"}, {"Switch focus to previous window", 0, NULL, "focus prev"}, {"Glue / Unglue Window to Desktop screen", 0, NULL, "wop * no_user_move"}, {"Set Window layer to On Top", 0, "20", "wop * layer 20"}, {"Set Window layer to Above", 0, "6", "wop * layer 6"}, {"Set Window layer to Normal", 0, "4", "wop * layer 4"}, {"Set Window layer to Below", 0, "2", "wop * layer 2"}, {"Set Window layer", 2, NULL, "wop * layer "}, {"Move Window to area on left", 0, "-1 0", "wop * area move -1 0"}, {"Move Window to area on right", 0, "1 0", "wop * area move 1 0"}, {"Move Window to area above", 0, "0 -1", "wop * area move 0 -1"}, {"Move Window to area below", 0, "0 1", "wop * area move 0 1"}, {"Move Window by area [X Y]", 3, NULL, "wop * area "}, {"Set Window border style to the Default", 0, "DEFAULT", "wop * border DEFAULT"}, {"Set Window border style to the Borderless", 0, "BORDERLESS", "wop * border BORDERLESS"}, {"Forget everything about Window", 0, "none", "wop * snap none"}, {"Remember all Window settings", 0, NULL, "wop * snap all"}, {"Remember Window Border", 0, "border", "wop * snap border"}, {"Remember Window Desktop", 0, "desktop", "wop * snap desktop"}, {"Remember Window Desktop Area", 0, "area", "wop * snap area"}, {"Remember Window Size", 0, "size", "wop * snap size"}, {"Remember Window Location", 0, "location", "wop * snap location"}, {"Remember Window Layer", 0, "layer", "wop * snap layer"}, {"Remember Window Stickyness", 0, "sticky", "wop * snap sticky"}, {"Remember Window Shadedness", 0, "shade", "wop * snap shade"}, {"Show Root Menu", 0, "ROOT_2", "menus show ROOT_2"}, {"Show Winops Menu", 0, "WINOPS_MENU", "menus show WINOPS_MENU"}, {"Show Named Menu", 1, NULL, "menus show "}, {NULL, 0, NULL, NULL} }; /* *INDENT-ON* */ static const ActionOpt *actions = NULL; static unsigned int action_count = sizeof(actions_default) / sizeof(ActionOpt); static unsigned int *action_index_to_row = NULL; static unsigned int *action_row_to_index = NULL; static int match_action_by_binding(const char *params) { int k, len; for (k = 0; actions[k].text; k++) { len = strlen(actions[k].command); if (strncmp(actions[k].command, params, len)) continue; return k; } return -1; } static int match_action_by_selection(const char *text) { int k; for (k = 0; actions[k].text; k++) { if (strcmp(text, actions[k].text)) continue; return k; } return -1; } static unsigned mod_short_to_index(const char *name_short) { unsigned int k; for (k = 0; k < N_MODIFIERS; k++) { if (!strcmp(name_short, modifiers[k].name_short)) return k; } return 0; /* Discard modifier */ } #if USE_GTK_TREEVIEW static int clist_sel_row_get(GtkTreeSelection * sel) { int row, *rows; GtkTreeIter iter; GtkTreeModel *model; GtkTreePath *path; row = -1; if (gtk_tree_selection_get_selected(sel, &model, &iter)) { path = gtk_tree_model_get_path(model, &iter); rows = gtk_tree_path_get_indices(path); row = rows[0]; } return row; } #endif static void clist_row_current_set_value(GtkWidget * widget, int col, const char *txt) { #if USE_GTK_TREEVIEW GtkTreeSelection *sel; GtkTreeModel *model; GtkTreeIter iter; sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); if (gtk_tree_selection_get_selected(sel, &model, &iter)) gtk_list_store_set(GTK_LIST_STORE(model), &iter, col, txt, -1); #else gtk_clist_set_text(GTK_CLIST(widget), last_row, col, txt); #endif } static void clist_row_moveto(GtkWidget * widget, int row) { #if USE_GTK_TREEVIEW GtkTreeSelection *sel; GtkTreePath *path; sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); path = gtk_tree_path_new_from_indices(row, -1); gtk_tree_selection_select_path(sel, path); gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(widget), path, NULL, FALSE, .5, .5); gtk_tree_path_free(path); #else gtk_clist_select_row(GTK_CLIST(widget), row, 0); gtk_clist_moveto(GTK_CLIST(widget), row, 0, 0.5, 0.5); #endif } static void e_cb_key_change(GtkWidget * widget __UNUSED__, gpointer data __UNUSED__) { GtkWidget *win, *frame, *vbox, *label; win = gtk_window_new(GTK_WINDOW_POPUP); gtk_window_set_position(GTK_WINDOW(win), GTK_WIN_POS_MOUSE); frame = gtk_frame_new(NULL); gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT); vbox = gtk_vbox_new(FALSE, 5); label = gtk_label_new("Please press the key on the keyboard\n" "you wish to modify this keyboard-shortcut\n" "to use from now on."); gtk_container_add(GTK_CONTAINER(win), frame); gtk_container_add(GTK_CONTAINER(frame), vbox); gtk_container_add(GTK_CONTAINER(vbox), label); gtk_container_set_border_width(GTK_CONTAINER(vbox), 32); gtk_widget_show_all(win); while (gtk_events_pending()) gtk_main_iteration(); gdk_flush(); while (gtk_events_pending()) gtk_main_iteration(); { char *key; XEvent ev; #define WIDGET_XID(widget) GDK_WINDOW_XID(gtk_widget_get_window(widget)) gdk_window_set_events(gtk_widget_get_window(win), GDK_KEY_PRESS_MASK); XGrabKeyboard(gdk_x11_get_default_xdisplay(), WIDGET_XID(win), False, GrabModeAsync, GrabModeAsync, CurrentTime); XSetInputFocus(gdk_x11_get_default_xdisplay(), WIDGET_XID(win), RevertToPointerRoot, CurrentTime); XWindowEvent(gdk_x11_get_default_xdisplay(), WIDGET_XID(win), KeyPressMask, &ev); XUngrabKeyboard(gdk_x11_get_default_xdisplay(), CurrentTime); key = XKeysymToString(XkbKeycodeToKeysym(gdk_x11_get_default_xdisplay(), ev.xkey.keycode, 0, 0)); gtk_entry_set_text(GTK_ENTRY(act_key), key); clist_row_current_set_value(clist, 1, key); } gtk_widget_destroy(win); } static void e_cb_modifier(GtkWidget * widget, gpointer data __UNUSED__) { int i; if (dont_update) return; i = gtk_combo_box_get_active(GTK_COMBO_BOX(widget)); clist_row_current_set_value(clist, 0, MOD_TEXT(i)); } static gchar * wait_for_ipc_msg(void) { e_ipc_msg = NULL; do { gtk_main_iteration(); } while (!e_ipc_msg); return e_ipc_msg; } #if USE_GTK_TREEVIEW static void change_action(GtkTreeSelection * sel, gpointer data __UNUSED__) #else static void change_action(GtkWidget * my_clist __UNUSED__, gint row, gint column __UNUSED__, GdkEventButton * event __UNUSED__, gpointer data __UNUSED__) #endif { int k; if (dont_update) return; #if USE_GTK_TREEVIEW int row; row = clist_sel_row_get(sel); #endif if (row < 0) return; k = action_row_to_index[row]; if (actions[k].param_tpe != 0) { gtk_editable_set_editable(GTK_EDITABLE(act_params), TRUE); gtk_widget_set_sensitive(act_params, TRUE); } else { gtk_editable_set_editable(GTK_EDITABLE(act_params), FALSE); gtk_widget_set_sensitive(act_params, FALSE); gtk_entry_set_text(GTK_ENTRY(act_params), ""); } dont_update = 1; if (actions[k].command) gtk_entry_set_text(GTK_ENTRY(act_params), actions[k].command); else gtk_entry_set_text(GTK_ENTRY(act_params), "* Not available *"); dont_update = 0; clist_row_current_set_value(clist, 2, actions[k].text); clist_row_current_set_value(clist, 3, gtk_entry_get_text(GTK_ENTRY(act_params))); } static char * dupcat(char *dst, const char *src) { char *s; int len1, len2; if (!dst) return strdup(src); len1 = strlen(dst); len2 = strlen(src); s = realloc(dst, len1 + len2 + 1); strcpy(s + len1, src); return s; } static void on_save_data(void) { char *buf = NULL; buf = dupcat(buf, "ac kb set\nAclass KEYBINDINGS global\n"); #if USE_GTK_TREEVIEW GtkTreeModel *model; GtkTreeIter iter; gboolean ok; model = gtk_tree_view_get_model(GTK_TREE_VIEW(clist)); for (ok = gtk_tree_model_get_iter_first(model, &iter); ok; ok = gtk_tree_model_iter_next(model, &iter)) #else int i; for (i = 0; i < real_rows; i++) #endif { char tmp[1024]; char *mod, *key, *prm; int modifier = 0; int j; #if USE_GTK_TREEVIEW gtk_tree_model_get(model, &iter, 0, &mod, 1, &key, 3, &prm, -1); #else gtk_clist_get_text(GTK_CLIST(clist), i, 0, &mod); gtk_clist_get_text(GTK_CLIST(clist), i, 1, &key); gtk_clist_get_text(GTK_CLIST(clist), i, 3, &prm); #endif for (j = 0; j < 21; j++) { if (!strcmp(MOD_TEXT(j), mod)) { modifier = j; } } snprintf(tmp, sizeof(tmp), "%s %s %s %s\n", "KeyDown", modifiers[modifier].name_short, key, prm); buf = dupcat(buf, tmp); } #if DEBUG > 0 printf("%s", buf); #endif CommsSend(buf); #if 0 CommsSend("save_config"); #endif free(buf); } #if USE_GTK_TREEVIEW static void selection_made(GtkTreeSelection * sel, gpointer data __UNUSED__) #else static void selection_made(GtkWidget * my_clist __UNUSED__, gint row, gint column __UNUSED__, GdkEventButton * event __UNUSED__, gpointer data __UNUSED__) #endif { gchar *mod, *key, *act, *prm; int i; #if USE_GTK_TREEVIEW int row; row = clist_sel_row_get(sel); #endif if (row < 0) return; dont_update = 1; #if USE_GTK_TREEVIEW GtkTreeIter iter; GtkTreeModel *model; if (gtk_tree_selection_get_selected(sel, &model, &iter)) { gtk_tree_model_get(model, &iter, 0, &mod, 1, &key, 2, &act, 3, &prm, -1); } #else gtk_clist_get_text(GTK_CLIST(clist), row, 0, &mod); gtk_clist_get_text(GTK_CLIST(clist), row, 1, &key); gtk_clist_get_text(GTK_CLIST(clist), row, 2, &act); gtk_clist_get_text(GTK_CLIST(clist), row, 3, &prm); #endif for (i = 0; i < 21; i++) { if (!strcmp(MOD_TEXT(i), mod)) gtk_combo_box_set_active(GTK_COMBO_BOX(act_mod), i); } gtk_entry_set_text(GTK_ENTRY(act_key), key); gtk_entry_set_text(GTK_ENTRY(act_params), prm); i = match_action_by_selection(act); if (i < 0 || actions[i].param_tpe == 0) { gtk_editable_set_editable(GTK_EDITABLE(act_params), FALSE); gtk_widget_set_sensitive(act_params, FALSE); } else { gtk_editable_set_editable(GTK_EDITABLE(act_params), TRUE); gtk_widget_set_sensitive(act_params, TRUE); } #if USE_GTK_TREEVIEW g_free(mod); g_free(key); g_free(act); g_free(prm); #endif if (i >= 0) { i = action_index_to_row[i]; clist_row_moveto(act_clist, i); } /* printf("%s\n%s\n%s\n%s\n",mod,key,act,prm); */ last_row = row; dont_update = 0; } static gchar *get_line(gchar * str, int num); static gchar * get_line(gchar * str, int num) { gchar *s1, *s2, *s; gint i, count, l; i = 0; count = 0; s1 = str; if (*str == '\n') i = 1; s2 = NULL; for (i = 0;; i++) { if ((str[i] == '\n') || (str[i] == 0)) { s2 = &(str[i]); if ((count == num) && (s2 > s1)) { l = s2 - s1; s = g_malloc(l + 1); strncpy(s, s1, l); s[l] = 0; return s; } count++; if (str[i] == 0) return NULL; s1 = s2 + 1; } } } #if ENABLE_SORTING static void on_resort_columns(GtkWidget * widget __UNUSED__, gint column, gpointer data __UNUSED__) { static int order = 0; static int last_col = 0; gtk_clist_set_sort_column(GTK_CLIST(clist), column); if (last_col == column) { if (order) { order = 0; gtk_clist_set_sort_type(GTK_CLIST(clist), GTK_SORT_DESCENDING); } else { order = 1; gtk_clist_set_sort_type(GTK_CLIST(clist), GTK_SORT_ASCENDING); } } else { order = 1; gtk_clist_set_sort_type(GTK_CLIST(clist), GTK_SORT_ASCENDING); last_col = column; } gtk_clist_sort(GTK_CLIST(clist)); } #endif /* ENABLE_SORTING */ static void on_delete_row(GtkWidget * widget __UNUSED__, gpointer data __UNUSED__) { #if USE_GTK_TREEVIEW GtkTreeSelection *sel; GtkTreeIter iter; GtkTreeModel *model; sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(clist)); if (!gtk_tree_selection_get_selected(sel, &model, &iter)) return; gtk_list_store_remove(GTK_LIST_STORE(model), &iter); #else gtk_clist_remove(GTK_CLIST(clist), last_row); #endif real_rows--; if (last_row >= real_rows) last_row--; clist_row_moveto(clist, last_row); } static void on_create_row(GtkWidget * widget __UNUSED__, gpointer data __UNUSED__) { #if USE_GTK_TREEVIEW GtkTreeModel *model; GtkTreeIter iter; model = gtk_tree_view_get_model(GTK_TREE_VIEW(clist)); gtk_list_store_append(GTK_LIST_STORE(model), &iter); gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, "", 1, "", 2, "", 3, "", -1); #else char *stuff[4]; stuff[0] = ""; stuff[1] = ""; stuff[2] = ""; stuff[3] = ""; gtk_clist_select_row(GTK_CLIST(clist), gtk_clist_append(GTK_CLIST(clist), stuff), 0); #endif last_row = real_rows++; clist_row_moveto(clist, last_row); } static void on_change_params(GtkWidget * widget, gpointer data __UNUSED__) { const char *txt; if (dont_update) return; txt = gtk_entry_get_text(GTK_ENTRY(widget)); clist_row_current_set_value(clist, 3, txt); } void on_exit_application(void) { exit(0); } static void on_save_and_exit_application(void) { on_save_data(); on_exit_application(); } static GtkWidget * create_list_window(void) { GtkWidget *list_window; GtkWidget *bigvbox; GtkWidget *menubar; GtkWidget *panes; GtkWidget *scrollybit; GtkWidget *vbox; GtkWidget *frames; GtkWidget *frame_vbox; GtkWidget *table; GtkWidget *label; GtkWidget *entry; GtkWidget *button; GtkWidget *hbox; GtkWidget *om; GtkWidget *menu; #if USE_GTK_TREEVIEW GtkCellRenderer *renderer; GtkListStore *store; GtkTreeIter iter; GtkTreeSelection *sel; #endif int i; list_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size(GTK_WINDOW(list_window), 400, 400); g_object_set_data(G_OBJECT(list_window), "key_editor", list_window); gtk_widget_set_can_focus(list_window, TRUE); gtk_widget_set_can_default(list_window, TRUE); gtk_window_set_title(GTK_WINDOW(list_window), "E Keys Editor"); bigvbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(list_window), bigvbox); menubar = gtk_menu_bar_new(); gtk_box_pack_start(GTK_BOX(bigvbox), menubar, FALSE, FALSE, 0); menu = CreateBarSubMenu(menubar, "File"); CreateMenuItem(menu, "Save", "", "Save Current Data", on_save_data, NULL); CreateMenuItem(menu, "Save & Quit", "", "Save Current Data & Quit Application", on_save_and_exit_application, NULL); CreateMenuItem(menu, "Quit", "", "Quit Without Saving", on_exit_application, NULL); #if 0 /* Not implemented */ menu = CreateRightAlignBarSubMenu(menubar, "Help"); menuitem = CreateMenuItem(menu, "About", "", "About E Keybinding Editor", NULL, "about"); menuitem = CreateMenuItem(menu, "Documentation", "", "Read the Keybinding Editor Documentation", NULL, "read docs"); #endif #if USE_GTK == 3 panes = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL); #else panes = gtk_hpaned_new(); #endif gtk_box_pack_start(GTK_BOX(bigvbox), panes, TRUE, TRUE, 0); scrollybit = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollybit), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_paned_pack1(GTK_PANED(panes), scrollybit, TRUE, FALSE); #if USE_GTK_TREEVIEW clist = gtk_tree_view_new(); renderer = gtk_cell_renderer_text_new(); gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(clist), -1, "Modifier", renderer, "text", 0, NULL); renderer = gtk_cell_renderer_text_new(); gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(clist), -1, "Key", renderer, "text", 1, NULL); renderer = gtk_cell_renderer_text_new(); gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(clist), -1, "Action to Perform", renderer, "text", 2, NULL); renderer = gtk_cell_renderer_text_new(); gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(clist), -1, "Command", renderer, "text", 3, NULL); store = gtk_list_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); #else clist = gtk_clist_new(4); gtk_clist_set_column_title(GTK_CLIST(clist), 0, "Modifier"); gtk_clist_set_column_title(GTK_CLIST(clist), 1, "Key"); gtk_clist_set_column_title(GTK_CLIST(clist), 2, "Action to Perform"); gtk_clist_set_column_title(GTK_CLIST(clist), 3, "Command"); #if 0 gtk_clist_set_column_auto_resize(GTK_CLIST(clist), 0, TRUE); gtk_clist_set_column_auto_resize(GTK_CLIST(clist), 1, TRUE); #endif gtk_clist_column_titles_show(GTK_CLIST(clist)); #endif gtk_container_add(GTK_CONTAINER(scrollybit), clist); { char *msg, *buf; int j, k, modifier; char event[128], mod[128], key[128], *params; const char *stuff[4]; int len; CommsSend("ac kb"); msg = wait_for_ipc_msg(); i = 0; while ((buf = get_line(msg, i++))) { if (strlen(buf) < 1) break; j = sscanf(buf, "%127s %127s %127s %n", event, mod, key, &len); #if DEBUG > 0 printf("buf(%d): %s\n", j, buf); #endif if (j < 3) goto next; if (strcmp(event, "KeyDown")) goto next; params = buf + len; #if DEBUG > 0 printf("event: %s, mod: %s, key: %s, params: %s\n", event, mod, key, params); #endif modifier = mod_short_to_index(mod); k = match_action_by_binding(params); #if DEBUG > 1 printf("key: %s, mod: %s, act=%d, params: %s\n", key, MOD_TEXT(modifier), k, params); #endif stuff[0] = MOD_TEXT(modifier); stuff[1] = key; stuff[2] = (k >= 0) ? actions[k].text : "* Not recognised *"; stuff[3] = params; #if USE_GTK_TREEVIEW gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, stuff[0], 1, stuff[1], 2, stuff[2], 3, stuff[3], -1); #else gtk_clist_append(GTK_CLIST(clist), (char **)stuff); #endif real_rows++; next: g_free(buf); } g_free(msg); } #if USE_GTK_TREEVIEW gtk_tree_view_set_model(GTK_TREE_VIEW(clist), GTK_TREE_MODEL(store)); g_object_unref(store); sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(clist)); gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); g_signal_connect(G_OBJECT(sel), "changed", G_CALLBACK(selection_made), NULL); #if ENABLE_SORTING g_signal_connect(G_OBJECT(clist), "click_column", /////////////////// CRAP G_CALLBACK(on_resort_columns), NULL); #endif #else gtk_clist_columns_autosize(GTK_CLIST(clist)); g_signal_connect(G_OBJECT(clist), "select_row", G_CALLBACK(selection_made), NULL); g_signal_connect(G_OBJECT(clist), "click_column", G_CALLBACK(on_resort_columns), NULL); #endif vbox = gtk_vbox_new(FALSE, 0); frames = gtk_frame_new("Edit Keybinding Properties"); gtk_container_set_border_width(GTK_CONTAINER(frames), 2); gtk_paned_pack2(GTK_PANED(panes), vbox, FALSE, FALSE); gtk_box_pack_start(GTK_BOX(vbox), frames, TRUE, TRUE, 0); frame_vbox = gtk_vbox_new(FALSE, 3); gtk_container_set_border_width(GTK_CONTAINER(frame_vbox), 4); gtk_container_add(GTK_CONTAINER(frames), frame_vbox); #if USE_GTK == 3 table = gtk_grid_new(); gtk_grid_set_row_spacing(GTK_GRID(table), 3); gtk_grid_set_column_spacing(GTK_GRID(table), 3); #else table = gtk_table_new(3, 3, FALSE); gtk_table_set_row_spacings(GTK_TABLE(table), 3); gtk_table_set_col_spacings(GTK_TABLE(table), 3); #endif gtk_box_pack_start(GTK_BOX(frame_vbox), table, FALSE, FALSE, 2); label = gtk_label_new("Key:"); #if USE_GTK == 3 gtk_widget_set_halign(label, GTK_ALIGN_END); gtk_grid_attach(GTK_GRID(table), label, 0, 0, 1, 1); #else gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, (GtkAttachOptions) (0), 0, 0); #endif label = gtk_label_new("Modifier:"); #if USE_GTK == 3 gtk_widget_set_halign(label, GTK_ALIGN_END); gtk_grid_attach(GTK_GRID(table), label, 0, 1, 1, 1); #else gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, (GtkAttachOptions) (0), 0, 0); #endif label = gtk_label_new("Command:"); #if USE_GTK == 3 gtk_widget_set_halign(label, GTK_ALIGN_END); gtk_grid_attach(GTK_GRID(table), label, 0, 2, 1, 1); #else gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, (GtkAttachOptions) (0), 0, 0); #endif act_key = entry = gtk_entry_new(); gtk_entry_set_max_length(GTK_ENTRY(entry), 4096); gtk_widget_set_sensitive(entry, FALSE); #if USE_GTK == 3 gtk_widget_set_hexpand(entry, GTK_EXPAND | GTK_FILL); gtk_grid_attach(GTK_GRID(table), entry, 1, 0, 1, 1); #else gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, (GtkAttachOptions) (0), 0, 0); #endif button = gtk_button_new_with_label("Change"); #if USE_GTK == 3 gtk_widget_set_hexpand(button, GTK_EXPAND | GTK_FILL); gtk_grid_attach(GTK_GRID(table), button, 2, 0, 1, 1); #else gtk_table_attach(GTK_TABLE(table), button, 2, 3, 0, 1, GTK_EXPAND | GTK_FILL, (GtkAttachOptions) (0), 0, 0); #endif g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(e_cb_key_change), NULL); act_mod = om = gtk_combo_box_text_new(); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(om), "None"); for (i = 1; i < 21; i++) gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(om), MOD_TEXT(i)); gtk_combo_box_set_active(GTK_COMBO_BOX(om), 0); g_signal_connect(G_OBJECT(om), "changed", G_CALLBACK(e_cb_modifier), NULL); #if USE_GTK == 3 gtk_widget_set_hexpand(om, GTK_EXPAND | GTK_FILL); gtk_grid_attach(GTK_GRID(table), om, 1, 1, 2, 1); #else gtk_table_attach(GTK_TABLE(table), om, 1, 3, 1, 2, GTK_EXPAND | GTK_FILL, (GtkAttachOptions) (0), 0, 0); #endif act_params = entry = gtk_entry_new(); gtk_entry_set_max_length(GTK_ENTRY(entry), 4096); gtk_widget_set_sensitive(entry, FALSE); #if USE_GTK == 3 gtk_widget_set_hexpand(entry, GTK_EXPAND | GTK_FILL); gtk_grid_attach(GTK_GRID(table), entry, 1, 2, 2, 1); #else gtk_table_attach(GTK_TABLE(table), entry, 1, 3, 2, 3, GTK_EXPAND | GTK_FILL, (GtkAttachOptions) (0), 0, 0); #endif g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(on_change_params), NULL); scrollybit = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollybit), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); #if USE_GTK_TREEVIEW act_clist = gtk_tree_view_new(); renderer = gtk_cell_renderer_text_new(); gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(act_clist), -1, "Action Used:", renderer, "text", 0, NULL); store = gtk_list_store_new(1, G_TYPE_STRING); #else act_clist = gtk_clist_new(1); gtk_clist_set_column_title(GTK_CLIST(act_clist), 0, "Action Used:"); gtk_clist_column_titles_show(GTK_CLIST(act_clist)); #endif gtk_box_pack_start(GTK_BOX(frame_vbox), scrollybit, TRUE, TRUE, 0); gtk_container_add(GTK_CONTAINER(scrollybit), act_clist); { const char *stuff[1]; int k, row; action_index_to_row = calloc(action_count, sizeof(int)); action_row_to_index = calloc(action_count, sizeof(int)); for (k = row = 0; (actions[k].text); k++) { stuff[0] = actions[k].text; #if USE_GTK_TREEVIEW gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, stuff[0], -1); #else gtk_clist_append(GTK_CLIST(act_clist), (char **)stuff); #endif action_index_to_row[k] = row; action_row_to_index[row++] = k; } } #if USE_GTK_TREEVIEW gtk_tree_view_set_model(GTK_TREE_VIEW(act_clist), GTK_TREE_MODEL(store)); g_object_unref(store); sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(act_clist)); gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); g_signal_connect(G_OBJECT(sel), "changed", G_CALLBACK(change_action), NULL); #else g_signal_connect(G_OBJECT(act_clist), "select_row", G_CALLBACK(change_action), NULL); #endif hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5); button = gtk_button_new_with_label(" New Keybinding "); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, FALSE, 5); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_create_row), NULL); button = gtk_button_new_with_label(" Delete Current Row "); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, FALSE, 5); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_delete_row), NULL); button = gtk_button_new_with_label(" Save "); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, FALSE, 5); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_save_data), NULL); button = gtk_button_new_with_label(" Quit "); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, FALSE, 5); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_exit_application), NULL); clist_row_moveto(clist, 0); return list_window; } static void receive_ipc_msg(gchar * msg) { e_ipc_msg = g_strdup(msg); } static void check_e16_version(void) { char *msg; const char *s; int ver, major, minor, micro; ver = major = minor = micro = 0; CommsSend("ver"); msg = wait_for_ipc_msg(); if (!msg) goto do_check; s = msg; while (*s && *s != '.') s++; s--; sscanf(s, "%d.%d.%d", &major, &minor, µ); ver = VER(major, minor, micro); free(msg); do_check: if (ver < VER(1, 0, 1)) { printf("Sorry, e16 version >= 1.0.1 is required.\n"); exit(1); } } static void load_actions(void) { char kbdb[1024], buf[1024], text[1024], command[1024]; const char *p; char *s; FILE *f; int n, opt; unsigned int nao; ActionOpt *pao; actions = actions_default; /* FIXME - Should be fetched via IPC. */ p = getenv("EROOT"); if (!p) p = DATADIR "/e16"; /* Default location */ snprintf(kbdb, sizeof(kbdb), "%s/config/e16keyedit.db", p); f = fopen(kbdb, "r"); if (!f) return; nao = 0; pao = NULL; for (;;) { s = fgets(buf, sizeof(buf), f); if (!s) break; while (isspace(*s)) s++; if (*s == '\0' || *s == '#') continue; n = strlen(s); while (n > 0 && (s[n - 1] == '\n' || s[n - 1] == '\r')) n--; if (n <= 0) continue; s[n] = '\0'; #if DEBUG > 0 printf("Got: %s\n", s); #endif text[0] = command[0] = '\0'; opt = -1; n = sscanf(s, "\"%1023[^\"]\", %d, \"%1023[^\"]\"", text, &opt, command); if (n < 2) { printf("*** ERROR: %s\n", buf); printf ("*** ERROR: Keybindings database (%s) corrupt, using defaults.\n", kbdb); if (pao) free(pao); fclose(f); return; } if (!command[0]) continue; #if DEBUG > 0 printf("n=%d t=%s o=%d c=%s\n", n, text, opt, command); #endif pao = realloc(pao, (nao + 1) * sizeof(ActionOpt)); memset(pao + nao, 0, sizeof(ActionOpt)); pao[nao].text = strdup(text); pao[nao].param_tpe = opt; pao[nao].command = strdup(command); nao++; } fclose(f); if (nao == 0) return; /* No entries ??? */ /* Add terminator record */ pao = realloc(pao, (nao + 1) * sizeof(ActionOpt)); memset(pao + nao, 0, sizeof(ActionOpt)); actions = pao; action_count = nao; } int main(int argc, char *argv[]) { GtkWidget *lister; setlocale(LC_ALL, ""); gtk_init(&argc, &argv); accel_group = gtk_accel_group_new(); if (CommsInit(receive_ipc_msg)) { GtkWidget *win, *frame, *vbox, *label, *button; win = gtk_window_new(GTK_WINDOW_POPUP); gtk_window_set_position(GTK_WINDOW(win), GTK_WIN_POS_CENTER); frame = gtk_frame_new(NULL); gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT); vbox = gtk_vbox_new(FALSE, 5); button = gtk_button_new_with_label("Quit"); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_exit_application), NULL); label = gtk_label_new("You are not running Enlightenment\n" "\n" "This window manager has to be running in order\n" "to configure it.\n" "\n"); gtk_container_add(GTK_CONTAINER(win), frame); gtk_container_add(GTK_CONTAINER(frame), vbox); gtk_container_set_border_width(GTK_CONTAINER(vbox), 32); gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0); gtk_widget_show_all(win); gtk_main(); exit(1); } CommsSend("set clientname Enlightenment Keybinding Configuration Utility"); CommsSend("set version " VERSION); #if 0 CommsSend("set author Mandrake (Geoff Harrison)"); CommsSend("set email mandrake@mandrake.net"); CommsSend("set web http://mandrake.net/"); CommsSend("set address C/O VA Linux Systems, USA"); CommsSend("set info " "This is the Enlightenemnt KeyBindings Configuration Utility\n" "that uses Enlightenment's IPC mechanism to configure\n" "it remotely."); #endif check_e16_version(); load_actions(); lister = create_list_window(); g_signal_connect(G_OBJECT(lister), "destroy", G_CALLBACK(on_exit_application), NULL); g_signal_connect(G_OBJECT(lister), "delete_event", G_CALLBACK(on_exit_application), NULL); gtk_widget_show_all(lister); gtk_main(); return 0; }