ref: 49b5472ee7b434f3c56af4a14d4907207f8ed1ad
parent: 705885553cced0300ed72722b20bad405af2bdce
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Sun Jan 1 19:49:48 EST 2023
evdump(1): a program to dump input and window events
--- /dev/null
+++ b/sys/man/1/evdump
@@ -1,0 +1,24 @@
+.TH EVDUMP 1
+.SH NAME
+evdump \- dump input and window events
+.SH SYNOPSIS
+.B evdump
+.SH DESCRIPTION
+.PP
+.I Evdump
+creates a new window, grabs the input and prints incoming
+keyboard, mouse and window events in a human-readable form.
+.PP
+It can be useful in a situation where a keyboard does not
+seem to produce any rune when a certain key is pressed. The
+event printed out, in this case, provides enough information
+to set a required rune via
+.IR /dev/kbmap .
+.SH SEE ALSO
+.IR rio (1) ,
+.IR kbdfs (8)
+.SH SOURCE
+.B /sys/src/cmd/evdump.c
+.SH HISTORY
+.I Evdump
+first appeared in 9front (January, 2023).
--- /dev/null
+++ b/sys/src/cmd/evdump.c
@@ -1,0 +1,312 @@
+#include <u.h>
+#include <libc.h>
+#include <ctype.h>
+#include <bio.h>
+#include <draw.h>
+#include <keyboard.h>
+#include <mouse.h>
+#include <thread.h>
+
+typedef struct {
+ u8int e;
+ u8int c;
+ Rune r;
+}K;
+
+enum {
+ Kmbase = 0xf0000,
+};
+
+static K k[10*128];
+static int nk;
+static int kbd;
+static Biobuf *kbmap, *wctl;
+
+static char *
+k2s(Rune r)
+{
+ switch(r){
+ case Ksbwd: return "Ksbwd";
+ case Ksfwd: return "Ksfwd";
+ case Kpause: return "Kpause";
+ case Kvoldn: return "Kvoldn";
+ case Kvolup: return "Kvolup";
+ case Kmute: return "Kmute";
+ case Kbrtdn: return "Kbrtdn";
+ case Kbrtup: return "Kbrtup";
+ case Kack: return "Kack";
+ case Kalt: return "Kalt";
+ case Kaltgr: return "Kaltgr";
+ case Kbreak: return "Kbreak";
+ case Kbs: return "Kbs";
+ case Kcaps: return "Kcaps";
+ case Kctl: return "Kctl";
+ case Kdel: return "Kdel";
+ case Kdown: return "Kdown";
+ case Kend: return "Kend";
+ case Kenq: return "Kenq";
+ case Keof: return "Keof";
+ case Kesc: return "Kesc";
+ case Ketb: return "Ketb";
+ case Ketx: return "Ketx";
+ case Khome: return "Khome";
+ case Kins: return "Kins";
+ case Kleft: return "Kleft";
+ case Kmiddle: return "Kmiddle";
+ case Kmod4: return "Kmod4";
+ case Knack: return "Knack";
+ case Knum: return "Knum";
+ case Kpgdown: return "Kpgdown";
+ case Kpgup: return "Kpgup";
+ case Kprint: return "Kprint";
+ case Kright: return "Kright";
+ case Kscroll: return "Kscroll";
+ case Kscrollonedown: return "Kscrollonedown";
+ case Kscrolloneup: return "Kscrolloneup";
+ case Kshift: return "Kshift";
+ case Ksoh: return "Ksoh";
+ case Kstx: return "Kstx";
+ case Kup: return "Kup";
+ case KF|1: return "F1";
+ case KF|2: return "F2";
+ case KF|3: return "F3";
+ case KF|4: return "F4";
+ case KF|5: return "F5";
+ case KF|6: return "F6";
+ case KF|7: return "F7";
+ case KF|8: return "F8";
+ case KF|9: return "F9";
+ case KF|10: return "F10";
+ case KF|11: return "F11";
+ case KF|12: return "F12";
+ case Kmouse|1: return "Kmouse1";
+ case Kmouse|2: return "Kmouse2";
+ case Kmouse|3: return "Kmouse3";
+ case Kmouse|4: return "Kmouse4";
+ case Kmouse|5: return "Kmouse5";
+ case '\n': return "\\n";
+ }
+
+ return nil;
+}
+
+static int
+kmreset(void *, char *)
+{
+ int i;
+
+ for(i = 0; i <= nk; i++)
+ Bprint(kbmap, "%d\t%d\t%d\n", k[i].e, k[i].c, k[i].r);
+ Bflush(kbmap);
+
+ return 0;
+}
+
+static void
+kmset(void)
+{
+ int i;
+
+ for(i = 0; i <= nk; i++)
+ Bprint(kbmap, "%d\t%d\t%d\n", k[i].e, k[i].c, Kmbase+i);
+ Bflush(kbmap);
+}
+
+static void
+key(Rune r, char *type)
+{
+ char *s, t[32];
+ Rune c;
+ K q;
+
+ if(r < Kmbase || r >= Kmbase+nk){
+ if((s = k2s(r)) != nil)
+ snprint(t, sizeof(t), "%s", s);
+ else if((r < 0x80 && isprint(r)) || r >= 0x20)
+ snprint(t, sizeof(t), "%C (0x%x)", r, r);
+ else
+ snprint(t, sizeof(t), "0x%x", r);
+ return;
+ }
+ q = k[r-Kmbase];
+ c = q.r;
+ if((s = k2s(c)) != nil)
+ snprint(t, sizeof(t), "%s", s);
+ else if((c < 0x80 && isprint(c)) || c >= 0x20)
+ snprint(t, sizeof(t), "%C (0x%x)", c, c);
+ else
+ snprint(t, sizeof(t), "0x%x", c);
+
+ print("key %s %s: %d %d 0x%ux\n", type, t, q.e, q.c, q.r);
+}
+
+static void
+wctlproc(void *)
+{
+ char s[256], *t[8];
+ int wctl, n;
+
+ if((wctl = open("/dev/wctl", OREAD)) < 0)
+ sysfatal("%r");
+ for(;;){
+ if((n = read(wctl, s, sizeof(s)-1)) <= 0)
+ break;
+ s[n] = 0;
+ if(tokenize(s, t, nelem(t)) < 6)
+ continue;
+
+ if(strcmp(t[4], "current") == 0)
+ kmset();
+ else if(strcmp(t[4], "notcurrent") == 0)
+ kmreset(nil, nil);
+
+ print("wctl %s %s\n", t[4], t[5]);
+ }
+ close(wctl);
+
+ threadexits(nil);
+}
+
+static void
+kbproc(void *)
+{
+ char *s, buf[128], buf2[128];
+ int kbd, n;
+ Rune r;
+
+ threadsetname("kbproc");
+ if((kbd = open("/dev/kbd", OREAD)) < 0)
+ sysfatal("/dev/kbd: %r");
+
+ buf2[0] = 0;
+ buf2[1] = 0;
+ buf[0] = 0;
+ for(;;){
+ if(buf[0] != 0){
+ n = strlen(buf)+1;
+ memmove(buf, buf+n, sizeof(buf)-n);
+ }
+ if(buf[0] == 0){
+ n = read(kbd, buf, sizeof(buf)-1);
+ if(n <= 0)
+ break;
+ buf[n-1] = 0;
+ buf[n] = 0;
+ }
+
+ switch(buf[0]){
+ case 'k':
+ for(s = buf+1; *s;){
+ s += chartorune(&r, s);
+ if(utfrune(buf2+1, r) == nil)
+ key(r, "down");
+ }
+ break;
+ case 'K':
+ for(s = buf2+1; *s;){
+ s += chartorune(&r, s);
+ if(utfrune(buf+1, r) == nil)
+ key(r, "up");
+ }
+ break;
+ case 'c':
+ if(chartorune(&r, buf+1) > 0 && r != Runeerror)
+ key(r, "repeat");
+ default:
+ continue;
+ }
+
+ strcpy(buf2, buf);
+ }
+
+ close(kbd);
+
+ threadexits(nil);
+}
+
+static void
+usage(void)
+{
+ fprint(2, "usage: %s\n", argv0);
+ threadexitsall("usage");
+}
+
+void
+threadmain(int argc, char **argv)
+{
+ Mousectl *mctl;
+ char tmp[32];
+ Mouse m;
+ char *s;
+ enum { Cmouse, Cresize, Numchan };
+ Alt a[Numchan+1] = {
+ [Cmouse] = { nil, &m, CHANRCV },
+ [Cresize] = { nil, nil, CHANRCV },
+ { nil, nil, CHANEND },
+ };
+
+ ARGBEGIN{
+ default:
+ usage();
+ }ARGEND
+
+ if(argc != 0)
+ usage();
+
+ if((kbmap = Bopen("/dev/kbmap", OREAD)) == nil)
+ sysfatal("%r");
+ for(nk = 0; nk < nelem(k); nk++){
+ if((s = Brdline(kbmap, '\n')) == nil)
+ break;
+ k[nk].e = strtoul(s, &s, 10);
+ k[nk].c = strtoul(s, &s, 10);
+ k[nk].r = strtoul(s, &s, 10);
+ }
+ Bterm(kbmap);
+
+ if((kbmap = Bopen("/dev/kbmap", OWRITE)) == nil)
+ sysfatal("%r");
+ threadnotify(kmreset, 1);
+
+ snprint(tmp, sizeof(tmp), "-pid %d -dx %d -dy %d", getpid(), 256, 256);
+ newwindow(tmp);
+
+ if(initdraw(nil, nil, "evdump") < 0)
+ sysfatal("initdraw: %r");
+ if((mctl = initmouse(nil, screen)) == nil)
+ sysfatal("initmouse: %r");
+ a[Cmouse].c = mctl->c;
+ a[Cresize].c = mctl->resizec;
+
+ proccreate(kbproc, nil, mainstacksize);
+ proccreate(wctlproc, nil, mainstacksize);
+
+ for(;;){
+ draw(screen, screen->r, display->black, nil, ZP);
+
+ switch(alt(a)){
+ case -1:
+ goto end;
+
+ case Cmouse:
+ print(
+ "mouse buttons 0x%x x %d y %d\n",
+ m.buttons,
+ m.xy.x, m.xy.y
+ );
+ break;
+
+ case Cresize:
+ getwindow(display, Refnone);
+ print(
+ "resize min %d %d max %d %d\n",
+ screen->r.min.x, screen->r.min.y,
+ screen->r.max.x, screen->r.max.y
+ );
+ break;
+ }
+ }
+
+end:
+ threadexitsall(nil);
+}