Пример #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;
	}
}
Пример #2
0
/*
 * Return a pointer to the graphics context with the specified id.
 * Returns NULL if the graphics context does not exist, with an
 * error saved.
 */
GR_GC *
GsFindGC(GR_GC_ID gcid)
{
	GR_GC		*gcp;		/* current graphics context pointer */

	/*
	 * See if this is the same graphics context as last time.
	 */
	if ((gcid == cachegcid) && gcid)
		return cachegcp;

	/*
	 * No, search for it and cache it for future calls.
	 */
	for (gcp = listgcp; gcp; gcp = gcp->next) {
		if (gcp->id == gcid) {
			cachegcid = gcid;
			cachegcp = gcp;
			return gcp;
		}
	}

	GsError(GR_ERROR_BAD_GC_ID, gcid);

	return NULL;
}
Пример #3
0
/*
 * 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.
 */
void GsCheckMouseEvent(void)
{
	COORD		rootx;		/* latest mouse x position */
	COORD		rooty;		/* latest mouse y position */
	BUTTON		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;
	} else if(mousestatus) /* Deliver events as appropriate: */	
		GsHandleMouseStatus(rootx, rooty, newbuttons);
}
Пример #4
0
/*
 * 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.
 */
void GsCheckKeyboardEvent(void)
{
	unsigned char	ch;		/* latest character */
	MODIFIER	modifiers;	/* latest modifiers */
	int		keystatus;	/* latest keyboard status */

	/* Read the latest keyboard status: */
	keystatus = GdReadKeyboard(&ch, &modifiers);
	if(keystatus < 0) {
		if(keystatus == -2)	/* special case for ESC pressed*/
			GsTerminate();
		GsError(GR_ERROR_KEYBOARD_ERROR, 0);
		return;
	} else if(keystatus) /* Deliver events as appropriate: */	
		GsDeliverKeyboardEvent(GR_EVENT_TYPE_KEY_DOWN, ch, modifiers);
}
Пример #5
0
/*
 * 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;
}
Пример #6
0
/*
 * 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;
}
Пример #7
0
/*
 * Map the window to possibly make it and its children visible on the screen.
 * This is a recursive routine which decrements the unmapcount values for
 * this window and all of its children, and causes exposure events for
 * those windows which become visible.
 * If temp is set, then window is being mapped again after a temporary
 * unmap, so don't reset focus or generate mouse/focus events.
 */
void GsWpMapWindow(GR_WINDOW *wp, GR_BOOL temp)
{
	if (wp == rootwp) {
		GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wp->id);
		return;
	}

	if (wp->unmapcount)
		--wp->unmapcount;

	if (!temp && wp->unmapcount == 0) {
		GsCheckMouseWindow();
		GsCheckFocusWindow();
		GsCheckCursor();
	}

	/* send update event if just mapped*/
	if (wp->unmapcount == 0) {
		GsDeliverUpdateEvent(wp, GR_UPDATE_MAP, wp->x, wp->y,
			wp->width, wp->height);
	}

	/*
	 * If the window is an output window and just became visible,
	 * then draw its border, clear it to the background color, and
	 * generate an exposure event.
	 */
	if (wp->output && (wp->unmapcount == 0)) {
		GsDrawBorder(wp);
		GsWpClearWindow(wp, 0, 0, wp->width, wp->height, GR_TRUE);
	}

	/*
	 * Do the same thing for the children.
	 */
	for (wp = wp->children; wp; wp = wp->siblings)
		GsWpMapWindow(wp, temp);
}
Пример #8
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;
}
Пример #9
0
/*
 * 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;
}
Пример #10
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;
}
Пример #11
0
/*
 * Unmap the window to make it and its children invisible on the screen.
 * This is a recursive routine which increments the unmapcount values for
 * this window and all of its children, and causes exposure events for
 * windows which are newly uncovered.
 * If temp_unmap set, don't reset focus or generate mouse/focus events,
 * as window will be mapped again momentarily (window move, resize, etc)
 */
void GsWpUnmapWindow(GR_WINDOW *wp, GR_BOOL temp_unmap)
{
	GR_WINDOW	*pwp;		/* parent window */
	GR_WINDOW	*sibwp;		/* sibling window */
	GR_WINDOW	*childwp;	/* child window */
	GR_SIZE		bs;		/* border size of this window */

	if (wp == rootwp) {
		GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wp->id);
		return;
	}

	if (wp == clipwp)
		clipwp = NULL;

	++wp->unmapcount;

	for (childwp = wp->children; childwp; childwp = childwp->siblings)
		GsWpUnmapWindow(childwp, temp_unmap);

	if (!temp_unmap && wp == mousewp) {
		GsCheckMouseWindow();
		GsCheckCursor();
	}

	if (!temp_unmap && wp == focuswp) {
		if (focusfixed)
			/* don't revert to mouse enter/leave focus if fixed*/
			focuswp = rootwp;
		else {
			focusfixed = GR_FALSE;
			GsCheckFocusWindow();
		}
	}

	/* Send update event if just unmapped*/
	if (wp->unmapcount == 1) {
		GsDeliverUpdateEvent(wp, 
			(temp_unmap? GR_UPDATE_UNMAPTEMP: GR_UPDATE_UNMAP),
			0, 0, 0, 0);
	}

	/*
	 * If this is an input-only window or the parent window is
	 * still unmapped, then we are all done.
	 */
	if (!wp->output || wp->parent->unmapcount)
		return;

	/*
	 * Clear the area in the parent for this window, causing an
	 * exposure event for it.  Take into account the border size.
	 */
	bs = wp->bordersize;
	pwp = wp->parent;
	GsWpClearWindow(pwp, wp->x - pwp->x - bs, wp->y - pwp->y - bs,
		wp->width + bs * 2, wp->height + bs * 2, GR_TRUE);

	/*
	 * Finally clear and redraw all parts of our lower sibling
	 * windows that were covered by this window.
	 */
	sibwp = wp;
	while (sibwp->siblings) {
		sibwp = sibwp->siblings;
		GsExposeArea(sibwp, wp->x - bs, wp->y - bs,
			wp->width + bs * 2, wp->height + bs * 2, NULL);
	}
}
Пример #12
0
/*
 * Destroy the specified window, and all of its children.
 * This is a recursive routine.
 */
void GsWpDestroyWindow(GR_WINDOW *wp)
{
	GR_WINDOW	*prevwp;	/* previous window pointer */
	GR_EVENT_CLIENT	*ecp;		/* selections for window */
	GR_WINDOW_ID	oldwid;		/* old selection owner */

	if (wp == rootwp) {
		GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wp->id);
		return;
	}

	/* Disable selection if this window is the owner */
	if(selection_owner.wid == wp->id) {
		oldwid = selection_owner.wid;
		selection_owner.wid = 0;
		if(selection_owner.typelist) free(selection_owner.typelist);
		GsDeliverSelectionChangedEvent(oldwid, 0);
	}

	/*
	 * Unmap the window first.
	 */
	if (wp->unmapcount == 0)
		GsWpUnmapWindow(wp, GR_FALSE);

	/* send update event*/
	GsDeliverUpdateEvent(wp, GR_UPDATE_DESTROY, wp->x, wp->y,
		wp->width, wp->height);

	/*
	 * Destroy all children.
	 */
	while (wp->children)
		GsWpDestroyWindow(wp->children);

	/*
	 * Free all client selection structures.
	 */
	while (wp->eventclients) {
		ecp = wp->eventclients;
		wp->eventclients = ecp->next;
		free(ecp);
	}

	/*
	 * Remove this window from the child list of its parent.
	 */
	prevwp = wp->parent->children;
	if (prevwp == wp)
		wp->parent->children = wp->siblings;
	else {
		while (prevwp->siblings != wp)
			prevwp = prevwp->siblings;
		prevwp->siblings = wp->siblings;
	}
	wp->siblings = NULL;

	/*
	 * Remove this window from the complete list of windows.
	 */
	prevwp = listwp;
	if (prevwp == wp)
		listwp = wp->next;
	else {
		while (prevwp->next != wp)
			prevwp = prevwp->next;
		prevwp->next = wp->next;
	}
	wp->next = NULL;

	/*
	 * Forget various information if they related to this window.
	 * Then finally free the structure.
	 */
	if (wp == clipwp)
		clipwp = NULL;
	if (wp == grabbuttonwp)
		grabbuttonwp = NULL;
	if (wp == cachewp) {
		cachewindowid = 0;
		cachewp = NULL;
	}
	if (wp == focuswp) {
		/* don't revert to mouse enter/leave focus if fixed*/
		/*focusfixed = GR_FALSE;*/
		focuswp = rootwp;
	}

	GsCheckMouseWindow();

	if(wp->title)
		free(wp->title);

	free(wp);
}
Пример #13
0
/*
 * Set the clip rectangles for a window taking into account other
 * windows that may be obscuring it.  The windows that may be obscuring
 * this one are the siblings of each direct ancestor which are higher
 * in priority than those ancestors.  Also, each parent limits the visible
 * area of the window.  The clipping is not done if it is already up to
 * date of if the window is not outputtable.
 */
