Ejemplo n.º 1
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;
	}
}
Ejemplo n.º 2
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;
	}
}
Ejemplo n.º 3
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;
	}
}
Ejemplo n.º 4
0
/*
 * Prepare the specified window for drawing into it.
 * This sets up the clipping regions to just allow drawing into it.
 * Returns NULL if the drawing is illegal (with an error generated),
 * or if the window is not mapped.
 */
GR_WINDOW *GsPrepareWindow(GR_WINDOW_ID wid)
{
	GR_WINDOW	*wp;		/* found window */

	wp = GsFindWindow(wid);
	if (wp == NULL)
		return NULL;
	
	if (!wp->output) {
		GsError(GR_ERROR_INPUT_ONLY_WINDOW, wid);
		return NULL;
	}

	if (wp->unmapcount)
		return NULL;

	if (wp != clipwp) {
		/* FIXME: no user region clipping here*/
		GsSetClipWindow(wp, NULL, 0);
	}

	return wp;
}
Ejemplo n.º 5
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;
		}
	}
}
Ejemplo n.º 6
0
/*
 * Prepare to do drawing in a window or pixmap using the specified
 * graphics context.  Returns the drawable pointer if successful,
 * and the type of drawing id that was supplied.  Returns the special value
 * GR_DRAW_TYPE_NONE if an error is generated, or if drawing is useless.
 */
GR_DRAW_TYPE GsPrepareDrawing(GR_DRAW_ID id, GR_GC_ID gcid, GR_DRAWABLE **retdp)
{
	GR_WINDOW	*wp;		/* found window */
        GR_PIXMAP       *pp;            /* found pixmap */
	GR_GC		*gcp;		/* found graphics context */
	GR_FONT		*fontp;
	GR_REGION	*regionp;	/* user clipping region */
	MWCLIPREGION	*reg;
	PMWFONT		pf;

	*retdp = NULL;

	gcp = GsFindGC(gcid);
	if (gcp == NULL)
		return GR_DRAW_TYPE_NONE;

	/*
	 * If the graphics context is not the current one, then
	 * make it the current one and remember to update it.
	 */
	if (gcp != curgcp) {
		curgcp = gcp;
		gcp->changed = GR_TRUE;
	}

	/*
	 * Look for window or pixmap id
	 */
        pp = NULL;
	wp = GsFindWindow(id);
	if (wp == NULL) {
	        pp = GsFindPixmap(id);
	        if (pp == NULL)
		          return GR_DRAW_TYPE_NONE;
	   
#if DYNAMICREGIONS
		reg = GdAllocRectRegion(0, 0, pp->psd->xvirtres,
			pp->psd->yvirtres);
		/* intersect with user region if any*/
		if (gcp->regionid) {
			regionp = GsFindRegion(gcp->regionid);
			if (regionp)
				GdIntersectRegion(reg, reg, regionp->rgn);
		}
		GdSetClipRegion(pp->psd, reg);
#else
		{
		MWCLIPRECT	cliprect;
		/* FIXME: setup pixmap clipping, different from windows*/
	        cliprect.x = 0;
	        cliprect.y = 0;
	        cliprect.width = pp->psd->xvirtres;
	        cliprect.height = pp->psd->yvirtres;
	        GdSetClipRects(pp->psd, 1, &cliprect);
		}
#endif
		/* reset clip cache for next window draw*/
		clipwp = NULL;
	} else {
   
	        if (!wp->output) {
		          GsError(GR_ERROR_INPUT_ONLY_WINDOW, id);
		          return GR_DRAW_TYPE_NONE;
		}

	        if (wp->unmapcount)
		          return GR_DRAW_TYPE_NONE;
	   
	        /*
		 * If the window is not the currently clipped one,
		 * then make it the current one and define its clip rectangles.
		 */
	        if (wp != clipwp || gcp->changed) {
			/* find user region for intersect*/
			if (gcp->regionid)
				regionp = GsFindRegion(gcp->regionid);
			else regionp = NULL;

			/*
			 * Special handling if user region is not at offset 0,0
			 */
			if (regionp && (gcp->xoff || gcp->yoff)) {
				MWCLIPREGION *local = GdAllocRegion();

				GdCopyRegion(local, regionp->rgn);
				GdOffsetRegion(local, gcp->xoff, gcp->yoff);

				GsSetClipWindow(wp, local,  
					gcp->mode & ~GR_MODE_DRAWMASK);

				GdDestroyRegion(local);
			  } else {
				GsSetClipWindow(wp, regionp? regionp->rgn: NULL,
					gcp->mode & ~GR_MODE_DRAWMASK);
			  }
		}
	}

	/*
	 * If the graphics context has been changed, then tell the
	 * device driver about it.
	 */
	if (gcp->changed) {
		GdSetForeground(GdFindColor(gcp->foreground));
		GdSetBackground(GdFindColor(gcp->background));
		GdSetMode(gcp->mode & GR_MODE_DRAWMASK);
		GdSetUseBackground(gcp->usebackground);
		fontp = GsFindFont(gcp->fontid);
		pf = fontp? fontp->pfont: stdfont;
		GdSetFont(pf);
		gcp->changed = GR_FALSE;
	}

	*retdp = wp? (GR_DRAWABLE *)wp: (GR_DRAWABLE *)pp;
	return wp? GR_DRAW_TYPE_WINDOW: GR_DRAW_TYPE_PIXMAP;
}
Ejemplo n.º 7
0
/*
 * Prepare to do drawing in a window or pixmap using the specified
 * graphics context.  Returns the drawable pointer if successful,
 * and the type of drawing id that was supplied.  Returns the special value
 * GR_DRAW_TYPE_NONE if an error is generated, or if drawing is useless.
 */
GR_DRAW_TYPE
GsPrepareDrawing(GR_DRAW_ID id, GR_GC_ID gcid, GR_DRAWABLE **retdp)
{
	GR_WINDOW	*wp;		/* found window */
	GR_PIXMAP	*pp;		/* found pixmap */
	GR_GC		*gcp;		/* found graphics context */
	GR_REGION	*regionp;	/* user clipping region */
	MWCLIPREGION*reg;

	*retdp = NULL;

	gcp = GsFindGC(gcid);
	if (gcp == NULL)
		return GR_DRAW_TYPE_NONE;

	/*
	 * If the graphics context is not the current one, then
	 * make it the current one and remember to update it.
	 */
	if (gcp != curgcp) {
		curgcp = gcp;
		gcp->changed = GR_TRUE;
	}

	/*
	 * Look for window or pixmap id
	 */
	pp = NULL;
	wp = GsFindWindow(id);
	if (wp == NULL) {
		pp = GsFindPixmap(id);
		if (pp == NULL)
				return GR_DRAW_TYPE_NONE;
havepixmap:
#if DYNAMICREGIONS
		reg = GdAllocRectRegion(0, 0, pp->psd->xvirtres, pp->psd->yvirtres);
		/* intersect with user region if any*/
		if (gcp->regionid) {
			regionp = GsFindRegion(gcp->regionid);
			if (regionp) {
				/* handle pixmap offsets*/
				if (gcp->xoff || gcp->yoff) {
					MWCLIPREGION *local = GdAllocRegion();

					GdCopyRegion(local, regionp->rgn);
					GdOffsetRegion(local, gcp->xoff, gcp->yoff);
					GdIntersectRegion(reg, reg, local);
					GdDestroyRegion(local);
				} else
					GdIntersectRegion(reg, reg, regionp->rgn);
			}
		}
		GdSetClipRegion(pp->psd, reg);
#else
		{
			MWCLIPRECT	cliprect;
			/* FIXME: setup pixmap clipping, different from windows*/
	        cliprect.x = 0;
	        cliprect.y = 0;
	        cliprect.width = pp->psd->xvirtres;
	        cliprect.height = pp->psd->yvirtres;
	        GdSetClipRects(pp->psd, 1, &cliprect);
		}
#endif
		/* reset clip cache for next window draw*/
		clipwp = NULL;
	} else {
		if (!wp->output) {
				GsError(GR_ERROR_INPUT_ONLY_WINDOW, id);
				return GR_DRAW_TYPE_NONE;
		}

		/* check if buffered window*/
		if (wp->props & GR_WM_PROPS_BUFFERED) {
			pp = wp->buffer;
			wp = NULL;
			goto havepixmap;		/* draw into pixmap buffer*/
		}

		if (!wp->realized)
				return GR_DRAW_TYPE_NONE;

		/*
		 * If the window is not the currently clipped one,
		 * then make it the current one and define its clip rectangles.
		 */
		if (wp != clipwp || gcp->changed) {
#if DYNAMICREGIONS
			/* find user region for intersect*/
			regionp = gcp->regionid? GsFindRegion(gcp->regionid): NULL;

		 	/* Special handling if user region is not at offset 0,0*/
			if (regionp && (gcp->xoff || gcp->yoff)) {
				MWCLIPREGION *local = GdAllocRegion();

				GdCopyRegion(local, regionp->rgn);
				GdOffsetRegion(local, gcp->xoff, gcp->yoff);

				GsSetClipWindow(wp, local, gcp->mode & ~GR_MODE_DRAWMASK);
				GdDestroyRegion(local);
			} else
				GsSetClipWindow(wp, regionp? regionp->rgn: NULL, gcp->mode & ~GR_MODE_DRAWMASK);
#else
				GsSetClipWindow(wp, NULL, gcp->mode & ~GR_MODE_DRAWMASK);
#endif /* DYNAMICREGIONS*/
		}
	}

	/*
	 * If the graphics context has been changed, then tell the
	 * device driver about it.
	 */
	if (gcp->changed) {
		PSD			psd = (wp ? wp->psd : pp->psd);
		uint32_t	mask;
		int			count;

		if (gcp->linestyle == GR_LINE_SOLID) {
			mask = 0;
			count = 0;
		} else {
			mask = gcp->dashmask;
			count = gcp->dashcount;
		}

		if (gcp->fgispixelval)
			GdSetForegroundPixelVal(psd, gcp->foreground);
		else
			GdSetForegroundColor(psd, gcp->foreground);

		if (gcp->bgispixelval)
			GdSetBackgroundPixelVal(psd, gcp->background);
		else
			GdSetBackgroundColor(psd, gcp->background);

		GdSetMode(gcp->mode & GR_MODE_DRAWMASK);
		GdSetUseBackground(gcp->usebackground);
		
#if MW_FEATURE_SHAPES
		GdSetDash(&mask, &count);
		GdSetFillMode(gcp->fillmode);
		GdSetTSOffset(gcp->ts_offset.x, gcp->ts_offset.y);

		switch(gcp->fillmode) {
		case GR_FILL_STIPPLE:
		case GR_FILL_OPAQUE_STIPPLE:
			GdSetStippleBitmap(gcp->stipple.bitmap, gcp->stipple.width, gcp->stipple.height);
			break;
		case GR_FILL_TILE:
			GdSetTilePixmap(gcp->tile.psd, gcp->tile.width, gcp->tile.height);
			break;
		}
#endif
		gcp->changed = GR_FALSE;
	}

	*retdp = wp? (GR_DRAWABLE *)wp: (GR_DRAWABLE *)pp;
	return wp? GR_DRAW_TYPE_WINDOW: GR_DRAW_TYPE_PIXMAP;
}
Ejemplo n.º 8
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;
	}
}