Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/planix-v0/sys/src/cmd/vnc/devmouse.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include	<u.h>
2
#include	<libc.h>
3
#include	"compat.h"
4
#include	"error.h"
5
 
6
#define	Image	IMAGE
7
#include	<draw.h>
8
#include	<memdraw.h>
9
#include	<cursor.h>
10
#include	"screen.h"
11
 
12
typedef struct Mouseinfo	Mouseinfo;
13
typedef struct Mousestate	Mousestate;
14
 
15
struct Mousestate
16
{
17
	Point	xy;			/* mouse.xy */
18
	int	buttons;		/* mouse.buttons */
19
	ulong	counter;	/* increments every update */
20
	ulong	msec;	/* time of last event */
21
};
22
 
23
struct Mouseinfo
24
{
25
	Mousestate;
26
	int	dx;
27
	int	dy;
28
	int	track;		/* dx & dy updated */
29
	int	redraw;		/* update cursor on screen */
30
	ulong	lastcounter;	/* value when /dev/mouse read */
31
	Rendez	r;
32
	Ref;
33
	QLock;
34
	int	open;
35
	int	acceleration;
36
	int	maxacc;
37
	Mousestate 	queue[16];	/* circular buffer of click events */
38
	int	ri;	/* read index into queue */
39
	int	wi;	/* write index into queue */
40
	uchar	qfull;	/* queue is full */
41
};
42
 
43
Mouseinfo	mouse;
44
Cursorinfo	cursor;
45
int		mouseshifted;
46
Cursor		curs;
47
 
48
void	Cursortocursor(Cursor*);
49
int	mousechanged(void*);
50
static void mouseclock(void);
51
 
52
enum{
53
	Qdir,
54
	Qcursor,
55
	Qmouse,
56
};
57
 
58
static Dirtab mousedir[]={
59
	".",	{Qdir, 0, QTDIR},	0,			DMDIR|0555,
60
	"cursor",	{Qcursor},	0,			0666,
61
	"mouse",	{Qmouse},	0,			0666,
62
};
63
 
64
static uchar buttonmap[8] = {
65
	0, 1, 2, 3, 4, 5, 6, 7,
66
};
67
static int mouseswap;
68
 
69
extern	Memimage*	gscreen;
70
extern	void mousewarpnote(Point);
71
 
72
static void
73
mousereset(void)
74
{
75
	curs = arrow;
76
	Cursortocursor(&arrow);
77
}
78
 
79
static void
80
mouseinit(void)
81
{
82
	cursoron(1);
83
}
84
 
85
static Chan*
86
mouseattach(char *spec)
87
{
88
	return devattach('m', spec);
89
}
90
 
91
static Walkqid*
92
mousewalk(Chan *c, Chan *nc, char **name, int nname)
93
{
94
	Walkqid *wq;
95
 
96
	wq = devwalk(c, nc, name, nname, mousedir, nelem(mousedir), devgen);
97
	if(wq != nil && wq->clone != c && (wq->clone->qid.type&QTDIR)==0)
98
		incref(&mouse);
99
	return wq;
100
}
101
 
102
static int
103
mousestat(Chan *c, uchar *db, int n)
104
{
105
	return devstat(c, db, n, mousedir, nelem(mousedir), devgen);
106
}
107
 
108
static Chan*
109
mouseopen(Chan *c, int omode)
110
{
111
	switch((ulong)c->qid.path){
112
	case Qdir:
113
		if(omode != OREAD)
114
			error(Eperm);
115
		break;
116
	case Qmouse:
117
		lock(&mouse);
118
		if(mouse.open){
119
			unlock(&mouse);
120
			error(Einuse);
121
		}
122
		mouse.open = 1;
123
		mouse.ref++;
124
		unlock(&mouse);
125
		break;
126
	default:
127
		incref(&mouse);
128
	}
129
	c->mode = openmode(omode);
130
	c->flag |= COPEN;
131
	c->offset = 0;
132
	return c;
133
}
134
 
135
static void
136
mousecreate(Chan*, char*, int, ulong)
137
{
138
	error(Eperm);
139
}
140
 
