Exemple #1
0
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)) ;
	}
}
Exemple #2
0
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);
}
Exemple #3
0
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);
	}
}
Exemple #4
0
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);
}
Exemple #5
0
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);
	}
}
Exemple #6
0
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);
}
Exemple #7
0
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);
}
Exemple #8
0
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;
}