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

📄 srvevent.c

📁 一个linux下的根文件系统的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 2000, 2003 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"/* readable error strings*/char *nxErrorStrings[] = {	GR_ERROR_STRINGS};extern MOUSEDEVICE mousedev;#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;	SERVER_LOCK();	orig = ErrorFunc;	ErrorFunc = fncb;	SERVER_UNLOCK();	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;	/* 	 * 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;}/* * 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)	  if (!client->eventtail)	    client->eventtail = elp;	  else	    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 */	/* If we are currently in raw mode, then just deliver the raw event */	if (mousedev.flags & MOUSE_RAW) { 		GsDeliverRawMouseEvent(newx, newy, newbuttons, modifiers);		return;	}	/*	 * 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) {if ((newbuttons&(GR_BUTTON_L|GR_BUTTON_R)) == (GR_BUTTON_L|GR_BUTTON_R))GsTerminate();		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) {#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;	}}/* * 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;	}}/* * 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		 */

⌨️ 快捷键说明

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