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

📄 srvutil.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * 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 utility routines for windows.
 */
#include <stdio.h>
#include <stdlib.h>

#ifndef __PACIFIC__
#include <fcntl.h>
#endif

#include "serv.h"

/*
 * Help prevent future bugs by defining this variable to an illegal value.
 * These routines should not be referencing this, but should be using
 * unmapcount instead.
 */
#define	mapped	cannotusemapped

/*
 * Redraw the screen completely.
 */
void
GsRedrawScreen(void)
{
	/* Redraw all windows*/
	GsExposeArea(rootwp, 0, 0, rootwp->width, rootwp->height, NULL);
}

/*
 * Activate Screen Saver.
 */
void
GsActivateScreenSaver(void *arg)
{
	screensaver_active = GR_TRUE;
	GsDeliverScreenSaverEvent(GR_TRUE);
}

/*
 * Deactivate screen saver and reset timer if active.
 */
void
GsResetScreenSaver(void)
{
	MWTIMER *timer;

	if(screensaver_active == GR_TRUE) {
		screensaver_active = GR_FALSE;
		GsDeliverScreenSaverEvent(GR_FALSE);
	}
	if(screensaver_delay) {
		if((timer = GdFindTimer(GsActivateScreenSaver)))
			GdDestroyTimer(timer);
		GdAddTimer(screensaver_delay, GsActivateScreenSaver,
			GsActivateScreenSaver);
	}
}

void
GsTimerCB (void *arg) 
{
    GR_TIMER *timer = (GR_TIMER*) arg;

    GsDeliverTimerEvent (timer->owner, timer->wid, timer->id);
}


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

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

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

/*
 * Draw a window's background pixmap.
 *
 * The flags mean:
 *   GR_BACKGROUND_TILE- tile the pixmap across the window (default).
 *   GR_BACKGROUND_TOPLEFT- draw the pixmap at (0,0) relative to the window.
 *   GR_BACKGROUND_CENTER- draw the pixmap in the middle of the window.
 *   GR_BACKGROUND_STRETCH- stretch the pixmap within the window.
 *   GR_BACKGROUND_TRANS- if the pixmap is smaller than the window and not
 *     using tile mode, there will be gaps around the pixmap. This flag causes
 *     to not fill in the spaces with the background colour.
 */
void GsWpDrawBackgroundPixmap(GR_WINDOW *wp, GR_PIXMAP *pm, GR_COORD x,
	GR_COORD y, GR_SIZE width, GR_SIZE height)
{
	GR_SIZE destwidth, destheight, fillwidth, fillheight, pmwidth, pmheight;
	GR_COORD fromx, fromy, destx, desty, pixmapx = 0, pixmapy = 0;

	if(wp->bgpixmapflags & (GR_BACKGROUND_TOPLEFT|GR_BACKGROUND_STRETCH)) {
		pixmapx = 0;
		pixmapy = 0;
	} else if(wp->bgpixmapflags & GR_BACKGROUND_CENTER) {
		if(pm->width >= wp->width) pixmapx = 0;
		else pixmapx = (wp->width - pm->width) / 2;
		if(pm->height >= wp->height) pixmapy = 0;
		else pixmapy = (wp->height - pm->height) / 2;
	} else { 
		/* GR_BACKGROUND_TILE (default)*/
		GsWpTileBackgroundPixmap(wp, pm, x, y, width, height);
		return;
	}

	if(pm->width > wp->width) pmwidth = wp->width;
	else pmwidth = pm->width;
	if(pm->height > wp->height) pmheight = wp->height;
	else pmheight = pm->height;

	if(x > pixmapx) {
		destx = x;
		fromx = x - pixmapx;
		destwidth = pixmapx + pmwidth - x;
	} else {
		destx = pixmapx;
		fromx = 0;
		destwidth = x + width - pixmapx;
	}

	if(y > pixmapy) {
		desty = y;
		fromy = y - pixmapy;
		destheight = pixmapy + pmheight - desty;
	} else {
		desty = pixmapy;
		fromy = 0;
		destheight = y + height - pixmapy;
	}

	if(destwidth > 0 && destheight > 0) {
		if (wp->bgpixmapflags & GR_BACKGROUND_STRETCH) {
			GdStretchBlit(wp->psd, destx + wp->x, desty + wp->y,
				destwidth, destheight, pm->psd, fromx, fromy,
				pm->width, pm->height, MWROP_COPY);
		} else GdBlit(wp->psd, destx + wp->x, desty + wp->y, destwidth,
			destheight, pm->psd, fromx, fromy, MWROP_COPY);
	}

	if(wp->bgpixmapflags & (GR_BACKGROUND_TRANS|GR_BACKGROUND_STRETCH))
		return;

	/* Fill in the gaps around the pixmap */
	if(x < pixmapx) {
		fillwidth = pixmapx - x;
		if(fillwidth > width) fillwidth = width;
		fillheight = height;
		GdFillRect(wp->psd, wp->x + x, wp->y + y, fillwidth,fillheight);
	}
	if((x + width) > (pixmapx + pmwidth)) {
		fillwidth = (x + width) - (pixmapx + pmwidth);
		if(fillwidth > width) fillwidth = width;
		fillheight = height;
		if(x < (pixmapx + pmwidth)) destx = pixmapx + pmwidth + wp->x;
		else destx = x + wp->x;
		GdFillRect(wp->psd, destx, wp->y + y, fillwidth, fillheight);
	}
	if(y < pixmapy) {
		fillheight = pixmapy - y;
		if(fillheight > height) fillheight = height;
		if(x < pixmapx) destx = pixmapx + wp->x;
		else destx = x + wp->x;
		if((x + width) > (pixmapx + pmwidth))
			fillwidth = pixmapx + pmwidth - destx;
		else fillwidth = x + width - destx;
		if((fillwidth > 0) && (fillheight > 0)) {
			GdFillRect(wp->psd, destx, wp->y + y, fillwidth,
							fillheight);
		}
	}
	if((y + height) > (pixmapy + pmheight)) {
		fillheight = (y + height) - (pixmapy + pmheight);
		if(fillheight > height) fillheight = height;
		if(x < pixmapx) destx = pixmapx + wp->x;
		else destx = x + wp->x;
		if(y < (pixmapy + pmheight)) desty = pixmapy + pmheight + wp->y;
		else desty = y + wp->y;
	
		if((x + width) > (pixmapx + pmwidth))
			fillwidth = pixmapx + pmwidth - destx;
		else fillwidth = x + width - destx;
		if((fillwidth > 0) && (fillheight > 0)) {
			GdFillRect(wp->psd, destx, desty, fillwidth,fillheight);
		}
	}
}

⌨️ 快捷键说明

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