Accept keysym/unicode symbols on keys
This is an enhancement to make non-ASCII symbol keys usable for implementation and configuration of Awesome. The enhancement was proposed and had been developed under the initiative of Daniel Hahler. Thanks to his sharing of his results with our community, we gradually deepened our understanding on the issue. This commit is the fruit his enthusiasm spawned. Closes https://github.com/awesomeWM/awesome/pull/538.
This commit is contained in:
parent
035e905836
commit
4db998fdf2
120
objects/key.c
120
objects/key.c
|
@ -42,6 +42,7 @@
|
|||
/* XStringToKeysym() and XKeysymToString */
|
||||
#include <X11/Xlib.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <glib.h>
|
||||
|
||||
/** Key object.
|
||||
*
|
||||
|
@ -64,28 +65,80 @@
|
|||
static void
|
||||
luaA_keystore(lua_State *L, int ud, const char *str, ssize_t len)
|
||||
{
|
||||
if(len <= 0 || !str)
|
||||
return;
|
||||
|
||||
keyb_t *key = luaA_checkudata(L, ud, &key_class);
|
||||
if(len)
|
||||
{
|
||||
if(*str != '#')
|
||||
{
|
||||
key->keysym = XStringToKeysym(str);
|
||||
if(!key->keysym)
|
||||
{
|
||||
|
||||
if(len == 1)
|
||||
key->keysym = *str;
|
||||
else
|
||||
warn("there's no keysym named \"%s\"", str);
|
||||
}
|
||||
{
|
||||
key->keycode = 0;
|
||||
key->keysym = str[0];
|
||||
}
|
||||
else
|
||||
else if(str[0] == '#')
|
||||
{
|
||||
key->keycode = atoi(str + 1);
|
||||
key->keysym = 0;
|
||||
}
|
||||
luaA_object_emit_signal(L, ud, "property::key", 0);
|
||||
else
|
||||
{
|
||||
key->keycode = 0;
|
||||
|
||||
if((key->keysym = XStringToKeysym(str)) == NoSymbol )
|
||||
{
|
||||
glong length;
|
||||
gunichar unicode;
|
||||
|
||||
if(!g_utf8_validate(str, -1, NULL))
|
||||
{
|
||||
warn("failed to convert \"%s\" into keysym (invalid UTF-8 string)", str);
|
||||
return;
|
||||
}
|
||||
|
||||
length = g_utf8_strlen(str, -1); /* This function counts combining characters. */
|
||||
if(length <= 0)
|
||||
{
|
||||
warn("failed to convert \"%s\" into keysym (empty UTF-8 string)", str);
|
||||
return;
|
||||
}
|
||||
else if(length > 1)
|
||||
{
|
||||
gchar *composed = g_utf8_normalize(str, -1, G_NORMALIZE_DEFAULT_COMPOSE);
|
||||
if(g_utf8_strlen(composed, -1) != 1)
|
||||
{
|
||||
p_delete(&composed);
|
||||
warn("failed to convert \"%s\" into keysym (failed to compose a single character)", str);
|
||||
return;
|
||||
}
|
||||
unicode = g_utf8_get_char(composed);
|
||||
p_delete(&composed);
|
||||
}
|
||||
else
|
||||
unicode = g_utf8_get_char(str);
|
||||
|
||||
if(unicode == (gunichar)-1 || unicode == (gunichar)-2)
|
||||
{
|
||||
warn("failed to convert \"%s\" into keysym (neither keysym nor single unicode)", str);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Unicode-to-Keysym Conversion
|
||||
*
|
||||
* http://www.x.org/releases/X11R7.7/doc/xproto/x11protocol.html#keysym_encoding
|
||||
*/
|
||||
if(unicode <= 0x0ff)
|
||||
key->keysym = unicode;
|
||||
else if(unicode >= 0x100 && unicode <= 0x10ffff)
|
||||
key->keysym = unicode | (1 << 24);
|
||||
else
|
||||
{
|
||||
warn("failed to convert \"%s\" into keysym (unicode out of range): \"%u\"", str, unicode);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
luaA_object_emit_signal(L, ud, "property::key", 0);
|
||||
}
|
||||
|
||||
/** Create a new key object.
|
||||
|
@ -196,6 +249,31 @@ luaA_key_set_modifiers(lua_State *L, keyb_t *k)
|
|||
|
||||
LUA_OBJECT_EXPORT_PROPERTY(key, keyb_t, modifiers, luaA_pushmodifiers)
|
||||
|
||||
/* It's caller's responsibility to release the returned string. */
|
||||
static char *
|
||||
get_keysym_name(xkb_keysym_t keysym)
|
||||
{
|
||||
const ssize_t bufsize = 64;
|
||||
char *buf = p_new(char, bufsize);
|
||||
ssize_t len;
|
||||
|
||||
if((len = xkb_keysym_get_name(keysym, buf, bufsize)) == -1)
|
||||
{
|
||||
p_delete(&buf);
|
||||
return NULL;
|
||||
}
|
||||
if(len + 1 > bufsize)
|
||||
{
|
||||
p_realloc(&buf, len + 1);
|
||||
if(xkb_keysym_get_name(keysym, buf, len + 1) != len)
|
||||
{
|
||||
p_delete(&buf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int
|
||||
luaA_key_get_key(lua_State *L, keyb_t *k)
|
||||
{
|
||||
|
@ -207,13 +285,11 @@ luaA_key_get_key(lua_State *L, keyb_t *k)
|
|||
}
|
||||
else
|
||||
{
|
||||
char buf[MAX(MB_LEN_MAX, 32)];
|
||||
|
||||
if (xkb_keysym_get_name(k->keysym, buf, countof(buf)) < 0) {
|
||||
char *name = get_keysym_name(k->keysym);
|
||||
if(!name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
lua_pushstring(L, buf);
|
||||
lua_pushstring(L, name);
|
||||
p_delete(&name);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -221,7 +297,11 @@ luaA_key_get_key(lua_State *L, keyb_t *k)
|
|||
static int
|
||||
luaA_key_get_keysym(lua_State *L, keyb_t *k)
|
||||
{
|
||||
lua_pushstring(L, XKeysymToString(k->keysym));
|
||||
char *name = get_keysym_name(k->keysym);
|
||||
if(!name)
|
||||
return 0;
|
||||
lua_pushstring(L, name);
|
||||
p_delete(&name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue