diff --git a/src/bin/e_border.c b/src/bin/e_border.c index f5d5dee4c..7eb8c4b13 100644 --- a/src/bin/e_border.c +++ b/src/bin/e_border.c @@ -1308,6 +1308,34 @@ e_border_act_kill_begin(E_Border *bd) e_object_del(E_OBJECT(bd)); } +void +e_border_button_bindings_ungrab_all(void) +{ + Evas_List *l; + + for (l = borders; l; l = l->next) + { + E_Border *bd; + + bd = l->data; + e_bindings_mouse_ungrab(E_BINDING_CONTEXT_BORDER, bd->win); + } +} + +void +e_border_button_bindings_grab_all(void) +{ + Evas_List *l; + + for (l = borders; l; l = l->next) + { + E_Border *bd; + + bd = l->data; + e_bindings_mouse_grab(E_BINDING_CONTEXT_BORDER, bd->win); + } +} + /* local subsystem functions */ static void _e_border_free(E_Border *bd) diff --git a/src/bin/e_border.h b/src/bin/e_border.h index c49672896..cd6908736 100644 --- a/src/bin/e_border.h +++ b/src/bin/e_border.h @@ -357,6 +357,9 @@ EAPI void e_border_act_resize_end(E_Border *bd, Ecore_X_Event_Mouse_Button_Up *e EAPI void e_border_act_menu_begin(E_Border *bd, Ecore_X_Event_Mouse_Button_Down *ev, int key); EAPI void e_border_act_close_begin(E_Border *bd); EAPI void e_border_act_kill_begin(E_Border *bd); + +EAPI void e_border_button_bindings_ungrab_all(void); +EAPI void e_border_button_bindings_grab_all(void); extern EAPI int E_EVENT_BORDER_RESIZE; extern EAPI int E_EVENT_BORDER_MOVE; diff --git a/src/bin/e_config.c b/src/bin/e_config.c index e4fe08de3..8a08d1194 100644 --- a/src/bin/e_config.c +++ b/src/bin/e_config.c @@ -732,6 +732,48 @@ e_config_domain_save(char *domain, E_Config_DD *edd, void *data) return ok; } +E_Config_Binding_Mouse * +e_config_binding_mouse_match(E_Config_Binding_Mouse *eb_in) +{ + Evas_List *l; + + for (l = e_config->mouse_bindings; l; l = l->next) + { + E_Config_Binding_Mouse *eb; + + eb = l->data; + if ((eb->context == eb_in->context) && + (eb->button == eb_in->button) && + (eb->modifiers == eb_in->modifiers) && + (eb->any_mod == eb_in->any_mod) && + (!strcmp(eb->action, eb_in->action)) && + (!strcmp(eb->action, eb_in->action))) + return eb; + } + return NULL; +} + +E_Config_Binding_Key * +e_config_binding_key_match(E_Config_Binding_Key *eb_in) +{ + Evas_List *l; + + for (l = e_config->key_bindings; l; l = l->next) + { + E_Config_Binding_Key *eb; + + eb = l->data; + if ((eb->context == eb_in->context) && + (eb->modifiers == eb_in->modifiers) && + (eb->any_mod == eb_in->any_mod) && + (!strcmp(eb->key, eb_in->key)) && + (!strcmp(eb->action, eb_in->action)) && + (!strcmp(eb->action, eb_in->action))) + return eb; + } + return NULL; +} + /* local subsystem functions */ static void _e_config_save_cb(void *data) diff --git a/src/bin/e_config.h b/src/bin/e_config.h index c81019a96..42a6e126b 100644 --- a/src/bin/e_config.h +++ b/src/bin/e_config.h @@ -108,6 +108,9 @@ EAPI int e_config_save(void); EAPI void e_config_save_flush(void); EAPI void e_config_save_queue(void); +EAPI E_Config_Binding_Mouse *e_config_binding_mouse_match(E_Config_Binding_Mouse *eb_in); +EAPI E_Config_Binding_Key *e_config_binding_key_match(E_Config_Binding_Key *eb_in); + extern EAPI E_Config *e_config; #endif diff --git a/src/bin/e_ipc.c b/src/bin/e_ipc.c index 7f57c2437..cc99c2016 100644 --- a/src/bin/e_ipc.c +++ b/src/bin/e_ipc.c @@ -471,10 +471,50 @@ _e_ipc_cb_client_data(void *data __UNUSED__, int type __UNUSED__, void *event) break; case E_IPC_OP_BINDING_MOUSE_ADD: { + E_Config_Binding_Mouse bind, *eb; + + _e_ipc_mouse_binding_dec(e->data, e->size, &bind); + { + eb = e_config_binding_mouse_match(&bind); + if (!eb) + { + eb = E_NEW(E_Config_Binding_Key, 1); + e_config->mouse_bindings = evas_list_append(e_config->mouse_bindings, eb); + eb->context = bind.context; + eb->button = bind.button; + eb->modifiers = bind.modifiers; + eb->any_mod = bind.any_mod; + eb->action = strdup(bind.action); + eb->params = strdup(bind.params); + e_border_button_bindings_ungrab_all(); + e_bindings_mouse_add(bind.context, bind.button, bind.modifiers, + bind.any_mod, bind.action, bind.params); + e_border_button_bindings_grab_all(); + e_config_save_queue(); + } + } } break; case E_IPC_OP_BINDING_MOUSE_DEL: { + E_Config_Binding_Mouse bind, *eb; + + _e_ipc_mouse_binding_dec(e->data, e->size, &bind); + { + eb = e_config_binding_mouse_match(&bind); + if (eb) + { + e_config->mouse_bindings = evas_list_remove(e_config->mouse_bindings, eb); + IF_FREE(eb->action); + IF_FREE(eb->params); + IF_FREE(eb); + e_border_button_bindings_ungrab_all(); + e_bindings_mouse_del(bind.context, bind.button, bind.modifiers, + bind.any_mod, bind.action, bind.params); + e_border_button_bindings_grab_all(); + e_config_save_queue(); + } + } } break; case E_IPC_OP_BINDING_KEY_LIST: @@ -495,10 +535,51 @@ _e_ipc_cb_client_data(void *data __UNUSED__, int type __UNUSED__, void *event) break; case E_IPC_OP_BINDING_KEY_ADD: { + E_Config_Binding_Key bind, *eb; + + _e_ipc_key_binding_dec(e->data, e->size, &bind); + { + eb = e_config_binding_key_match(&bind); + if (!eb) + { + eb = E_NEW(E_Config_Binding_Key, 1); + e_config->key_bindings = evas_list_append(e_config->key_bindings, eb); + eb->context = bind.context; + eb->modifiers = bind.modifiers; + eb->any_mod = bind.any_mod; + eb->key = strdup(bind.key); + eb->action = strdup(bind.action); + eb->params = strdup(bind.params); + e_managers_keys_ungrab(); + e_bindings_key_add(bind.context, bind.key, bind.modifiers, + bind.any_mod, bind.action, bind.params); + e_managers_keys_grab(); + e_config_save_queue(); + } + } } break; case E_IPC_OP_BINDING_KEY_DEL: { + E_Config_Binding_Key bind, *eb; + + _e_ipc_key_binding_dec(e->data, e->size, &bind); + { + eb = e_config_binding_key_match(&bind); + if (eb) + { + e_config->key_bindings = evas_list_remove(e_config->key_bindings, eb); + IF_FREE(eb->key); + IF_FREE(eb->action); + IF_FREE(eb->params); + IF_FREE(eb); + e_managers_keys_ungrab(); + e_bindings_key_del(bind.context, bind.key, bind.modifiers, + bind.any_mod, bind.action, bind.params); + e_managers_keys_grab(); + e_config_save_queue(); + } + } } break; default: diff --git a/src/bin/e_remote_main.c b/src/bin/e_remote_main.c index 53011fe8d..4b90d08a6 100644 --- a/src/bin/e_remote_main.c +++ b/src/bin/e_remote_main.c @@ -49,6 +49,194 @@ static const char *display_name = NULL; static int reply_count = 0; static int reply_expect = 0; +static void +_e_opt_binding_mouse_parse(E_Config_Binding_Mouse *eb, char **params) +{ + if (!strcmp(params[0], "NONE")) eb->context = E_BINDING_CONTEXT_NONE; + else if (!strcmp(params[0], "UNKNOWN")) eb->context = E_BINDING_CONTEXT_UNKNOWN; + else if (!strcmp(params[0], "BORDER")) eb->context = E_BINDING_CONTEXT_BORDER; + else if (!strcmp(params[0], "ZONE")) eb->context = E_BINDING_CONTEXT_ZONE; + else if (!strcmp(params[0], "MANAGER")) eb->context = E_BINDING_CONTEXT_MANAGER; + else if (!strcmp(params[0], "ANY")) eb->context = E_BINDING_CONTEXT_ANY; + else + { + printf("OPT1 (CONTEXT) is not a valid context. Must be:\n" + " NONE UNKNOWN BORDER ZONE MANAGER ANY\n"); + exit(-1); + } + eb->button = atoi(params[1]); + /* M1[|M2...] */ + { + char *p, *pp; + + eb->modifiers = 0; + pp = params[2]; + for (;;) + { + p = strchr(pp, '|'); + if (p) + { + if (!strncmp(pp, "SHIFT|", 6)) eb->modifiers |= E_BINDING_MODIFIER_SHIFT; + else if (!strncmp(pp, "CTRL|", 5)) eb->modifiers |= E_BINDING_MODIFIER_CTRL; + else if (!strncmp(pp, "ALT|", 4)) eb->modifiers |= E_BINDING_MODIFIER_ALT; + else if (!strncmp(pp, "WIN|", 4)) eb->modifiers |= E_BINDING_MODIFIER_WIN; + else + { + printf("OPT3 moidifier unknonw. Must be or mask of:\n" + " SHIFT CTRL ALT WIN\n"); + exit(-1); + } + pp = p + 1; + } + else + { + if (!strcmp(pp, "SHIFT")) eb->modifiers |= E_BINDING_MODIFIER_SHIFT; + else if (!strcmp(pp, "CTRL")) eb->modifiers |= E_BINDING_MODIFIER_CTRL; + else if (!strcmp(pp, "ALT")) eb->modifiers |= E_BINDING_MODIFIER_ALT; + else if (!strcmp(pp, "WIN")) eb->modifiers |= E_BINDING_MODIFIER_WIN; + else + { + printf("OPT3 moidifier unknonw. Must be or mask of:\n" + " SHIFT CTRL ALT WIN\n"); + exit(-1); + } + break; + } + } + } + eb->any_mod = atoi(params[3]); + eb->action = params[4]; + eb->params = params[5]; +} + +static void +_e_opt_binding_mouse_add(char **params) +{ + E_Config_Binding_Mouse bind; + int bytes; + char *data; + + _e_opt_binding_mouse_parse(&bind, params); + data = _e_ipc_mouse_binding_enc(&bind, &bytes); + ecore_ipc_server_send(_e_ipc_server, + E_IPC_DOMAIN_REQUEST, + E_IPC_OP_BINDING_MOUSE_ADD, + 0/*ref*/, 0/*ref_to*/, 0/*response*/, + data, bytes); + free(data); +} + +static void +_e_opt_binding_mouse_del(char **params) +{ + E_Config_Binding_Mouse bind; + int bytes; + char *data; + + _e_opt_binding_mouse_parse(&bind, params); + data = _e_ipc_mouse_binding_enc(&bind, &bytes); + ecore_ipc_server_send(_e_ipc_server, + E_IPC_DOMAIN_REQUEST, + E_IPC_OP_BINDING_MOUSE_DEL, + 0/*ref*/, 0/*ref_to*/, 0/*response*/, + data, bytes); + free(data); +} + +static void +_e_opt_binding_key_parse(E_Config_Binding_Key *eb, char **params) +{ + if (!strcmp(params[0], "NONE")) eb->context = E_BINDING_CONTEXT_NONE; + else if (!strcmp(params[0], "UNKNOWN")) eb->context = E_BINDING_CONTEXT_UNKNOWN; + else if (!strcmp(params[0], "BORDER")) eb->context = E_BINDING_CONTEXT_BORDER; + else if (!strcmp(params[0], "ZONE")) eb->context = E_BINDING_CONTEXT_ZONE; + else if (!strcmp(params[0], "MANAGER")) eb->context = E_BINDING_CONTEXT_MANAGER; + else if (!strcmp(params[0], "ANY")) eb->context = E_BINDING_CONTEXT_ANY; + else + { + printf("OPT1 (CONTEXT) is not a valid context. Must be:\n" + " NONE UNKNOWN BORDER ZONE MANAGER ANY\n"); + exit(-1); + } + eb->key = params[1]; + /* M1[|M2...] */ + { + char *p, *pp; + + eb->modifiers = 0; + pp = params[2]; + for (;;) + { + p = strchr(pp, '|'); + if (p) + { + if (!strncmp(pp, "SHIFT|", 6)) eb->modifiers |= E_BINDING_MODIFIER_SHIFT; + else if (!strncmp(pp, "CTRL|", 5)) eb->modifiers |= E_BINDING_MODIFIER_CTRL; + else if (!strncmp(pp, "ALT|", 4)) eb->modifiers |= E_BINDING_MODIFIER_ALT; + else if (!strncmp(pp, "WIN|", 4)) eb->modifiers |= E_BINDING_MODIFIER_WIN; + else + { + printf("OPT3 moidifier unknonw. Must be or mask of:\n" + " SHIFT CTRL ALT WIN\n"); + exit(-1); + } + pp = p + 1; + } + else + { + if (!strcmp(pp, "SHIFT")) eb->modifiers |= E_BINDING_MODIFIER_SHIFT; + else if (!strcmp(pp, "CTRL")) eb->modifiers |= E_BINDING_MODIFIER_CTRL; + else if (!strcmp(pp, "ALT")) eb->modifiers |= E_BINDING_MODIFIER_ALT; + else if (!strcmp(pp, "WIN")) eb->modifiers |= E_BINDING_MODIFIER_WIN; + else + { + printf("OPT3 moidifier unknonw. Must be or mask of:\n" + " SHIFT CTRL ALT WIN\n"); + exit(-1); + } + break; + } + } + } + eb->any_mod = atoi(params[3]); + eb->action = params[4]; + eb->params = params[5]; +} + +static void +_e_opt_binding_key_add(char **params) +{ + E_Config_Binding_Key bind; + int bytes; + char *data; + + _e_opt_binding_key_parse(&bind, params); + data = _e_ipc_key_binding_enc(&bind, &bytes); + ecore_ipc_server_send(_e_ipc_server, + E_IPC_DOMAIN_REQUEST, + E_IPC_OP_BINDING_KEY_ADD, + 0/*ref*/, 0/*ref_to*/, 0/*response*/, + data, bytes); + free(data); +} + +static void +_e_opt_binding_key_del(char **params) +{ + E_Config_Binding_Key bind; + int bytes; + char *data; + + _e_opt_binding_key_parse(&bind, params); + data = _e_ipc_key_binding_enc(&bind, &bytes); + ecore_ipc_server_send(_e_ipc_server, + E_IPC_DOMAIN_REQUEST, + E_IPC_OP_BINDING_KEY_DEL, + 0/*ref*/, 0/*ref_to*/, 0/*response*/, + data, bytes); + free(data); +} + #define SIMPLE_REQ 0 #define SIMPLE_STR_REQ 1 #define FULL_FUNC 2 @@ -87,7 +275,11 @@ E_IPC_Opt_Handler handlers[] = OREQ("-lang-list", "List all available languages", E_IPC_OP_LANG_LIST, 1), OSTR("-lang-set", "Set the current language", E_IPC_OP_LANG_SET, 0), OREQ("-binding-mouse-list", "List all mouse bindings", E_IPC_OP_BINDING_MOUSE_LIST, 1), - OREQ("-binding-key-list", "List all key bindings", E_IPC_OP_BINDING_KEY_LIST, 1) + OFNC("-binding-mouse-add", "Add or replace an existing mouse binding. OPT1 = Context, OPT2 = button, OPT3 = modifiers, OPT4 = any modifier ok, OPT5 = action, OPT6 = action parameters", 6, _e_opt_binding_mouse_add, 0), + OFNC("-binding-mouse-del", "Delete an existing mouse binding. OPT1 = Context, OPT2 = button, OPT3 = modifiers, OPT4 = any modifier ok, OPT5 = action, OPT6 = action parameters", 6, _e_opt_binding_mouse_del, 0), + OREQ("-binding-key-list", "List all key bindings", E_IPC_OP_BINDING_KEY_LIST, 1), + OFNC("-binding-key-add", "Add or replace an existing key binding. OPT1 = Context, OPT2 = key, OPT3 = modifiers, OPT4 = any modifier ok, OPT5 = action, OPT6 = action parameters", 6, _e_opt_binding_key_add, 0), + OFNC("-binding-key-del", "Delete an existing key binding. OPT1 = Context, OPT2 = key, OPT3 = modifiers, OPT4 = any modifier ok, OPT5 = action, OPT6 = action parameters", 6, _e_opt_binding_key_del, 0) }; /* externally accessible functions */