#include <u.h>#include <libc.h>#include <stdio.h>#include <draw.h>#include <thread.h>#include <mouse.h>#include <keyboard.h>#include "dat.h"#include "fns.h" extern int resized;extern Point center;extern Channel *fuckchan, *tchan;extern Rectangle grabr; cvar_t *in_joystick;cvar_t *sensitivity;cvar_t *lookstrafe;cvar_t *lookspring;cvar_t *freelook;cvar_t *m_pitch; static cvar_t *m_filter;static cvar_t *m_windowed;static cvar_t *m_yaw;static cvar_t *m_side;static cvar_t *m_forward; static int mouseon, fixms;static int mlooking;static int dx, dy;static int oldmwin; typedef struct Kev Kev;struct Kev{ int key; int down; int isrep;};enum{ Nbuf = 64};static Channel *kchan, *mchan;static int iop = -1, pfd[2];static QLock killock; char *Sys_ConsoleInput(void){ static char buf[256]; int n; if(dedicated != nil && dedicated->value && iop >= 0){ if(flen(pfd[1]) < 1) /* only poll for input */ return nil; if((n = read(pfd[1], buf, sizeof buf)) < 0) sysfatal("Sys_ConsoleInput:read: %r"); if(n == 0){ iop = -1; return nil; } return buf; } return nil;} voidIN_Grabm(int on){ static char nocurs[2*4+2*2*16]; static int fd = -1; if(mouseon == on) return; if(mouseon = on && m_windowed->value){ if((fd = open("/dev/cursor", ORDWR|OCEXEC)) < 0){ sysfatal("IN_Grabm:open: %r\n"); return; } write(fd, nocurs, sizeof nocurs); fixms++; }else if(fd >= 0){ close(fd); fd = -1; }} voidIN_Commands(void){ /* joystick stuff */} voidbtnev(int btn, ulong msec){ static int oldb; int i, b; for(i = 0; i < 3; i++){ b = 1<<i; if(btn & b && ~oldb & b) Key_Event(K_MOUSE1+i, true, false, msec); else if(~btn & b && oldb & b) Key_Event(K_MOUSE1+i, false, false, msec); } oldb = btn & 7; /* mwheelup and mwheeldn buttons are never held down */ for(i = 3; i < 5; i++){ b = 1<<i; if(btn & b){ Key_Event(K_MOUSE1+i, true, false, msec); Key_Event(K_MOUSE1+i, false, false, msec); } }} voidKBD_Update(void){ int r; Kev ev; Mouse m; if(oldmwin != m_windowed->value){ oldmwin = m_windowed->value; IN_Grabm(m_windowed->value); } while((r = nbrecv(kchan, &ev)) > 0) Key_Event(ev.key, ev.down, ev.isrep, Sys_Milliseconds()); if(r < 0) sysfatal("KBD_Update:nbrecv: %r\n"); while((r = nbrecv(mchan, &m)) > 0){ dx += m.xy.x; dy += m.xy.y; btnev(m.buttons, m.msec); } if(r < 0) sysfatal("KBD_Update:nbrecv: %r\n");} voidIN_Move(usercmd_t *cmd){ static double oldmx, oldmy; double mx, my; if(!mouseon) return; if(m_filter->value){ mx = (dx + oldmx) * 0.5; my = (dy + oldmy) * 0.5; }else{ mx = dx; my = dy; } oldmx = dx; oldmy = dy; dx = dy = 0; mx *= sensitivity->value; my *= sensitivity->value; /* add mouse x/y movement to cmd */ if(in_strafe.state & 1 || lookstrafe->value && mlooking) cmd->sidemove += m_side->value * mx; else cl.viewangles[YAW] -= m_yaw->value * mx; if((mlooking || freelook->value) && ~in_strafe.state & 1) cl.viewangles[PITCH] += m_pitch->value * my; else cmd->forwardmove -= m_forward->value * my;} /* called on focus/unfocus in win32 */voidIN_Activate(qboolean){} /* called every frame even if not generating commands */voidIN_Frame(void){} voidIN_ForceCenterView(void){ cl.viewangles[PITCH] = 0;} voidIN_MLookDown(void){ mlooking = true;} voidIN_MLookUp(void){ mlooking = false; IN_CenterView();} static intrunetokey(Rune r){ int k = 0; switch(r){ case Kpgup: k = K_PGUP; break; case Kpgdown: k = K_PGDN; break; case Khome: k = K_HOME; break; case Kend: k = K_END; break; case Kleft: k = K_LEFTARROW; break; case Kright: k = K_RIGHTARROW; break; case Kdown: k = K_DOWNARROW; break; case Kup: k = K_UPARROW; break; case Kesc: k = K_ESCAPE; break; case '\n': k = K_ENTER; break; case '\t': k = K_TAB; break; case KF|1: k = K_F1; break; case KF|2: k = K_F2; break; case KF|3: k = K_F3; break; case KF|4: k = K_F4; break; case KF|5: k = K_F5; break; case KF|6: k = K_F6; break; case KF|7: k = K_F7; break; case KF|8: k = K_F8; break; case KF|9: k = K_F9; break; case KF|10: k = K_F10; break; case KF|11: k = K_F11; break; case KF|12: k = K_F12; break; case Kbs: k = K_BACKSPACE; break; case Kdel: k = K_DEL; break; case Kbreak: k = K_PAUSE; break; case Kshift: k = K_SHIFT; break; case Kctl: k = K_CTRL; break; case Kalt: case Kaltgr: k = K_ALT; break; case Kins: k = K_INS; break; case L'§': k = '~'; break; default: if(r < 0x80) k = r; }; return k;} static voidkproc(void *){ int n, k, fd, rep; char buf[128], kdown[128], *s, *p; Rune r; Kev ev, evc; if((fd = open("/dev/kbd", OREAD)) < 0) sysfatal("kproc: %r"); memset(buf, 0, sizeof buf); memset(kdown, 0, sizeof kdown); evc.key = K_ENTER; evc.down = true; evc.isrep = true; ev.isrep = false; rep = 0; for(;;){ if(buf[0] != 0){ n = strlen(buf)+1; memmove(buf, buf+n, sizeof(buf)-n); } if(buf[0] == 0){ if((n = read(fd, buf, sizeof(buf)-1)) <= 0) break; buf[n-1] = 0; buf[n] = 0; } switch(buf[0]){ case 'c': if(rep++ > 0 && send(kchan, &evc) < 0) threadexits(nil); default: continue; case 'k': ev.down = true; s = buf+1; p = kdown+1; break; case 'K': ev.down = false; s = kdown+1; p = buf+1; break; } while(*s != 0){ s += chartorune(&r, s); if(utfrune(p, r) == nil){ if((k = runetokey(r)) == 0) continue; ev.key = k; if(send(kchan, &ev) < 0) threadexits(nil); if(ev.down){ evc.key = k; rep = 0; } } } strcpy(kdown, buf); }} static voidmproc(void *){ int n, nerr, fd; char buf[1+5*12]; Mouse m; Point p, o; if((fd = open("/dev/mouse", ORDWR)) < 0) sysfatal("mproc: %r"); for(nerr=0;;){ if((n = read(fd, buf, sizeof buf)) != 1+4*12){ if(n < 0 || ++nerr > 10) break; fprint(2, "mproc: bad count %d not 49: %r\n", n); continue; } nerr = 0; switch(*buf){ case 'r': resized = 1; /* fall through */ case 'm': if(!mouseon) break; if(fixms){ fixms = 0; goto res; } p.x = atoi(buf+1+0*12); p.y = atoi(buf+1+1*12); m.xy.x = p.x - o.x; m.xy.y = p.y - o.y; m.buttons = atoi(buf+1+2*12); m.msec = atoi(buf+1+3*12); if(nbsend(mchan, &m) < 0) goto end; if(!ptinrect(p, grabr)){ res: fprint(fd, "m%d %d", center.x, center.y); p = center; } o = p; break; } }end:;} static voidtproc(void *) /* stupid select() timeout bullshit */{ int t, ms, n, r; t = ms = 0; for(;;){ sleep(1); t++; if((r = nbrecv(tchan, &n)) < 0) sysfatal("tproc:nbrecv: %r"); if(r == 0){ if(t == ms && nbsend(fuckchan, nil) < 0) sysfatal("tproc:nbsend: %r"); continue; } if(n <= 0) ms = 0; else{ ms = n; t = 0; } }} static voidiproc(void *){ int n; char s[256]; if((iop = pipe(pfd)) < 0) sysfatal("iproc:pipe: %r"); for(;;){ if((n = read(0, s, sizeof s)) <= 0) break; s[n-1] = 0; if((write(pfd[0], s, n)) != n) break; if(nbsend(fuckchan, nil) < 0) sysfatal("iproc:nbsend: %r"); } fprint(2, "iproc %d: %r\n", threadpid(threadid())); iop = -1;} voidIN_Shutdown(void){ IN_Grabm(0); iop = -1; close(pfd[0]); close(pfd[1]); if(kchan != nil) chanfree(kchan); if(mchan != nil) chanfree(mchan);} voidIN_Init(void){ if(dedicated->value){ if(proccreate(iproc, nil, 8192) < 0) sysfatal("proccreate iproc: %r"); if(proccreate(tproc, nil, 8192) < 0) sysfatal("proccreate tproc: %r"); return; } in_joystick = Cvar_Get("in_joystick", "0", CVAR_ARCHIVE); sensitivity = Cvar_Get("sensitivity", "3", CVAR_ARCHIVE); freelook = Cvar_Get("freelook", "1", CVAR_ARCHIVE); lookspring = Cvar_Get("lookspring", "0", CVAR_ARCHIVE); lookstrafe = Cvar_Get("lookstrafe", "0", CVAR_ARCHIVE); m_pitch = Cvar_Get("m_pitch", "0.022", CVAR_ARCHIVE); m_yaw = Cvar_Get("m_yaw", "0.022", CVAR_ARCHIVE); m_forward = Cvar_Get("m_forward", "1", CVAR_ARCHIVE); m_side = Cvar_Get("m_side", "0.8", CVAR_ARCHIVE); m_windowed = Cvar_Get("m_windowed", "1", CVAR_ARCHIVE); m_filter = Cvar_Get("m_filter", "0", CVAR_ARCHIVE); Cmd_AddCommand("+mlook", IN_MLookDown); Cmd_AddCommand("-mlook", IN_MLookUp); Cmd_AddCommand("force_centerview", IN_ForceCenterView); if((kchan = chancreate(sizeof(Kev), Nbuf)) == nil) sysfatal("chancreate kchan: %r"); if(proccreate(kproc, nil, 8192) < 0) sysfatal("proccreate kproc: %r"); if((mchan = chancreate(sizeof(Mouse), Nbuf)) == nil) sysfatal("chancreate kchan: %r"); if(proccreate(mproc, nil, 8192) < 0) sysfatal("proccreate mproc: %r");}
#include <u.h>
#include <libc.h>
#include <stdio.h>
#include <draw.h>
#include <thread.h>
#include <mouse.h>
#include <keyboard.h>
#include "dat.h"
#include "fns.h"
extern int resized;
extern Point center;
extern Channel *fuckchan, *tchan;
extern Rectangle grabr;
cvar_t *in_joystick;
cvar_t *sensitivity;
cvar_t *lookstrafe;
cvar_t *lookspring;
cvar_t *freelook;
cvar_t *m_pitch;
static cvar_t *m_filter;
static cvar_t *m_windowed;
static cvar_t *m_yaw;
static cvar_t *m_side;
static cvar_t *m_forward;
static int mouseon, fixms;
static int mlooking;
static int dx, dy;
static int oldmwin;
typedef struct Kev Kev;
struct Kev{
int key;
int down;
int isrep;
};
enum{
Nbuf = 64
};
static Channel *kchan, *mchan;
static int iop = -1, pfd[2];
static QLock killock;
char *
Sys_ConsoleInput(void)
{
static char buf[256];
int n;
if(dedicated != nil && dedicated->value && iop >= 0){
if(flen(pfd[1]) < 1) /* only poll for input */
return nil;
if((n = read(pfd[1], buf, sizeof buf)) < 0)
sysfatal("Sys_ConsoleInput:read: %r");
if(n == 0){
iop = -1;
return nil;
}
return buf;
}
return nil;
}
void
IN_Grabm(int on)
{
static char nocurs[2*4+2*2*16];
static int fd = -1;
if(mouseon == on)
return;
if(mouseon = on && m_windowed->value){
if((fd = open("/dev/cursor", ORDWR|OCEXEC)) < 0){
sysfatal("IN_Grabm:open: %r\n");
return;
}
write(fd, nocurs, sizeof nocurs);
fixms++;
}else if(fd >= 0){
close(fd);
fd = -1;
}
}
void
IN_Commands(void)
{
/* joystick stuff */
}
void
btnev(int btn, ulong msec)
{
static int oldb;
int i, b;
for(i = 0; i < 3; i++){
b = 1<<i;
if(btn & b && ~oldb & b)
Key_Event(K_MOUSE1+i, true, false, msec);
else if(~btn & b && oldb & b)
Key_Event(K_MOUSE1+i, false, false, msec);
}
oldb = btn & 7;
/* mwheelup and mwheeldn buttons are never held down */
for(i = 3; i < 5; i++){
b = 1<<i;
if(btn & b){
Key_Event(K_MOUSE1+i, true, false, msec);
Key_Event(K_MOUSE1+i, false, false, msec);
}
}
}
void
KBD_Update(void)
{
int r;
Kev ev;
Mouse m;
if(oldmwin != m_windowed->value){
oldmwin = m_windowed->value;
IN_Grabm(m_windowed->value);
}
while((r = nbrecv(kchan, &ev)) > 0)
Key_Event(ev.key, ev.down, ev.isrep, Sys_Milliseconds());
if(r < 0)
sysfatal("KBD_Update:nbrecv: %r\n");
while((r = nbrecv(mchan, &m)) > 0){
dx += m.xy.x;
dy += m.xy.y;
btnev(m.buttons, m.msec);
}
if(r < 0)
sysfatal("KBD_Update:nbrecv: %r\n");
}
void
IN_Move(usercmd_t *cmd)
{
static double oldmx, oldmy;
double mx, my;
if(!mouseon)
return;
if(m_filter->value){
mx = (dx + oldmx) * 0.5;
my = (dy + oldmy) * 0.5;
}else{
mx = dx;
my = dy;
}
oldmx = dx;
oldmy = dy;
dx = dy = 0;
mx *= sensitivity->value;
my *= sensitivity->value;
/* add mouse x/y movement to cmd */
if(in_strafe.state & 1 || lookstrafe->value && mlooking)
cmd->sidemove += m_side->value * mx;
else
cl.viewangles[YAW] -= m_yaw->value * mx;
if((mlooking || freelook->value) && ~in_strafe.state & 1)
cl.viewangles[PITCH] += m_pitch->value * my;
else
cmd->forwardmove -= m_forward->value * my;
}
/* called on focus/unfocus in win32 */
void
IN_Activate(qboolean)
{
}
/* called every frame even if not generating commands */
void
IN_Frame(void)
{
}
void
IN_ForceCenterView(void)
{
cl.viewangles[PITCH] = 0;
}
void
IN_MLookDown(void)
{
mlooking = true;
}
void
IN_MLookUp(void)
{
mlooking = false;
IN_CenterView();
}
static int
runetokey(Rune r)
{
int k = 0;
switch(r){
case Kpgup: k = K_PGUP; break;
case Kpgdown: k = K_PGDN; break;
case Khome: k = K_HOME; break;
case Kend: k = K_END; break;
case Kleft: k = K_LEFTARROW; break;
case Kright: k = K_RIGHTARROW; break;
case Kdown: k = K_DOWNARROW; break;
case Kup: k = K_UPARROW; break;
case Kesc: k = K_ESCAPE; break;
case '\n': k = K_ENTER; break;
case '\t': k = K_TAB; break;
case KF|1: k = K_F1; break;
case KF|2: k = K_F2; break;
case KF|3: k = K_F3; break;
case KF|4: k = K_F4; break;
case KF|5: k = K_F5; break;
case KF|6: k = K_F6; break;
case KF|7: k = K_F7; break;
case KF|8: k = K_F8; break;
case KF|9: k = K_F9; break;
case KF|10: k = K_F10; break;
case KF|11: k = K_F11; break;
case KF|12: k = K_F12; break;
case Kbs: k = K_BACKSPACE; break;
case Kdel: k = K_DEL; break;
case Kbreak: k = K_PAUSE; break;
case Kshift: k = K_SHIFT; break;
case Kctl: k = K_CTRL; break;
case Kalt:
case Kaltgr: k = K_ALT; break;
case Kins: k = K_INS; break;
case L'§': k = '~'; break;
default:
if(r < 0x80)
k = r;
};
return k;
}
static void
kproc(void *)
{
int n, k, fd, rep;
char buf[128], kdown[128], *s, *p;
Rune r;
Kev ev, evc;
if((fd = open("/dev/kbd", OREAD)) < 0)
sysfatal("kproc: %r");
memset(buf, 0, sizeof buf);
memset(kdown, 0, sizeof kdown);
evc.key = K_ENTER;
evc.down = true;
evc.isrep = true;
ev.isrep = false;
rep = 0;
for(;;){
if(buf[0] != 0){
n = strlen(buf)+1;
memmove(buf, buf+n, sizeof(buf)-n);
}
if(buf[0] == 0){
if((n = read(fd, buf, sizeof(buf)-1)) <= 0)
break;
buf[n-1] = 0;
buf[n] = 0;
}
switch(buf[0]){
case 'c':
if(rep++ > 0 && send(kchan, &evc) < 0)
threadexits(nil);
default:
continue;
case 'k':
ev.down = true;
s = buf+1;
p = kdown+1;
break;
case 'K':
ev.down = false;
s = kdown+1;
p = buf+1;
break;
}
while(*s != 0){
s += chartorune(&r, s);
if(utfrune(p, r) == nil){
if((k = runetokey(r)) == 0)
continue;
ev.key = k;
if(send(kchan, &ev) < 0)
threadexits(nil);
if(ev.down){
evc.key = k;
rep = 0;
}
}
}
strcpy(kdown, buf);
}
}
static void
mproc(void *)
{
int n, nerr, fd;
char buf[1+5*12];
Mouse m;
Point p, o;
if((fd = open("/dev/mouse", ORDWR)) < 0)
sysfatal("mproc: %r");
for(nerr=0;;){
if((n = read(fd, buf, sizeof buf)) != 1+4*12){
if(n < 0 || ++nerr > 10)
break;
fprint(2, "mproc: bad count %d not 49: %r\n", n);
continue;
}
nerr = 0;
switch(*buf){
case 'r':
resized = 1;
/* fall through */
case 'm':
if(!mouseon)
break;
if(fixms){
fixms = 0;
goto res;
}
p.x = atoi(buf+1+0*12);
p.y = atoi(buf+1+1*12);
m.xy.x = p.x - o.x;
m.xy.y = p.y - o.y;
m.buttons = atoi(buf+1+2*12);
m.msec = atoi(buf+1+3*12);
if(nbsend(mchan, &m) < 0)
goto end;
if(!ptinrect(p, grabr)){
res:
fprint(fd, "m%d %d", center.x, center.y);
p = center;
}
o = p;
break;
}
}
end:;
}
static void
tproc(void *) /* stupid select() timeout bullshit */
{
int t, ms, n, r;
t = ms = 0;
for(;;){
sleep(1);
t++;
if((r = nbrecv(tchan, &n)) < 0)
sysfatal("tproc:nbrecv: %r");
if(r == 0){
if(t == ms && nbsend(fuckchan, nil) < 0)
sysfatal("tproc:nbsend: %r");
continue;
}
if(n <= 0)
ms = 0;
else{
ms = n;
t = 0;
}
}
}
static void
iproc(void *)
{
int n;
char s[256];
if((iop = pipe(pfd)) < 0)
sysfatal("iproc:pipe: %r");
for(;;){
if((n = read(0, s, sizeof s)) <= 0)
break;
s[n-1] = 0;
if((write(pfd[0], s, n)) != n)
break;
if(nbsend(fuckchan, nil) < 0)
sysfatal("iproc:nbsend: %r");
}
fprint(2, "iproc %d: %r\n", threadpid(threadid()));
iop = -1;
}
void
IN_Shutdown(void)
{
IN_Grabm(0);
iop = -1;
close(pfd[0]);
close(pfd[1]);
if(kchan != nil)
chanfree(kchan);
if(mchan != nil)
chanfree(mchan);
}
void
IN_Init(void)
{
if(dedicated->value){
if(proccreate(iproc, nil, 8192) < 0)
sysfatal("proccreate iproc: %r");
if(proccreate(tproc, nil, 8192) < 0)
sysfatal("proccreate tproc: %r");
return;
}
in_joystick = Cvar_Get("in_joystick", "0", CVAR_ARCHIVE);
sensitivity = Cvar_Get("sensitivity", "3", CVAR_ARCHIVE);
freelook = Cvar_Get("freelook", "1", CVAR_ARCHIVE);
lookspring = Cvar_Get("lookspring", "0", CVAR_ARCHIVE);
lookstrafe = Cvar_Get("lookstrafe", "0", CVAR_ARCHIVE);
m_pitch = Cvar_Get("m_pitch", "0.022", CVAR_ARCHIVE);
m_yaw = Cvar_Get("m_yaw", "0.022", CVAR_ARCHIVE);
m_forward = Cvar_Get("m_forward", "1", CVAR_ARCHIVE);
m_side = Cvar_Get("m_side", "0.8", CVAR_ARCHIVE);
m_windowed = Cvar_Get("m_windowed", "1", CVAR_ARCHIVE);
m_filter = Cvar_Get("m_filter", "0", CVAR_ARCHIVE);
Cmd_AddCommand("+mlook", IN_MLookDown);
Cmd_AddCommand("-mlook", IN_MLookUp);
Cmd_AddCommand("force_centerview", IN_ForceCenterView);
if((kchan = chancreate(sizeof(Kev), Nbuf)) == nil)
sysfatal("chancreate kchan: %r");
if(proccreate(kproc, nil, 8192) < 0)
sysfatal("proccreate kproc: %r");
if((mchan = chancreate(sizeof(Mouse), Nbuf)) == nil)
sysfatal("chancreate kchan: %r");
if(proccreate(mproc, nil, 8192) < 0)
sysfatal("proccreate mproc: %r");
}