void
GsSetClipWindow(GR_WINDOW *wp, MWCLIPREGION *userregion, int flags)
{
	GR_WINDOW	*pwp;		/* parent window */
	GR_WINDOW	*sibwp;		/* sibling windows */
	MWCLIPRECT	*clip;		/* first clip rectangle */
	GR_COUNT	count;		/* number of clip rectangles */
	GR_COUNT	newcount;	/* number of new rectangles */
	GR_COUNT	i;		/* current index */
	GR_COORD	minx;		/* minimum clip x coordinate */
	GR_COORD	miny;		/* minimum clip y coordinate */
	GR_COORD	maxx;		/* maximum clip x coordinate */
	GR_COORD	maxy;		/* maximum clip y coordinate */
	GR_COORD	diff;		/* difference in coordinates */
	GR_SIZE		bs;		/* border size */
	GR_BOOL		toomany;	/* TRUE if too many clip rects */
	MWCLIPRECT	cliprects[MAX_CLIPRECTS];	/* clip rectangles */

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

	clipwp = wp;

	/*
	 * Start with the rectangle for the complete window.
	 * We will then cut pieces out of it as needed.
	 */
	count = 1;
	clip = cliprects;
	clip->x = wp->x;
	clip->y = wp->y;
	clip->width = wp->width;
	clip->height = wp->height;

	/*
	 * First walk upwards through all parent windows,
	 * and restrict the visible part of this window to the part
	 * that shows through all of those parent windows.
	 */
	pwp = wp;
	while (pwp != rootwp) {
		pwp = pwp->parent;

		diff = pwp->x - clip->x;
		if (diff > 0) {
			clip->width -= diff;
			clip->x = pwp->x;
		}

		diff = (pwp->x + pwp->width) - (clip->x + clip->width);
		if (diff < 0)
			clip->width += diff;

		diff = pwp->y - clip->y;
		if (diff > 0) {
			clip->height -= diff;
			clip->y = pwp->y;
		}

		diff = (pwp->y + pwp->height) - (clip->y + clip->height);
		if (diff < 0)
			clip->height += diff;
	}

	/*
	 * If the window is completely clipped out of view, then
	 * set the clipping region to indicate that.
	 */
	if ((clip->width <= 0) || (clip->height <= 0)) {
		GdSetClipRects(clipwp->psd, 1, cliprects);
		return;
	}

	/*
	 * Now examine all windows that obscure this window, and
	 * for each obscuration, break up the clip rectangles into
	 * the smaller pieces that are still visible.  The windows
	 * that can obscure us are the earlier siblings of all of
	 * our parents.
 	 */
	toomany = GR_FALSE;
	pwp = wp;
/*while (pwp != rootwp) {*/
	while (pwp != NULL) {
		wp = pwp;
		pwp = wp->parent;

		if(!pwp) {
			/* We're clipping the root window*/
			sibwp = rootwp->children;
			wp = NULL;
		} else
			sibwp = pwp->children;

		for (; sibwp != wp; sibwp = sibwp->siblings) {
			if (!sibwp->realized || !sibwp->output)
				continue;

			bs = sibwp->bordersize;
			minx = sibwp->x - bs;
			miny = sibwp->y - bs;
			maxx = sibwp->x + sibwp->width + bs - 1;
			maxy = sibwp->y + sibwp->height + bs - 1;

			newcount = count;
			for (i = 0; i < count; i++) {
				if (newcount > MAX_CLIPRECTS - 3) {
					toomany = GR_TRUE;
					break;
				}
				newcount += GsSplitClipRect(&cliprects[i],
					&cliprects[newcount],
					minx, miny, maxx, maxy);
			}
			count = newcount;
		}
if(pwp == rootwp)
break;
	}

	if (toomany) {
		GsError(GR_ERROR_TOO_MUCH_CLIPPING, wp->id);
		clip->x = 0;
		clip->y = 0;
		clip->width = -1;
		clip->height = -1;
		count = 1;
	}

	/*
	 * Set the clip rectangles.
	 */
	GdSetClipRects(clipwp->psd, count, cliprects);
}
Пример #14
0
/*
 * Destroy the specified window, and all of its children.
 * This is a recursive routine.
 */
void
GsDestroyWindow(GR_WINDOW *wp)
{
	GR_WINDOW	*prevwp;	/* previous window pointer */
	GR_EVENT_CLIENT	*ecp;		/* selections for window */
	GR_WINDOW_ID	oldwid;		/* old selection owner */
	GR_GRABBED_KEY *keygrab;
	GR_GRABBED_KEY **keygrab_prev_next;

	if (wp == rootwp) {
		GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wp->id);
		return;
	}

	/* Disable selection if this window is the owner */
	if(selection_owner.wid == wp->id) {
		oldwid = selection_owner.wid;
		selection_owner.wid = 0;
		if(selection_owner.typelist)
			free(selection_owner.typelist);
		selection_owner.typelist = NULL;
		GsDeliverSelectionChangedEvent(oldwid, 0);
	}

	/*
	 * Unmap the window first.
	 */
	if (wp->realized)
		GsUnrealizeWindow(wp, GR_FALSE);

	/* send destroy update event*/
	GsDeliverUpdateEvent(wp, GR_UPDATE_DESTROY, wp->x, wp->y,
		wp->width, wp->height);

	/*
	 * Destroy all children.
	 */
	while (wp->children)
		GsDestroyWindow(wp->children);

	/*
	 * Free all client selection structures.
	 */
	while (wp->eventclients) {
		ecp = wp->eventclients;
		wp->eventclients = ecp->next;
DPRINTF("FREE 1 %lx\n", (long)ecp);			// FIXME
		free(ecp);
	}

	/*
	 * Remove this window from the child list of its parent.
	 */
	prevwp = wp->parent->children;
	if (prevwp == wp)
		wp->parent->children = wp->siblings;
	else {
		while (prevwp->siblings != wp)
			prevwp = prevwp->siblings;
		prevwp->siblings = wp->siblings;
	}
	wp->siblings = NULL;

	/*
	 * Remove this window from the complete list of windows.
	 */
	prevwp = listwp;
	if (prevwp == wp)
		listwp = wp->next;
	else {
		while (prevwp->next != wp)
			prevwp = prevwp->next;
		prevwp->next = wp->next;
	}
	wp->next = NULL;

	/*
	 * Forget various information if they related to this window.
	 * Then finally free the structure.
	 */
	if (wp == clipwp)
		clipwp = NULL;
	if (wp == grabbuttonwp)
		grabbuttonwp = NULL;
	if (wp == cachewp) {
		cachewindowid = 0;
		cachewp = NULL;
	}
	if (wp == focuswp) {
		/* don't revert to mouse enter/leave focus if fixed*/
		/*focusfixed = GR_FALSE;*/
		focuswp = rootwp;
	}

	GsCheckMouseWindow();

	/*
	 * Free title, pixmaps and clipregions associated with window.
	 */
	if (wp->title)
		free(wp->title);
	if (wp->bgpixmap)
		GsDestroyPixmap(wp->bgpixmap);
	if (wp->buffer)
		GsDestroyPixmap(wp->buffer);
#if DYNAMICREGIONS
	if (wp->clipregion)
		GdDestroyRegion(wp->clipregion);
#endif

	/* Remove any grabbed keys for this window. */
	keygrab_prev_next = &list_grabbed_keys;
	keygrab           =  list_grabbed_keys;
	while (keygrab != NULL) {
		if (keygrab->wid == wp->id){
			/* Delete keygrab. */
			*keygrab_prev_next = keygrab->next;
			free(keygrab);
			keygrab = *keygrab_prev_next;
		} else {
			keygrab_prev_next = &keygrab->next;
			keygrab           =  keygrab->next;
		}
	}

	free(wp);
}
Пример #15
0
/*
 * Map the window to possibly make it and its children visible on the screen.
 * This is a recursive routine which realizes this window and all of its
 * children, and causes exposure events for those windows which become visible.
 * If temp is set, then window is being mapped again after a temporary
 * unmap, so don't reset focus or generate mouse/focus events.
 */
void
GsRealizeWindow(GR_WINDOW *wp, GR_BOOL temp)
{
	if (wp == rootwp) {
		GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wp->id);
		return;
	}
/*printf("RealizeWindow %d, map %d realized %d, parent_realized %d\n",
wp->id, wp->mapped, wp->realized, wp->parent->realized);*/

#define OLDWAY 0
#if OLDWAY /* old way, doesn't quite work with unmap/map yourself*/
	/* 
	 * If window is already realized, or if window
	 * isn't set to be mapped, or parent isn't
	 * realized, then we're done
	 */
	if (wp->realized || !wp->mapped || !wp->parent->realized)
		return;

#else /* new way, still small bug with xfreecell and popup windows*/
	/* if window is already realized, we're done*/
	if (wp->realized)
		return;

	/* 
	 * Send map update event for window manager or others
	 */
	/* send map update event if not temp unmap/map*/
	if (!temp) {
		GsDeliverUpdateEvent(wp, GR_UPDATE_MAP, wp->x, wp->y,
			wp->width, wp->height);
	}

	/* 
	 * If window isn't set to be mapped, or parent isn't
	 * realized, then we're done
	 */
	if (!wp->mapped || !wp->parent->realized)
		return;
#endif

	/* set window visible flag*/
	wp->realized = GR_TRUE;

	if (!temp) {
		GsCheckMouseWindow();
		GsCheckFocusWindow();
		GsCheckCursor();
	}

#if OLDWAY
	/* send map update event if not temp unmap/map*/
	if (!temp) {
		GsDeliverUpdateEvent(wp, GR_UPDATE_MAP, wp->x, wp->y,
			wp->width, wp->height);
	}
#endif
	/*
	 * If the window is an output window, then draw its border, 
	 * clear it to the background color, and generate an exposure event.
	 */
	if (wp->output) {
		GsDrawBorder(wp);
		GsClearWindow(wp, 0, 0, wp->width, wp->height, 1);
	}

	/*
	 * Do the same thing for the children.
	 */
	for (wp = wp->children; wp; wp = wp->siblings)
		GsRealizeWindow(wp, temp);
}
Пример #16
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;
}