vncs: /dev/kbd support by running kbdfs and forwarding keycodes thru kbdin
This commit is contained in:
parent
f2b6ec3140
commit
ce6b942ff1
10 changed files with 190 additions and 603 deletions
|
@ -20,6 +20,7 @@ kbdfs \- keyboard and console filesystem
|
|||
.B /dev/cons
|
||||
.B /dev/consctl
|
||||
.B /dev/kbd
|
||||
.B /dev/kbdin
|
||||
.B /dev/kbin
|
||||
.B /dev/kbmap
|
||||
.fi
|
||||
|
@ -34,6 +35,8 @@ translates raw keyboard scancodes from
|
|||
.IR kbd (3))
|
||||
and its
|
||||
.BR kbin
|
||||
and
|
||||
.BR kbdin
|
||||
file and optionaly reads console input from
|
||||
.I consfile
|
||||
to provide initial keyboard and console input.
|
||||
|
@ -42,6 +45,7 @@ It serves a one-level directory containing the files
|
|||
.BR cons,
|
||||
.BR consctl,
|
||||
.BR kbd,
|
||||
.BR kbdin,
|
||||
.BR kbin
|
||||
and
|
||||
.BR kbmap.
|
||||
|
@ -171,17 +175,9 @@ message is send when a key is pressed down
|
|||
and
|
||||
.B K
|
||||
when a key is released. The following string contains all the keycodes
|
||||
of the keys that are currently pressed down in decomposed form.
|
||||
of the keys that are currently pressed down in unshifted form.
|
||||
This includes all keys that have a keyboard mapping and modifier keys.
|
||||
Some keys may produce multiple characters like
|
||||
.B Shift
|
||||
and
|
||||
.B a
|
||||
will produce
|
||||
.B Shift,
|
||||
.B a,
|
||||
.B A
|
||||
in the string. The string following the
|
||||
The string following the
|
||||
.B c
|
||||
message contains the single character that would have been returned
|
||||
on the
|
||||
|
@ -198,6 +194,25 @@ file disables input processing on the
|
|||
.BR cons
|
||||
file until it is closed again.
|
||||
.PP
|
||||
.B K,
|
||||
.B k
|
||||
and
|
||||
.B c
|
||||
messages can be written to
|
||||
.BR kbdin
|
||||
and will forwarded to the reader of
|
||||
.BR cons
|
||||
or
|
||||
.BR kbd.
|
||||
Writing a
|
||||
.B r
|
||||
or
|
||||
.B R
|
||||
message followed by a
|
||||
.SM UTF
|
||||
encoded rune will simulate the press or
|
||||
release of that particular rune.
|
||||
.PP
|
||||
Raw scancodes can be written to the
|
||||
.BR kbin
|
||||
file for external keyboard input (used for USB keyboards).
|
||||
|
@ -241,6 +256,6 @@ to represent a control character.
|
|||
.IR utf (6),
|
||||
.IR kbd (3)
|
||||
.SH FILES
|
||||
.B /dev/lib/kbmap/*
|
||||
.B /sys/lib/kbmap/*
|
||||
.SH SOURCE
|
||||
.B /sys/src/cmd/aux/kbdfs
|
||||
|
|
|
@ -11,6 +11,7 @@ enum {
|
|||
|
||||
Qroot= 0,
|
||||
Qkbd,
|
||||
Qkbdin,
|
||||
Qkbin,
|
||||
Qkbmap,
|
||||
Qcons,
|
||||
|
@ -58,6 +59,10 @@ struct Qtab {
|
|||
0600,
|
||||
0,
|
||||
|
||||
"kbdin",
|
||||
0200,
|
||||
0,
|
||||
|
||||
"kbin",
|
||||
0200,
|
||||
0,
|
||||
|
@ -353,8 +358,7 @@ utfconv(Rune *r, int n)
|
|||
|
||||
/*
|
||||
* Read key events from keychan and produce characters to
|
||||
* rawchan and keystate in kbdchan. this way here is only
|
||||
* one global keystate even if multiple keyboards are used.
|
||||
* rawchan and keystate in kbdchan.
|
||||
*/
|
||||
void
|
||||
keyproc(void *)
|
||||
|
@ -369,9 +373,6 @@ keyproc(void *)
|
|||
|
||||
nb = 0;
|
||||
while(recv(keychan, &key) > 0){
|
||||
if(key.down && key.r)
|
||||
send(rawchan, &key.r);
|
||||
|
||||
rb[0] = 0;
|
||||
for(i=0; i<nb && cb[i] != key.c; i++)
|
||||
;
|
||||
|
@ -386,14 +387,14 @@ keyproc(void *)
|
|||
cb[nb] = key.c;
|
||||
rb[nb+1] = key.b;
|
||||
nb++;
|
||||
if(nb < nelem(cb) && key.r && key.b != key.r){
|
||||
cb[nb] = key.c;
|
||||
rb[nb+1] = key.r;
|
||||
nb++;
|
||||
}
|
||||
rb[0] = 'k';
|
||||
}
|
||||
if(rb[0]){
|
||||
if(kbdopen){
|
||||
s = utfconv(rb, nb+1);
|
||||
if(nbsendp(kbdchan, s) <= 0)
|
||||
free(s);
|
||||
}
|
||||
if(mctlfd >= 0){
|
||||
if(key.r == Kshift){
|
||||
if(key.down){
|
||||
|
@ -405,12 +406,9 @@ keyproc(void *)
|
|||
}
|
||||
fprint(mctlfd, "twitch");
|
||||
}
|
||||
if(kbdopen){
|
||||
s = utfconv(rb, nb+1);
|
||||
if(nbsendp(kbdchan, s) <= 0)
|
||||
free(s);
|
||||
}
|
||||
}
|
||||
if(key.down && key.r)
|
||||
send(rawchan, &key.r);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1084,8 +1082,10 @@ static void
|
|||
fswrite(Req *r)
|
||||
{
|
||||
Fid *f;
|
||||
char *p;
|
||||
Scan *a;
|
||||
char *p, *s;
|
||||
int n, i;
|
||||
Key k;
|
||||
|
||||
f = r->fid;
|
||||
switch((ulong)f->qid.path){
|
||||
|
@ -1116,6 +1116,80 @@ fswrite(Req *r)
|
|||
r->ofcall.count = n;
|
||||
break;
|
||||
|
||||
case Qkbdin:
|
||||
p = r->ifcall.data;
|
||||
n = r->ifcall.count;
|
||||
if(n <= 0)
|
||||
n = 0;
|
||||
r->ofcall.count = n;
|
||||
if(p[n-1] != 0){
|
||||
/*
|
||||
* old format as used by bitsy keyboard:
|
||||
* just a string of characters, no keyup
|
||||
* information.
|
||||
*/
|
||||
s = emalloc9p(n+1);
|
||||
memmove(s, p, n);
|
||||
s[n] = 0;
|
||||
p = s;
|
||||
while(*p){
|
||||
p += chartorune(&k.r, p);
|
||||
if(k.r)
|
||||
send(rawchan, &k.r);
|
||||
}
|
||||
free(s);
|
||||
break;
|
||||
}
|
||||
switch(p[0]){
|
||||
case 'R':
|
||||
case 'r':
|
||||
/* rune up/down */
|
||||
chartorune(&k.r, p+1);
|
||||
if(k.r == 0)
|
||||
break;
|
||||
k.b = k.r;
|
||||
k.c = 0x100 + k.r; /* fake */
|
||||
k.down = (p[0] == 'r');
|
||||
if(f->aux == nil){
|
||||
f->aux = emalloc9p(sizeof(Scan));
|
||||
memset(f->aux, 0, sizeof(Scan));
|
||||
}
|
||||
a = f->aux;
|
||||
/*
|
||||
* handle ^X forms according to keymap,
|
||||
* assign base and scancode if any
|
||||
*/
|
||||
for(i=0; i<Nscan; i++){
|
||||
if((a->shift && kbtabshift[i] == k.r) || (kbtab[i] == k.r)){
|
||||
k.c = i;
|
||||
k.b = kbtab[i];
|
||||
if(a->shift)
|
||||
k.r = kbtabshift[i];
|
||||
else if(a->altgr)
|
||||
k.r = kbtabaltgr[i];
|
||||
else if(a->ctl)
|
||||
k.r = kbtabctl[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
send(keychan, &k);
|
||||
if(k.r == Kshift)
|
||||
a->shift = k.down;
|
||||
else if(k.r == Kaltgr)
|
||||
a->altgr = k.down;
|
||||
else if(k.r == Kctl)
|
||||
a->ctl = k.down;
|
||||
break;
|
||||
default:
|
||||
if(!kbdopen)
|
||||
break;
|
||||
s = emalloc9p(n);
|
||||
memmove(s, p, n);
|
||||
if(nbsendp(kbdchan, s) <= 0)
|
||||
free(s);
|
||||
}
|
||||
break;
|
||||
|
||||
case Qkbin:
|
||||
if(f->aux == nil){
|
||||
f->aux = emalloc9p(sizeof(Scan));
|
||||
|
@ -1155,6 +1229,7 @@ fsdestroyfid(Fid *f)
|
|||
|
||||
if(f->omode != -1)
|
||||
switch((ulong)f->qid.path){
|
||||
case Qkbdin:
|
||||
case Qkbin:
|
||||
case Qkbmap:
|
||||
if(p = f->aux){
|
||||
|
|
|
@ -4,180 +4,10 @@
|
|||
#include "kbd.h"
|
||||
#include "error.h"
|
||||
|
||||
typedef struct Queue Queue;
|
||||
struct Queue
|
||||
{
|
||||
QLock qwait;
|
||||
Rendez rwait;
|
||||
|
||||
Lock lock;
|
||||
int notempty;
|
||||
char buf[1024];
|
||||
char *w;
|
||||
char *r;
|
||||
char *e;
|
||||
};
|
||||
|
||||
Queue* kbdq; /* unprocessed console input */
|
||||
Queue* lineq; /* processed console input */
|
||||
Snarf snarf = {
|
||||
.vers = 1
|
||||
};
|
||||
|
||||
static struct
|
||||
{
|
||||
QLock;
|
||||
int raw; /* true if we shouldn't process input */
|
||||
int ctl; /* number of opens to the control file */
|
||||
int x; /* index into line */
|
||||
char line[1024]; /* current input line */
|
||||
} kbd;
|
||||
|
||||
/*
|
||||
* cheapo fixed-length queues
|
||||
*/
|
||||
static void
|
||||
qwrite(Queue *q, void *v, int n)
|
||||
{
|
||||
char *buf, *next;
|
||||
int i;
|
||||
|
||||
buf = v;
|
||||
lock(&q->lock);
|
||||
for(i = 0; i < n; i++){
|
||||
next = q->w+1;
|
||||
if(next >= q->e)
|
||||
next = q->buf;
|
||||
if(next == q->r)
|
||||
break;
|
||||
*q->w = buf[i];
|
||||
q->w = next;
|
||||
}
|
||||
q->notempty = 1;
|
||||
unlock(&q->lock);
|
||||
rendwakeup(&q->rwait);
|
||||
}
|
||||
|
||||
static int
|
||||
qcanread(void *vq)
|
||||
{
|
||||
Queue *q;
|
||||
int ne;
|
||||
|
||||
q = vq;
|
||||
lock(&q->lock);
|
||||
ne = q->notempty;
|
||||
unlock(&q->lock);
|
||||
return ne;
|
||||
}
|
||||
|
||||
static int
|
||||
qread(Queue *q, void *v, int n)
|
||||
{
|
||||
char *a;
|
||||
int nn, notempty;
|
||||
|
||||
if(n == 0)
|
||||
return 0;
|
||||
a = v;
|
||||
nn = 0;
|
||||
for(;;){
|
||||
lock(&q->lock);
|
||||
|
||||
while(nn < n && q->r != q->w){
|
||||
a[nn++] = *q->r++;
|
||||
if(q->r >= q->e)
|
||||
q->r = q->buf;
|
||||
}
|
||||
|
||||
notempty = q->notempty;
|
||||
q->notempty = q->r != q->w;
|
||||
unlock(&q->lock);
|
||||
if(notempty)
|
||||
break;
|
||||
|
||||
/*
|
||||
* wait for something to show up in the kbd buffer.
|
||||
*/
|
||||
qlock(&q->qwait);
|
||||
if(waserror()){
|
||||
qunlock(&q->qwait);
|
||||
nexterror();
|
||||
}
|
||||
rendsleep(&q->rwait, qcanread, q);
|
||||
qunlock(&q->qwait);
|
||||
poperror();
|
||||
}
|
||||
return nn;
|
||||
}
|
||||
|
||||
static Queue *
|
||||
mkqueue(void)
|
||||
{
|
||||
Queue *q;
|
||||
|
||||
q = smalloc(sizeof(Queue));
|
||||
q->r = q->buf;
|
||||
q->w = q->r;
|
||||
q->e = &q->buf[sizeof q->buf];
|
||||
q->notempty = 0;
|
||||
return q;
|
||||
}
|
||||
|
||||
static void
|
||||
echoscreen(char *buf, int n)
|
||||
{
|
||||
char *e, *p;
|
||||
char ebuf[128];
|
||||
int x;
|
||||
|
||||
p = ebuf;
|
||||
e = ebuf + sizeof(ebuf) - 4;
|
||||
while(n-- > 0){
|
||||
if(p >= e){
|
||||
screenputs(ebuf, p - ebuf);
|
||||
p = ebuf;
|
||||
}
|
||||
x = *buf++;
|
||||
if(x == 0x15){
|
||||
*p++ = '^';
|
||||
*p++ = 'U';
|
||||
*p++ = '\n';
|
||||
} else
|
||||
*p++ = x;
|
||||
}
|
||||
if(p != ebuf)
|
||||
screenputs(ebuf, p - ebuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Put character, possibly a rune, into read queue at interrupt time.
|
||||
* Called at interrupt time to process a character.
|
||||
*/
|
||||
void
|
||||
kbdputc(int ch)
|
||||
{
|
||||
int n;
|
||||
char buf[3];
|
||||
Rune r;
|
||||
|
||||
r = ch;
|
||||
n = runetochar(buf, &r);
|
||||
qwrite(kbdq, buf, n);
|
||||
if(!kbd.raw)
|
||||
echoscreen(buf, n);
|
||||
}
|
||||
|
||||
static void
|
||||
kbdputcinit(void)
|
||||
{
|
||||
kbdq = mkqueue();
|
||||
lineq = mkqueue();
|
||||
kbd.raw = 0;
|
||||
kbd.ctl = 0;
|
||||
kbd.x = 0;
|
||||
}
|
||||
|
||||
enum{
|
||||
Qdir,
|
||||
Qcons,
|
||||
|
@ -194,12 +24,6 @@ static Dirtab consdir[]={
|
|||
"winname", {Qwinname}, 0, 0000,
|
||||
};
|
||||
|
||||
static void
|
||||
consinit(void)
|
||||
{
|
||||
kbdputcinit();
|
||||
}
|
||||
|
||||
static Chan*
|
||||
consattach(char *spec)
|
||||
{
|
||||
|
@ -225,9 +49,6 @@ consopen(Chan *c, int omode)
|
|||
c = devopen(c, omode, consdir, nelem(consdir), devgen);
|
||||
switch((ulong)c->qid.path){
|
||||
case Qconsctl:
|
||||
qlock(&kbd);
|
||||
kbd.ctl++;
|
||||
qunlock(&kbd);
|
||||
break;
|
||||
case Qsnarf:
|
||||
if((c->mode&3) == OWRITE || (c->mode&3) == ORDWR)
|
||||
|
@ -266,12 +87,6 @@ consclose(Chan *c)
|
|||
switch((ulong)c->qid.path){
|
||||
/* last close of control file turns off raw */
|
||||
case Qconsctl:
|
||||
if(c->flag&COPEN){
|
||||
qlock(&kbd);
|
||||
if(--kbd.ctl == 0)
|
||||
kbd.raw = 0;
|
||||
qunlock(&kbd);
|
||||
}
|
||||
break;
|
||||
/* odd behavior but really ok: replace snarf buffer when /dev/snarf is closed */
|
||||
case Qsnarf:
|
||||
|
@ -289,9 +104,6 @@ consclose(Chan *c)
|
|||
static long
|
||||
consread(Chan *c, void *buf, long n, vlong off)
|
||||
{
|
||||
char ch;
|
||||
int send;
|
||||
|
||||
if(n <= 0)
|
||||
return n;
|
||||
switch((ulong)c->qid.path){
|
||||
|
@ -310,48 +122,8 @@ consread(Chan *c, void *buf, long n, vlong off)
|
|||
return devdirread(c, buf, n, consdir, nelem(consdir), devgen);
|
||||
|
||||
case Qcons:
|
||||
qlock(&kbd);
|
||||
if(waserror()){
|
||||
qunlock(&kbd);
|
||||
nexterror();
|
||||
}
|
||||
while(!qcanread(lineq)){
|
||||
qread(kbdq, &ch, 1);
|
||||
send = 0;
|
||||
if(ch == 0){
|
||||
/* flush output on rawoff -> rawon */
|
||||
if(kbd.x > 0)
|
||||
send = !qcanread(kbdq);
|
||||
}else if(kbd.raw){
|
||||
kbd.line[kbd.x++] = ch;
|
||||
send = !qcanread(kbdq);
|
||||
}else{
|
||||
switch(ch){
|
||||
case '\b':
|
||||
if(kbd.x > 0)
|
||||
kbd.x--;
|
||||
break;
|
||||
case 0x15: /* ^U */
|
||||
kbd.x = 0;
|
||||
break;
|
||||
case '\n':
|
||||
case 0x04: /* ^D */
|
||||
send = 1;
|
||||
default:
|
||||
if(ch != 0x04)
|
||||
kbd.line[kbd.x++] = ch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(send || kbd.x == sizeof kbd.line){
|
||||
qwrite(lineq, kbd.line, kbd.x);
|
||||
kbd.x = 0;
|
||||
}
|
||||
}
|
||||
n = qread(lineq, buf, n);
|
||||
qunlock(&kbd);
|
||||
poperror();
|
||||
return n;
|
||||
error(Egreg);
|
||||
return -1;
|
||||
|
||||
default:
|
||||
print("consread 0x%llux\n", c->qid.path);
|
||||
|
@ -364,8 +136,7 @@ static long
|
|||
conswrite(Chan *c, void *va, long n, vlong)
|
||||
{
|
||||
Snarf *t;
|
||||
char buf[256], *a;
|
||||
char ch;
|
||||
char *a;
|
||||
|
||||
switch((ulong)c->qid.path){
|
||||
case Qcons:
|
||||
|
@ -373,22 +144,7 @@ conswrite(Chan *c, void *va, long n, vlong)
|
|||
break;
|
||||
|
||||
case Qconsctl:
|
||||
if(n >= sizeof(buf))
|
||||
n = sizeof(buf)-1;
|
||||
strncpy(buf, va, n);
|
||||
buf[n] = 0;
|
||||
for(a = buf; a;){
|
||||
if(strncmp(a, "rawon", 5) == 0){
|
||||
kbd.raw = 1;
|
||||
/* clumsy hack - wake up reader */
|
||||
ch = 0;
|
||||
qwrite(kbdq, &ch, 1);
|
||||
} else if(strncmp(a, "rawoff", 6) == 0){
|
||||
kbd.raw = 0;
|
||||
}
|
||||
if(a = strchr(a, ' '))
|
||||
a++;
|
||||
}
|
||||
error(Egreg);
|
||||
break;
|
||||
|
||||
case Qsnarf:
|
||||
|
@ -416,7 +172,7 @@ Dev consdevtab = {
|
|||
"cons",
|
||||
|
||||
devreset,
|
||||
consinit,
|
||||
devinit,
|
||||
consattach,
|
||||
conswalk,
|
||||
consstat,
|
||||
|
|
|
@ -14,9 +14,8 @@ enum
|
|||
};
|
||||
|
||||
extern Snarf snarf;
|
||||
extern int kbdin;
|
||||
|
||||
long latin1(Rune *k, int n);
|
||||
void kbdputc(int c);
|
||||
void screenputs(char*, int);
|
||||
void vncputc(int, int);
|
||||
void setsnarf(char *buf, int n, int *vers);
|
||||
|
|
|
@ -1,81 +1,48 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <keyboard.h>
|
||||
#include "compat.h"
|
||||
#include "kbd.h"
|
||||
#include "ksym2utf.h"
|
||||
|
||||
enum
|
||||
{
|
||||
enum {
|
||||
VKSpecial = 0xff00,
|
||||
|
||||
/*
|
||||
* plan 9 key mappings
|
||||
*/
|
||||
Spec= 0xF800,
|
||||
|
||||
PF= Spec|0x20, /* num pad function key */
|
||||
View= Spec|0x00, /* view (shift window up) */
|
||||
KF= 0xF000, /* function key (begin Unicode private space) */
|
||||
Shift= Spec|0x60,
|
||||
Break= Spec|0x61,
|
||||
Ctrl= Spec|0x62,
|
||||
Latin= Spec|0x63,
|
||||
Caps= Spec|0x64,
|
||||
Num= Spec|0x65,
|
||||
Middle= Spec|0x66,
|
||||
No= 0x00, /* peter */
|
||||
|
||||
Home= KF|13,
|
||||
Up= KF|14,
|
||||
Pgup= KF|15,
|
||||
Print= KF|16,
|
||||
Left= KF|17,
|
||||
Right= KF|18,
|
||||
End= '\r',
|
||||
Down= View,
|
||||
Pgdown= KF|19,
|
||||
Ins= KF|20,
|
||||
Del= 0x7F,
|
||||
Scroll= KF|21,
|
||||
|
||||
Esc = 0x1b,
|
||||
Delete = 0x7f,
|
||||
};
|
||||
|
||||
static Rune vnckeys[] =
|
||||
{
|
||||
[0x00] No, No, No, No, No, No, No, No,
|
||||
[0x08] '\b', '\t', '\r', No, No, '\n', No, No,
|
||||
[0x10] No, No, No, No, Scroll, No, No, No,
|
||||
[0x18] No, No, No, Esc, No, No, No, No,
|
||||
[0x20] No, No, No, No, No, No, No, No,
|
||||
[0x28] No, No, No, No, No, No, No, No,
|
||||
[0x30] No, No, No, No, No, No, No, No,
|
||||
[0x38] No, No, No, No, No, No, No, No,
|
||||
[0x40] No, No, No, No, No, No, No, No,
|
||||
[0x48] No, No, No, No, No, No, No, No,
|
||||
[0x50] Home, Left, Up, Right, Down, Pgup, Pgdown, No,
|
||||
[0x58] No, No, No, No, No, No, No, No,
|
||||
[0x60] No, Print, No, Ins, No, No, No, No,
|
||||
[0x68] No, No, No, Break, No, No, No, No,
|
||||
[0x70] No, No, No, No, No, No, No, No,
|
||||
[0x78] No, No, No, No, No, No, No, Num,
|
||||
[0x80] No, No, No, No, No, No, No, No,
|
||||
[0x88] No, No, No, No, No, No, No, No,
|
||||
[0x90] No, No, No, No, No, No, No, No,
|
||||
[0x98] No, No, No, No, No, No, No, No,
|
||||
[0xa0] No, No, No, No, No, No, No, No,
|
||||
[0xa8] No, No, '*', '+', No, '-', '.', '/',
|
||||
[0x00] 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
[0x08] '\b', '\t', '\r', 0, 0, '\n', 0, 0,
|
||||
[0x10] 0, 0, 0, 0, Kscroll,0, 0, 0,
|
||||
[0x18] 0, 0, 0, Kesc, 0, 0, 0, 0,
|
||||
[0x20] 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
[0x28] 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
[0x30] 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
[0x38] 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
[0x40] 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
[0x48] 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
[0x50] Khome, Kleft, Kup, Kright, Kdown, Kpgup, Kpgdown,0,
|
||||
[0x58] 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
[0x60] 0, Kprint, 0, Kins, 0, 0, 0, 0,
|
||||
[0x68] 0, 0, 0, Kbreak, 0, 0, 0, 0,
|
||||
[0x70] 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
[0x78] 0, 0, 0, 0, 0, 0, 0, Knum,
|
||||
[0x80] 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
[0x88] 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
[0x90] 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
[0x98] 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
[0xa0] 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
[0xa8] 0, 0, '*', '+', 0, '-', '.', '/',
|
||||
[0xb0] '0', '1', '2', '3', '4', '5', '6', '7',
|
||||
[0xb8] '8', '9', No, No, No, '=', No, No,
|
||||
[0xc0] No, No, No, No, No, No, No, No,
|
||||
[0xc8] No, No, No, No, No, No, No, No,
|
||||
[0xd0] No, No, No, No, No, No, No, No,
|
||||
[0xd8] No, No, No, No, No, No, No, No,
|
||||
[0xe0] No, Shift, Shift, Ctrl, Ctrl, Caps, Caps, No,
|
||||
[0xe8] No, Latin, Latin, No, No, No, No, No,
|
||||
[0xf0] No, No, No, No, No, No, No, No,
|
||||
[0xf8] No, No, No, No, No, No, No, Delete,
|
||||
[0xb8] '8', '9', 0, 0, 0, '=', 0, 0,
|
||||
[0xc0] 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
[0xc8] 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
[0xd0] 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
[0xd8] 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
[0xe0] 0, Kshift, Kshift, Kctl, Kctl, Kcaps, Kcaps, 0,
|
||||
[0xe8] 0, Kalt, Kalt, 0, 0, 0, 0, 0,
|
||||
[0xf0] 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
[0xf8] 0, 0, 0, 0, 0, 0, 0, Kdel,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -84,90 +51,24 @@ static Rune vnckeys[] =
|
|||
void
|
||||
vncputc(int keyup, int c)
|
||||
{
|
||||
int i;
|
||||
static int esc1, esc2;
|
||||
static int alt, caps, ctl, num, shift;
|
||||
static int collecting, nk;
|
||||
static Rune kc[5];
|
||||
|
||||
if(caps && c<='z' && c>='a')
|
||||
c += 'A' - 'a';
|
||||
char buf[16];
|
||||
|
||||
/*
|
||||
* character mapping
|
||||
*/
|
||||
if((c & VKSpecial) == VKSpecial){
|
||||
c = vnckeys[c & 0xff];
|
||||
if(c == No)
|
||||
if(c == 0)
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* map an xkeysym onto a utf-8 char
|
||||
*/
|
||||
if((c & 0xff00) && c < nelem(ksym2utf) && ksym2utf[c] != 0)
|
||||
c = ksym2utf[c];
|
||||
|
||||
/*
|
||||
* keyup only important for shifts
|
||||
*/
|
||||
if(keyup){
|
||||
switch(c){
|
||||
case Latin:
|
||||
alt = 0;
|
||||
break;
|
||||
case Shift:
|
||||
shift = 0;
|
||||
break;
|
||||
case Ctrl:
|
||||
ctl = 0;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* normal character
|
||||
*/
|
||||
if(!(c & (Spec|KF))){
|
||||
if(ctl){
|
||||
c &= 0x1f;
|
||||
}
|
||||
if(!collecting){
|
||||
kbdputc(c);
|
||||
return;
|
||||
}
|
||||
kc[nk++] = c;
|
||||
c = latin1(kc, nk);
|
||||
if(c < -1) /* need more keystrokes */
|
||||
return;
|
||||
if(c != -1) /* valid sequence */
|
||||
kbdputc(c);
|
||||
else /* dump characters */
|
||||
for(i=0; i<nk; i++)
|
||||
kbdputc(kc[i]);
|
||||
nk = 0;
|
||||
collecting = 0;
|
||||
return;
|
||||
}else{
|
||||
switch(c){
|
||||
case Caps:
|
||||
caps ^= 1;
|
||||
return;
|
||||
case Num:
|
||||
num ^= 1;
|
||||
return;
|
||||
case Shift:
|
||||
shift = 1;
|
||||
return;
|
||||
case Latin:
|
||||
alt = 1;
|
||||
collecting = 1;
|
||||
nk = 0;
|
||||
return;
|
||||
case Ctrl:
|
||||
ctl = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
kbdputc(c);
|
||||
c = ksym2utf[c];
|
||||
snprint(buf, sizeof(buf), "r%C", c);
|
||||
if(keyup)
|
||||
buf[0] = 'R';
|
||||
if(kbdin >= 0)
|
||||
write(kbdin, buf, strlen(buf)+1);
|
||||
}
|
||||
|
|
|
@ -229,11 +229,12 @@ readkbd(Vnc *v)
|
|||
}
|
||||
break;
|
||||
case 'c':
|
||||
chartorune(&r, buf+1);
|
||||
if(utfrune(buf2+1, Kctl) || utfrune(buf2+1, Kalt) || utfrune(buf2+1, Kaltgr))
|
||||
continue;
|
||||
if(utfrune(buf2+1, r))
|
||||
keyevent(v, runetovnc(r), 1);
|
||||
chartorune(&r, buf+1);
|
||||
keyevent(v, runetovnc(r), 1);
|
||||
if(utfrune(buf2+1, r) == nil)
|
||||
keyevent(v, runetovnc(r), 0);
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
#include <u.h>
|
||||
|
||||
/*
|
||||
* The code makes two assumptions: strlen(ld) is 1 or 2; latintab[i].ld can be a
|
||||
* prefix of latintab[j].ld only when j<i.
|
||||
*/
|
||||
struct cvlist
|
||||
{
|
||||
char *ld; /* must be seen before using this conversion */
|
||||
char *si; /* options for last input characters */
|
||||
Rune *so; /* the corresponding Rune for each si entry */
|
||||
} latintab[] = {
|
||||
#include "latin1.h"
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
* Given 5 characters k[0]..k[4], find the rune or return -1 for failure.
|
||||
*/
|
||||
long
|
||||
unicode(Rune *k)
|
||||
{
|
||||
long i, c;
|
||||
|
||||
k++; /* skip 'X' */
|
||||
c = 0;
|
||||
for(i=0; i<4; i++,k++){
|
||||
c <<= 4;
|
||||
if('0'<=*k && *k<='9')
|
||||
c += *k-'0';
|
||||
else if('a'<=*k && *k<='f')
|
||||
c += 10 + *k-'a';
|
||||
else if('A'<=*k && *k<='F')
|
||||
c += 10 + *k-'A';
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given n characters k[0]..k[n-1], find the corresponding rune or return -1 for
|
||||
* failure, or something < -1 if n is too small. In the latter case, the result
|
||||
* is minus the required n.
|
||||
*/
|
||||
long
|
||||
latin1(Rune *k, int n)
|
||||
{
|
||||
struct cvlist *l;
|
||||
int c;
|
||||
char* p;
|
||||
|
||||
if(k[0] == 'X')
|
||||
if(n>=5)
|
||||
return unicode(k);
|
||||
else
|
||||
return -5;
|
||||
for(l=latintab; l->ld!=0; l++)
|
||||
if(k[0] == l->ld[0]){
|
||||
if(n == 1)
|
||||
return -2;
|
||||
if(l->ld[1] == 0)
|
||||
c = k[1];
|
||||
else if(l->ld[1] != k[1])
|
||||
continue;
|
||||
else if(n == 2)
|
||||
return -3;
|
||||
else
|
||||
c = k[2];
|
||||
for(p=l->si; *p!=0; p++)
|
||||
if(*p == c)
|
||||
return l->so[p - l->si];
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
" ", " i", L"␣ı",
|
||||
"!~", "-=~", L"≄≇≉",
|
||||
"!", "!<=>?bmp", L"¡≮≠≯‽⊄∉⊅",
|
||||
"\"*", "IUiu", L"ΪΫϊϋ",
|
||||
"\"", "\"AEIOUYaeiouy", L"¨ÄËÏÖÜŸäëïöüÿ",
|
||||
"$*", "fhk", L"ϕϑϰ",
|
||||
"$", "BEFHILMRVaefglopv", L"ℬℰℱℋℐℒℳℛƲɑℯƒℊℓℴ℘ʋ",
|
||||
"\'\"", "Uu", L"Ǘǘ",
|
||||
"\'", "\'ACEILNORSUYZacegilnorsuyz", L"´ÁĆÉÍĹŃÓŔŚÚÝŹáćéģíĺńóŕśúýź",
|
||||
"*", "*ABCDEFGHIKLMNOPQRSTUWXYZabcdefghiklmnopqrstuwxyz", L"∗ΑΒΞΔΕΦΓΘΙΚΛΜΝΟΠΨΡΣΤΥΩΧΗΖαβξδεφγθικλμνοπψρστυωχηζ",
|
||||
"+", "-O", L"±⊕",
|
||||
",", ",ACEGIKLNORSTUacegiklnorstu", L"¸ĄÇĘĢĮĶĻŅǪŖŞŢŲąçęģįķļņǫŗşţų",
|
||||
"-*", "l", L"ƛ",
|
||||
"-", "+-2:>DGHILOTZbdghiltuz~", L"∓ƻ÷→ÐǤĦƗŁ⊖ŦƵƀðǥℏɨłŧʉƶ≂",
|
||||
".", ".CEGILOZceglz", L"·ĊĖĠİĿ⊙Żċėġŀż",
|
||||
"/", "Oo", L"Øø",
|
||||
"1", ".234568", L"․½⅓¼⅕⅙⅛",
|
||||
"2", "-.35", L"ƻ‥⅔⅖",
|
||||
"3", ".458", L"…¾⅗⅜",
|
||||
"4", "5", L"⅘",
|
||||
"5", "68", L"⅚⅝",
|
||||
"7", "8", L"⅞",
|
||||
":", "()-=", L"☹☺÷≔",
|
||||
"<!", "=~", L"≨⋦",
|
||||
"<", "-<=>~", L"←«≤≶≲",
|
||||
"=", ":<=>OV", L"≕⋜≡⋝⊜⇒",
|
||||
">!", "=~", L"≩⋧",
|
||||
">", "<=>~", L"≷≥»≳",
|
||||
"?", "!?", L"‽¿",
|
||||
"@\'", "\'", L"ъ",
|
||||
"@@", "\'EKSTYZekstyz", L"ьЕКСТЫЗекстыз",
|
||||
"@C", "Hh", L"ЧЧ",
|
||||
"@E", "Hh", L"ЭЭ",
|
||||
"@K", "Hh", L"ХХ",
|
||||
"@S", "CHch", L"ЩШЩШ",
|
||||
"@T", "Ss", L"ЦЦ",
|
||||
"@Y", "AEOUaeou", L"ЯЕЁЮЯЕЁЮ",
|
||||
"@Z", "Hh", L"ЖЖ",
|
||||
"@c", "h", L"ч",
|
||||
"@e", "h", L"э",
|
||||
"@k", "h", L"х",
|
||||
"@s", "ch", L"щш",
|
||||
"@t", "s", L"ц",
|
||||
"@y", "aeou", L"яеёю",
|
||||
"@z", "h", L"ж",
|
||||
"@", "ABDFGIJLMNOPRUVXabdfgijlmnopruvx", L"АБДФГИЙЛМНОПРУВХабдфгийлмнопрувх",
|
||||
"A", "E", L"Æ",
|
||||
"C", "ACU", L"⋂ℂ⋃",
|
||||
"Dv", "Zz", L"DŽDž",
|
||||
"D", "-e", L"Ð∆",
|
||||
"G", "-", L"Ǥ",
|
||||
"H", "-H", L"Ħℍ",
|
||||
"I", "-J", L"ƗIJ",
|
||||
"L", "&-Jj|", L"⋀ŁLJLj⋁",
|
||||
"M", "#48bs", L"♮♩♪♭♯",
|
||||
"N", "JNj", L"NJℕNj",
|
||||
"O", "*+-./=EIcoprx", L"⊛⊕⊖⊙⊘⊜ŒƢ©⊚℗®⊗",
|
||||
"P", "P", L"ℙ",
|
||||
"Q", "Q", L"ℚ",
|
||||
"R", "R", L"ℝ",
|
||||
"S", "S", L"§",
|
||||
"T", "-u", L"Ŧ⊨",
|
||||
"V", "=", L"⇐",
|
||||
"Y", "R", L"Ʀ",
|
||||
"Z", "-ACSZ", L"Ƶℤ",
|
||||
"^", "ACEGHIJOSUWYaceghijosuwy", L"ÂĈÊĜĤÎĴÔŜÛŴŶâĉêĝĥîĵôŝûŵŷ",
|
||||
"_\"", "AUau", L"ǞǕǟǖ",
|
||||
"_,", "Oo", L"Ǭǭ",
|
||||
"_.", "Aa", L"Ǡǡ",
|
||||
"_", "AEIOU_aeiou", L"ĀĒĪŌŪ¯āēīōū",
|
||||
"`\"", "Uu", L"Ǜǜ",
|
||||
"`", "AEIOUaeiou", L"ÀÈÌÒÙàèìòù",
|
||||
"a", "ben", L"↔æ∠",
|
||||
"b", "()+-0123456789=bknpqru", L"₍₎₊₋₀₁₂₃₄₅₆₇₈₉₌♝♚♞♟♛♜•",
|
||||
"c", "$Oagu", L"¢©∩≅∪",
|
||||
"dv", "z", L"dž",
|
||||
"d", "-adegz", L"ð↓‡°†ʣ",
|
||||
"e", "$lmns", L"€⋯—–∅",
|
||||
"f", "a", L"∀",
|
||||
"g", "$-r", L"¤ǥ∇",
|
||||
"h", "-v", L"ℏƕ",
|
||||
"i", "-bfjps", L"ɨ⊆∞ij⊇∫",
|
||||
"l", "\"$&\'-jz|", L"“£∧‘łlj⋄∨",
|
||||
"m", "iou", L"µ∈×",
|
||||
"n", "jo", L"nj¬",
|
||||
"o", "AOUaeiu", L"Å⊚Ůåœƣů",
|
||||
"p", "Odgrt", L"℗∂¶∏∝",
|
||||
"r", "\"\'O", L"”’®",
|
||||
"s", "()+-0123456789=abnoprstu", L"⁽⁾⁺⁻⁰¹²³⁴⁵⁶⁷⁸⁹⁼ª⊂ⁿº⊃√ß∍∑",
|
||||
"t", "-efmsu", L"ŧ∃∴™ς⊢",
|
||||
"u", "-AEGIOUaegiou", L"ʉĂĔĞĬŎŬ↑ĕğĭŏŭ",
|
||||
"v\"", "Uu", L"Ǚǚ",
|
||||
"v", "ACDEGIKLNORSTUZacdegijklnorstuz", L"ǍČĎĚǦǏǨĽŇǑŘŠŤǓŽǎčďěǧǐǰǩľňǒřšťǔž",
|
||||
"w", "bknpqr", L"♗♔♘♙♕♖",
|
||||
"x", "O", L"⊗",
|
||||
"y", "$", L"¥",
|
||||
"z", "-", L"ƶ",
|
||||
"|", "Pp|", L"Þþ¦",
|
||||
"~!", "=", L"≆",
|
||||
"~", "-=AINOUainou~", L"≃≅ÃĨÑÕŨãĩñõũ≈",
|
|
@ -18,7 +18,6 @@ SOFILES=\
|
|||
compat.$O\
|
||||
exportfs.$O\
|
||||
kbds.$O\
|
||||
latin1.$O\
|
||||
rre.$O\
|
||||
rlist.$O\
|
||||
|
||||
|
@ -34,7 +33,6 @@ HFILES=\
|
|||
compat.h\
|
||||
errstr.h\
|
||||
kbd.h\
|
||||
latin1.h\
|
||||
vncv.h\
|
||||
vncs.h\
|
||||
|
||||
|
|
|
@ -55,6 +55,8 @@ struct {
|
|||
int shared;
|
||||
int sleeptime = 5;
|
||||
int verbose = 0;
|
||||
int kbdin = -1;
|
||||
|
||||
char *cert;
|
||||
char *pixchan = "r5g6b5";
|
||||
static int cmdpid;
|
||||
|
@ -88,6 +90,7 @@ main(int argc, char **argv)
|
|||
int altnet, baseport, cfd, display, exnum, fd, h, killing, w;
|
||||
char adir[NETPATHLEN], ldir[NETPATHLEN];
|
||||
char net[NETPATHLEN], *p;
|
||||
char *kbdfs[] = { "/bin/aux/kbdfs", "-dq", nil };
|
||||
char *rc[] = { "/bin/rc", "-i", nil };
|
||||
Vncs *v;
|
||||
|
||||
|
@ -190,7 +193,7 @@ main(int argc, char **argv)
|
|||
bind("#c", "/dev", MREPL);
|
||||
|
||||
/* run the command */
|
||||
switch(cmdpid = rfork(RFPROC|RFFDG|RFNOTEG|RFNAMEG|RFREND)){
|
||||
switch(cmdpid = rfork(RFPROC|RFFDG|RFNOTEG)){
|
||||
case -1:
|
||||
sysfatal("rfork: %r");
|
||||
break;
|
||||
|
@ -198,12 +201,20 @@ main(int argc, char **argv)
|
|||
if(mounter("/dev", MBEFORE, fd, exnum) < 0)
|
||||
sysfatal("mounter: %r");
|
||||
close(exportfd);
|
||||
close(0);
|
||||
close(1);
|
||||
close(2);
|
||||
open("/dev/cons", OWRITE);
|
||||
open("/dev/cons", OWRITE);
|
||||
if(rfork(RFPROC|RFMEM|RFFDG) == 0){
|
||||
exec(kbdfs[0], kbdfs);
|
||||
_exits("kbdfs");
|
||||
}
|
||||
waitpid();
|
||||
rfork(RFNAMEG);
|
||||
rendezvous(&cmdpid, 0);
|
||||
rfork(RFREND);
|
||||
close(0);
|
||||
open("/dev/cons", OREAD);
|
||||
open("/dev/cons", OWRITE);
|
||||
open("/dev/cons", OWRITE);
|
||||
exec(argv[0], argv);
|
||||
fprint(2, "exec %s: %r\n", argv[0]);
|
||||
_exits(nil);
|
||||
|
@ -212,6 +223,11 @@ main(int argc, char **argv)
|
|||
break;
|
||||
}
|
||||
|
||||
rendezvous(&cmdpid, 0);
|
||||
kbdin = open("/dev/kbdin", OWRITE);
|
||||
unmount(nil, "/dev");
|
||||
bind("#c", "/dev", MREPL);
|
||||
|
||||
/* run the service */
|
||||
srvfd = vncannounce(net, display, adir, baseport);
|
||||
if(srvfd < 0)
|
||||
|
@ -385,6 +401,8 @@ killall(void)
|
|||
srvfd = -1;
|
||||
close(exportfd);
|
||||
exportfd = -1;
|
||||
close(kbdin);
|
||||
kbdin = -1;
|
||||
postnote(PNGROUP, getpid(), killkin);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue