mirror of
https://github.com/mpv-player/mpv
synced 2025-03-25 04:38:01 +00:00
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.
This commit is contained in:
parent
b4564c2d4f
commit
67fd58d6f0
@ -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
|
||||
|
135
input/input.c
135
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;
|
||||
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(i = 0; key_names[i].name != NULL; i++) {
|
||||
if(key_names[i].key == key)
|
||||
return key_names[i].name;
|
||||
}
|
||||
for (int i = 0; key_names[i].name != NULL; i++) {
|
||||
if (strcasecmp(key_names[i].name, name) == 0)
|
||||
return key_names[i].key + modifiers;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user