141
static void
142
mouseclose(Chan *c)
143
{
144
	if((c->qid.type&QTDIR)==0 && (c->flag&COPEN)){
145
		lock(&mouse);
146
		if(c->qid.path == Qmouse)
147
			mouse.open = 0;
148
		if(--mouse.ref == 0){
149
			cursoroff(1);
150
			curs = arrow;
151
			Cursortocursor(&arrow);
152
			cursoron(1);
153
		}
154
		unlock(&mouse);
155
	}
156
}
157
 
158
 
159
static long
160
mouseread(Chan *c, void *va, long n, vlong off)
161
{
162
	char buf[4*12+1];
163
	uchar *p;
164
	static int map[8] = {0, 4, 2, 6, 1, 5, 3, 7 };
165
	ulong offset = off;
166
	Mousestate m;
167
	int b;
168
 
169
	p = va;
170
	switch((ulong)c->qid.path){
171
	case Qdir:
172
		return devdirread(c, va, n, mousedir, nelem(mousedir), devgen);
173
 
174
	case Qcursor:
175
		if(offset != 0)
176
			return 0;
177
		if(n < 2*4+2*2*16)
178
			error(Eshort);
179
		n = 2*4+2*2*16;
180
		lock(&cursor);
181
		BPLONG(p+0, curs.offset.x);
182
		BPLONG(p+4, curs.offset.y);
183
		memmove(p+8, curs.clr, 2*16);
184
		memmove(p+40, curs.set, 2*16);
185
		unlock(&cursor);
186
		return n;
187
 
188
	case Qmouse:
189
		while(mousechanged(0) == 0)
190
			rendsleep(&mouse.r, mousechanged, 0);
191
 
192
		mouse.qfull = 0;
193
 
194
		/*
195
		 * No lock of the indicies is necessary here, because ri is only
196
		 * updated by us, and there is only one mouse reader
197
		 * at a time.  I suppose that more than one process
198
		 * could try to read the fd at one time, but such behavior
199
		 * is degenerate and already violates the calling
200
		 * conventions for sleep above.
201
		 */
202
		if(mouse.ri != mouse.wi){
203
			m = mouse.queue[mouse.ri];
204
			if(++mouse.ri == nelem(mouse.queue))
205
				mouse.ri = 0;
206
		} else {
207
			lock(&cursor);
208
 
209
			m = mouse.Mousestate;
210
			unlock(&cursor);
211
		}
212
 
213
		b = buttonmap[m.buttons&7];
214
		/* put buttons 4 and 5 back in */
215
		b |= m.buttons & (3<<3);
216
		sprint(buf, "m%11d %11d %11d %11lud",
217
			m.xy.x, m.xy.y,
218
			b,
219
			m.msec);
220
		mouse.lastcounter = m.counter;
221
		if(n > 1+4*12)
222
			n = 1+4*12;
223
		memmove(va, buf, n);
224
		return n;
225
	}
226
	return 0;
227
}
228
 
229
static void
230
setbuttonmap(char* map)
231
{
232
	int i, x, one, two, three;
233
 
234
	one = two = three = 0;
235
	for(i = 0; i < 3; i++){
236
		if(map[i] == 0)
237
			error(Ebadarg);
238
		if(map[i] == '1'){
239
			if(one)
240
				error(Ebadarg);
241
			one = 1<<i;
242
		}
243
		else if(map[i] == '2'){
244
			if(two)
245
				error(Ebadarg);
246
			two = 1<<i;
247
		}
248
		else if(map[i] == '3'){
249
			if(three)
250
				error(Ebadarg);
251
			three = 1<<i;
252
		}
253
		else
254
			error(Ebadarg);
255
	}
256
	if(map[i])
257
		error(Ebadarg);
258
 
259
	memset(buttonmap, 0, 8);
260
	for(i = 0; i < 8; i++){
261
		x = 0;
262
		if(i & 1)
263
			x |= one;
264
		if(i & 2)
265
			x |= two;
266
		if(i & 4)
267
			x |= three;
268
		buttonmap[x] = i;
269
	}
270
}
271
 
