mirror of
git://git.proxmox.com/git/spiceterm.git
synced 2025-08-22 18:17:13 +00:00
use kvm keymap files
This commit is contained in:
parent
68c2b067e2
commit
7f3ff8c0e4
11
Makefile
11
Makefile
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
PROGRAMS=spiceterm
|
PROGRAMS=spiceterm
|
||||||
|
|
||||||
HEADERS=translations.h event_loop.h glyphs.h spiceterm.h
|
HEADERS=translations.h event_loop.h glyphs.h spiceterm.h keysyms.h
|
||||||
SOURCES=screen.c event_loop.c input.c spiceterm.c auth-pve.c
|
SOURCES=screen.c event_loop.c input.c spiceterm.c auth-pve.c
|
||||||
|
|
||||||
#export G_MESSAGES_DEBUG=all
|
#export G_MESSAGES_DEBUG=all
|
||||||
@ -10,12 +10,15 @@ SOURCES=screen.c event_loop.c input.c spiceterm.c auth-pve.c
|
|||||||
all: ${PROGRAMS}
|
all: ${PROGRAMS}
|
||||||
|
|
||||||
spiceterm: ${SOURCES} ${HEADERS} spiceterm.c
|
spiceterm: ${SOURCES} ${HEADERS} spiceterm.c
|
||||||
gcc -Werror -Wall -Wtype-limits ${SOURCES} -g -O2 -o $@ -lutil $(shell pkg-config --cflags gdk-3.0) $(shell pkg-config --cflags --libs gthread-2.0,spice-protocol,spice-server)
|
gcc -Werror -Wall -Wtype-limits ${SOURCES} -g -O2 -o $@ -lutil $(shell pkg-config --cflags gdk-3.0) $(shell pkg-config --cflags --libs gthread-2.0,spice-protocol,spice-server,gdk-3.0)
|
||||||
|
|
||||||
|
keysyms.h: genkeysym.pl
|
||||||
|
./genkeysym.pl >$@
|
||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test: spiceterm
|
test: spiceterm
|
||||||
#./spiceterm & remote-viewer spice://localhost:5900
|
./spiceterm --noauth --keymap de & remote-viewer spice://localhost?tls-port=5900
|
||||||
G_MESSAGES_DEBUG=all SPICE_DEBUG=1 SPICE_TICKET=test ./spiceterm & G_MESSAGES_DEBUG=all SPICE_DEBUG=1 remote-viewer --debug 'spice://localhost?tls-port=5900' --spice-ca-file /etc/pve/pve-root-ca.pem --spice-secure-channels=all
|
#G_MESSAGES_DEBUG=all SPICE_DEBUG=1 SPICE_TICKET=test ./spiceterm & G_MESSAGES_DEBUG=all SPICE_DEBUG=1 remote-viewer --debug 'spice://localhost?tls-port=5900' --spice-ca-file /etc/pve/pve-root-ca.pem --spice-secure-channels=all
|
||||||
|
|
||||||
.PHONY: distclean
|
.PHONY: distclean
|
||||||
distclean: clean
|
distclean: clean
|
||||||
|
62
genkeysym.pl
Executable file
62
genkeysym.pl
Executable file
@ -0,0 +1,62 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
|
||||||
|
my $header = "/usr/include/X11/keysymdef.h";
|
||||||
|
|
||||||
|
print <<__EOD;
|
||||||
|
typedef struct {
|
||||||
|
const char* name;
|
||||||
|
int keysym;
|
||||||
|
int unicode;
|
||||||
|
} name2keysym_t;
|
||||||
|
|
||||||
|
static const name2keysym_t name2keysym[] = {
|
||||||
|
__EOD
|
||||||
|
|
||||||
|
open(TMP, "<$header");
|
||||||
|
while (defined(my $line = <TMP>)) {
|
||||||
|
next if $line !~ m/\#define /;
|
||||||
|
my @ea = split(/\s+/, $line, 4);
|
||||||
|
|
||||||
|
next if $ea[1] !~ m/^XK_(\S+)$/;
|
||||||
|
my $name = $1;
|
||||||
|
|
||||||
|
next if $ea[2] !~ m/^0x([A-Za-z0-9]+)$/;
|
||||||
|
my $keysym = hex($ea[2]);
|
||||||
|
|
||||||
|
my $unicode = 0;
|
||||||
|
if ($ea[3] && $ea[3] =~ m/\/\* U\+([0-9A-Fa-f]{4,6}) /) {
|
||||||
|
$unicode = hex($1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$unicode) {
|
||||||
|
# Latin-1 characters (1:1 mapping)
|
||||||
|
if (($keysym >= 0x0020 && $keysym <= 0x007e) ||
|
||||||
|
($keysym >= 0x00a0 && $keysym <= 0x00ff)) {
|
||||||
|
$unicode = $keysym;
|
||||||
|
} elsif (($keysym & 0xff000000) == 0x01000000) {
|
||||||
|
# directly encoded 24-bit UCS characters */
|
||||||
|
$unicode = $keysym & 0x00ffffff;
|
||||||
|
} elsif ($keysym >= 0x0ff08 && $keysym <= 0x0ff1b) {
|
||||||
|
# tty BS, LF, RETURN, Delete
|
||||||
|
$unicode = $keysym - 0x0ff00;
|
||||||
|
} elsif ($keysym >= 0x0ffaa && $keysym <= 0x0ffaf) {
|
||||||
|
# keypad +*-/
|
||||||
|
$unicode = $keysym - 0x0ff80;
|
||||||
|
} elsif ($keysym >= 0x0ffb0 && $keysym <= 0x0ffb9) {
|
||||||
|
# keypad 01234...
|
||||||
|
$unicode = $keysym - 0x0ff80;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" { \"%s\", 0x%03x, 0x%04x },\n", $name, $keysym, $unicode);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" { NULL, 0x%03x, 0x%04x },\n", 0, 0);
|
||||||
|
|
||||||
|
print <<__EOD;
|
||||||
|
};
|
||||||
|
__EOD
|
275
input.c
275
input.c
@ -28,8 +28,10 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#include "spiceterm.h"
|
#include "spiceterm.h"
|
||||||
|
#include "keysyms.h"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <spice.h>
|
#include <spice.h>
|
||||||
@ -53,13 +55,42 @@ my_kbd_get_leds(SpiceKbdInstance *sin)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define MOD_MASK_SHIFT (1<<0)
|
||||||
|
#define MOD_MASK_ALTGR (1<<1)
|
||||||
|
#define MOD_MASK_NUMLOCK (1<<2)
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct keymap_entry {
|
||||||
|
gint hkey; //(mask << 8 || keycode)
|
||||||
|
guint8 mask; // MOD_MASK_*
|
||||||
|
guint8 keycode;
|
||||||
|
guint keysym;
|
||||||
|
guint unicode;
|
||||||
|
} keymap_entry;
|
||||||
|
|
||||||
|
static GHashTable *keymap = NULL;
|
||||||
|
|
||||||
#define KBD_MOD_CONTROL_L_FLAG (1<<0)
|
#define KBD_MOD_CONTROL_L_FLAG (1<<0)
|
||||||
#define KBD_MOD_CONTROL_R_FLAG (1<<1)
|
#define KBD_MOD_CONTROL_R_FLAG (1<<1)
|
||||||
#define KBD_MOD_SHIFT_L_FLAG (1<<2)
|
#define KBD_MOD_SHIFT_L_FLAG (1<<2)
|
||||||
#define KBD_MOD_SHIFT_R_FLAG (1<<3)
|
#define KBD_MOD_SHIFT_R_FLAG (1<<3)
|
||||||
|
#define KBD_MOD_ALTGR_FLAG (1<<4)
|
||||||
|
#define KBD_MOD_NUMLOCK (1<<5)
|
||||||
|
#define KBD_MOD_SHIFTLOCK (1<<6)
|
||||||
|
|
||||||
static int kbd_flags = 0;
|
static int kbd_flags = 0;
|
||||||
|
|
||||||
|
static const name2keysym_t *
|
||||||
|
lookup_keysym(const char *name)
|
||||||
|
{
|
||||||
|
const name2keysym_t *p;
|
||||||
|
for(p = name2keysym; p->name != NULL; p++) {
|
||||||
|
if (!strcmp(p->name, name))
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
my_kbd_push_key(SpiceKbdInstance *sin, uint8_t frag)
|
my_kbd_push_key(SpiceKbdInstance *sin, uint8_t frag)
|
||||||
{
|
{
|
||||||
@ -80,6 +111,12 @@ my_kbd_push_key(SpiceKbdInstance *sin, uint8_t frag)
|
|||||||
case 0x9d: // release Control_R
|
case 0x9d: // release Control_R
|
||||||
kbd_flags &= ~KBD_MOD_CONTROL_R_FLAG;
|
kbd_flags &= ~KBD_MOD_CONTROL_R_FLAG;
|
||||||
break;
|
break;
|
||||||
|
case 0x38: // press ALTGR
|
||||||
|
kbd_flags |= KBD_MOD_ALTGR_FLAG;
|
||||||
|
break;
|
||||||
|
case 0xb8: // release ALTGR
|
||||||
|
kbd_flags &= ~KBD_MOD_ALTGR_FLAG;
|
||||||
|
break;
|
||||||
case 0x47: // press Home
|
case 0x47: // press Home
|
||||||
esc = "OH";
|
esc = "OH";
|
||||||
break;
|
break;
|
||||||
@ -101,6 +138,9 @@ my_kbd_push_key(SpiceKbdInstance *sin, uint8_t frag)
|
|||||||
case 0x52: // press INSERT
|
case 0x52: // press INSERT
|
||||||
esc = "[2~";
|
esc = "[2~";
|
||||||
break;
|
break;
|
||||||
|
case 0x53: // press Delete
|
||||||
|
esc = "[3~";
|
||||||
|
break;
|
||||||
case 0x49: // press PAGE_UP
|
case 0x49: // press PAGE_UP
|
||||||
if (kbd_flags & (KBD_MOD_SHIFT_L_FLAG|KBD_MOD_SHIFT_R_FLAG)) {
|
if (kbd_flags & (KBD_MOD_SHIFT_L_FLAG|KBD_MOD_SHIFT_R_FLAG)) {
|
||||||
spiceterm_virtual_scroll(vt, -vt->height/2);
|
spiceterm_virtual_scroll(vt, -vt->height/2);
|
||||||
@ -136,28 +176,50 @@ my_kbd_push_key(SpiceKbdInstance *sin, uint8_t frag)
|
|||||||
kbd_flags &= ~KBD_MOD_SHIFT_R_FLAG;
|
kbd_flags &= ~KBD_MOD_SHIFT_R_FLAG;
|
||||||
break;
|
break;
|
||||||
case 0x52: // press KP_INSERT
|
case 0x52: // press KP_INSERT
|
||||||
esc = "[2~";
|
if (!(kbd_flags & KBD_MOD_NUMLOCK))
|
||||||
|
esc = "[2~";
|
||||||
break;
|
break;
|
||||||
case 0x53: // press KP_Delete
|
case 0x53: // press KP_Delete
|
||||||
esc = "[3~";
|
if (!(kbd_flags & KBD_MOD_NUMLOCK))
|
||||||
|
esc = "[3~";
|
||||||
break;
|
break;
|
||||||
case 0x47: // press KP_Home
|
case 0x45: // press Numlock
|
||||||
esc = "OH";
|
if (kbd_flags & KBD_MOD_NUMLOCK) {
|
||||||
|
kbd_flags &= ~KBD_MOD_NUMLOCK;
|
||||||
|
} else {
|
||||||
|
kbd_flags |= KBD_MOD_NUMLOCK;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x3a: // press Shiftlock
|
||||||
|
if (kbd_flags & KBD_MOD_SHIFTLOCK) {
|
||||||
|
kbd_flags &= ~KBD_MOD_SHIFTLOCK;
|
||||||
|
} else {
|
||||||
|
kbd_flags |= KBD_MOD_SHIFTLOCK;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x47: // press KP_Home
|
||||||
|
if (!(kbd_flags & KBD_MOD_NUMLOCK))
|
||||||
|
esc = "OH";
|
||||||
break;
|
break;
|
||||||
case 0x4f: // press KP_END
|
case 0x4f: // press KP_END
|
||||||
esc = "OF";
|
if (!(kbd_flags & KBD_MOD_NUMLOCK))
|
||||||
|
esc = "OF";
|
||||||
break;
|
break;
|
||||||
case 0x48: // press KP_UP
|
case 0x48: // press KP_UP
|
||||||
esc = "OA";
|
if (!(kbd_flags & KBD_MOD_NUMLOCK))
|
||||||
|
esc = "OA";
|
||||||
break;
|
break;
|
||||||
case 0x50: // press KP_DOWN
|
case 0x50: // press KP_DOWN
|
||||||
esc = "OB";
|
if (!(kbd_flags & KBD_MOD_NUMLOCK))
|
||||||
|
esc = "OB";
|
||||||
break;
|
break;
|
||||||
case 0x4b: // press KP_LEFT
|
case 0x4b: // press KP_LEFT
|
||||||
esc = "OD";
|
if (!(kbd_flags & KBD_MOD_NUMLOCK))
|
||||||
|
esc = "OD";
|
||||||
break;
|
break;
|
||||||
case 0x4d: // press KP_RIGHT
|
case 0x4d: // press KP_RIGHT
|
||||||
esc = "OC";
|
if (!(kbd_flags & KBD_MOD_NUMLOCK))
|
||||||
|
esc = "OC";
|
||||||
break;
|
break;
|
||||||
case 0x3b: // press F1
|
case 0x3b: // press F1
|
||||||
esc = "OP";
|
esc = "OP";
|
||||||
@ -208,48 +270,62 @@ my_kbd_push_key(SpiceKbdInstance *sin, uint8_t frag)
|
|||||||
}
|
}
|
||||||
|
|
||||||
spiceterm_update_watch_mask(vt, TRUE);
|
spiceterm_update_watch_mask(vt, TRUE);
|
||||||
}
|
} else if (frag < 128) {
|
||||||
|
|
||||||
|
guint mask = 0;
|
||||||
|
if (kbd_flags & (KBD_MOD_SHIFT_L_FLAG|KBD_MOD_SHIFT_R_FLAG)) {
|
||||||
|
mask |= MOD_MASK_SHIFT;
|
||||||
|
}
|
||||||
|
if (kbd_flags & KBD_MOD_SHIFTLOCK) {
|
||||||
|
if (mask & MOD_MASK_SHIFT) {
|
||||||
|
mask &= ~MOD_MASK_SHIFT;
|
||||||
|
} else {
|
||||||
|
mask |= MOD_MASK_SHIFT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (kbd_flags & KBD_MOD_ALTGR_FLAG) {
|
||||||
|
mask |= MOD_MASK_ALTGR;
|
||||||
|
}
|
||||||
|
if (kbd_flags & KBD_MOD_NUMLOCK) {
|
||||||
|
mask |= MOD_MASK_NUMLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gint hkey = mask << 8 | (frag & 127);
|
||||||
|
keymap_entry *e = (keymap_entry *)g_hash_table_lookup(keymap, &hkey);
|
||||||
|
if (!e && (kbd_flags & KBD_MOD_NUMLOCK)) {
|
||||||
|
mask &= ~ MOD_MASK_NUMLOCK;
|
||||||
|
hkey = mask << 8 | (frag & 127);
|
||||||
|
e = (keymap_entry *)g_hash_table_lookup(keymap, &hkey);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e && e->unicode) {
|
||||||
|
guint32 uc = e->unicode;
|
||||||
|
gchar buf[32];
|
||||||
|
guint8 len;
|
||||||
|
if (uc && ((len = g_unichar_to_utf8(uc, buf)) > 0)) {
|
||||||
|
if (kbd_flags & (KBD_MOD_CONTROL_L_FLAG|KBD_MOD_CONTROL_R_FLAG)) {
|
||||||
|
if (buf[0] >= 'a' && buf[0] <= 'z') {
|
||||||
|
uint8_t ctrl[1] = { buf[0] - 'a' + 1 };
|
||||||
|
spiceterm_respond_data(vt, 1, ctrl);
|
||||||
|
spiceterm_update_watch_mask(vt, TRUE);
|
||||||
|
} else if (buf[0] >= 'A' && buf[0] <= 'Z') {
|
||||||
|
uint8_t ctrl[1] = { buf[0] - 'A' + 1 };
|
||||||
|
spiceterm_respond_data(vt, 1, ctrl);
|
||||||
|
spiceterm_update_watch_mask(vt, TRUE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
spiceterm_respond_data(vt, len, (uint8_t *)buf);
|
||||||
|
spiceterm_update_watch_mask(vt, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
DPRINTF(1, "leave frag=%02x flags=%08x", frag, kbd_flags);
|
DPRINTF(1, "leave frag=%02x flags=%08x", frag, kbd_flags);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
my_kbd_push_utf8(SpiceKbdInstance *sin, uint32_t size, uint8_t *data)
|
|
||||||
{
|
|
||||||
spiceTerm *vt = SPICE_CONTAINEROF(sin, spiceTerm, keyboard_sin);
|
|
||||||
|
|
||||||
DPRINTF(1, " size=%d data[0]=%02x", size, data[0]);
|
|
||||||
|
|
||||||
if (kbd_flags & (KBD_MOD_CONTROL_L_FLAG|KBD_MOD_CONTROL_R_FLAG)) {
|
|
||||||
if (size != 1) return;
|
|
||||||
if (data[0] >= 'a' && data[0] <= 'z') {
|
|
||||||
uint8_t buf[1] = { data[0] - 'a' + 1 };
|
|
||||||
spiceterm_respond_data(vt, 1, buf);
|
|
||||||
|
|
||||||
} else if (data[0] >= 'A' && data[0] <= 'Z') {
|
|
||||||
uint8_t buf[1] = { data[0] - 'A' + 1 };
|
|
||||||
spiceterm_respond_data(vt, 1, buf);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (size == 1 && data[0] == 0x7f) {
|
|
||||||
/* use an escape sequence for DELETE, else it behaves like BACKSPACE */
|
|
||||||
spiceterm_respond_esc(vt, "[3~");
|
|
||||||
} else {
|
|
||||||
spiceterm_respond_data(vt, size, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vt->y_displ != vt->y_base) {
|
|
||||||
vt->y_displ = vt->y_base;
|
|
||||||
spiceterm_refresh(vt);
|
|
||||||
}
|
|
||||||
|
|
||||||
spiceterm_update_watch_mask(vt, TRUE);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static SpiceKbdInterface my_keyboard_sif = {
|
static SpiceKbdInterface my_keyboard_sif = {
|
||||||
.base.type = SPICE_INTERFACE_KEYBOARD,
|
.base.type = SPICE_INTERFACE_KEYBOARD,
|
||||||
.base.description = "spiceterm keyboard device",
|
.base.description = "spiceterm keyboard device",
|
||||||
@ -257,7 +333,6 @@ static SpiceKbdInterface my_keyboard_sif = {
|
|||||||
.base.minor_version = SPICE_INTERFACE_KEYBOARD_MINOR,
|
.base.minor_version = SPICE_INTERFACE_KEYBOARD_MINOR,
|
||||||
.push_scan_freg = my_kbd_push_key,
|
.push_scan_freg = my_kbd_push_key,
|
||||||
.get_leds = my_kbd_get_leds,
|
.get_leds = my_kbd_get_leds,
|
||||||
.push_utf8 = my_kbd_push_utf8,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -619,13 +694,117 @@ static SpiceCharDeviceInterface my_vdagent_sif = {
|
|||||||
.read = vmc_read,
|
.read = vmc_read,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_keymap_entry(guint8 mask, guint8 keycode, guint keysym, guint unicode)
|
||||||
|
{
|
||||||
|
keymap_entry *e = g_new0(keymap_entry, 1);
|
||||||
|
e->mask = mask;
|
||||||
|
e->keysym = keysym;
|
||||||
|
e->unicode = unicode;
|
||||||
|
e->keycode = keycode;
|
||||||
|
e->hkey = mask << 8 | (keycode & 255);
|
||||||
|
|
||||||
|
// only insert first mapping (other are most likely dead keys)
|
||||||
|
if (!g_hash_table_lookup(keymap, &e->hkey)) {
|
||||||
|
g_hash_table_insert(keymap, &e->hkey, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
parse_keymap(const char *language)
|
||||||
|
{
|
||||||
|
char line[1024];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
printf("parse keymap %s\n", language);
|
||||||
|
|
||||||
|
char *filename = g_strdup_printf("/usr/share/kvm/keymaps/%s", language);
|
||||||
|
FILE *f = fopen(filename, "r");
|
||||||
|
g_free(filename);
|
||||||
|
if (!f) {
|
||||||
|
fprintf(stderr, "Could not read keymap file: '%s'\n", language);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
if (fgets(line, 1024, f) == NULL)
|
||||||
|
break;
|
||||||
|
len = strlen(line);
|
||||||
|
if (len > 0 && line[len - 1] == '\n')
|
||||||
|
line[len - 1] = '\0';
|
||||||
|
if (line[0] == '#' || line[0] == '\0')
|
||||||
|
continue;
|
||||||
|
if (!strncmp(line, "map ", 4))
|
||||||
|
continue;
|
||||||
|
if (!strncmp(line, "include ", 8)) {
|
||||||
|
parse_keymap(line + 8);
|
||||||
|
} else {
|
||||||
|
printf("LINE: %s\n", line);
|
||||||
|
char *tok = strtok(line, " ");
|
||||||
|
if (!tok) {
|
||||||
|
fprintf(stderr, "Warning: unknown keysym\n");
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
const name2keysym_t *map = lookup_keysym(tok);
|
||||||
|
if (!map) {
|
||||||
|
fprintf(stderr, "Warning: unknown keysym '%s'\n", tok);
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
guint8 mask = 0;
|
||||||
|
guint keycode = 0;
|
||||||
|
gboolean addupper = FALSE;
|
||||||
|
|
||||||
|
while ((tok = strtok(NULL, " "))) {
|
||||||
|
if (!strcmp(tok, "shift")) {
|
||||||
|
mask |= MOD_MASK_SHIFT;
|
||||||
|
} else if (!strcmp(tok, "numlock")) {
|
||||||
|
mask |= MOD_MASK_NUMLOCK;
|
||||||
|
} else if (!strcmp(tok, "altgr")) {
|
||||||
|
mask |= MOD_MASK_ALTGR;
|
||||||
|
} else if (!strcmp(tok, "addupper")) {
|
||||||
|
addupper = TRUE;
|
||||||
|
} else if (!strcmp(tok, "inhibit")) {
|
||||||
|
// fixme
|
||||||
|
} else if (!strcmp(tok, "localstate")) {
|
||||||
|
//skip
|
||||||
|
} else {
|
||||||
|
char *endptr;
|
||||||
|
errno = 0;
|
||||||
|
keycode = strtol(tok, &endptr, 0);
|
||||||
|
if (errno != 0 || *endptr != '\0' || keycode >= 255) {
|
||||||
|
printf("got unknown modifier '%s' %d\n", tok, keycode);
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("got keycode %u ==> %02x:%d\n", map->keysym, mask, keycode);
|
||||||
|
|
||||||
|
add_keymap_entry(mask, keycode, map->keysym, map->unicode);
|
||||||
|
if (addupper) {
|
||||||
|
gchar uc = g_ascii_toupper(line[0]);
|
||||||
|
if (uc != line[0]) {
|
||||||
|
char ucname[] = { uc, '\0' };
|
||||||
|
if ((map = lookup_keysym(ucname))) {
|
||||||
|
add_keymap_entry(mask|MOD_MASK_SHIFT, keycode,
|
||||||
|
map->keysym, map->unicode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
spiceTerm *
|
spiceTerm *
|
||||||
spiceterm_create(uint32_t width, uint32_t height, SpiceTermOptions *opts)
|
spiceterm_create(uint32_t width, uint32_t height, SpiceTermOptions *opts)
|
||||||
{
|
{
|
||||||
SpiceCoreInterface *core = basic_event_loop_init();
|
SpiceCoreInterface *core = basic_event_loop_init();
|
||||||
SpiceScreen *spice_screen = spice_screen_new(core, width, height, opts);
|
SpiceScreen *spice_screen = spice_screen_new(core, width, height, opts);
|
||||||
|
|
||||||
//spice_server_set_image_compression(server, SPICE_IMAGE_COMPRESS_OFF);
|
keymap = g_hash_table_new(g_int_hash, g_int_equal);
|
||||||
|
parse_keymap(opts->keymap ? opts->keymap : "en-us");
|
||||||
|
|
||||||
spice_screen->image_cache = g_hash_table_new(g_int_hash, g_int_equal);
|
spice_screen->image_cache = g_hash_table_new(g_int_hash, g_int_equal);
|
||||||
|
|
||||||
|
@ -1613,6 +1613,7 @@ spiceterm_print_usage(const char *msg)
|
|||||||
fprintf(stderr, " --addr <addr> Bind to address <addr>\n");
|
fprintf(stderr, " --addr <addr> Bind to address <addr>\n");
|
||||||
fprintf(stderr, " --sasl Enable SASL based authentication\n");
|
fprintf(stderr, " --sasl Enable SASL based authentication\n");
|
||||||
fprintf(stderr, " --noauth Disable authentication\n");
|
fprintf(stderr, " --noauth Disable authentication\n");
|
||||||
|
fprintf(stderr, " --keymap Spefify keymap (uses kvm keymap files)\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -1641,12 +1642,13 @@ main (int argc, char** argv)
|
|||||||
{ "permissions", required_argument, 0, 'P' },
|
{ "permissions", required_argument, 0, 'P' },
|
||||||
{ "port", required_argument, 0, 'p' },
|
{ "port", required_argument, 0, 'p' },
|
||||||
{ "addr", required_argument, 0, 'a' },
|
{ "addr", required_argument, 0, 'a' },
|
||||||
|
{ "keymap", required_argument, 0, 'k' },
|
||||||
{ "noauth", no_argument, 0, 'n' },
|
{ "noauth", no_argument, 0, 'n' },
|
||||||
{ "sasl", no_argument, 0, 's' },
|
{ "sasl", no_argument, 0, 's' },
|
||||||
{ NULL, 0, 0, 0 },
|
{ NULL, 0, 0, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, "nst:a:p:P:", long_options, NULL)) != -1) {
|
while ((c = getopt_long(argc, argv, "nkst:a:p:P:", long_options, NULL)) != -1) {
|
||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'n':
|
case 'n':
|
||||||
@ -1655,6 +1657,9 @@ main (int argc, char** argv)
|
|||||||
case 's':
|
case 's':
|
||||||
opts.sasl = TRUE;
|
opts.sasl = TRUE;
|
||||||
break;
|
break;
|
||||||
|
case 'k':
|
||||||
|
opts.keymap = optarg;
|
||||||
|
break;
|
||||||
case 'A':
|
case 'A':
|
||||||
pve_auth_set_path(optarg);
|
pve_auth_set_path(optarg);
|
||||||
break;
|
break;
|
||||||
|
@ -28,6 +28,7 @@ typedef struct SpiceTermOptions {
|
|||||||
guint timeout;
|
guint timeout;
|
||||||
int port;
|
int port;
|
||||||
char *addr;
|
char *addr;
|
||||||
|
char *keymap;
|
||||||
gboolean noauth;
|
gboolean noauth;
|
||||||
gboolean sasl;
|
gboolean sasl;
|
||||||
} SpiceTermOptions;
|
} SpiceTermOptions;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user