mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-15 11:20:03 +00:00
187 lines
3.1 KiB
C
187 lines
3.1 KiB
C
#include <u.h>
|
|
#include "x11-inc.h"
|
|
#include <libc.h>
|
|
#include <draw.h>
|
|
#include <cursor.h>
|
|
#include <event.h>
|
|
#include <memdraw.h>
|
|
#include "x11-memdraw.h"
|
|
|
|
/*
|
|
* Should change this to support etimer and estartfn again.
|
|
* The main eread() would prepare a select mask from the keys
|
|
* and then call select() to wait for input. Then it would read an
|
|
* event from the readied fd and return it. Use XCheckWindowEvent
|
|
* to poll the X connection.
|
|
*/
|
|
|
|
ulong
|
|
event(Event *e)
|
|
{
|
|
return eread(~0UL, e);
|
|
}
|
|
|
|
static void
|
|
eflush(void)
|
|
{
|
|
/* avoid generating a message if there's nothing to show. */
|
|
/* this test isn't perfect, though; could do flushimage(display, 0) then call extract */
|
|
/* also: make sure we don't interfere if we're multiprocessing the display */
|
|
if(display->locking){
|
|
/* if locking is being done by program, this means it can't depend on automatic flush in emouse() etc. */
|
|
if(canqlock(&display->qlock)){
|
|
if(display->bufp > display->buf)
|
|
flushimage(display, 1);
|
|
unlockdisplay(display);
|
|
}
|
|
}else
|
|
if(display->bufp > display->buf)
|
|
flushimage(display, 1);
|
|
}
|
|
|
|
ulong
|
|
eread(ulong keys, Event *e)
|
|
{
|
|
int r;
|
|
ulong xmask;
|
|
XEvent xevent;
|
|
|
|
xmask = ExposureMask;
|
|
|
|
eflush();
|
|
|
|
if(keys&Emouse)
|
|
xmask |= MouseMask|StructureNotifyMask;
|
|
if(keys&Ekeyboard){
|
|
xmask |= KeyPressMask;
|
|
if((r = _xtoplan9kbd(nil)) >= 0){
|
|
e->kbdc = r;
|
|
return Ekeyboard;
|
|
}
|
|
}
|
|
|
|
xmask |= EnterWindowMask|LeaveWindowMask;
|
|
|
|
XSelectInput(_x.display, _x.drawable, xmask);
|
|
again:
|
|
XWindowEvent(_x.display, _x.drawable, xmask, &xevent);
|
|
|
|
switch(xevent.type){
|
|
case Expose:
|
|
_xexpose(&xevent, _x.display);
|
|
goto again;
|
|
case DestroyNotify:
|
|
if(_xdestroy(&xevent, _x.display))
|
|
postnote(PNGROUP, getpgrp(), "hangup");
|
|
goto again;
|
|
case ConfigureNotify:
|
|
if(_xconfigure(&xevent, _x.display))
|
|
eresized(1);
|
|
goto again;
|
|
case ButtonPress:
|
|
case ButtonRelease:
|
|
case MotionNotify:
|
|
if(_xtoplan9mouse(_x.display, &xevent, &e->mouse) < 0)
|
|
goto again;
|
|
return Emouse;
|
|
case KeyPress:
|
|
e->kbdc = _xtoplan9kbd(&xevent);
|
|
if(e->kbdc == -1)
|
|
goto again;
|
|
return Ekeyboard;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void
|
|
einit(ulong keys)
|
|
{
|
|
keys &= ~(Emouse|Ekeyboard);
|
|
if(keys){
|
|
fprint(2, "unknown keys in einit\n");
|
|
abort();
|
|
}
|
|
}
|
|
|
|
int
|
|
ekbd(void)
|
|
{
|
|
Event e;
|
|
|
|
eread(Ekeyboard, &e);
|
|
return e.kbdc;
|
|
}
|
|
|
|
Mouse
|
|
emouse(void)
|
|
{
|
|
Event e;
|
|
|
|
eread(Emouse, &e);
|
|
return e.mouse;
|
|
}
|
|
|
|
int
|
|
ecanread(ulong keys)
|
|
{
|
|
int can;
|
|
|
|
can = 0;
|
|
if(keys&Emouse)
|
|
can |= ecanmouse();
|
|
if(keys&Ekeyboard)
|
|
can |= ecankbd();
|
|
return can;
|
|
}
|
|
|
|
int
|
|
ecanmouse(void)
|
|
{
|
|
XEvent xe;
|
|
Mouse m;
|
|
|
|
eflush();
|
|
again:
|
|
if(XCheckWindowEvent(_x.display, _x.drawable, MouseMask, &xe)){
|
|
if(_xtoplan9mouse(_x.display, &xe, &m) < 0)
|
|
goto again;
|
|
XPutBackEvent(_x.display, &xe);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
ecankbd(void)
|
|
{
|
|
XEvent xe;
|
|
int r;
|
|
|
|
eflush();
|
|
if((r = _xtoplan9kbd(nil)) >= 0){
|
|
_xtoplan9kbd((XEvent*)-1);
|
|
return 1;
|
|
}
|
|
again:
|
|
if(XCheckWindowEvent(_x.display, _x.drawable, KeyPressMask, &xe)){
|
|
if(_xtoplan9kbd(&xe) == -1)
|
|
goto again;
|
|
XPutBackEvent(_x.display, &xe);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
emoveto(Point p)
|
|
{
|
|
_xmoveto(p);
|
|
}
|
|
|
|
void
|
|
esetcursor(Cursor *c)
|
|
{
|
|
_xsetcursor(c);
|
|
}
|
|
|