summaryrefslogtreecommitdiff
path: root/src/cmd/drawmouse/drawmouse.c
blob: c65030c4fff0dcd0209216d8f10a3369cc9ffcb2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <camellia.h>
#include <camellia/syscalls.h>
#include <err.h>
#include <shared/ring.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <draw.h>

#define MOUSE_SIZE 10

struct framebuf fb, lastbehind;
struct rect dirty;

static uint8_t r_buf[64];
static ring_t r = {(void*)r_buf, sizeof r_buf, 0, 0};
static struct {uint32_t x, y;} cursor, lastcur;


static void draw_mouse(void) {
	static bool drawn = false;
	if (drawn)
		fb_cpy(&fb, &lastbehind, lastcur.x, lastcur.y, 0, 0, MOUSE_SIZE, MOUSE_SIZE);
	drawn = true;
	dirty_mark(&dirty, lastcur.x, lastcur.y);
	dirty_mark(&dirty, lastcur.x + MOUSE_SIZE, lastcur.y + MOUSE_SIZE);
	fb_cpy(&lastbehind, &fb, 0, 0, cursor.x, cursor.y, MOUSE_SIZE, MOUSE_SIZE);
	for (int i = 0; i < MOUSE_SIZE; i++) {
		for (int j = 0; j < MOUSE_SIZE - i; j++) {
			uint32_t *px = fb_pixel(&fb, cursor.x + i, cursor.y + j);
			if (px) {
				*px ^= 0x808080;
				dirty_mark(&dirty, cursor.x + i, cursor.y + j);
			}
		}
	}
	lastcur = cursor;
}


struct packet {
	uint8_t left     : 1;
	uint8_t right    : 1;
	uint8_t middle   : 1;
	uint8_t _useless : 5;
	int8_t dx, dy;
} __attribute__((packed));

int main(void) {
	char buf[64];
	hid_t fd = camellia_open("/kdev/ps2/mouse", OPEN_READ);
	if (fd < 0) {
		err(1, "open");
		return 1;
	}

	if (fb_setup(&fb, "/kdev/video/") < 0) {
		err(1, "fb_setup");
		return 1;
	}
	fb_anon(&lastbehind, MOUSE_SIZE, MOUSE_SIZE);


	for (;;) {
		int len = _sys_read(fd, buf, sizeof buf, 0);
		if (len == 0) break;
		ring_put(&r, buf, len);
		while (ring_used(&r) >= 3) {
			struct packet p;
			ring_get(&r, &p, sizeof p);
			p.dy *= -1;
			// TODO check mouse click
			if (-p.dx > (int)cursor.x) p.dx = -cursor.x;
			if (-p.dy > (int)cursor.y) p.dy = -cursor.y;
			cursor.x += p.dx;
			cursor.y += p.dy;
			if (cursor.x >= fb.width)  cursor.x = fb.width - 1;
			if (cursor.y >= fb.height) cursor.y = fb.height - 1;
			draw_mouse();
			if (p.left && p.right) return 0;
		}
		dirty_flush(&dirty, &fb);
	}
	return 0;
}