272
static long
273
mousewrite(Chan *c, void *va, long n, vlong)
274
{
275
	char *p;
276
	Point pt;
277
	char buf[64];
278
 
279
	p = va;
280
	switch((ulong)c->qid.path){
281
	case Qdir:
282
		error(Eisdir);
283
 
284
	case Qcursor:
285
		cursoroff(1);
286
		if(n < 2*4+2*2*16){
287
			curs = arrow;
288
			Cursortocursor(&arrow);
289
		}else{
290
			n = 2*4+2*2*16;
291
			curs.offset.x = BGLONG(p+0);
292
			curs.offset.y = BGLONG(p+4);
293
			memmove(curs.clr, p+8, 2*16);
294
			memmove(curs.set, p+40, 2*16);
295
			Cursortocursor(&curs);
296
		}
297
		qlock(&mouse);
298
		mouse.redraw = 1;
299
		mouseclock();
300
		qunlock(&mouse);
301
		cursoron(1);
302
		return n;
303
 
304
	case Qmouse:
305
		if(n > sizeof buf-1)
306
			n = sizeof buf -1;
307
		memmove(buf, va, n);
308
		buf[n] = 0;
309
		p = 0;
310
		pt.x = strtoul(buf+1, &p, 0);
311
		if(p == 0)
312
			error(Eshort);
313
		pt.y = strtoul(p, 0, 0);
314
		qlock(&mouse);
315
		if(ptinrect(pt, gscreen->r)){
316
			mousetrack(pt.x, pt.y, mouse.buttons, nsec()/(1000*1000LL));
317
			mousewarpnote(pt);
318
		}
319
		qunlock(&mouse);
320
		return n;
321
	}
322
 
323
	error(Egreg);
324
	return -1;
325
}
326
 
327
Dev mousedevtab = {
328
	'm',
329
	"mouse",
330
 
331
	mousereset,
332
	mouseinit,
333
	mouseattach,
334
	mousewalk,
335
	mousestat,
336
	mouseopen,
337
	mousecreate,
338
	mouseclose,
339
	mouseread,
340
	devbread,
341
	mousewrite,
342
	devbwrite,
343
	devremove,
344
	devwstat,
345
};
346
 
347
void
348
Cursortocursor(Cursor *c)
349
{
350
	lock(&cursor);
351
	memmove(&cursor.Cursor, c, sizeof(Cursor));
352
	setcursor(c);
353
	unlock(&cursor);
354
}
355
 
356
static int
357
scale(int x)
358
{
359
	int sign = 1;
360
 
361
	if(x < 0){
362
		sign = -1;
363
		x = -x;
364
	}
365
	switch(x){
366
	case 0:
367
	case 1:
368
	case 2:
369
	case 3:
370
		break;
371
	case 4:
372
		x = 6 + (mouse.acceleration>>2);
373
		break;
374
	case 5:
375
		x = 9 + (mouse.acceleration>>1);
376
		break;
377
	default:
378
		x *= mouse.maxacc;
379
		break;
380
	}
381
	return sign*x;
382
}
383
 
384
static void
385
mouseclock(void)
386
{
387
	lock(&cursor);
388
	if(mouse.redraw){
389
		mouse.redraw = 0;
390
		cursoroff(0);
391
		mouse.redraw = cursoron(0);
392
	}
393
	unlock(&cursor);
394
}
395
 
396
/*
397
 *  called at interrupt level to update the structure and
398
 *  awaken any waiting procs.
399
 */
400
void
401
mousetrack(int x, int y, int b, int msec)
402
{
403
	int lastb;
404
 
405
	lastb = mouse.buttons;
406
	mouse.xy = Pt(x, y);
407
	mouse.buttons = b;
408
	mouse.redraw = 1;
409
	mouse.counter++;
410
	mouse.msec = msec;
411
 
412
	/*
413
	 * if the queue fills, we discard the entire queue and don't
414
	 * queue any more events until a reader polls the mouse.
415
	 */
416
	if(!mouse.qfull && lastb != b){	/* add to ring */
417
		mouse.queue[mouse.wi] = mouse.Mousestate;
418
		if(++mouse.wi == nelem(mouse.queue))
419
			mouse.wi = 0;
420
		if(mouse.wi == mouse.ri)
421
			mouse.qfull = 1;
422
	}
423
	rendwakeup(&mouse.r);
424
	mouseclock();
425
}
426
 
427
int
428
mousechanged(void*)
429
{
430
	return mouse.lastcounter != mouse.counter;
431
}
432
 
433
Point
434
mousexy(void)
435
{
436
	return mouse.xy;
437
}
438
 
439
void
440
mouseaccelerate(int x)
441
{
442
	mouse.acceleration = x;
443
	if(mouse.acceleration < 3)
444
		mouse.maxacc = 2;
445
	else
446
		mouse.maxacc = mouse.acceleration;
447
}