/* * XEVENT.C - Handle X events for our display * * Obtains the next X event, blocking if necessary, and allocates and returns * a Frame.Event structure. */ #include "defs.h" static XEvent xsave; void RUNESYSCALL(xEvent)(void *args __unused, ReferenceStor *res) { XEvent xevent; Event *event; int state = 0; for (;;) { int aggMode = 1; /* * Wait for the next event. If no events remain and we have a saved * event pending, use the saved event. Otherwise block and loop. */ if (XCheckMaskEvent(SaveDisplay, -1, &xevent) == False) { if (xsave.type) { xevent = xsave; xsave.type = 0; aggMode = 0; break; } threadWaitEvent(((_XPrivDisplay) SaveDisplay)->fd, THWAIT_READ); continue; } /* * Aggregate exposure events. This results in very efficient display * updates. */ if (xevent.type == Expose && aggMode) { if (xsave.type == 0) { xsave = xevent; continue; } if (xsave.xany.window != xevent.xany.window) break; if (xsave.xexpose.x > xevent.xexpose.x) { xsave.xexpose.width += xsave.xexpose.x - xevent.xexpose.x; xsave.xexpose.x = xevent.xexpose.x; } if (xsave.xexpose.x + xsave.xexpose.width < xevent.xexpose.x + xevent.xexpose.width ) { xsave.xexpose.width = xevent.xexpose.x + xevent.xexpose.width - xsave.xexpose.x; } if (xsave.xexpose.y > xevent.xexpose.y) { xsave.xexpose.height += xsave.xexpose.y - xevent.xexpose.y; xsave.xexpose.y = xevent.xexpose.y; } if (xsave.xexpose.y + xsave.xexpose.height < xevent.xexpose.y + xevent.xexpose.height ) { xsave.xexpose.height = xevent.xexpose.y + xevent.xexpose.height - xsave.xexpose.y; } continue; } break; } /* * Process and return the xevent. Note that xsave may still be valid and * we will hold it until the next request. * * XXX result space is not initialized. * * XXX returns LOCK+REFD xevent. return storage not initialized on call * so don't RSPut() (yet). */ /* RuneRunTime_RSPut(res->s_RefStor); */ event = heapAlloc(res, &EventType); /* automatic RSGet by heapAlloc() */ event->ev_Type = xevent.type; event->ev_XId = xevent.xany.window; event->ev_FocusType = 0; event->ev_Width = -1; event->ev_Height = -1; switch (xevent.type) { case KeyPress: case KeyRelease: { int modState = 0; KeySym key; event->ev_FocusType = 2; event->ev_MPos.x = xevent.xkey.x; event->ev_MPos.y = xevent.xkey.y; state = xevent.xkey.state; XLookupString(&xevent.xkey, &event->ev_KeyChar, 1, &key, NULL); switch (key) { case XK_Shift_L: case XK_Shift_R: modState = ShiftMask; break; case XK_Control_L: case XK_Control_R: modState = ControlMask; break; case XK_Caps_Lock: modState = LockMask; break; case XK_Shift_Lock: /* XXX */ break; case XK_Meta_L: case XK_Meta_R: /* XXX */ break; case XK_Alt_L: case XK_Alt_R: modState = Mod1Mask; break; case XK_Num_Lock: modState = Mod2Mask; break; case XK_Scroll_Lock: modState = Mod5Mask; break; case XK_Super_L: case XK_Super_R: case XK_Hyper_L: case XK_Hyper_R: /* XXX */ break; } if (xevent.type == KeyRelease) { event->ev_KeySym = -key; state &= ~modState; } else { event->ev_KeySym = key; state |= modState; } } break; case ButtonPress: event->ev_FocusType = 1; event->ev_MPos.x = xevent.xbutton.x; event->ev_MPos.y = xevent.xbutton.y; event->ev_KeySym = xevent.xbutton.button - Button1 + XK_Pointer_Button1; state = xevent.xbutton.state | (Button1Mask << (xevent.xbutton.button - Button1)); break; case ButtonRelease: event->ev_FocusType = 1; event->ev_MPos.x = xevent.xbutton.x; event->ev_MPos.y = xevent.xbutton.y; event->ev_KeySym = -(xevent.xkey.keycode - Button1 + XK_Pointer_Button1); state = xevent.xkey.state & ~(Button1Mask << (xevent.xbutton.button - Button1)); break; case MotionNotify: event->ev_FocusType = 1; event->ev_MPos.x = xevent.xmotion.x; event->ev_MPos.y = xevent.xmotion.y; state = xevent.xmotion.state; break; case EnterNotify: case LeaveNotify: event->ev_FocusType = 1; event->ev_MPos.x = xevent.xcrossing.x; event->ev_MPos.y = xevent.xcrossing.y; state = xevent.xcrossing.state; break; case FocusIn: case FocusOut: case KeymapNotify: break; case Expose: event->ev_MPos.x = xevent.xexpose.x; event->ev_MPos.y = xevent.xexpose.y; event->ev_Width = xevent.xexpose.width; event->ev_Height = xevent.xexpose.height; event->ev_FocusType = 3; break; case MapNotify: case VisibilityNotify: event->ev_FocusType = 3; break; case GraphicsExpose: break; case NoExpose: event->ev_FocusType = 3; break; case CreateNotify: case DestroyNotify: case UnmapNotify: case MapRequest: case ReparentNotify: break; case ConfigureNotify: event->ev_MPos.x = xevent.xconfigure.x; event->ev_MPos.y = xevent.xconfigure.y; event->ev_Width = xevent.xconfigure.width; event->ev_Height = xevent.xconfigure.height; event->ev_FocusType = 4; break; case ConfigureRequest: case GravityNotify: case ResizeRequest: case CirculateNotify: case CirculateRequest: case PropertyNotify: case SelectionClear: case SelectionRequest: case SelectionNotify: case ColormapNotify: case ClientMessage: case MappingNotify: break; } event->ev_MetaMask = state; }