⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 srvevent.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 2 页
字号:
 * 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;

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

	GsResetScreenSaver();

	/* 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;
			return;			/* only one client gets it */
		}

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

		wp = wp->parent;
	}
}

/*
 * 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->unmapcount || !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;
	}
}

/*
 * Search for an enclosed expose event in the specified client's
 * event queue, and remove it.  This is used to prevent multiple expose
 * events from being delivered, thus providing a more pleasing visual
 * redraw effect than if the events were all sent.
 */
void
GsFreeExposureEvent(GR_CLIENT *client, GR_WINDOW_ID wid, GR_COORD x,
	GR_COORD y, GR_SIZE width, GR_SIZE height)
{
	GR_EVENT_LIST	*elp;		/* current element list */
	GR_EVENT_LIST	*prevelp;	/* previous element list */

	prevelp = NULL;
	for (elp = client->eventhead; elp; prevelp = elp, elp = elp->next) {
		if (elp->event.type != GR_EVENT_TYPE_EXPOSURE ||
		    elp->event.exposure.wid != wid)
			continue;
		if (elp->event.exposure.x < x || elp->event.exposure.y < y ||
		    elp->event.exposure.x+elp->event.exposure.width > x+width ||
		    elp->event.exposure.y+elp->event.exposure.height > y+height)
			continue;

		/*
		 * Found one, remove it and put it back on the free list.
		 */
		if (prevelp)
			prevelp->next = elp->next;
		else
			client->eventhead = elp->next;
		if (client->eventtail == elp)
			client->eventtail = prevelp;

		elp->next = eventfree;
		eventfree = elp;
		return;
	}
}

/*
 * 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;
	}
}

/*
 * 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;
	}
}

/*
 * 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;
		}
	}
}

/*
 * 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;
	}
}

/*
 * 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;
	}
}

/*
 * 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;
	}
}

/*
 * Search for a matching mouse position event in the specified client's
 * event queue, and remove it.  This is used to prevent multiple position
 * events from being delivered, thus providing a more efficient rubber-
 * banding effect than if the mouse motion events were all sent.
 */
void
GsFreePositionEvent(GR_CLIENT *client, GR_WINDOW_ID wid, GR_WINDOW_ID subwid)
{
	GR_EVENT_LIST	*elp;		/* current element list */
	GR_EVENT_LIST	*prevelp;	/* previous element list */

	prevelp = NULL;
	for (elp = client->eventhead; elp; prevelp = elp, elp = elp->next) {
		if (elp->event.type != GR_EVENT_TYPE_MOUSE_POSITION)
			continue;
		if (elp->event.mouse.wid != wid)
			continue;
		if (elp->event.mouse.subwid != subwid)
			continue;

		/*
		 * Found one, remove it and put it back on the free list.
		 */
		if (prevelp)
			prevelp->next = elp->next;
		else
			client->eventhead = elp->next;
		if (client->eventtail == elp)
			client->eventtail = prevelp;

		elp->next = eventfree;
		eventfree = elp;
		return;
	}
}

/*
 * 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;

		fprintf(stderr, "Delivering a selection changed event\n");
		gp = (GR_EVENT_SELECTION_CHANGED *) GsAllocEvent(ecp->client);
		if (gp == NULL)
			continue;

		gp->type = GR_EVENT_TYPE_SELECTION_CHANGED;
		gp->new_owner = new_owner;
	}
}

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;
        }
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -