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
--
⑨