Example #1
0
/*
 * Try to deliver a exposure event to the clients which have selected for it.
 * This does not send exposure events for unmapped or input-only windows.
 * Exposure events do not propagate upwards.
 */
void
GsDeliverExposureEvent(GR_WINDOW *wp, GR_COORD x, GR_COORD y,
	GR_SIZE width, GR_SIZE height)
{
	GR_EVENT_EXPOSURE	*ep;		/* exposure event */
	GR_EVENT_CLIENT		*ecp;		/* current event client */

	if (!wp->realized || !wp->output)
		return;

	for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
		if ((ecp->eventmask & GR_EVENT_MASK_EXPOSURE) == 0)
			continue;

		GsFreeExposureEvent(ecp->client, wp->id, x, y, width, height);

		ep = (GR_EVENT_EXPOSURE *) GsAllocEvent(ecp->client);
		if (ep == NULL)
			continue;

		ep->type = GR_EVENT_TYPE_EXPOSURE;
		ep->wid = wp->id;
		ep->x = x;
		ep->y = y;
		ep->width = width;
		ep->height = height;
	}
}
Example #2
0
/*
 * Try to deliver a general event such as focus in, focus out, mouse enter,
 * or mouse exit to the clients which have selected for it.  These events
 * only have the window id as data, and do not propagate upwards.
 */
void
GsDeliverGeneralEvent(GR_WINDOW *wp, GR_EVENT_TYPE type, GR_WINDOW *other)
{
	GR_EVENT_GENERAL	*gp;		/* general event */
	GR_EVENT_CLIENT		*ecp;		/* current event client */
	GR_EVENT_MASK		eventmask;	/* event mask */

	eventmask = GR_EVENTMASK(type);
	if (eventmask == 0)
		return;

	for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
		if ((ecp->eventmask & eventmask) == 0)
			continue;

		gp = (GR_EVENT_GENERAL *) GsAllocEvent(ecp->client);
		if (gp == NULL)
			continue;

		gp->type = type;
		gp->wid = wp->id;
		if (other)
			gp->otherid = other->id;
		else gp->otherid = 0;
	}
}
Example #3
0
/*
 * Deliver a client data request event. Delivered to the clients who have
 * selected for this event on the specified window only.
 */
void
GsDeliverClientDataReqEvent(GR_WINDOW_ID wid, GR_WINDOW_ID rid,
	GR_SERIALNO serial, GR_MIMETYPE mimetype)
{
	GR_EVENT_CLIENT_DATA_REQ *gp;		/* client data request event */
	GR_EVENT_CLIENT		*ecp;		/* current event client */
	GR_WINDOW *wp;

	if(!(wp = GsFindWindow(wid)))
		return;

	for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
		if ((ecp->eventmask & GR_EVENT_MASK_CLIENT_DATA_REQ) == 0)
			continue;

		gp = (GR_EVENT_CLIENT_DATA_REQ *) GsAllocEvent(ecp->client);
		if (gp == NULL)
			continue;

		gp->type = GR_EVENT_TYPE_CLIENT_DATA_REQ;
		gp->wid = wid;
		gp->rid = rid;
		gp->serial = serial;
		gp->mimetype = mimetype;
		continue;
	}
}
Example #4
0
/*
 * Deliver a client data event. Delivered to the clients who have selected for
 * this event on the specified window only.
 */
void
GsDeliverClientDataEvent(GR_WINDOW_ID wid, GR_WINDOW_ID rid,
	GR_SERIALNO serial, GR_LENGTH len, GR_LENGTH thislen, void *data)
{
	GR_EVENT_CLIENT_DATA *gp;		/* client data request event */
	GR_EVENT_CLIENT		*ecp;		/* current event client */
	GR_WINDOW *wp;

	if(!(wp = GsFindWindow(wid)))
		return;

	for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
		if ((ecp->eventmask & GR_EVENT_MASK_CLIENT_DATA) == 0)
			continue;

		gp = (GR_EVENT_CLIENT_DATA *) GsAllocEvent(ecp->client);
		if (gp == NULL)
			continue;

		gp->type = GR_EVENT_TYPE_CLIENT_DATA;
		gp->wid = wid;
		gp->rid = rid;
		gp->serial = serial;
		gp->len = len;
		gp->datalen = thislen;
		if(!(gp->data = malloc(thislen))) {
			GsError(GR_ERROR_MALLOC_FAILED, wid);
			return;
		}
		memcpy(gp->data, data, thislen);
		continue;
	}
}
Example #5
0
/*
 * Generate an error from a graphics function.
 * This creates a special event which describes the error.
 * Only one error event at a time can be saved for delivery to a client.
 * This is ok since there are usually lots of redundant errors generated
 * before the client can notice, errors occurs after the fact, and clients
 * can't do much about them except complain and die.  The error is saved
 * specially so that memory problems cannot occur.
 */
void GsError(GR_ERROR code, GR_ID id)
{
	GR_EVENT_ERROR	*ep;		/* event to describe error */

	EPRINTF("nano-X: GsError ");
	if(curfunc)
		EPRINTF("(%s) ", curfunc);
	EPRINTF(nxErrorStrings[code], id);

	/* if no clients, nothing to report*/
	if (!curclient)
		return;

	/* 
	 * If we ran out of memory, another call to GsAllocEvent will
	 * simply get us back here, so don't bother trying to report the event.
	 */
	if (code == GR_ERROR_MALLOC_FAILED)
		return;

	/* queue the error event regardless of GrSelectEvents*/
	ep = (GR_EVENT_ERROR *)GsAllocEvent(curclient);
	ep->type = GR_EVENT_TYPE_ERROR;
	ep->name[0] = 0;
	if(curfunc) {
		strncpy(ep->name, curfunc, sizeof(GR_FUNC_NAME));
		ep->name[sizeof(GR_FUNC_NAME)-1] = '\0';
	}
	ep->code = code;
	ep->id = id;
}
Example #6
0
/*
 * Try to deliver an update event to the clients which have selected for it.
 */
void
GsDeliverUpdateEvent(GR_WINDOW *wp, GR_UPDATE_TYPE utype, GR_COORD x,
	GR_COORD y, GR_SIZE width, GR_SIZE height)
{
	GR_EVENT_MASK		cmask = GR_EVENT_MASK_UPDATE;
	GR_EVENT_UPDATE		*ep;		/* update event */
	GR_EVENT_CLIENT		*ecp;		/* current event client */
	GR_WINDOW_ID		id = wp->id;
	int			lcount = 0;

	/* adjust reported x,y to be parent-relative*/
	if (wp->parent) {
		x -= wp->parent->x;
		y -= wp->parent->y;
	}

update_again:
	for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
		if ((ecp->eventmask & cmask) == 0)
			continue;

		ep = (GR_EVENT_UPDATE *) GsAllocEvent(ecp->client);
		if (ep == NULL)
			continue;

		ep->type = lcount? 
			GR_EVENT_TYPE_CHLD_UPDATE: GR_EVENT_TYPE_UPDATE;
		ep->utype = utype;
		ep->wid = wp->id;	/* GrSelectEvents window id*/
		ep->subwid = id;	/* update window id*/
		ep->x = x;
		ep->y = y;
		ep->width = width;
		ep->height = height;
	}

	/* If we are currently checking the window updated, go back and 
	 * check its parent too */
	if (!lcount++) {	
		wp = wp->parent;
		/* check for NULL on root window id*/
		if (wp == NULL)
			return;
		cmask = GR_EVENT_MASK_CHLD_UPDATE;
		goto update_again;
	}
}
Example #7
0
/*
 * Deliver a Screen Saver event. There is only one parameter- activate the
 * screen saver or deactivate it. We only deliver it to the root window,
 * but we do send it to every client which has selected for it (because the
 * program which starts the screen saver on an activate event might not also
 * be the screen saver program which wants to catch the deactivate event).
 */
void
GsDeliverScreenSaverEvent(GR_BOOL activate)
{
	GR_EVENT_SCREENSAVER	*gp;		/* screensaver event */
	GR_EVENT_CLIENT		*ecp;		/* current event client */

	for (ecp = rootwp->eventclients; ecp; ecp = ecp->next) {
		if ((ecp->eventmask & GR_EVENT_MASK_SCREENSAVER) == 0)
			continue;

		gp = (GR_EVENT_SCREENSAVER *) GsAllocEvent(ecp->client);
		if (gp == NULL)
			continue;

		gp->type = GR_EVENT_TYPE_SCREENSAVER;
		gp->activate = activate;
	}
}
Example #8
0
/*
 * Deliver a portrait mode changed event to all windows which
 * have selected for it.
 */
void
GsDeliverPortraitChangedEvent(void)
{
	GR_WINDOW		*wp;
	GR_EVENT_GENERAL	*gp;
	GR_EVENT_CLIENT		*ecp;

	for (wp=listwp; wp; wp=wp->next) {
		for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
			if ((ecp->eventmask & GR_EVENT_MASK_PORTRAIT_CHANGED) == 0)
				continue;

			gp = (GR_EVENT_GENERAL *) GsAllocEvent(ecp->client);
			if (gp == NULL)
				continue;

			gp->type = GR_EVENT_TYPE_PORTRAIT_CHANGED;
			gp->wid = wp->id;
			gp->otherid = 0;
		}
	}
}
Example #9
0
/*
 * Deliver a "selection owner changed" event to all windows which have
 * selected for it. We deliver this event to all clients which have selected
 * to receive GR_EVENT_TYPE_SELECTION_CHANGED events for the window of the
 * _previous_ selection owner.
 */
void
GsDeliverSelectionChangedEvent(GR_WINDOW_ID old_owner, GR_WINDOW_ID new_owner)
{
	GR_EVENT_SELECTION_CHANGED *gp;		/* selection changed event */
	GR_EVENT_CLIENT		*ecp;		/* current event client */
	GR_WINDOW *wp;

	if(!(wp = GsFindWindow(old_owner)))
		return;

	for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
		if ((ecp->eventmask & GR_EVENT_MASK_SELECTION_CHANGED) == 0)
			continue;

		gp = (GR_EVENT_SELECTION_CHANGED *) GsAllocEvent(ecp->client);
		if (gp == NULL)
			continue;

		gp->type = GR_EVENT_TYPE_SELECTION_CHANGED;
		gp->new_owner = new_owner;
	}
}
Example #10
0
void
GsDeliverTimerEvent(GR_CLIENT * client, GR_WINDOW_ID wid, GR_TIMER_ID tid)
{
	GR_EVENT_TIMER *event;	/* general event */
	GR_EVENT_CLIENT *ecp;	/* current event client */
	GR_WINDOW *wp;		/* current window */

	if ((wp = GsFindWindow(wid)) == NULL)
		return;

	for (ecp = wp->eventclients; ecp != NULL; ecp = ecp->next) {
		if ((ecp->client == client)
		    && ((ecp->eventmask & GR_EVENT_MASK_TIMER) != 0)) {
			event = (GR_EVENT_TIMER *) GsAllocEvent(client);
			if (event == NULL)
				break;

			event->type = GR_EVENT_TYPE_TIMER;
			event->wid = wid;
			event->tid = tid;
		}
	}
}
Example #11
0
void
GsSelect(GR_TIMEOUT timeout)
{
	int mouseevents = 0;
	int keybdevents = 0;
	GR_TIMEOUT waittime = 0;
	GR_EVENT_GENERAL *gp;


	/* input gathering loop */
	while (1)
	{

		/* perform pre-select duties, if any */
		if(scrdev.PreSelect)
		{
			scrdev.PreSelect(&scrdev);
		}


		/* If mouse data present, service it */
		while (mousedev.Poll() > 0)
		{
			GsCheckMouseEvent();
			if (mouseevents++ > MAX_MOUSEEVENTS)
			{
				/* don't handle too many events at one shot */
				break;
			}
		}


		/* If keyboard data present, service it */
		while (kbddev.Poll() > 0)
		{
			GsCheckKeyboardEvent();
			if (keybdevents++ > MAX_KEYBDEVENTS)
			{
				/* don't handle too many events at one shot */
				break;
			}
		}


		/* did we process any input yet? */
		if ((mouseevents > 0) || (keybdevents > 0))
		{
			/* yep -- return without sleeping */
			return;
		}


		/* give up time-slice & sleep for a bit */
		GdSleep(POLLTIME);
		waittime += POLLTIME;


		/* have we timed out? */
		if (waittime >= timeout)
		{
			/* special case: polling when timeout == 0 -- don't send timeout event */
			if (timeout != 0)
			{
				/* Timeout has occured.
				** Currently return a timeout event regardless of whether client
				**   has selected for it.
				*/
				if ((gp = (GR_EVENT_GENERAL *)GsAllocEvent(curclient)) != NULL)
				{
					gp->type = GR_EVENT_TYPE_TIMEOUT;
				}
			}
			return;
		}
	}

}
Example #12
0
void 
GsSelect(GR_TIMEOUT timeout)
{
	int numevents = 0;
	GR_TIMEOUT waittime = 0;
	GR_EVENT_GENERAL *gp;

#if MW_FEATURE_TIMERS
	struct timeval tout;
	if (timeout != (GR_TIMEOUT)-1L)
		GdGetNextTimeout(&tout, timeout);	/* set initial mainloop timeout*/
#endif
#if EMSCRIPTEN
	if (timeout == (GR_TIMEOUT)-1L)
		timeout = 1;				/* need to give up some CPU in GdDelay even on poll*/
#endif
	/* input gathering loop */
	while (1)
	{
		/* perform single update of aggregate screen update region*/
		if(scrdev.PreSelect)
			scrdev.PreSelect(&scrdev);

		/* poll for mouse data and service if found*/
		while (GsCheckMouseEvent())
			if (++numevents > 10)
				break;				/* don't handle too many events at one shot*/

		/* poll for keyboard data and service if found*/
		while (GsCheckKeyboardEvent())
			if (++numevents > 10)
				break;				/* don't handle too many events at one shot*/
		
		/* did we handle any input or were we just polling?*/
		if (numevents || timeout == (GR_TIMEOUT)-1L)
			return;					/* yes - return without sleeping*/

		/* give up time-slice & sleep for a bit */
		GdDelay(WAITTIME);
		waittime += WAITTIME; 

		/* have we timed out? */
		if (waittime >= timeout)
		{
#if MW_FEATURE_TIMERS
			/* check for timer timeouts and service if found*/
			if (GdTimeout())
#else
			/* special case: polling when timeout == 0 -- don't send timeout event */
			if (timeout != 0)
#endif
			{
				/* Timeout has occured.  
				 * Currently return a timeout event regardless of whether client 
				 * has selected for it.
				 */
				if ((gp = (GR_EVENT_GENERAL *)GsAllocEvent(curclient)) != NULL)
					gp->type = GR_EVENT_TYPE_TIMEOUT;
			}
			return;
		}
	}
}
Example #13
0
void
GsSelect (GR_TIMEOUT timeout)
{
	struct MW_UID_MESSAGE m;
	long uid_timeout;
	GR_EVENT_GENERAL *gp;
	int rc;
#if MW_FEATURE_TIMERS
	struct timeval tout;
#endif

	/* perform pre-select duties, if any*/
	if (scrdev.PreSelect)
		scrdev.PreSelect(&scrdev);

	/* let's make sure that the type is invalid */
	m.type = MV_UID_INVALID;

	/* wait up for events */
	if (timeout == (GR_TIMEOUT) -1)
		uid_timeout = 0;
	else {
#if MW_FEATURE_TIMERS
		if (GdGetNextTimeout(&tout, timeout))
			uid_timeout = tout.tv_sec * 1000 + (tout.tv_usec + 500) / 1000;
		else
#endif
		{
			if (timeout == 0)
				uid_timeout = (unsigned long) -1;
			else
				uid_timeout = timeout;
		}
	}
	rc = uid_read_message (&m, uid_timeout);

	/* return if timed-out or something went wrong */
	if (rc < 0)
	{
		if (errno != ETIMEDOUT)
				EPRINTF(" rc= %d, errno=%d\n", rc, errno);
		else
		{
#if MW_FEATURE_TIMERS
			/* check for timer timeouts and service if found*/
			if (GdTimeout())
#else
			if (timeout != 0)
#endif
			{
				/*
		 		 * Timeout has occured. Currently return a timeout event
		 		 * regardless of whether client has selected for it.
				 */
				if ((gp = (GR_EVENT_GENERAL *)GsAllocEvent(curclient)) != NULL)
					gp->type = GR_EVENT_TYPE_TIMEOUT;
			}
		}
		return;
	}

	/* let's pass the event up to Microwindows */
	switch (m.type) {
	case MV_UID_REL_POS:	/* Mouse or Touch Screen event */
	case MV_UID_ABS_POS:
		m_mou = m;
		while (GsCheckMouseEvent())
			continue;
		break;
	case MV_UID_KBD:	/* KBD event */
		m_kbd = m;
		GsCheckKeyboardEvent ();
		break;
	case MV_UID_TIMER:	/* Microwindows does nothing with these.. */
	case MV_UID_INVALID:
	default:
	        break;
	}
}
Example #14
0
void
GsSelect(GR_TIMEOUT timeout)
{
	fd_set	rfds;
	int 	e;
	int	setsize = 0;
	struct timeval tout;
	struct timeval *to;
#if NONETWORK
	int	fd;
#endif
#if HAVE_VNCSERVER 
#if VNCSERVER_PTHREADED
        int dummy;
#else
        rfbClientIteratorPtr i;
        rfbClientPtr cl;
#endif 
#endif

	/* X11/SDL perform single update of aggregate screen update region*/
	if (scrdev.PreSelect)
	{
		/* returns # pending events*/
		if (scrdev.PreSelect(&scrdev))
		{
			/* poll for mouse data and service if found*/
			while (GsCheckMouseEvent())
				continue;

			/* poll for keyboard data and service if found*/
			while (GsCheckKeyboardEvent())
				continue;

			/* events found, return with no sleep*/
			return;
		}
	}

	/* Set up the FDs for use in the main select(): */
	FD_ZERO(&rfds);
	if(mouse_fd >= 0)
	{
		FD_SET(mouse_fd, &rfds);
		if (mouse_fd > setsize)
			setsize = mouse_fd;
	}
	if(keyb_fd >= 0)
	{
		FD_SET(keyb_fd, &rfds);
		if (keyb_fd > setsize)
			setsize = keyb_fd;
	}
#if MW_FEATURE_TWO_KEYBOARDS
	if(keyb2_fd >= 0)
	{
		FD_SET(keyb2_fd, &rfds);
		if (keyb2_fd > setsize)
			setsize = keyb2_fd;
	}
#endif
#if NONETWORK
	/* handle registered input file descriptors*/
	for (fd = 0; fd < regfdmax; fd++)
	{
		if (!FD_ISSET(fd, &regfdset))
			continue;

		FD_SET(fd, &rfds);
		if (fd > setsize) setsize = fd;
	}
#else /* !NONETWORK */
	/* handle client socket connections*/
	FD_SET(un_sock, &rfds);
	if (un_sock > setsize) setsize = un_sock;
	curclient = root_client;
	while(curclient)
	{
		if(curclient->waiting_for_event && curclient->eventhead)
		{
			curclient->waiting_for_event = FALSE;
			GrGetNextEventWrapperFinish(curclient->id);
			return;
		}
		FD_SET(curclient->id, &rfds);
		if(curclient->id > setsize) setsize = curclient->id;
		curclient = curclient->next;
	}
#endif /* NONETWORK */

#if HAVE_VNCSERVER 
#if VNCSERVER_PTHREADED
	/* Add file vnc thread fd. This is useful to force handling of events generated by the VNC thread*/
	FD_SET( vnc_thread_fd, &(rfds) );
	if ( vnc_thread_fd > setsize )
		setsize = vnc_thread_fd;
#else
        /* Add all VNC open sockets to nano-X select set */
        FD_SET( rfbScreen->listenSock, &(rfds) );
        if ( rfbScreen->listenSock > setsize )
                setsize = rfbScreen->listenSock;

        FD_SET( rfbScreen->httpListenSock, &(rfds) );
        if ( rfbScreen->httpListenSock > setsize )
                setsize = rfbScreen->httpListenSock;

        i = rfbGetClientIterator(rfbScreen);
        cl = rfbClientIteratorNext(i);

        while ( cl ) {
                if ( cl->sock >= 0 ) {
                        FD_SET( cl->sock, &(rfds) );
                        if ( cl->sock > setsize )
                                setsize = cl->sock;

                }
                cl = rfbClientIteratorNext(i);
        }
        rfbReleaseClientIterator(i);
#endif
#endif /* HAVE_VNCSERVER*/


	/* setup timeval struct for block or poll in select()*/
	tout.tv_sec = tout.tv_usec = 0;					/* setup for assumed poll*/
	to = &tout;
	int poll = (timeout == (GR_TIMEOUT) -1L);		/* timeout = -1 means just poll*/
	if (!poll)
	{
#if MW_FEATURE_TIMERS
		/* get next timer or use passed timeout and convert to timeval struct*/
		if (!GdGetNextTimeout(&tout, timeout))		/* no app timers or VTSWITCH?*/
#else
		if (timeout)								/* setup mwin poll timer*/
		{
			/* convert wait timeout to timeval struct*/
			tout.tv_sec = timeout / 1000;
			tout.tv_usec = (timeout % 1000) * 1000;
		}
		else
#endif
		{
			to = NULL;								/* no timers, block*/
		}
	}

	/* some drivers can't block in select as backend is poll based (SDL)*/
	if (scrdev.flags & PSF_CANTBLOCK)
	{
#define WAITTIME	100
		/* check if would block permanently or timeout > WAITTIME*/
		if (to == NULL || tout.tv_sec != 0 || tout.tv_usec > WAITTIME)
		{
			/* override timeouts and wait for max WAITTIME ms*/
			to = &tout;
			tout.tv_sec = 0;
			tout.tv_usec = WAITTIME;
		}
	}

	/* Wait for some input on any of the fds in the set or a timeout*/
#if NONETWORK
	SERVER_UNLOCK();	/* allow other threads to run*/
#endif
	e = select(setsize+1, &rfds, NULL, NULL, to);
#if NONETWORK
	SERVER_LOCK();
#endif
	if(e > 0)			/* input ready*/
	{
		/* service mouse file descriptor*/
		if(mouse_fd >= 0 && FD_ISSET(mouse_fd, &rfds))
			while(GsCheckMouseEvent())
				continue;

		/* service keyboard file descriptor*/
		if( (keyb_fd >= 0 && FD_ISSET(keyb_fd, &rfds))
#if MW_FEATURE_TWO_KEYBOARDS
		    || (keyb2_fd >= 0 && FD_ISSET(keyb2_fd, &rfds))
#endif
		  )
			while(GsCheckKeyboardEvent())
				continue;

#if HAVE_VNCSERVER && VNCSERVER_PTHREADED
        if(vnc_thread_fd >= 0 && FD_ISSET(vnc_thread_fd, &rfds))
            /* Read from vnc pipe */
            read( vnc_thread_fd, &dummy, sizeof(int));

#endif
#if NONETWORK
		/* check for input on registered file descriptors */
		for (fd = 0; fd < regfdmax; fd++)
		{
			GR_EVENT_FDINPUT *	gp;

			if (!FD_ISSET(fd, &regfdset)  ||  !FD_ISSET(fd, &rfds))
				continue;

			gp = (GR_EVENT_FDINPUT *)GsAllocEvent(curclient);
			if(gp) {
				gp->type = GR_EVENT_TYPE_FDINPUT;
				gp->fd = fd;
			}
		}
#else /* !NONETWORK */

		/* If a client is trying to connect, accept it: */
		if(FD_ISSET(un_sock, &rfds))
			GsAcceptClient();

		/* If a client is sending us a command, handle it: */
		curclient = root_client;
		while (curclient)
		{
			GR_CLIENT *curclient_next;

			/* curclient may be freed in GsDropClient*/
			curclient_next = curclient->next;
			if(FD_ISSET(curclient->id, &rfds))
				GsHandleClient(curclient->id);
			curclient = curclient_next;
		}

#if HAVE_VNCSERVER && !VNCSERVER_PTHREADED
		rfbProcessEvents(rfbScreen, 0);
#endif
		
#endif /* NONETWORK */
	} 
	else if (e == 0)		/* timeout*/
	{
#if NONETWORK
		/* 
		 * Timeout has occured. Currently return a timeout event
		 * regardless of whether client has selected for it.
		 * Note: this will be changed back to GR_EVENT_TYPE_NONE
		 * for the GrCheckNextEvent/LINK_APP_TO_SERVER case
		 */
#if MW_FEATURE_TIMERS
		if(GdTimeout())
#endif
		{
			GR_EVENT_GENERAL *	gp;
			if ((gp = (GR_EVENT_GENERAL *)GsAllocEvent(curclient)) != NULL)
				gp->type = GR_EVENT_TYPE_TIMEOUT;
		}
#else /* !NONETWORK */
#if MW_FEATURE_TIMERS
		/* check for timer timeouts and service if found*/
		GdTimeout();
#endif
#endif /* NONETWORK */
	} else if(errno != EINTR)
		EPRINTF("Select() call in main failed\n");
}
Example #15
0
/* This is a bit of a misnomer - this will deliver the normal events
   but it doesn't bother doing any sort of bounds checking or anything,
   we just start at the "focus" window and try to deliver events to the path
*/
void
GsDeliverRawMouseEvent(int rx, int ry, int buttons, int modifiers)
{
	int i;

	GR_WINDOW *wp;		/* current window */
	GR_CLIENT *client;	/* current client */
	GR_WINDOW_ID subwid;	/* subwindow id event is for */

	GR_EVENT_CLIENT *ecp;

	/* Start with the "focus" window and move up */
	/* Since the raw mouse position doesn't match the actual
	   geometry, this is all we can do */
	wp = mousewp;
	subwid = wp->id;

	for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
		GR_EVENT_MOUSE *ep;

		if ((ecp->eventmask & GR_EVENT_MASK_MOUSE_POSITION) == 0)
			continue;

		client = ecp->client;

		GsFreePositionEvent(client, wp->id, subwid);

		ep = (GR_EVENT_MOUSE *) GsAllocEvent(client);
		if (ep == NULL)
			continue;

		ep->type = GR_EVENT_TYPE_MOUSE_POSITION;
		ep->wid = wp->id;
		ep->subwid = subwid;
		ep->rootx = rx;
		ep->rooty = ry;
		ep->x = 0;	/* These make no sense in raw mode */
		ep->y = 0;
		ep->buttons = buttons;
		ep->modifiers = modifiers;

		if ((wp == rootwp)
		    || (wp->nopropmask & GR_EVENT_MASK_MOUSE_POSITION))
			break;

		wp = wp->parent;
	}

	/* Deliver button events if we have to */
	for (i = 0; i < 2; i++) {
		GR_EVENT_BUTTON *gp;
		unsigned long cbuttons = 0;
		GR_EVENT_TYPE etype = (i == 0) ? GR_EVENT_TYPE_BUTTON_DOWN :
			GR_EVENT_TYPE_BUTTON_UP;

		if (i == 0)
			cbuttons = (curbuttons & ~buttons);
		else
			cbuttons = (~buttons & curbuttons);
		if (!cbuttons)
			continue;

		wp = mousewp;
		subwid = wp->id;

		for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
			client = ecp->client;

			if ((ecp->eventmask & GR_EVENTMASK(etype)) == 0)
				continue;

			gp = (GR_EVENT_BUTTON *) GsAllocEvent(ecp->client);

			if (gp == NULL)
				continue;

			gp->type = etype;
			gp->wid = wp->id;
			gp->subwid = subwid;
			gp->rootx = rx;
			gp->rooty = ry;
			gp->x = 0;
			gp->y = 0;
			gp->buttons = buttons;
			gp->changebuttons = cbuttons;
			gp->modifiers = modifiers;
			gp->time = GsGetTickCount();

			if ((wp == rootwp) || (wp->nopropmask & GR_EVENTMASK(etype)))
				break;

			wp = wp->parent;
		}
	}

	curbuttons = buttons;
}
Example #16
0
/*
 * Deliver a mouse button event to the clients which have selected for it.
 * Each client can only be delivered one instance of the event.  The window
 * the event is delivered for is either the smallest one containing the
 * mouse coordinates, or else one of its direct ancestors.  The lowest
 * window in that tree which has enabled for the event gets it.  This scan
 * is done independently for each client.  If a window with the correct
 * noprop mask is reached, or if no window selects for the event, then the
 * event is discarded for that client.  Special case: for the first client
 * that is enabled for both button down and button up events in a window,
 * then the pointer is implicitly grabbed by that window when a button is
 * pressed down in that window.  The grabbing remains until all buttons are
 * released.  While the pointer is grabbed, no other clients or windows can
 * receive button down or up events.
 */
void GsDeliverButtonEvent(GR_EVENT_TYPE type, int buttons, int changebuttons,
			int modifiers)
{
	GR_EVENT_BUTTON	*ep;		/* mouse button event */
	GR_WINDOW	*wp;		/* current window */
	GR_EVENT_CLIENT	*ecp;		/* current event client */
	GR_CLIENT	*client;	/* current client */
	GR_WINDOW_ID	subwid;		/* subwindow id event is for */
	GR_EVENT_MASK	eventmask;	/* event mask */
	GR_EVENT_MASK	tempmask;	/* to get around compiler bug */

	eventmask = GR_EVENTMASK(type);
	if (eventmask == 0)
		return;

	/*
	 * If the pointer is implicitly grabbed, then the only window
	 * which can receive button events is that window.  Otherwise
	 * the window the pointer is in gets the events.  Determine the
	 * subwindow by seeing if it is a child of the grabbed button.
	 */
	wp = mousewp;
	subwid = wp->id;

	if (grabbuttonwp) {
#if 0
		while ((wp != rootwp) && (wp != grabbuttonwp))
			wp = wp->parent;
		if (wp != grabbuttonwp)
			subwid = grabbuttonwp->id;
#endif
		wp = grabbuttonwp;
	}

	for (;;) {
		for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
			if ((ecp->eventmask & eventmask) == 0)
				continue;

			client = ecp->client;

			/*
			 * If this is a button down, the buttons are not
			 * yet grabbed, and this client is enabled for both
			 * button down and button up events, then implicitly
			 * grab the window for him.
			 */
			if ((type == GR_EVENT_TYPE_BUTTON_DOWN)
				&& (grabbuttonwp == NULL))
			{
				tempmask = GR_EVENT_MASK_BUTTON_UP;
				if (ecp->eventmask & tempmask) {
					DPRINTF("nano-X: implicit grab on window %d\n", wp->id);
					grabbuttonwp = wp;
				}
			}

			ep = (GR_EVENT_BUTTON *) GsAllocEvent(client);
			if (ep == NULL)
				continue;

			ep->type = type;
			ep->wid = wp->id;
			ep->subwid = subwid;
			ep->rootx = cursorx;
			ep->rooty = cursory;
			ep->x = cursorx - wp->x;
			ep->y = cursory - wp->y;
			ep->buttons = buttons;
			ep->changebuttons = changebuttons;
			ep->modifiers = modifiers;
			ep->time = GsGetTickCount();
		}

		/*
		 * Events do not propagate if the window was grabbed.
		 * Also release the grab if the buttons are now all released,
		 * which can cause various events.
		 */
		if (grabbuttonwp) {
			if (buttons == 0) {
				DPRINTF("nano-X: implicit ungrab on window %d\n", grabbuttonwp->id);
				grabbuttonwp = NULL;
				GrMoveCursor(cursorx, cursory);
			}
			return;
		}

		if ((wp == rootwp) || (wp->nopropmask & eventmask))
			return;

		wp = wp->parent;
	}
}
Example #17
0
/*
 * Deliver a mouse motion event to the clients which have selected for it.
 * Each client can only be delivered one instance of the event.  The window
 * the event is delivered for is either the smallest one containing the
 * mouse coordinates, or else one of its direct ancestors.  The lowest
 * window in that tree which has enabled for the event gets it.  This scan
 * is done independently for each client.  If a window with the correct
 * noprop mask is reached, or if no window selects for the event, then the
 * event is discarded for that client.  Special case: If the event type is
 * GR_EVENT_TYPE_MOUSE_POSITION, then only the last such event is queued for
 * any single client to reduce events.  If the mouse is implicitly grabbed,
 * then only the grabbing window receives the events, and continues to do
 * so even if the mouse is currently outside of the grabbing window.
 */
void GsDeliverMotionEvent(GR_EVENT_TYPE type, int buttons, MWKEYMOD modifiers)
{
	GR_EVENT_MOUSE	*ep;		/* mouse motion event */
	GR_WINDOW	*wp;		/* current window */
	GR_EVENT_CLIENT	*ecp;		/* current event client */
	GR_CLIENT	*client;	/* current client */
	GR_WINDOW_ID	subwid;		/* subwindow id event is for */
	GR_EVENT_MASK	eventmask;	/* event mask */

	eventmask = GR_EVENTMASK(type);
	if (eventmask == 0)
		return;

	wp = mousewp;
	subwid = wp->id;

	if (grabbuttonwp) {
#if 0
		while ((wp != rootwp) && (wp != grabbuttonwp))
			wp = wp->parent;
		if (wp != grabbuttonwp)
			subwid = grabbuttonwp->id;
#endif
		wp = grabbuttonwp;
	}

	for (;;) {
		for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
			if ((ecp->eventmask & eventmask) == 0)
				continue;

			client = ecp->client;

			/*
			 * If the event is for just the latest position,
			 * then search the event queue for an existing
			 * event of this type (if any), and free it.
			 */
			if (type == GR_EVENT_TYPE_MOUSE_POSITION) 
				GsFreePositionEvent(client, wp->id, subwid);

			ep = (GR_EVENT_MOUSE *) GsAllocEvent(client);
			if (ep == NULL)
				continue;

			ep->type = type;
			ep->wid = wp->id;
			ep->subwid = subwid;
			ep->rootx = cursorx;
			ep->rooty = cursory;
			ep->x = cursorx - wp->x;
			ep->y = cursory - wp->y;
			ep->buttons = buttons;
			ep->modifiers = modifiers;
		}

		if ((wp == rootwp) || grabbuttonwp ||
			(wp->nopropmask & eventmask))
				return;

		wp = wp->parent;
	}
}
Example #18
0
void
GsSelect(GR_TIMEOUT timeout)
{
	fd_set	rfds;
	int 	e;
	int	setsize = 0;
	struct timeval tout;
	struct timeval *to;
#if NONETWORK
	int	fd;
#endif

	/* perform pre-select duties, if any*/
	if(rootwp->psd->PreSelect)
		rootwp->psd->PreSelect(rootwp->psd);

	/* Set up the FDs for use in the main select(): */
	FD_ZERO(&rfds);
	if(mouse_fd >= 0) {
		FD_SET(mouse_fd, &rfds);
		if (mouse_fd > setsize)
			setsize = mouse_fd;
	}
	if(keyb_fd >= 0) {
		FD_SET(keyb_fd, &rfds);
		if (keyb_fd > setsize)
			setsize = keyb_fd;
	}
#ifdef MW_FEATURE_TWO_KEYBOARDS
	if(keyb2_fd >= 0) {
		FD_SET(keyb2_fd, &rfds);
		if (keyb2_fd > setsize)
			setsize = keyb2_fd;
	}
#endif
#if NONETWORK
	/* handle registered input file descriptors*/
	for (fd = 0; fd < regfdmax; fd++) {
		if (!FD_ISSET(fd, &regfdset))
			continue;

		FD_SET(fd, &rfds);
		if (fd > setsize) setsize = fd;
	}
#else /* not NONETWORK */
	/* handle client socket connections*/
	FD_SET(un_sock, &rfds);
	if (un_sock > setsize) setsize = un_sock;
	curclient = root_client;
	while(curclient) {
		if(curclient->waiting_for_event && curclient->eventhead) {
			curclient->waiting_for_event = FALSE;
			GrGetNextEventWrapperFinish(curclient->id);
			return;
		}
		FD_SET(curclient->id, &rfds);
		if(curclient->id > setsize) setsize = curclient->id;
		curclient = curclient->next;
	}
#endif /* NONETWORK */
	/* Set up the timeout for the main select(): */
	if (timeout == (GR_TIMEOUT) -1L) {
		/* poll*/
		tout.tv_sec = 0;
		tout.tv_usec = 0;
		to = &tout;
	} else {
#if MW_FEATURE_TIMERS
		if(GdGetNextTimeout(&tout, timeout) == TRUE)
			to = &tout;
		else
#endif /* MW_FEATURE_TIMERS */
			to = NULL;
	}

	/* Wait for some input on any of the fds in the set or a timeout: */
	if((e = select(setsize+1, &rfds, NULL, NULL, to)) > 0) {
		/* If data is present on the mouse fd, service it: */
		if(mouse_fd >= 0 && FD_ISSET(mouse_fd, &rfds))
			while(GsCheckMouseEvent())
				continue;

		/* If data is present on the keyboard fd, service it: */
		if( (keyb_fd >= 0 && FD_ISSET(keyb_fd, &rfds))
#ifdef MW_FEATURE_TWO_KEYBOARDS
		 || (keyb2_fd >= 0 && FD_ISSET(keyb2_fd, &rfds))
#endif
		  )
			while(GsCheckKeyboardEvent())
				continue;

#if NONETWORK
		/* check for input on registered file descriptors */
		for (fd = 0; fd < regfdmax; fd++) {
			GR_EVENT_FDINPUT *	gp;

			if (!FD_ISSET(fd, &regfdset)  ||  !FD_ISSET(fd, &rfds))
				continue;

			gp =(GR_EVENT_FDINPUT *)GsAllocEvent(curclient);
			if(gp) {
				gp->type = GR_EVENT_TYPE_FDINPUT;
				gp->fd = fd;
			}
		}
#else /* not NONETWORK */

		/* If a client is trying to connect, accept it: */
		if(FD_ISSET(un_sock, &rfds))
			GsAcceptClient();

		/* If a client is sending us a command, handle it: */
		curclient = root_client;
		while(curclient) {
			GR_CLIENT *curclient_next;

			/* curclient may be freed in GsDropClient*/
			curclient_next = curclient->next;
			if(FD_ISSET(curclient->id, &rfds))
				GsHandleClient(curclient->id);
			curclient = curclient_next;
		}
#endif /* NONETWORK */
	}
	else if (e == 0) {
#if NONETWORK
		/*
		 * Timeout has occured.  Currently return
		 * a timeout event regardless of whether
		 * client has selected for it.
		 * Note: this will be changed back to GR_EVENT_TYPE_NONE
		 * for the GrCheckNextEvent/LINK_APP_TO_SERVER case
		 */
#if MW_FEATURE_TIMERS
		if(GdTimeout() == TRUE)
#endif
		{
			GR_EVENT_GENERAL *	gp;
			gp = (GR_EVENT_GENERAL *)GsAllocEvent(curclient);
			if(gp)
				gp->type = GR_EVENT_TYPE_TIMEOUT;
		}
#else /* not NONETWORK */
#if MW_FEATURE_TIMERS
		GdTimeout();
#endif
#endif /* NONETWORK */
	} else
		if(errno != EINTR)
			EPRINTF("Select() call in main failed\n");
}
Example #19
0
/*
 * Deliver a keyboard event to one of the clients which have selected for it.
 * Only the first client found gets the event (no duplicates are sent).  The
 * window the event is delivered to is either the smallest one containing
 * the mouse coordinates, or else one of its direct ancestors (if such a
 * window is a descendant of the focus window), or else just the focus window.
 * The lowest window in that tree which has enabled for the event gets it.
 * If a window with the correct noprop mask is reached, or if no window selects
 * for the event, then the event is discarded.
 */
void GsDeliverKeyboardEvent(GR_WINDOW_ID wid, GR_EVENT_TYPE type,
	GR_KEY keyvalue, GR_KEYMOD modifiers, GR_SCANCODE scancode)
{
	GR_EVENT_KEYSTROKE	*ep;		/* keystroke event */
	GR_WINDOW		*wp;		/* current window */
	GR_WINDOW		*tempwp;	/* temporary window pointer */
	GR_EVENT_CLIENT		*ecp;		/* current event client */
	GR_WINDOW_ID		subwid;		/* subwindow id event is for */
	GR_EVENT_MASK		eventmask;	/* event mask */
	GR_WINDOW		*kwp;
	GR_GRABBED_KEY		*keygrab;

	eventmask = GR_EVENTMASK(type);
	if (eventmask == 0)
		return;

	GsResetScreenSaver();

	/* Check for grabbed keystroke.
	 * - GR_GRAB_HOTKEY events are sent (possibly multiple times) here,
	 *   and the loop terminates normally with keygrab==NULL so the
	 *   event is also delivered normally.
	 * - GR_GRAB_HOTKEY_EXCLUSIVE sends the hotkey events then returns.
	 * - Other exclusive events (GR_GRAB_EXCLUSIVE_MOUSE and GR_GRAB_EXCLUSIVE)
	 *   cause the loop to terminate with keygrab != NULL.  The checking
	 *   for these events happens after the loop.
	 *
	 * Note: This algorithm requires any GR_GRAB_HOTKEY grabs to be
	 * listed _after_ any exclusive grabs for the same key.  The
	 * GrGrabKey() and GrUngrabKey() methods ensure this property holds.
	 */
	for (keygrab = list_grabbed_keys; keygrab != NULL; keygrab = keygrab->next) {
		if (keygrab->key == keyvalue) {
			if ((keygrab->type == GR_GRAB_HOTKEY)
			 || (keygrab->type == GR_GRAB_HOTKEY_EXCLUSIVE)) {
				ep = (GR_EVENT_KEYSTROKE *) GsAllocEvent(keygrab->owner);
				if (ep == NULL)
					continue;

				ep->type = type;
				ep->wid = keygrab->wid;
				ep->subwid = keygrab->wid;
				ep->rootx = cursorx;
				ep->rooty = cursory;
				ep->x = cursorx;
				ep->y = cursory;
				ep->buttons = curbuttons;
				ep->modifiers = modifiers;
				ep->ch = keyvalue;
				ep->scancode = scancode;
				ep->hotkey = GR_TRUE;
				if (keygrab->type == GR_GRAB_HOTKEY_EXCLUSIVE)
					return;	/* only one client gets it */
			} else {
				/* GR_GRAB_EXCLUSIVE or GR_GRAB_EXCLUSIVE_MOUSE */
				break; /* found it, exit the loop. */
			}
		}
	}

	/* Handle a grabbed key:
	 * The associated window must be an ancestor of the focused window,
	 * or (for GR_GRAB_EXCLUSIVE_MOUSE only) a descendent that contains the
	 * pointer.
	 */
	if (keygrab != NULL) {
		/* The key grab must be of type GR_GRAB_EXCLUSIVE or
		 * GR_GRAB_EXCLUSIVE_MOUSE
		 */

		/* Find the window that has the grab */
		wp = GsFindWindow(keygrab->wid);
		if (wp == NULL)
			return; /* Key is reserved by window that doesn't exist. */

		/* See if the grabbing window is an ancestor of the focussed window. */
		kwp = focuswp;
		while (kwp != wp && kwp != rootwp)
			kwp = kwp->parent;

		/* Want to send event if:
		 * GR_GRAB_EXCLUSIVE: grabbing window is an ancestor of focussed window
		 * GR_GRAB_EXCLUSIVE_MOUSE: same as GR_GRAB_EXCLUSIVE OR
		 *                    the mouse is in the grabbing window.
		 */
		if (kwp != wp && (keygrab->type != GR_GRAB_EXCLUSIVE_MOUSE || wp != mousewp))
			return;

		subwid = wp->id;
	} else {
		/* if window id passed, use it, otherwise focus window */
		if (wid) {
			kwp = GsFindWindow(wid);
			if (!kwp)
				return;
		} else
			kwp = focuswp;
		wp = mousewp;
		subwid = wp->id;

		/*
		 * See if the actual window the pointer is in is a descendant of
		 * the focus window.  If not, then ignore it, and force the input
		 * into the focus window itself.
		 */
		tempwp = wp;
		while (tempwp != kwp && tempwp != rootwp)
			tempwp = tempwp->parent;

		if (tempwp != kwp) {
			wp = kwp;
			subwid = wp->id;
		}
	}

	/*
	 * Now walk upwards looking for the first window which will accept
	 * the keyboard event.  However, do not go beyond the focus window,
	 * and only give the event to one client.
	 */
	for (;;) {
		for (ecp = wp->eventclients; ecp; ecp = ecp->next) {

			if ((ecp->eventmask & eventmask) == 0)
				continue;

			ep = (GR_EVENT_KEYSTROKE *) GsAllocEvent(ecp->client);
			if (ep == NULL)
				return;

			ep->type = type;
			ep->wid = wp->id;
			ep->subwid = subwid;
			ep->rootx = cursorx;
			ep->rooty = cursory;
			ep->x = cursorx - wp->x;
			ep->y = cursory - wp->y;
			ep->buttons = curbuttons;
			ep->modifiers = modifiers;
			ep->ch = keyvalue;
			ep->scancode = scancode;
			ep->hotkey = GR_FALSE;
			return;			/* only one client gets it */
		}

		if ((wp == rootwp) || (wp == kwp) ||
			(wp->nopropmask & eventmask))
				return;

		wp = wp->parent;
	}
}
Example #20
0
void
GsSelect(void)
{
	fd_set	rfds;
	int 	e;
	int	setsize = 0;
	struct timeval to;

	/* Set up the FDs for use in the main select(): */
	FD_ZERO(&rfds);
	FD_SET(mouse_fd, &rfds);
	FD_SET(keyb_fd, &rfds);
	if (mouse_fd > setsize) setsize = mouse_fd;
	if (keyb_fd > setsize) setsize = keyb_fd;
#if NONETWORK
	/* handle registered input file descriptors*/
	if (regfd != -1) {
		FD_SET(regfd, &rfds);
		if (regfd > setsize) setsize = regfd;
	}
#else
	/* handle client socket connections*/
	FD_SET(un_sock, &rfds);
	if (un_sock > setsize) setsize = un_sock;
	curclient = root_client;
	while(curclient) {
		if(curclient->waiting_for_event && curclient->eventhead) {
			curclient->waiting_for_event = FALSE;
			GsGetNextEventWrapperFinish();
			return;
		}
		FD_SET(curclient->id, &rfds);
		if(curclient->id > setsize) setsize = curclient->id;
		curclient = curclient->next;
	}
#endif
	++setsize;

	/* Set up the timeout for the main select(): */
	to.tv_sec = 0L;
	to.tv_usec = 10000L;

	/* Wait for some input on any of the fds in the set or a timeout: */
	if((e = select(setsize, &rfds, NULL, NULL, &to)) > 0) {
		
		/* If data is present on the mouse fd, service it: */
		if(FD_ISSET(mouse_fd, &rfds))
			GsCheckMouseEvent();

		/* If data is present on the keyboard fd, service it: */
		if(FD_ISSET(keyb_fd, &rfds))
			GsCheckKeyboardEvent();

#if NONETWORK
		/* If registered input descriptor, handle it*/
		if(regfd != -1 && FD_ISSET(regfd, &rfds)) {
			GR_EVENT_FDINPUT *	gp;
			gp = (GR_EVENT_FDINPUT *)GsAllocEvent(curclient);
			if(gp) {
				gp->type = GR_EVENT_TYPE_FDINPUT;
				gp->fd = regfd;
			}
		}
#else
		/* If a client is trying to connect, accept it: */
		if(FD_ISSET(un_sock, &rfds))
			GsAcceptClient();

		/* If a client is sending us a command, handle it: */
		curclient = root_client;
		while(curclient) {
			if(FD_ISSET(curclient->id, &rfds))
				GsHandleClient(curclient->id);
			curclient = curclient->next;
		}
#endif

	} 
	else if(!e) {
#if FRAMEBUFFER | BOGL
		if(fb_CheckVtChange())
			GsRedrawScreen();
#endif
	} else
		if(errno != EINTR)
			perror("Select() call in main failed");
}
Example #21
0
/*
 * Deliver a keyboard event to one of the clients which have selected for it.
 * Only the first client found gets the event (no duplicates are sent).  The
 * window the event is delivered to is either the smallest one containing
 * the mouse coordinates, or else one of its direct ancestors (if such a
 * window is a descendant of the focus window), or else just the focus window.
 * The lowest window in that tree which has enabled for the event gets it.
 * If a window with the correct noprop mask is reached, or if no window selects
 * for the event, then the event is discarded.
 */
void GsDeliverKeyboardEvent(GR_EVENT_TYPE type, GR_CHAR ch, MODIFIER modifiers)
{
	GR_EVENT_KEYSTROKE	*ep;		/* keystroke event */
	GR_WINDOW		*wp;		/* current window */
	GR_WINDOW		*tempwp;	/* temporary window pointer */
	GR_EVENT_CLIENT		*ecp;		/* current event client */
	GR_WINDOW_ID		subwid;		/* subwindow id event is for */
	GR_EVENT_MASK		eventmask;	/* event mask */

	eventmask = GR_EVENTMASK(type);
	if (eventmask == 0)
		return;

	wp = mousewp;
	subwid = wp->id;

	/*
	 * See if the actual window the pointer is in is a descendant of
	 * the focus window.  If not, then ignore it, and force the input
	 * into the focus window itself.
	 */
	tempwp = wp;
	while ((tempwp != focuswp) && (tempwp != rootwp))
		tempwp = tempwp->parent;

	if (tempwp != focuswp) {
		wp = focuswp;
		subwid = wp->id;
	}

	/*
	 * Now walk upwards looking for the first window which will accept
	 * the keyboard event.  However, do not go beyond the focus window,
	 * and only give the event to one client.
	 */
	for (;;) {
		for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
			if ((ecp->eventmask & eventmask) == 0)
				continue;

			ep = (GR_EVENT_KEYSTROKE *) GsAllocEvent(ecp->client);
			if (ep == NULL)
				return;

			ep->type = type;
			ep->wid = wp->id;
			ep->subwid = subwid;
			ep->rootx = cursorx;
			ep->rooty = cursory;
			ep->x = cursorx - wp->x;
			ep->y = cursory - wp->y;
			ep->buttons = curbuttons;
			ep->modifiers = modifiers;
			ep->ch = ch;
			return;			/* only one client gets it */
		}

		if ((wp == rootwp) || (wp == focuswp) ||
			(wp->nopropmask & eventmask))
				return;

		wp = wp->parent;
	}
}