summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUoti Urpala <uau@glyph.nonexistent.invalid>2010-12-19 12:12:20 +0200
committerUoti Urpala <uau@glyph.nonexistent.invalid>2010-12-20 19:02:24 +0200
commit67fd58d6f01ad84387421e2fc861c28dcf5c4f3c (patch)
treef1b93bc0ac9effc590771ce86aacc09eb050fbc1
parentb4564c2d4fdc14f1fcb6987b8f57a2c27a08bf54 (diff)
downloadmpv-67fd58d6f01ad84387421e2fc861c28dcf5c4f3c.tar.bz2
mpv-67fd58d6f01ad84387421e2fc861c28dcf5c4f3c.tar.xz
input: support bindings with modifier keys for X input
Add support for binding commands to modifier+key combinations like "Shift+Left" or "Ctrl+Alt+x", and support reading such combinations from the output window of X VOs. The recognized modifier names are Shift, Ctrl, Alt and Meta. Any combination of those and then a non-modifier key name, separated by '+', is accepted as a key name in input.conf. For non-special keys that produce characters shift is ignored as a modifier. For example "A" is handled as a key without modifiers even if you use shift to write the capital letter; 'a' vs 'A' already distinguishes the combinations with a normal keymap, and having separate 'a', 'Shift+A' and 'A' (written with caps lock for example) would bring more confusion than benefit. Currently reading the modifier+key combinations is only supported in the output window of those VOs that use x11_common.c event handling. It's not possible to input the key combinations in other VOs or in a terminal window.
-rw-r--r--etc/input.conf4
-rw-r--r--input/input.c137
-rw-r--r--libvo/x11_common.c21
-rw-r--r--libvo/x11_common.h2
-rw-r--r--osdep/keycodes.h6
5 files changed, 114 insertions, 56 deletions
diff --git a/etc/input.conf b/etc/input.conf
index 0bcfdec9f7..df7bcb60cd 100644
--- a/etc/input.conf
+++ b/etc/input.conf
@@ -10,6 +10,10 @@
## If you wish to unbind a key, use key ignore.
## e.g. ENTER ignore
##
+## You can use modifier-key combinations like Shift+Left or Ctrl+Alt+x with
+## modifiers Shift, Ctrl, Alt and Meta, but note that currently reading
+## key combinations is only supported through the video windows of X-based
+## output drivers (not in output windows of other drivers or in a terminal).
RIGHT seek +10
LEFT seek -10
diff --git a/input/input.c b/input/input.c
index 72725a5409..7df91a6922 100644
--- a/input/input.c
+++ b/input/input.c
@@ -45,6 +45,7 @@
#include "path.h"
#include "talloc.h"
#include "options.h"
+#include "bstr.h"
#include "joystick.h"
@@ -361,6 +362,16 @@ static const mp_key_name_t key_names[] = {
{ 0, NULL }
};
+struct mp_key_name modifier_names[] = {
+ { KEY_MODIFIER_SHIFT, "Shift" },
+ { KEY_MODIFIER_CTRL, "Ctrl" },
+ { KEY_MODIFIER_ALT, "Alt" },
+ { KEY_MODIFIER_META, "Meta" },
+ { 0 }
+};
+
+#define KEY_MODIFIER_MASK (KEY_MODIFIER_SHIFT | KEY_MODIFIER_CTRL | KEY_MODIFIER_ALT | KEY_MODIFIER_META)
+
// This is the default binding. The content of input.conf overrides these.
// The first arg is a null terminated array of key codes.
// The second is the command
@@ -620,8 +631,27 @@ static const m_option_t mp_input_opts[] = {
static int default_cmd_func(int fd,char* buf, int l);
-static char *get_key_name(int key, char buffer[12]);
+static char *get_key_name(int key)
+{
+ char *ret = talloc_strdup(NULL, "");
+ for (int i = 0; modifier_names[i].name; i++) {
+ if (modifier_names[i].key & key) {
+ ret = talloc_asprintf_append_buffer(ret, "%s+",
+ modifier_names[i].name);
+ key -= modifier_names[i].key;
+ }
+ }
+ for (int i = 0; key_names[i].name != NULL; i++) {
+ if (key_names[i].key == key)
+ return talloc_asprintf_append_buffer(ret, "%s", key_names[i].name);
+ }
+
+ if (isascii(key))
+ return talloc_asprintf_append_buffer(ret, "%c", key);
+ // Print the hex key code
+ return talloc_asprintf_append_buffer(ret, "%#-8x", key);
+}
int mp_input_add_cmd_fd(struct input_ctx *ictx, int fd, int select,
mp_cmd_func_t read_func, mp_close_func_t close_func)
@@ -1034,7 +1064,6 @@ static mp_cmd_t *get_cmd_from_keys(struct input_ctx *ictx, int n, int *keys)
{
char* cmd = NULL;
mp_cmd_t* ret;
- char key_buf[12];
if (ictx->cmd_binds)
cmd = find_bind_for_key(ictx->cmd_binds, n, keys);
@@ -1044,12 +1073,16 @@ static mp_cmd_t *get_cmd_from_keys(struct input_ctx *ictx, int n, int *keys)
cmd = find_bind_for_key(def_cmd_binds,n,keys);
if(cmd == NULL) {
- mp_tmsg(MSGT_INPUT,MSGL_WARN,"No bind found for key '%s'.", get_key_name(keys[0],
- key_buf));
+ char *key_buf = get_key_name(keys[0]);
+ mp_tmsg(MSGT_INPUT,MSGL_WARN,"No bind found for key '%s'.", key_buf);
+ talloc_free(key_buf);
if(n > 1) {
int s;
- for(s=1; s < n; s++)
- mp_msg(MSGT_INPUT,MSGL_WARN,"-%s", get_key_name(keys[s], key_buf));
+ for(s=1; s < n; s++) {
+ key_buf = get_key_name(keys[s]);
+ mp_msg(MSGT_INPUT,MSGL_WARN,"-%s", key_buf);
+ talloc_free(key_buf);
+ }
}
mp_msg(MSGT_INPUT,MSGL_WARN," \n");
return NULL;
@@ -1057,13 +1090,16 @@ static mp_cmd_t *get_cmd_from_keys(struct input_ctx *ictx, int n, int *keys)
if (strcmp(cmd, "ignore") == 0) return NULL;
ret = mp_input_parse_cmd(cmd);
if(!ret) {
- mp_tmsg(MSGT_INPUT,MSGL_ERR,"Invalid command for bound key %s",
- get_key_name(ictx->key_down[0], key_buf));
+ char *key_buf = get_key_name(ictx->key_down[0]);
+ mp_tmsg(MSGT_INPUT,MSGL_ERR,"Invalid command for bound key %s", key_buf);
+ talloc_free(key_buf);
if (ictx->num_key_down > 1) {
unsigned int s;
- for(s=1; s < ictx->num_key_down; s++)
- mp_msg(MSGT_INPUT,MSGL_ERR,"-%s", get_key_name(ictx->key_down[s],
- key_buf));
+ for(s=1; s < ictx->num_key_down; s++) {
+ char *key_buf = get_key_name(ictx->key_down[s]);
+ mp_msg(MSGT_INPUT,MSGL_ERR,"-%s", key_buf);
+ talloc_free(key_buf);
+ }
}
mp_msg(MSGT_INPUT,MSGL_ERR," : %s \n",cmd);
}
@@ -1076,6 +1112,14 @@ static mp_cmd_t* interpret_key(struct input_ctx *ictx, int code)
unsigned int j;
mp_cmd_t* ret;
+ /* On normal keyboards shift changes the character code of non-special
+ * keys, so don't count the modifier separately for those. In other words
+ * we want to have "a" and "A" instead of "a" and "Shift+A"; but a separate
+ * shift modifier is still kept for special keys like arrow keys.
+ */
+ if ((code & ~KEY_MODIFIER_MASK) < 256)
+ code &= ~KEY_MODIFIER_SHIFT;
+
if(mp_input_key_cb) {
if (code & MP_KEY_DOWN)
return NULL;
@@ -1371,41 +1415,34 @@ mp_cmd_clone(mp_cmd_t* cmd) {
return ret;
}
-static char *get_key_name(int key, char buffer[12])
+int mp_input_get_key_from_name(const char *name)
{
- int i;
-
- for(i = 0; key_names[i].name != NULL; i++) {
- if(key_names[i].key == key)
- return key_names[i].name;
- }
-
- if(isascii(key)) {
- snprintf(buffer, 12, "%c",(char)key);
- return buffer;
- }
-
- // Print the hex key code
- snprintf(buffer, 12, "%#-8x",key);
- return buffer;
-
-}
-
-int
-mp_input_get_key_from_name(const char *name) {
- int i,ret = 0,len = strlen(name);
- if(len == 1) { // Direct key code
- ret = (unsigned char)name[0];
- return ret;
- } else if(len > 2 && strncasecmp("0x",name,2) == 0)
- return strtol(name,NULL,16);
-
- for(i = 0; key_names[i].name != NULL; i++) {
- if(strcasecmp(key_names[i].name,name) == 0)
- return key_names[i].key;
- }
+ int modifiers = 0;
+ const char *p;
+ while (p = strchr(name, '+')) {
+ for (struct mp_key_name *m = modifier_names; m->name; m++)
+ if (!bstrcasecmp(BSTR(m->name), (struct bstr){name, p - name})) {
+ modifiers |= m->key;
+ goto found;
+ }
+ if (!strcmp(name, "+"))
+ return '+' + modifiers;
+ return -1;
+ found:
+ name = p + 1;
+ }
+ int len = strlen(name);
+ if (len == 1) // Direct key code
+ return (unsigned char)name[0] + modifiers;
+ else if (len > 2 && strncasecmp("0x", name, 2) == 0)
+ return strtol(name, NULL, 16) + modifiers;
+
+ for (int i = 0; key_names[i].name != NULL; i++) {
+ if (strcasecmp(key_names[i].name, name) == 0)
+ return key_names[i].key + modifiers;
+ }
- return -1;
+ return -1;
}
static int get_input_from_name(char* name,int* keys) {
@@ -1595,10 +1632,14 @@ static int parse_config(struct input_ctx *ictx, char *file)
// Found new line
if(iter[0] == '\n' || iter[0] == '\r') {
int i;
- char key_buf[12];
- mp_tmsg(MSGT_INPUT,MSGL_ERR,"No command found for key %s", get_key_name(keys[0], key_buf));
- for(i = 1; keys[i] != 0 ; i++)
- mp_msg(MSGT_INPUT,MSGL_ERR,"-%s", get_key_name(keys[i], key_buf));
+ char *key_buf = get_key_name(keys[0]);
+ mp_tmsg(MSGT_INPUT,MSGL_ERR,"No command found for key %s", key_buf);
+ talloc_free(key_buf);
+ for(i = 1; keys[i] != 0 ; i++) {
+ char *key_buf = get_key_name(keys[i]);
+ mp_msg(MSGT_INPUT,MSGL_ERR,"-%s", key_buf);
+ talloc_free(key_buf);
+ }
mp_msg(MSGT_INPUT,MSGL_ERR,"\n");
keys[0] = 0;
if(iter > buffer) {
diff --git a/libvo/x11_common.c b/libvo/x11_common.c
index b7fbb72307..596645662c 100644
--- a/libvo/x11_common.c
+++ b/libvo/x11_common.c
@@ -540,12 +540,12 @@ static const struct mp_keymap keysym_map[] = {
{0, 0}
};
-static void vo_x11_putkey_ext(struct vo *vo, int keysym)
+static void vo_x11_putkey_ext(struct vo *vo, int keysym, int modifiers)
{
struct mp_fifo *f = vo->key_fifo;
int mpkey = lookup_keymap_table(keysym_map, keysym);
if (mpkey)
- mplayer_put_key(f, mpkey);
+ mplayer_put_key(f, mpkey + modifiers);
}
#endif
@@ -584,7 +584,7 @@ static const struct mp_keymap keymap[] = {
{0, 0}
};
-void vo_x11_putkey(struct vo *vo, int key)
+static void vo_x11_putkey(struct vo *vo, int key, int modifiers)
{
static const char *passthrough_keys = " -+*/<>`~!@#$%^&()_{}:;\"\',.?\\|=[]";
int mpkey = 0;
@@ -598,7 +598,7 @@ void vo_x11_putkey(struct vo *vo, int key)
mpkey = lookup_keymap_table(keymap, key);
if (mpkey)
- mplayer_put_key(vo->key_fifo, mpkey);
+ mplayer_put_key(vo->key_fifo, mpkey + modifiers);
}
@@ -814,13 +814,22 @@ int vo_x11_check_events(struct vo *vo)
XLookupString(&Event.xkey, buf, sizeof(buf), &keySym,
&x11->compose_status);
+ int modifiers = 0;
+ if (Event.xkey.state & ShiftMask)
+ modifiers |= KEY_MODIFIER_SHIFT;
+ if (Event.xkey.state & ControlMask)
+ modifiers |= KEY_MODIFIER_CTRL;
+ if (Event.xkey.state & Mod1Mask)
+ modifiers |= KEY_MODIFIER_ALT;
+ if (Event.xkey.state & Mod4Mask)
+ modifiers |= KEY_MODIFIER_META;
#ifdef XF86XK_AudioPause
- vo_x11_putkey_ext(vo, keySym);
+ vo_x11_putkey_ext(vo, keySym, modifiers);
#endif
key =
((keySym & 0xff00) !=
0 ? ((keySym & 0x00ff) + 256) : (keySym));
- vo_x11_putkey(vo, key);
+ vo_x11_putkey(vo, key, modifiers);
ret |= VO_EVENT_KEYPRESS;
}
break;
diff --git a/libvo/x11_common.h b/libvo/x11_common.h
index 57b1d79f33..824f55b4c8 100644
--- a/libvo/x11_common.h
+++ b/libvo/x11_common.h
@@ -170,8 +170,6 @@ void xv_setup_colorkeyhandling(struct vo *vo, const char *ck_method_str, const c
int xv_test_ck( void * arg );
int xv_test_ckm( void * arg );
-void vo_x11_putkey(struct vo *vo, int key);
-
#ifdef CONFIG_XF86VM
void vo_vm_switch(struct vo *vo);
void vo_vm_close(struct vo *vo);
diff --git a/osdep/keycodes.h b/osdep/keycodes.h
index 4d153a24aa..d197c8e3e9 100644
--- a/osdep/keycodes.h
+++ b/osdep/keycodes.h
@@ -94,4 +94,10 @@
#define KEY_INTERN (0x1000)
#define KEY_CLOSE_WIN (KEY_INTERN+0)
+/* Modifiers added to individual keys */
+#define KEY_MODIFIER_SHIFT 0x2000
+#define KEY_MODIFIER_CTRL 0x4000
+#define KEY_MODIFIER_ALT 0x8000
+#define KEY_MODIFIER_META 0x10000
+
#endif /* MPLAYER_KEYCODES_H */