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

📄 srvevent.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 2000 Greg Haerr <greg@censoft.com> * Copyright (c) 1991 David I. Bell * Permission is granted to use, distribute, or modify this source, * provided that this copyright notice remains intact. * * Graphics server event routines for windows. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include "serv.h"#ifndef __ECOS/* readable error strings*/char *nxErrorStrings[] = {	GR_ERROR_STRINGS};#endif#if NONETWORK/* [copied from client.c] * The following is the user defined function for handling errors. * If this is not set, then the default action is to close the connection * to the server, describe the error, and then exit.  This error function * will only be called when the client asks for events. */static GR_FNCALLBACKEVENT ErrorFunc = GrDefaultErrorHandler;/*  * The default error handler which is called when the server * reports an error event and the client hasn't set a handler for error events. */void GrDefaultErrorHandler(GR_EVENT *ep){	if (ep->type == GR_EVENT_TYPE_ERROR) {		EPRINTF("nxclient: Error (%s) ", ep->error.name);		EPRINTF(nxErrorStrings[ep->error.code], ep->error.id);		GrClose();		exit(1);	}}/* * Set an error handling routine, which will be called on any errors from * the server (when events are asked for by the client).  If zero is given, * then errors will be returned as regular events.   * Returns the previous error handler. */GR_FNCALLBACKEVENTGrSetErrorHandler(GR_FNCALLBACKEVENT fncb){	GR_FNCALLBACKEVENT orig = ErrorFunc;	ErrorFunc = fncb;	return orig;}#endif /* NONETWORK*//* * 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;	/* 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;}/* * Allocate an event to be passed back to the specified client. * The event is already chained onto the event queue, and only * needs filling out.  Returns NULL with an error generated if * the event cannot be allocated. */GR_EVENT *GsAllocEvent(GR_CLIENT *client){	GR_EVENT_LIST	*elp;		/* current element list */	GR_CLIENT	*oldcurclient;	/* old current client */	/*	 * Get a new event structure from the free list, or else	 * allocate it using malloc.	 */	elp = eventfree;	if (elp)		eventfree = elp->next;	else {		elp = (GR_EVENT_LIST *) malloc(sizeof(GR_EVENT_LIST));		if (elp == NULL) {			oldcurclient = curclient;			curclient = client;			GsError(GR_ERROR_MALLOC_FAILED, 0);			curclient = oldcurclient;			return NULL;		}	}	/*	 * Add the event to the end of the event list.	 */	if (client->eventhead)		client->eventtail->next = elp;	else		client->eventhead = elp;	client->eventtail = elp;	elp->next = NULL;	elp->event.type = GR_EVENT_TYPE_NONE;	return &elp->event;}/* * Update mouse status and issue events on it if necessary. * This function doesn't block, but is normally only called when * there is known to be some data waiting to be read from the mouse. */GR_BOOL GsCheckMouseEvent(void){	GR_COORD	rootx;		/* latest mouse x position */	GR_COORD	rooty;		/* latest mouse y position */	int		newbuttons;	/* latest buttons */	int		mousestatus;	/* latest mouse status */	/* Read the latest mouse status: */	mousestatus = GdReadMouse(&rootx, &rooty, &newbuttons);	if(mousestatus < 0) {		GsError(GR_ERROR_MOUSE_ERROR, 0);		return FALSE;	} else if(mousestatus) {	/* Deliver events as appropriate: */			GsHandleMouseStatus(rootx, rooty, newbuttons);		/* possibly reset portrait mode based on mouse position*/		if (autoportrait)			GsSetPortraitModeFromXY(rootx, rooty);		return TRUE;	}	return FALSE;}/* * Update keyboard status and issue events on it if necessary. * This function doesn't block, but is normally only called when * there is known to be some data waiting to be read from the keyboard. */GR_BOOL GsCheckKeyboardEvent(void){	MWKEY	 	mwkey;		/* latest character */	MWKEYMOD 	modifiers;	/* latest modifiers */	MWSCANCODE	scancode;	int	 	keystatus;	/* latest keyboard status */	/* Read the latest keyboard status: */	keystatus = GdReadKeyboard(&mwkey, &modifiers, &scancode);	if(keystatus < 0) {		if(keystatus == -2)	/* special case return code*/			GsTerminate();		GsError(GR_ERROR_KEYBOARD_ERROR, 0);		return FALSE;	} else if(keystatus) {		/* Deliver events as appropriate: */			switch (mwkey) {		case MWKEY_QUIT:			GsTerminate();			/* no return*/		case MWKEY_REDRAW:			GsRedrawScreen();			break;		case MWKEY_PRINT:			if (keystatus == 1)				GdCaptureScreen("screen.bmp");			break;		}		GsDeliverKeyboardEvent(0,			(keystatus==1?			GR_EVENT_TYPE_KEY_DOWN: GR_EVENT_TYPE_KEY_UP),			mwkey, modifiers, scancode);		return TRUE;	}	return FALSE;}/* * Handle all mouse events.  These are mouse enter, mouse exit, mouse * motion, mouse position, button down, and button up.  This also moves * the cursor to the new mouse position and changes it shape if needed. */void GsHandleMouseStatus(GR_COORD newx, GR_COORD newy, int newbuttons){	int	 changebuttons;	/* buttons that have changed */	MWKEYMOD modifiers;	/* latest modifiers */	GdGetModifierInfo(NULL, &modifiers); /* Read kbd modifiers */	/*	 * First, if the mouse has moved, then position the cursor to the	 * new location, which will send mouse enter, mouse exit, focus in,	 * and focus out events if needed.  Check here for mouse motion and	 * mouse position events.  Flush the device queue to make sure the	 * new cursor location is quickly seen by the user.	 */	if ((newx != cursorx) || (newy != cursory)) {		GsResetScreenSaver();		GrMoveCursor(newx, newy);		GsDeliverMotionEvent(GR_EVENT_TYPE_MOUSE_MOTION,			newbuttons, modifiers);		GsDeliverMotionEvent(GR_EVENT_TYPE_MOUSE_POSITION,			newbuttons, modifiers);	}	/*	 * Next, generate a button up event if any buttons have been released.	 */	changebuttons = (curbuttons & ~newbuttons);	if (changebuttons) {		GsResetScreenSaver();		GsDeliverButtonEvent(GR_EVENT_TYPE_BUTTON_UP,			newbuttons, changebuttons, modifiers);	}	/*	 * Finally, generate a button down event if any buttons have been	 * pressed.	 */	changebuttons = (~curbuttons & newbuttons);	if (changebuttons) {		GsResetScreenSaver();		GsDeliverButtonEvent(GR_EVENT_TYPE_BUTTON_DOWN,			newbuttons, changebuttons, modifiers);	}	curbuttons = newbuttons;}/* * 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) {		while ((wp != rootwp) && (wp != grabbuttonwp))			wp = wp->parent;#if 0		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) {				grabbuttonwp = NULL;				GrMoveCursor(cursorx, cursory);			}			return;		}		if ((wp == rootwp) || (wp->nopropmask & eventmask))			return;		wp = wp->parent;	}}/* * 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) {		while ((wp != rootwp) && (wp != grabbuttonwp))			wp = wp->parent;#if 0		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;	}}/* * 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

⌨️ 快捷键说明

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