void kputc(int c) { zlock(); kbd.r[kbd.wi++] = c; if(kbd.wi == nelem(kbd.r)) kbd.wi = 0; if(kbd.ri == kbd.wi) kbd.stall = 1; matchkbd(); zunlock(); }
/* * Handle an incoming X event. */ void runxevent(XEvent *xev) { int c; KeySym k; static Mouse m; XButtonEvent *be; XKeyEvent *ke; #ifdef SHOWEVENT static int first = 1; if(first){ dup(create("/tmp/devdraw.out", OWRITE, 0666), 1); setbuf(stdout, 0); first = 0; } #endif if(xev == 0) return; #ifdef SHOWEVENT print("\n"); ShowEvent(xev); #endif switch(xev->type){ case Expose: _xexpose(xev); break; case DestroyNotify: if(_xdestroy(xev)) exits(0); break; case ConfigureNotify: if(_xconfigure(xev)){ mouse.resized = 1; _xreplacescreenimage(); sendmouse(m); } break; case ButtonPress: be = (XButtonEvent*)xev; if(be->button == 1) { if(kstate & ControlMask) be->button = 2; else if(kstate & Mod1Mask) be->button = 3; } // fall through case ButtonRelease: altdown = 0; // fall through case MotionNotify: if(mouse.stall) return; if(_xtoplan9mouse(xev, &m) < 0) return; sendmouse(m); break; case KeyRelease: case KeyPress: ke = (XKeyEvent*)xev; XLookupString(ke, NULL, 0, &k, NULL); c = ke->state; switch(k) { case XK_Alt_L: case XK_Meta_L: /* Shift Alt on PCs */ case XK_Alt_R: case XK_Meta_R: /* Shift Alt on PCs */ case XK_Multi_key: if(xev->type == KeyPress) altdown = 1; else if(altdown) { altdown = 0; sendalt(); } break; } switch(k) { case XK_Control_L: if(xev->type == KeyPress) c |= ControlMask; else c &= ~ControlMask; goto kbutton; case XK_Alt_L: case XK_Shift_L: if(xev->type == KeyPress) c |= Mod1Mask; else c &= ~Mod1Mask; kbutton: kstate = c; if(m.buttons || kbuttons) { altdown = 0; // used alt kbuttons = 0; if(c & ControlMask) kbuttons |= 2; if(c & Mod1Mask) kbuttons |= 4; sendmouse(m); break; } } if(xev->type != KeyPress) break; if(k == XK_F11){ fullscreen = !fullscreen; _xmovewindow(fullscreen ? screenrect : windowrect); return; } if(kbd.stall) return; if((c = _xtoplan9kbd(xev)) < 0) return; kbd.r[kbd.wi++] = c; if(kbd.wi == nelem(kbd.r)) kbd.wi = 0; if(kbd.ri == kbd.wi) kbd.stall = 1; matchkbd(); break; case FocusOut: abortcompose(); break; case SelectionRequest: _xselect(xev); break; } }
/* * Handle a single wsysmsg. * Might queue for later (kbd, mouse read) */ void runmsg(Wsysmsg *m) { uchar buf[65536]; int n; Memimage *i; switch(m->type){ case Tinit: memimageinit(); i = _xattach(m->label, m->winsize); _initdisplaymemimage(i); replymsg(m); break; case Trdmouse: mousetags.t[mousetags.wi++] = m->tag; if(mousetags.wi == nelem(mousetags.t)) mousetags.wi = 0; if(mousetags.wi == mousetags.ri) sysfatal("too many queued mouse reads"); /* fprint(2, "mouse unstall\n"); */ mouse.stall = 0; matchmouse(); break; case Trdkbd: kbdtags.t[kbdtags.wi++] = m->tag; if(kbdtags.wi == nelem(kbdtags.t)) kbdtags.wi = 0; if(kbdtags.wi == kbdtags.ri) sysfatal("too many queued keyboard reads"); kbd.stall = 0; matchkbd(); break; case Tmoveto: _xmoveto(m->mouse.xy); replymsg(m); break; case Tcursor: if(m->arrowcursor) _xsetcursor(nil); else _xsetcursor(&m->cursor); replymsg(m); break; case Tbouncemouse: _xbouncemouse(&m->mouse); replymsg(m); break; case Tlabel: _xsetlabel(m->label); replymsg(m); break; case Trdsnarf: m->snarf = _xgetsnarf(); replymsg(m); free(m->snarf); break; case Twrsnarf: _xputsnarf(m->snarf); replymsg(m); break; case Trddraw: n = m->count; if(n > sizeof buf) n = sizeof buf; n = _drawmsgread(buf, n); if(n < 0) replyerror(m); else{ m->count = n; m->data = buf; replymsg(m); } break; case Twrdraw: if(_drawmsgwrite(m->data, m->count) < 0) replyerror(m); else replymsg(m); break; case Ttop: _xtopwindow(); replymsg(m); break; case Tresize: _xresizewindow(m->rect); replymsg(m); break; } }