diff options
author | Peter Mikkelsen <petermikkelsen10@gmail.com> | 2024-02-16 20:21:57 +0000 |
---|---|---|
committer | Peter Mikkelsen <petermikkelsen10@gmail.com> | 2024-02-16 20:21:57 +0000 |
commit | ab90a480eb5233abc4d7122739c24656dd42cc94 (patch) | |
tree | 0034aeb8d6e04268d637ed6cbce6fc01f26674f6 /event.c | |
parent | 58363833ce933924ef340eb53f0caa4d0d1f6ae5 (diff) |
Add missing file
Diffstat (limited to 'event.c')
-rw-r--r-- | event.c | 204 |
1 files changed, 204 insertions, 0 deletions
@@ -0,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 |