shithub: qk2

ref: 9bd6cfa17e9cbbfcc7ab9efcbe0b495691e59c9f
dir: /plan9/in_9.c/

View raw version
#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"

cvar_t	*in_mouse;
cvar_t	*in_joystick;
cvar_t	*m_filter;
cvar_t	*m_windowed;
cvar_t	*sensitivity;
cvar_t	*lookstrafe;
cvar_t	*m_side;
cvar_t	*m_yaw;
cvar_t	*m_pitch;
cvar_t	*m_forward;
cvar_t	*freelook;

qboolean mouseon;
qboolean mlooking;
int mx, my, mbtn, dx, dy, oldmx, oldmy, oldmbtn;
int oldmwin;

typedef struct Kev Kev;
struct Kev{
	int key;
	int down;
};
enum{
	Nbuf	= 64
};
Channel *kchan;
int ktid = -1, mtid = -1;

/* rw_9.c */
extern int resized;
extern Point center;
extern refimport_t ri;

void IN_Grabm(int on)
{
	static char nocurs[2*4+2*2*16];
	static int fd = -1;

	if(mouseon == on)
		return;
	if(mouseon = on){
		if((fd = open("/dev/cursor", ORDWR|OCEXEC)) < 0){
			sysfatal("IN_Grabm:open: %r\n");
			return;
		}
		write(fd, nocurs, sizeof nocurs);
	}else if(fd >= 0){
		close(fd);
		fd = -1;
	}
}

void IN_Commands (void)
{
	int i;

	if(!mouseon)
		return;
	for(i = 0; i < 3; i++){
		if(mbtn & 1<<i && ~oldmbtn & 1<<i)
			Key_Event(K_MOUSE1+i, true, Sys_Milliseconds());
		if(~mbtn & 1<<i && oldmbtn & 1<<i)
			Key_Event(K_MOUSE1+i, false, Sys_Milliseconds());
	}
	oldmbtn = mbtn;
}

void KBD_Update (void)
{
	Kev ev;
	int r;

	if(oldmwin != m_windowed->value){
		oldmwin = m_windowed->value;
		if(!m_windowed->value)
			IN_Grabm(0);
		else
			IN_Grabm(1);
	}
	while((r = nbrecv(kchan, &ev)) > 0)
		Key_Event(ev.key, ev.down, Sys_Milliseconds());
	if(r < 0)
		sysfatal("KBD_Update:nbrecv: %r\n");
}

void IN_Move (usercmd_t *cmd)
{
	if(!mouseon)
		return;

	if(m_filter->value){
		mx = (mx + oldmx) * 0.5;
		my = (my + oldmy) * 0.5;
	}else{
		mx = dx;
		my = dy;
	}
	oldmx = dx;
	oldmy = dy;
	if(!mx && !my)
		return;
	mx *= sensitivity->value;
	my *= sensitivity->value;
	dx = dy = 0;

	/* 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();
}

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;
	default:
		if(r < 0x80)
			k = r;
	};
	return k;
}

void kproc (void *)
{
	int n, k, fd;
	char buf[128], kdown[128] = {0}, *s;
	Rune r;
	Kev ev;

	if((fd = open("/dev/kbd", OREAD)) < 0)
		sysfatal("open /dev/kbd: %r");

	while((n = read(fd, buf, sizeof buf)) > 0){
		buf[n-1] = 0;
		switch(*buf){
		case 'c':
		default:
			continue;
		case 'k':
			s = buf+1;
			while(*s){
				s += chartorune(&r, s);
				if(utfrune(kdown+1, r) == nil){
					if(k = runetokey(r)){
						ev.key = k;
						ev.down = true;
						if(nbsend(kchan, &ev) < 0)
							sysfatal("kproc:nbsend: %r\n");
					}
				}
			}
			break;
		case 'K':
			s = kdown+1;
			while(*s){
				s += chartorune(&r, s);
				if(utfrune(buf+1, r) == nil){
					if(k = runetokey(r)){
						ev.key = k;
						ev.down = false;
						if(nbsend(kchan, &ev) < 0)
							sysfatal("mproc:nbsend: %r\n");
					}
				}
			}
			break;
		}
		strcpy(kdown, buf);
	}
	close(fd);
	ktid = -1;
}

void mproc (void *)
{
	int b, n, nerr = 0, fd;
	char buf[1+5*12];
	int x, y;

	if((fd = open("/dev/mouse", ORDWR)) < 0)
		sysfatal("open /dev/mouse: %r");

	for(;;){
		if((n = read(fd, buf, sizeof buf)) != 1+4*12){
			fprint(2, "mproc:read: bad count %d not 49: %r\n", n);
			if(n < 0 || ++nerr > 10)
				break;
			continue;
		}
		nerr = 0;
		switch(*buf){
		case 'r':
			resized = 1;
			/* fall through */
		case 'm':
			if(!mouseon)
				break;

			x = atoi(buf+1+0*12) - center.x;
			y = atoi(buf+1+1*12) - center.y;
			b = atoi(buf+1+2*12);

			mbtn = b&1 | (b&2)<<1 | (b&4)>>1;
			dx += x;
			dy += y;
			if(m_windowed->value && (x != 0 || y != 0))
				fprint(fd, "m%d %d", center.x, center.y);
			break;
		}
	}
	close(fd);
	mtid = -1;
}

void IN_Shutdown (void)
{
	IN_Grabm(0);
	if(ktid != -1){
		threadkill(ktid);
		ktid = -1;
	}
	if(mtid != -1){
		threadkill(mtid);
		mtid = -1;
	}
	if(kchan != nil){
		chanfree(kchan);
		kchan = nil;
	}
	mouseon = false;
}

void sucks (void *, char *note)
{
	if(!strncmp(note, "sys:", 4))
		IN_Shutdown();
	noted(NDFLT);
}

void IN_Init (void)
{
	in_mouse = ri.Cvar_Get("in_mouse", "1", CVAR_ARCHIVE);
	in_joystick = ri.Cvar_Get("in_joystick", "0", CVAR_ARCHIVE);
	m_windowed = ri.Cvar_Get("m_windowed", "0", CVAR_ARCHIVE);
	m_filter = ri.Cvar_Get("m_filter", "0", 0);
	freelook = ri.Cvar_Get("freelook", "0", 0);
	lookstrafe = ri.Cvar_Get("lookstrafe", "0", 0);
	sensitivity = ri.Cvar_Get("sensitivity", "3", 0);
	m_pitch = ri.Cvar_Get("m_pitch", "0.022", 0);
	m_yaw = ri.Cvar_Get("m_yaw", "0.022", 0);
	m_forward = ri.Cvar_Get("m_forward", "1", 0);
	m_side = ri.Cvar_Get("m_side", "0.8", 0);

	ri.Cmd_AddCommand("+mlook", IN_MLookDown);
	ri.Cmd_AddCommand("-mlook", IN_MLookUp);
	ri.Cmd_AddCommand("force_centerview", IN_ForceCenterView);

	notify(sucks);
	kchan = chancreate(sizeof(Kev), Nbuf);
	if((ktid = proccreate(kproc, nil, 8192)) < 0)
		sysfatal("proccreate kproc: %r");
	if(m_windowed->value)
		IN_Grabm(1);
	if((mtid = proccreate(mproc, nil, 8192)) < 0)
		sysfatal("proccreate mproc: %r");
	mx = my = 0;
}