LOCAL void rfb_focuswindow(struct rfb_Display *mod, struct rfb_Window *v) { TAPTR TExecBase = TGetExecBase(mod); TIMSG *imsg; if (v == mod->rfb_FocusWindow || (v && (v->rfbw_Flags & RFBWFL_IS_POPUP))) return; if (mod->rfb_FocusWindow) { if (rfb_getimsg(mod, mod->rfb_FocusWindow, &imsg, TITYPE_FOCUS)) { imsg->timsg_Code = 0; TPutMsg(mod->rfb_FocusWindow->rfbw_IMsgPort, TNULL, imsg); } } if (v) { if (rfb_getimsg(mod, v, &imsg, TITYPE_FOCUS)) { imsg->timsg_Code = 1; TPutMsg(v->rfbw_IMsgPort, TNULL, imsg); } } mod->rfb_FocusWindow = v; }
static TBOOL rfb_passevent(RFBDISPLAY *mod, RFBWINDOW *v, TIMSG *omsg) { TAPTR TExecBase = TGetExecBase(mod); TUINT type = omsg->timsg_Type; if (v && (v->rfbw_InputMask & type)) { TIMSG *imsg; if (rfb_getimsg(mod, v, &imsg, omsg->timsg_Type)) { TINT x = omsg->timsg_MouseX; TINT y = omsg->timsg_MouseY; mod->rfb_MouseX = x; mod->rfb_MouseY = y; imsg->timsg_Code = omsg->timsg_Code; imsg->timsg_Qualifier = omsg->timsg_Qualifier; imsg->timsg_MouseX = x - v->rfbw_WinRect[0]; imsg->timsg_MouseY = y - v->rfbw_WinRect[1]; imsg->timsg_ScreenMouseX = x; imsg->timsg_ScreenMouseY = y; memcpy(imsg->timsg_KeyCode, omsg->timsg_KeyCode, 8); TPutMsg(v->rfbw_IMsgPort, TNULL, imsg); return TTRUE; } } return TFALSE; }
LOCAL TINT rfb_sendevent(struct rfb_Display *mod, TUINT type, TUINT code, TINT x, TINT y) { TIMSG *msg; if (!rfb_getimsg(mod, TNULL, &msg, type)) return 0; msg->timsg_Code = code; msg->timsg_MouseX = x; msg->timsg_MouseY = y; TINT res = 1; switch (type) { case TITYPE_MOUSEMOVE: rfb_passevent_mousemove(mod, msg); break; case TITYPE_MOUSEBUTTON: rfb_passevent_mousebutton(mod, msg); break; case TITYPE_KEYUP: case TITYPE_KEYDOWN: rfb_passevent_keyboard(mod, msg); break; default: TDBPRINTF(TDB_ERROR, ("illegal message type\n")); res = 0; } /* put back prototype message */ TAddTail(&mod->rfb_IMsgPool, &msg->timsg_Node); return res; }
static TBOOL rfb_passevent(struct rfb_Display *mod, struct rfb_Window *v, TIMSG *omsg) { TAPTR TExecBase = TGetExecBase(mod); TUINT type = omsg->timsg_Type; if (v && (v->rfbw_InputMask & type)) { TIMSG *imsg; if (rfb_getimsg(mod, v, &imsg, omsg->timsg_Type)) { /* note: screen coordinates */ TINT x = omsg->timsg_MouseX; TINT y = omsg->timsg_MouseY; mod->rfb_MouseX = x; mod->rfb_MouseY = y; imsg->timsg_Code = omsg->timsg_Code; imsg->timsg_Qualifier = omsg->timsg_Qualifier; imsg->timsg_MouseX = x - v->rfbw_ScreenRect.r[0]; imsg->timsg_MouseY = y - v->rfbw_ScreenRect.r[1]; imsg->timsg_ScreenMouseX = x; imsg->timsg_ScreenMouseY = y; memcpy(imsg->timsg_KeyCode, omsg->timsg_KeyCode, 8); TPutMsg(v->rfbw_IMsgPort, TNULL, imsg); return TTRUE; } } return TFALSE; }
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 TBOOL rfb_damage(struct rfb_Display *mod, TINT drect[], struct rfb_Window *v) { TAPTR TExecBase = TGetExecBase(mod); struct RectPool *pool = &mod->rfb_RectPool; struct Region A, B; if (!region_init(pool, &A, drect)) return TFALSE; TDBPRINTF(TDB_TRACE, ("incoming damage: %d %d %d %d\n", drect[0], drect[1], drect[2], drect[3])); /* traverse window stack; refresh B where A and B overlap ; A = A - B */ struct TNode *next, *node = mod->rfb_VisualList.tlh_Head.tln_Succ; TBOOL success = TTRUE; TBOOL below = TFALSE; TLock(mod->rfb_InstanceLock); for (; success && !region_isempty(pool, &A) && (next = node->tln_Succ); node = next) { struct rfb_Window *bv = (struct rfb_Window *) node; if (v && !below) { if (bv == v) below = TTRUE; else /* above: subtract current from rect to be damaged: */ success = region_subrect(pool, &A, bv->rfbw_ScreenRect.r); continue; } success = TFALSE; if (region_init(pool, &B, bv->rfbw_ScreenRect.r)) { if (region_andregion(pool, &B, &A)) { region_shift(&B, bv->rfbw_WinRect.r[0] - bv->rfbw_ScreenRect.r[0], bv->rfbw_WinRect.r[1] - bv->rfbw_ScreenRect.r[1]); struct TNode *next, *node = B.rg_Rects.rl_List.tlh_Head.tln_Succ; for (; (next = node->tln_Succ); node = next) { struct RectNode *r = (struct RectNode *) node; if (bv->rfbw_Flags & RFBWFL_BACKBUFFER) { rfb_markdirty(mod, bv, r->rn_Rect); } else if (bv->rfbw_InputMask & TITYPE_REFRESH) { TIMSG *imsg; if (rfb_getimsg(mod, bv, &imsg, TITYPE_REFRESH)) { TDBPRINTF(TDB_TRACE, ("send refresh %d %d %d %d\n", r->rn_Rect[0], r->rn_Rect[1], r->rn_Rect[2], r->rn_Rect[3])); imsg->timsg_X = r->rn_Rect[0]; imsg->timsg_Y = r->rn_Rect[1]; imsg->timsg_Width = r->rn_Rect[2] - r->rn_Rect[0] + 1; imsg->timsg_Height = r->rn_Rect[3] - r->rn_Rect[1] + 1; imsg->timsg_X -= bv->rfbw_ScreenRect.r[0]; imsg->timsg_Y -= bv->rfbw_ScreenRect.r[1]; TPutMsg(bv->rfbw_IMsgPort, TNULL, imsg); } } } success = TTRUE; } region_free(pool, &B); } if (success) success = region_subrect(pool, &A, bv->rfbw_ScreenRect.r); } TUnlock(mod->rfb_InstanceLock); region_free(pool, &A); return success; }