📄 srvutil.c
字号:
/*
* 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 + -