static void x11_processevent(struct X11Display *mod) { TAPTR TExecBase = TGetExecBase(mod); struct TNode *next, *node; XEvent ev; struct X11Window *v; Window w; while ((XPending(mod->x11_Display)) > 0) { XNextEvent(mod->x11_Display, &ev); if (ev.type == mod->x11_ShmEvent) { if (mod->x11_RequestInProgress) { TReplyMsg(mod->x11_RequestInProgress); mod->x11_RequestInProgress = TNULL; TDBPRINTF(TDB_TRACE, ("Released request (ShmEvent)\n")); } else TDBPRINTF(TDB_ERROR, ("shm event while no request pending\n")); continue; } /* lookup window: */ w = ev.xany.window; v = TNULL; node = mod->x11_vlist.tlh_Head.tln_Succ; for (; (next = node->tln_Succ); node = next) { v = (struct X11Window *) node; if (v->window == w) break; v = TNULL; } if (v == TNULL) { TDBPRINTF(TDB_INFO, ("Message Type %04x from unknown window: %p\n", ev.type, w)); continue; } /* while true, spool out messages for this particular event: */ while (x11_processvisualevent(mod, v, TNULL, &ev)) ; } }
static void fb_runinstance(TAPTR task) { struct TExecBase *TExecBase = TGetExecBase(task); WINDISPLAY *mod = TGetTaskData(task); struct TVRequest *req; TUINT sig; /* interval time: 1/50s: */ TTIME intt = { 20000 }; /* next absolute time to send interval message: */ TTIME nextt; TTIME waitt, nowt; TGetSystemTime(&nextt); TAddTime(&nextt, &intt); TDBPRINTF(TDB_INFO,("Device instance running\n")); do { TBOOL do_interval = TFALSE; while ((req = TGetMsg(mod->fbd_CmdPort))) { fb_docmd(mod, req); TReplyMsg(req); } fb_notifywindows(mod); /* calculate new delta to wait: */ TGetSystemTime(&nowt); waitt = nextt; TSubTime(&waitt, &nowt); TWaitTime(&waitt, mod->fbd_CmdPortSignal); /* check if time interval has expired: */ TGetSystemTime(&nowt); if (TCmpTime(&nowt, &nextt) > 0) { /* expired; send interval: */ do_interval = TTRUE; TAddTime(&nextt, &intt); if (TCmpTime(&nowt, &nextt) >= 0) { /* nexttime expired already; create new time from now: */ nextt = nowt; TAddTime(&nextt, &intt); } } /* send out input messages: */ fb_sendimessages(mod, do_interval); /* get signal state: */ sig = TSetSignal(0, TTASK_SIG_ABORT); } while (!(sig & TTASK_SIG_ABORT)); TDBPRINTF(TDB_INFO,("Device instance closedown\n")); fb_exitinstance(mod); }
static void rfb_processevent(RFBDISPLAY *mod) { TAPTR TExecBase = TGetExecBase(mod); TIMSG *msg; if (mod->rfb_RndIMsgPort == TNULL) return; while ((msg = TGetMsg(mod->rfb_RndIMsgPort))) { /*RFBWINDOW *v = (RFBWINDOW *) msg->timsg_Instance;*/ TIMSG *imsg; switch (msg->timsg_Type) { case TITYPE_INTERVAL: TDBPRINTF(TDB_WARN,("unhandled event: INTERVAL\n")); break; case TITYPE_REFRESH: { TINT drect[4]; drect[0] = msg->timsg_X; drect[1] = msg->timsg_Y; drect[2] = msg->timsg_X + msg->timsg_Width - 1; drect[3] = msg->timsg_Y + msg->timsg_Height - 1; rfb_damage(mod, drect, TNULL); break; } case TITYPE_NEWSIZE: TDBPRINTF(TDB_WARN,("unhandled event: NEWSIZE\n")); break; case TITYPE_CLOSE: { /* send to root window */ TLock(mod->rfb_InstanceLock); RFBWINDOW *v = (RFBWINDOW *) TLASTNODE(&mod->rfb_VisualList); if (rfb_getimsg(mod, v, &imsg, TITYPE_CLOSE)) TPutMsg(v->rfbw_IMsgPort, TNULL, imsg); TUnlock(mod->rfb_InstanceLock); break; } case TITYPE_FOCUS: TDBPRINTF(TDB_INFO,("unhandled event: FOCUS\n")); break; case TITYPE_MOUSEOVER: TDBPRINTF(TDB_INFO,("unhandled event: MOUSEOVER\n")); break; case TITYPE_KEYUP: case TITYPE_KEYDOWN: /* pass keyboard events to focused window, else to the * hovered window (also setting the focus): */ if (!rfb_passevent_to_focus(mod, msg)) rfb_passevent_by_mousexy(mod, msg, TTRUE); break; case TITYPE_MOUSEMOVE: /* pass mouse movements to focused and hovered window: */ if (rfb_passevent_by_mousexy(mod, msg, TFALSE) != mod->rfb_FocusWindow) rfb_passevent_to_focus(mod, msg); break; case TITYPE_MOUSEBUTTON: { /* set focus on mousebutton down */ TBOOL focus = msg->timsg_Code & (TMBCODE_LEFTDOWN | TMBCODE_RIGHTDOWN | TMBCODE_MIDDLEDOWN); rfb_passevent_by_mousexy(mod, msg, focus); break; } } TReplyMsg(msg); } }
static void rfb_runtask(struct TTask *task) { TAPTR TExecBase = TGetExecBase(task); RFBDISPLAY *mod = TGetTaskData(task); struct TVRequest *req; TUINT sig; TTIME intt = { RAWFB_INTERVAL_MICROS }; /* next absolute time to send interval message: */ TTIME nextt; TTIME waitt, nowt; TAPTR cmdport = TGetUserPort(task); TUINT cmdportsignal = TGetPortSignal(cmdport); TUINT imsgportsignal = TGetPortSignal(mod->rfb_RndIMsgPort); TDBPRINTF(TDB_INFO,("RawFB device context running\n")); TGetSystemTime(&nowt); nextt = nowt; TAddTime(&nextt, &intt); do { /* process input messages: */ rfb_processevent(mod); /* do draw commands: */ while ((req = TGetMsg(cmdport))) { rfb_docmd(mod, req); TReplyMsg(req); } /* check if time interval has expired: */ TGetSystemTime(&nowt); if (TCmpTime(&nowt, &nextt) > 0) { /* expired; send intervals: */ TLock(mod->rfb_InstanceLock); struct TNode *next, *node = mod->rfb_VisualList.tlh_Head; for (; (next = node->tln_Succ); node = next) { RFBWINDOW *v = (RFBWINDOW *) node; TIMSG *imsg; if ((v->rfbw_InputMask & TITYPE_INTERVAL) && rfb_getimsg(mod, v, &imsg, TITYPE_INTERVAL)) TPutMsg(v->rfbw_IMsgPort, TNULL, imsg); } TUnlock(mod->rfb_InstanceLock); TAddTime(&nextt, &intt); } /* calculate new wait time: */ waitt = nextt; TGetSystemTime(&nowt); TSubTime(&waitt, &nowt); if (waitt.tdt_Int64 <= 0 || waitt.tdt_Int64 > RAWFB_INTERVAL_MICROS) { /* something's wrong with the clock, recalculate */ TDBPRINTF(TDB_INFO,("clock problem: %lld\n", waitt.tdt_Int64)); nextt = nowt; TAddTime(&nextt, &intt); waitt = nextt; TSubTime(&waitt, &nowt); } sig = TWaitTime(&waitt, cmdportsignal | imsgportsignal | TTASK_SIG_ABORT); } while (!(sig & TTASK_SIG_ABORT)); TDBPRINTF(TDB_INFO,("RawFB device context closedown\n")); rfb_exittask(mod); }
static void rfb_processevent(struct rfb_Display *mod) { TAPTR TExecBase = TGetExecBase(mod); TIMSG *msg; if (mod->rfb_RndIMsgPort == TNULL) return; while ((msg = TGetMsg(mod->rfb_RndIMsgPort))) { /*struct rfb_Window *v = (struct rfb_Window *) msg->timsg_Instance; */ TIMSG *imsg; switch (msg->timsg_Type) { case TITYPE_INTERVAL: TDBPRINTF(TDB_WARN, ("unhandled event: INTERVAL\n")); break; case TITYPE_REFRESH: { TINT drect[4]; drect[0] = msg->timsg_X; drect[1] = msg->timsg_Y; drect[2] = msg->timsg_X + msg->timsg_Width - 1; drect[3] = msg->timsg_Y + msg->timsg_Height - 1; rfb_damage(mod, drect, TNULL); rfb_flush_clients(mod, TTRUE); break; } case TITYPE_NEWSIZE: if ((mod->rfb_Flags & RFBFL_BUFFER_OWNER) && (mod->rfb_Flags & RFBFL_BUFFER_CAN_RESIZE)) { region_free(&mod->rfb_RectPool, &mod->rfb_DirtyRegion); mod->rfb_Flags &= ~RFBFL_DIRTY; TINT neww = mod->rfb_Width = msg->timsg_Width; TINT newh = mod->rfb_Height = msg->timsg_Height; TUINT pixfmt = mod->rfb_PixBuf.tpb_Format; TUINT bpp = TVPIXFMT_BYTES_PER_PIXEL(pixfmt); TUINT bpl = bpp * neww; struct TVPixBuf newbuf; newbuf.tpb_BytesPerLine = bpl; newbuf.tpb_Format = mod->rfb_PixBuf.tpb_Format; newbuf.tpb_Data = TAlloc(mod->rfb_MemMgr, bpl * newh); if (newbuf.tpb_Data == TNULL) break; struct TNode *next, *node = mod->rfb_VisualList.tlh_Head.tln_Succ; for (; (next = node->tln_Succ); node = next) { struct rfb_Window *v = (struct rfb_Window *) node; rfb_setrealcliprect(mod, v); TINT w0 = REGION_RECT_WIDTH(&v->rfbw_ScreenRect); TINT h0 = REGION_RECT_HEIGHT(&v->rfbw_ScreenRect); if ((v->rfbw_Flags & RFBWFL_FULLSCREEN)) { v->rfbw_ScreenRect.r[0] = 0; v->rfbw_ScreenRect.r[1] = 0; v->rfbw_ScreenRect.r[2] = neww - 1; v->rfbw_ScreenRect.r[3] = newh - 1; } TINT ww = REGION_RECT_WIDTH(&v->rfbw_ScreenRect); TINT wh = REGION_RECT_HEIGHT(&v->rfbw_ScreenRect); if (v->rfbw_MinWidth > 0 && ww < v->rfbw_MinWidth) v->rfbw_ScreenRect.r[0] = v->rfbw_ScreenRect.r[2] - v->rfbw_MinWidth; if (v->rfbw_MinHeight > 0 && wh < v->rfbw_MinHeight) v->rfbw_ScreenRect.r[1] = v->rfbw_ScreenRect.r[3] - v->rfbw_MinHeight; ww = REGION_RECT_WIDTH(&v->rfbw_ScreenRect); wh = REGION_RECT_HEIGHT(&v->rfbw_ScreenRect); if (v->rfbw_Flags & RFBWFL_BACKBUFFER) rfb_resizewinbuffer(mod, v, w0, h0, ww, wh); else v->rfbw_PixBuf = newbuf; rfb_setwinrect(mod, v); if (ww != w0 || wh != h0) { if (rfb_getimsg(mod, v, &imsg, TITYPE_NEWSIZE)) { imsg->timsg_Width = ww; imsg->timsg_Height = wh; TPutMsg(v->rfbw_IMsgPort, TNULL, imsg); } } } TFree(mod->rfb_PixBuf.tpb_Data); mod->rfb_PixBuf = newbuf; struct Rect drect; REGION_RECT_SET(&drect, 0, 0, neww - 1, newh - 1); rfb_damage(mod, drect.r, TNULL); } else TDBPRINTF(TDB_WARN, ("Cannot resize this framebuffer\n")); break; case TITYPE_CLOSE: { /* send to root window */ TLock(mod->rfb_InstanceLock); struct rfb_Window *v = (struct rfb_Window *) TLASTNODE(&mod->rfb_VisualList); if (rfb_getimsg(mod, v, &imsg, TITYPE_CLOSE)) TPutMsg(v->rfbw_IMsgPort, TNULL, imsg); TUnlock(mod->rfb_InstanceLock); break; } case TITYPE_FOCUS: TDBPRINTF(TDB_INFO, ("unhandled event: FOCUS\n")); break; case TITYPE_MOUSEOVER: TDBPRINTF(TDB_INFO, ("unhandled event: MOUSEOVER\n")); break; case TITYPE_KEYUP: case TITYPE_KEYDOWN: rfb_passevent_keyboard(mod, msg); break; case TITYPE_MOUSEMOVE: rfb_passevent_mousemove(mod, msg); break; case TITYPE_MOUSEBUTTON: rfb_passevent_mousebutton(mod, msg); break; } TReplyMsg(msg); } }
static void rfb_runtask(struct TTask *task) { TAPTR TExecBase = TGetExecBase(task); struct rfb_Display *mod = TGetTaskData(task); struct TVRequest *req; TUINT sig = 0; TTIME intt = { 20000 }; /* next absolute time to send interval message: */ TTIME nextt; TTIME waitt, nowt, *pwaitt; TAPTR cmdport = TGetUserPort(task); TUINT cmdportsignal = TGetPortSignal(cmdport); TUINT imsgportsignal = TGetPortSignal(mod->rfb_RndIMsgPort); TUINT waitsigs = cmdportsignal | imsgportsignal | TTASK_SIG_ABORT; TDBPRINTF(TDB_INFO, ("RawFB device context running\n")); TGetSystemTime(&nowt); nextt = nowt; TAddTime(&nextt, &intt); do { if (sig & cmdportsignal) { TBOOL checkrect = mod->rfb_Flags & RFBFL_PTR_VISIBLE; TINT arec[4]; while ((req = TGetMsg(cmdport))) { if (checkrect) { TINT res = rfb_cmdrectaffected(mod, req, arec, TTRUE); if (res < 0 || (res > 0 && REGION_OVERLAPRECT(mod->rfb_PtrBackBuffer.rect, arec))) { rfb_restoreptrbg(mod); checkrect = TFALSE; } } rfb_docmd(mod, req); TReplyMsg(req); } } if (mod->rfb_Flags & RFBFL_SHOWPTR) rfb_drawpointer(mod); /* check if time interval has expired: */ TGetSystemTime(&nowt); /* do interval timers */ if (mod->rfb_NumInterval > 0) { if (TCmpTime(&nowt, &nextt) >= 0) { /* expired; send intervals: */ TLock(mod->rfb_InstanceLock); struct TNode *next, *node = mod->rfb_VisualList.tlh_Head.tln_Succ; for (; (next = node->tln_Succ); node = next) { struct rfb_Window *v = (struct rfb_Window *) node; TIMSG *imsg; if ((v->rfbw_InputMask & TITYPE_INTERVAL) && rfb_getimsg(mod, v, &imsg, TITYPE_INTERVAL)) TPutMsg(v->rfbw_IMsgPort, TNULL, imsg); } TUnlock(mod->rfb_InstanceLock); TAddTime(&nextt, &intt); } /* calculate new wait time: */ waitt = nextt; TSubTime(&waitt, &nowt); if (waitt.tdt_Int64 <= 0 || waitt.tdt_Int64 > 20000) { nextt = nowt; TAddTime(&nextt, &intt); waitt = nextt; TSubTime(&waitt, &nowt); } pwaitt = &waitt; } else pwaitt = TNULL; #if defined(ENABLE_LINUXFB) rfb_linux_wait(mod, pwaitt); sig = TSetSignal(0, waitsigs); #else sig = TWaitTime(pwaitt, waitsigs); #endif if (sig & imsgportsignal) rfb_processevent(mod); } while (!(sig & TTASK_SIG_ABORT)); TDBPRINTF(TDB_INFO, ("RawFB device context closedown\n")); rfb_exittask(mod); }
LOCAL void x11_taskfunc(struct TTask *task) { TAPTR TExecBase = TGetExecBase(task); struct X11Display *inst = TGetTaskData(task); TUINT sig = 0; fd_set rset; struct TVRequest *req; TIMSG *imsg; char buf[256]; struct timeval tv, *ptv; struct TMsgPort *cmdport = TGetUserPort(task); TUINT cmdportsignal = TGetPortSignal(cmdport); TUINT ireplysignal = TGetPortSignal(inst->x11_IReplyPort); TUINT waitsigs = cmdportsignal | ireplysignal | TTASK_SIG_ABORT; /* interval time: 1/50s: */ TTIME intt = { 20000 }; /* next absolute time to send interval message: */ TTIME nextt; TTIME waitt, nowt; TDBPRINTF(TDB_INFO, ("Device instance running\n")); TGetSystemTime(&nowt); nextt = nowt; TAddTime(&nextt, &intt); do { if (sig & ireplysignal) { while ((imsg = TGetMsg(inst->x11_IReplyPort))) { /* returned input message */ if (imsg->timsg_Type == TITYPE_REQSELECTION) { XSelectionEvent *reply = (XSelectionEvent *) imsg->timsg_Requestor; struct TTagItem *replytags = (struct TTagItem *) imsg->timsg_ReplyData; size_t len = TGetTag(replytags, TIMsgReply_UTF8SelectionLen, 0); TUINT8 *xdata = (TUINT8 *) TGetTag(replytags, TIMsgReply_UTF8Selection, TNULL); XChangeProperty(inst->x11_Display, reply->requestor, reply->property, XA_ATOM, 8, PropModeReplace, (unsigned char *) xdata, len); XSendEvent(inst->x11_Display, reply->requestor, 0, NoEventMask, (XEvent *) reply); XSync(inst->x11_Display, False); TFree((TAPTR) imsg->timsg_Requestor); TFree(xdata); /* reqselect roundtrip ended */ } TFree(imsg); } } if (sig & cmdportsignal) { while (inst->x11_RequestInProgress == TNULL && (req = TGetMsg(cmdport))) { x11_docmd(inst, req); if (inst->x11_RequestInProgress) break; TReplyMsg(req); } } XFlush(inst->x11_Display); FD_ZERO(&rset); FD_SET(inst->x11_fd_display, &rset); FD_SET(inst->x11_fd_sigpipe_read, &rset); TGetSystemTime(&nowt); if (inst->x11_NumInterval > 0 || inst->x11_RequestInProgress) { if (TCmpTime(&nowt, &nextt) >= 0) { /* expired; send interval: */ struct TNode *next, *node = inst->x11_vlist.tlh_Head.tln_Succ; for (; (next = node->tln_Succ); node = next) { struct X11Window *v = (struct X11Window *) node; TIMSG *imsg; if ((v->eventmask & TITYPE_INTERVAL) && x11_getimsg(inst, v, &imsg, TITYPE_INTERVAL)) TPutMsg(v->imsgport, TNULL, imsg); } TAddTime(&nextt, &intt); } /* calculate new wait time: */ waitt = nextt; TSubTime(&waitt, &nowt); if (waitt.tdt_Int64 <= 0 || waitt.tdt_Int64 > 20000) { nextt = nowt; TAddTime(&nextt, &intt); waitt = nextt; TSubTime(&waitt, &nowt); } tv.tv_sec = waitt.tdt_Int64 / 1000000; tv.tv_usec = waitt.tdt_Int64 % 1000000; ptv = &tv; } else ptv = NULL; /* wait for display, signal fd and timeout: */ if (select(inst->x11_fd_max, &rset, NULL, NULL, ptv) > 0) { int nbytes; /* consume signal: */ if (FD_ISSET(inst->x11_fd_sigpipe_read, &rset)) { ioctl(inst->x11_fd_sigpipe_read, FIONREAD, &nbytes); if (nbytes > 0) if (read(inst->x11_fd_sigpipe_read, buf, TMIN(sizeof(buf), (size_t) nbytes)) != nbytes) TDBPRINTF(TDB_ERROR, ("could not read wakeup signal\n")); } } /* process input messages: */ x11_processevent(inst); /* send out input messages to owners: */ x11_sendimessages(inst); /* get signal state: */ sig = TSetSignal(0, waitsigs); } while (!(sig & TTASK_SIG_ABORT)); TDBPRINTF(TDB_INFO, ("Device instance exit\n")); x11_exitinstance(inst); }
static TBOOL x11_processvisualevent(struct X11Display *mod, struct X11Window *v, TAPTR msgstate, XEvent *ev) { TAPTR TExecBase = TGetExecBase(mod); TIMSG *imsg; switch (ev->type) { case ClientMessage: if ((v->eventmask & TITYPE_CLOSE) && (Atom) ev->xclient.data.l[0] == v->atom_wm_delete_win) { if (x11_getimsg(mod, v, &imsg, TITYPE_CLOSE)) TAddTail(&v->imsgqueue, &imsg->timsg_Node); } break; case ConfigureNotify: if (mod->x11_RequestInProgress && (v->flags & X11WFL_WAIT_RESIZE)) { TReplyMsg(mod->x11_RequestInProgress); mod->x11_RequestInProgress = TNULL; v->flags &= ~X11WFL_WAIT_RESIZE; TDBPRINTF(TDB_INFO, ("Released request (ConfigureNotify)\n")); } v->winleft = ev->xconfigure.x; v->wintop = ev->xconfigure.y; if ((v->winwidth != ev->xconfigure.width || v->winheight != ev->xconfigure.height)) { v->flags |= X11WFL_WAIT_EXPOSE; v->winwidth = ev->xconfigure.width; v->winheight = ev->xconfigure.height; if (v->eventmask & TITYPE_NEWSIZE) { if (x11_getimsg(mod, v, &imsg, TITYPE_NEWSIZE)) { imsg->timsg_Width = v->winwidth; imsg->timsg_Height = v->winheight; TAddTail(&v->imsgqueue, &imsg->timsg_Node); } TDBPRINTF(TDB_TRACE, ("Configure: NEWSIZE: %d %d\n", v->winwidth, v->winheight)); } } break; case EnterNotify: case LeaveNotify: if (v->eventmask & TITYPE_MOUSEOVER) { if (x11_getimsg(mod, v, &imsg, TITYPE_MOUSEOVER)) { imsg->timsg_Code = (ev->type == EnterNotify); TAddTail(&v->imsgqueue, &imsg->timsg_Node); } } break; case MapNotify: if (mod->x11_RequestInProgress) { TReplyMsg(mod->x11_RequestInProgress); mod->x11_RequestInProgress = TNULL; v->flags |= X11WFL_WAIT_EXPOSE; TDBPRINTF(TDB_TRACE, ("Released request (MapNotify)\n")); } break; case Expose: if (v->flags & X11WFL_WAIT_EXPOSE) v->flags &= ~X11WFL_WAIT_EXPOSE; else if ((v->eventmask & TITYPE_REFRESH) && x11_getimsg(mod, v, &imsg, TITYPE_REFRESH)) { imsg->timsg_X = ev->xexpose.x; imsg->timsg_Y = ev->xexpose.y; imsg->timsg_Width = ev->xexpose.width; imsg->timsg_Height = ev->xexpose.height; TAddTail(&v->imsgqueue, &imsg->timsg_Node); TDBPRINTF(TDB_TRACE, ("Expose: REFRESH: %d %d %d %d\n", imsg->timsg_X, imsg->timsg_Y, imsg->timsg_Width, imsg->timsg_Height)); } break; case GraphicsExpose: if (mod->x11_CopyExposeHook) { TINT rect[4]; rect[0] = ev->xgraphicsexpose.x; rect[1] = ev->xgraphicsexpose.y; rect[2] = rect[0] + ev->xgraphicsexpose.width - 1; rect[3] = rect[1] + ev->xgraphicsexpose.height - 1; TCallHookPkt(mod->x11_CopyExposeHook, mod->x11_RequestInProgress->tvr_Op.CopyArea.Window, (TTAG) rect); } if (ev->xgraphicsexpose.count > 0) break; /* no more graphics expose events, fallthru: */ case NoExpose: if (mod->x11_RequestInProgress) { TReplyMsg(mod->x11_RequestInProgress); mod->x11_RequestInProgress = TNULL; mod->x11_CopyExposeHook = TNULL; TDBPRINTF(TDB_TRACE, ("Released request (NoExpose)\n")); } else TDBPRINTF(TDB_INFO, ("NoExpose: TITYPE_REFRESH not set\n")); break; case FocusIn: case FocusOut: mod->x11_KeyQual = 0; if (v->eventmask & TITYPE_FOCUS) { if (x11_getimsg(mod, v, &imsg, TITYPE_FOCUS)) { imsg->timsg_Code = (ev->type == FocusIn); TAddTail(&v->imsgqueue, &imsg->timsg_Node); } } break; case MotionNotify: { struct TNode *next, *node = mod->x11_vlist.tlh_Head.tln_Succ; x11_setmousepos(mod, v, ev->xmotion.x, ev->xmotion.y); v->mousex = mod->x11_ScreenMouseX - v->winleft; v->mousey = mod->x11_ScreenMouseY - v->wintop; for (; (next = node->tln_Succ); node = next) { struct X11Window *v = (struct X11Window *) node; if (v->eventmask & TITYPE_MOUSEMOVE && x11_getimsg(mod, v, &imsg, TITYPE_MOUSEMOVE)) TAddTail(&v->imsgqueue, &imsg->timsg_Node); } break; } case ButtonRelease: case ButtonPress: x11_setmousepos(mod, v, ev->xbutton.x, ev->xbutton.y); if (v->eventmask & TITYPE_MOUSEBUTTON) { if (x11_getimsg(mod, v, &imsg, TITYPE_MOUSEBUTTON)) { unsigned int button = ev->xbutton.button; if (ev->type == ButtonPress) { switch (button) { case Button1: imsg->timsg_Code = TMBCODE_LEFTDOWN; break; case Button2: imsg->timsg_Code = TMBCODE_MIDDLEDOWN; break; case Button3: imsg->timsg_Code = TMBCODE_RIGHTDOWN; break; case Button4: imsg->timsg_Code = TMBCODE_WHEELUP; break; case Button5: imsg->timsg_Code = TMBCODE_WHEELDOWN; break; } } else { switch (button) { case Button1: imsg->timsg_Code = TMBCODE_LEFTUP; break; case Button2: imsg->timsg_Code = TMBCODE_MIDDLEUP; break; case Button3: imsg->timsg_Code = TMBCODE_RIGHTUP; break; } } TAddTail(&v->imsgqueue, &imsg->timsg_Node); } } break; case KeyRelease: x11_processkey(mod, v, (XKeyEvent *) ev, TFALSE); break; case KeyPress: x11_processkey(mod, v, (XKeyEvent *) ev, TTRUE); break; case SelectionRequest: { XSelectionRequestEvent *req = (XSelectionRequestEvent *) ev; XEvent replyevent; XSelectionEvent *reply = &replyevent.xselection; memset(&replyevent, 0, sizeof replyevent); reply->type = SelectionNotify; reply->serial = ev->xany.send_event; reply->send_event = True; reply->display = req->display; reply->requestor = req->requestor; reply->selection = req->selection; reply->property = req->property; reply->target = None; reply->time = req->time; if (req->target == mod->x11_XA_TARGETS) { XChangeProperty(mod->x11_Display, req->requestor, req->property, XA_ATOM, 32, PropModeReplace, (unsigned char *) &mod->x11_XA_UTF8_STRING, 1); } else if (req->target == mod->x11_XA_UTF8_STRING) { XSelectionEvent *rcopy = TAlloc(TNULL, sizeof *reply); if (rcopy && x11_getimsg(mod, v, &imsg, TITYPE_REQSELECTION)) { *rcopy = *reply; imsg->timsg_Requestor = (TTAG) rcopy; imsg->timsg_Code = req->selection == mod->x11_XA_PRIMARY ? 2 : 1; TAddTail(&v->imsgqueue, &imsg->timsg_Node); break; } TFree(rcopy); } else reply->property = None; XSendEvent(mod->x11_Display, req->requestor, 0, NoEventMask, &replyevent); XSync(mod->x11_Display, False); break; } } return TFALSE; }