shithub: guifs

Download patch

ref: ab90a480eb5233abc4d7122739c24656dd42cc94
parent: 58363833ce933924ef340eb53f0caa4d0d1f6ae5
author: Peter Mikkelsen <petermikkelsen10@gmail.com>
date: Fri Feb 16 15:21:57 EST 2024

Add missing file

--- /dev/null
+++ b/event.c
@@ -1,0 +1,204 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <mouse.h>
+#include <keyboard.h>
+#include <thread.h>
+
+#include "guifs.h"
+
+GuiElement *
+elementat(Point p)
+{
+	GuiElement *g = nil;
+
+	rlock(&root->lock);
+	if(ptinrect(p, root->rect))
+		g = root;
+	runlock(&root->lock);
+
+	while(g){
+		GuiElement *next = nil;
+		rlock(&g->lock);
+		for(int n = 0; n < g->nchildren && next == nil; n++){
+			GuiElement *child = g->children[n];
+			rlock(&child->lock);
+			if(ptinrect(p, child->rect)) /* TODO: does not account for floating elements (not a thing yet) */
+				next = child;
+			runlock(&child->lock);
+		}
+		runlock(&g->lock);
+		if(next)
+			g = next;
+		else
+			break;
+	}
+	return g;
+}
+
+typedef struct SendEvent SendEvent;
+struct SendEvent {
+	Channel *chan;
+	char *event;
+};
+
+void
+sendeventthread(void *arg)
+{
+	SendEvent *s = arg;
+	send(s->chan, &s->event);
+}
+
+void
+sendevent(GuiElement *g, Event event)
+{
+	SendEvent *s = emalloc(sizeof(SendEvent));
+	s->chan = g->events;
+
+	Event *e = emalloc(sizeof(Event));
+	memcpy(e, &event, sizeof(Event));
+
+	switch(e->type){
+	case Xmousedown:
+		s->event = smprint("mousedown %C\n", e->r);
+		break;
+	case Xmouseup:
+		s->event = smprint("mouseup %C\n", e->r);
+		break;
+	case Xmouseclick:
+		s->event = smprint("mouseclick %C\n", e->r);
+		break;
+	case Xmousescroll:
+		s->event = smprint("mousescroll %s\n", e->direction == Up ? "up" : "down");
+		break;
+	case Xkeyboard:
+		s->event = smprint("key %C\n", e->r);
+		break;
+	default:
+		s->event = smprint("???\n");
+		break;
+	}
+
+	if(nbsend(s->chan, &s->event) == 0)
+		threadcreate(sendeventthread, s, 1024);
+}
+
+int
+mouseevent(Mouse m)
+{
+	GuiElement *g = elementat(mousexy);
+
+	static int lastbuttons = 0;
+	static GuiElement *lastL = nil;
+	static GuiElement *lastM = nil;
+	static GuiElement *lastR = nil;
+
+	int b = lastbuttons ^ m.buttons;
+	lastbuttons = m.buttons;
+	if(b&4 && m.buttons&4)
+		lastR = g;
+	if(b&2 && m.buttons&2)
+		lastM = g;
+	if(b&1 && m.buttons&1)
+		lastL = g;
+
+	if(!g)
+		return 0;
+
+	wlock(&g->lock);
+	if(!g->listening){
+		wunlock(&g->lock);
+		return 0;
+	}
+
+	b = g->buttons ^ m.buttons;
+	g->buttons = m.buttons;
+
+	Event e;
+	if(b&16 && m.buttons&16){
+		e.type = Xmousescroll;
+		e.direction = Down;
+		sendevent(g, e);
+	}
+
+	if(b&8 && m.buttons&8){
+		e.type = Xmousescroll;
+		e.direction = Up;
+		sendevent(g, e);
+	}
+
+	if(b&4){
+		e.type = (m.buttons&4) ? Xmousedown : Xmouseup;
+		e.r = 'R';
+		sendevent(g, e);
+		if(e.type == Xmouseup){
+			if(lastR == g){
+				e.type = Xmouseclick;
+				sendevent(g, e);
+			}
+			lastR = nil;
+		}
+	}
+
+	if(b&2){
+		e.type = (m.buttons&2) ? Xmousedown : Xmouseup;
+		e.r = 'M';
+		sendevent(g, e);
+		if(e.type == Xmouseup){
+			if(lastM == g){
+				e.type = Xmouseclick;
+				sendevent(g, e);
+			}
+			lastM = nil;
+		}
+	}
+
+	if(b&1){
+		e.type = (m.buttons&1) ? Xmousedown : Xmouseup;
+		e.r = 'L';
+		sendevent(g, e);
+		if(e.type == Xmouseup){
+			if(lastL == g){
+				e.type = Xmouseclick;
+				sendevent(g, e);
+			}
+			lastL = nil;
+		}
+	}
+
+	wunlock(&g->lock);
+	return 0;
+}
+
+int
+keyboardevent(Rune r)
+{
+	if(r == Kdel){ /* The user hit DEL */
+		postnote(PNGROUP, getpid(), "interrupt");
+		exits("interrupt");
+	}
+
+	GuiElement *g = elementat(mousexy);
+	if(!g)
+		return 0;
+
+	wlock(&g->lock);
+	if(g->listening){
+		Event e;
+		e.type = Xkeyboard;
+		e.r = r;
+		sendevent(g, e);
+	}
+
+	if(g->type == Gtextbox){
+		PropVal val = getprop(g, Ptext, 0);
+		long len = runestrlen(val.text);
+		Rune *text = emalloc(sizeof(Rune) * (len + 2));
+		memcpy(text, val.text, sizeof(Rune) * len);
+		text[len] = r;
+		val.text = text;
+		setprop(g, Ptext, val, 0);
+	}
+	wunlock(&g->lock);
+	return 1;
+}
\ No newline at end of file