📄 srvfunc.c
字号:
/* * Copyright (c) 1999, 2000, 2001, 2002, 2003 Greg Haerr <greg@censoft.com> * Portions Copyright (c) 2002 by Koninklijke Philips Electronics N.V. * Copyright (c) 2000 Alex Holden <alex@linuxhacker.org> * Copyright (c) 1991 David I. Bell * Permission is granted to use, distribute, or modify this source, * provided that this copyright notice remains intact. */#include <stdio.h>#include <stdlib.h>#include <string.h>#define MWINCLUDECOLORS#include "serv.h"static int nextid = GR_ROOT_WINDOW_ID + 1;static void CheckNextEvent(GR_EVENT *ep, GR_BOOL doCheckEvent); /* * Return information about the screen for clients to use. */void GrGetScreenInfo(GR_SCREEN_INFO *sip){ SERVER_LOCK(); GdGetScreenInfo(rootwp->psd, sip); /* set virtual screen sizing (for PDA emulation on desktop)*/ sip->vs_width = nxres? nxres: sip->cols; sip->vs_height = nyres? nyres: sip->rows; /* set workspace equal to virtual screen area minus 22 pixel taskbar*/ sip->ws_width = sip->vs_width; sip->ws_height = sip->vs_height - 22; SERVER_UNLOCK();}/* * Return the size of a text string for the font in a graphics context. * This is the width of the string, the height of the string, * and the height above the bottom of the font of the baseline for the font. */void GrGetGCTextSize(GR_GC_ID gc, void *str, int count, GR_TEXTFLAGS flags, GR_SIZE *retwidth, GR_SIZE *retheight, GR_SIZE *retbase){ GR_GC *gcp; GR_FONT *fontp; PMWFONT pf; SERVER_LOCK(); gcp = GsFindGC(gc); if (gcp == NULL) fontp = NULL; else fontp = GsFindFont(gcp->fontid); pf = fontp? fontp->pfont: stdfont; GdGetTextSize(pf, str, count, retwidth, retheight, retbase, flags); SERVER_UNLOCK();}#if NONETWORK/* * Return the next waiting event for a client, or wait for one if there * is none yet. The event is copied into the specified structure, and * then is moved from the event queue to the free event queue. If there * is an error event waiting, it is delivered before any other events. */voidGrGetNextEvent(GR_EVENT *ep){ GrGetNextEventTimeout(ep, 0L);}/* * Return the next event from the event queue, or * wait for a new one if one is not ready. If timeout * is nonzero, return timeout event if time elapsed. */voidGrGetNextEventTimeout(GR_EVENT *ep, GR_TIMEOUT timeout){ SERVER_LOCK(); /* If no event ready, wait for one*/ /* Note: won't work for multiple clients*/ /* This is OK, since only static linked apps call this function*/ while(curclient->eventhead == NULL) GsSelect(timeout); CheckNextEvent(ep, GR_FALSE); SERVER_UNLOCK();}/* * Wait until an event is available for a client, and then peek at it. */voidGrPeekWaitEvent(GR_EVENT *ep){ SERVER_LOCK(); while(curclient->eventhead == NULL) GsSelect(0L); GrPeekEvent(ep); SERVER_UNLOCK();}#endif/* * Return the next event from the event queue if one is ready. * If one is not ready, then the type GR_EVENT_TYPE_NONE is returned. * If it is an error event, then a user-specified routine is called * if it was defined, otherwise we clean up and exit. */voidGrCheckNextEvent(GR_EVENT *ep){ SERVER_LOCK(); CheckNextEvent(ep, GR_TRUE); SERVER_UNLOCK();}static voidCheckNextEvent(GR_EVENT *ep, GR_BOOL doCheckEvent){ GR_EVENT_LIST * elp;#if 0 /* was NONETWORK*/ /* NOTE: select() now called through GrPeekEvent when bound to server*/ if (doCheckEvent) GsSelect(1L);#endif /* Copy first event if any*/ if(!GrPeekEvent(ep)) return; /* Get first event again*/ elp = curclient->eventhead;#if NONETWORK /* if GrCheckEvent, turn timeouts into no event*/ if (doCheckEvent && elp->event.type == GR_EVENT_TYPE_TIMEOUT) ep->type = GR_EVENT_TYPE_NONE;#endif /* Remove first event from queue*/ curclient->eventhead = elp->next; if (curclient->eventtail == elp) curclient->eventtail = NULL; elp->next = eventfree; eventfree = elp;}/* * Peek at the event queue for the current client to see if there are any * outstanding events. Returns the event at the head of the queue, or * else a null event type. The event is still left in the queue, however. */intGrPeekEvent(GR_EVENT *ep){ GR_EVENT_LIST * elp; SERVER_LOCK(); elp = curclient->eventhead;#if NONETWORK /* if no events on queue, force select() event check*/ if (elp == NULL) { GsSelect(-1L); /* poll*/ elp = curclient->eventhead; }#endif if(elp == NULL) { ep->type = GR_EVENT_TYPE_NONE; SERVER_UNLOCK(); return 0; } /* copy event out*/ *ep = elp->event; SERVER_UNLOCK(); return 1;}/* * Return information about a window id. */voidGrGetWindowInfo(GR_WINDOW_ID wid, GR_WINDOW_INFO *infoptr){ GR_WINDOW *wp; /* window structure */ GR_PIXMAP *pp; GR_EVENT_CLIENT *evp; /* event-client structure */ SERVER_LOCK(); /* first check window list*/ wp = GsFindWindow(wid); if (wp) { infoptr->wid = wid; /* report parent-relative x,y coordinates*/ infoptr->x = wp->x - (wp->parent ? wp->parent->x : 0); infoptr->y = wp->y - (wp->parent ? wp->parent->y : 0); infoptr->width = wp->width; infoptr->height = wp->height; infoptr->parent = wp->parent? wp->parent->id: 0; infoptr->child = wp->children? wp->children->id: 0; infoptr->sibling = wp->siblings? wp->siblings->id: 0; infoptr->mapped = wp->mapped; infoptr->realized = wp->realized; infoptr->inputonly = !wp->output; infoptr->bordersize = wp->bordersize; infoptr->bordercolor = wp->bordercolor; infoptr->background = wp->background; infoptr->props = wp->props; infoptr->cursor = wp->cursorid; infoptr->processid = wp->owner? wp->owner->processid: 0; infoptr->eventmask = 0; for (evp = wp->eventclients; evp; evp = evp->next) { if (evp->client == curclient) infoptr->eventmask = evp->eventmask; } SERVER_UNLOCK(); return; } /* then pixmap list*/ pp = GsFindPixmap(wid); if (pp) { infoptr->wid = wid; infoptr->x = pp->x; infoptr->y = pp->y; infoptr->width = pp->width; infoptr->height = pp->height; infoptr->parent = 0; infoptr->child = 0; infoptr->sibling = 0; infoptr->mapped = GR_FALSE; infoptr->realized = GR_TRUE; infoptr->inputonly = GR_FALSE; infoptr->bordersize = 0; infoptr->bordercolor = 0; infoptr->background = 0; infoptr->eventmask = 0; infoptr->cursor = 0; infoptr->processid = pp->owner? pp->owner->processid: 0; SERVER_UNLOCK(); return; } /* No error if window id is invalid.*/ memset(infoptr, 0, sizeof(GR_WINDOW_INFO)); SERVER_UNLOCK();}/* * Destroy an existing window and all of its children. * Also used to destroy a pixmap. */voidGrDestroyWindow(GR_WINDOW_ID wid){ GR_WINDOW *wp; /* window structure */ GR_PIXMAP *pp; GR_PIXMAP *prevpp; PSD psd; SERVER_LOCK(); wp = GsFindWindow(wid); if (wp) { GsWpDestroyWindow(wp); } else { pp = GsFindPixmap(wid); if (pp) { psd = pp->psd; /* deallocate pixmap memory*/ if (psd->flags & PSF_ADDRMALLOC) free(psd->addr); /* deallocate mem gc*/ psd->FreeMemGC(psd); /* * Remove this pixmap from the complete list of pixmaps. */ prevpp = listpp; if (prevpp == pp) listpp = pp->next; else { while (prevpp->next != pp) prevpp = prevpp->next; prevpp->next = pp->next; } /* * Forget various information if they related to this * pixmap. Then finally free the structure. */ if (pp == cachepp) { cachepixmapid = 0; cachepp = NULL; } free(pp); } } SERVER_UNLOCK();}/* * Raise a window to the highest level among its siblings. */voidGrRaiseWindow(GR_WINDOW_ID wid){ GR_WINDOW *wp; /* window structure */ GR_WINDOW *prevwp; /* previous window pointer */ GR_BOOL overlap; /* TRUE if there was overlap */ SERVER_LOCK(); wp = GsFindWindow(wid); if ((wp == NULL) || (wp == rootwp)) { SERVER_UNLOCK(); return; } /* * If this is already the highest window then we are done. */ prevwp = wp->parent->children; if (prevwp == wp) { SERVER_UNLOCK(); return; } /* * Find the sibling just before this window so we can unlink it. * Also, determine if any sibling ahead of us overlaps the window. * Remember that for exposure events. */ overlap = GR_FALSE; while (prevwp->siblings != wp) { overlap |= GsCheckOverlap(prevwp, wp); prevwp = prevwp->siblings; } overlap |= GsCheckOverlap(prevwp, wp); /* * Now unlink the window and relink it in at the front of the * sibling chain. */ prevwp->siblings = wp->siblings; wp->siblings = wp->parent->children; wp->parent->children = wp; /* * Finally redraw the window if necessary. */ if (overlap) { GsDrawBorder(wp); GsExposeArea(wp, wp->x, wp->y, wp->width, wp->height, NULL); } SERVER_UNLOCK();}/* * Lower a window to the lowest level among its siblings. */voidGrLowerWindow(GR_WINDOW_ID wid){ GR_WINDOW *wp; /* window structure */ GR_WINDOW *prevwp; /* previous window pointer */ GR_WINDOW *sibwp; /* sibling window */ GR_WINDOW *expwp; /* siblings being exposed */ SERVER_LOCK(); wp = GsFindWindow(wid); if ((wp == NULL) || (wp == rootwp)) { SERVER_UNLOCK(); return; } if (wp->siblings == NULL) { SERVER_UNLOCK(); return; } /* * Find the sibling just before this window so we can unlink us. */ prevwp = wp->parent->children; if (prevwp != wp) { while (prevwp->siblings != wp) prevwp = prevwp->siblings; } /* * Remember the first sibling that is after us, so we can * generate exposure events for the remaining siblings. Then * walk down the sibling chain looking for the last sibling. */ expwp = wp->siblings; sibwp = wp; while (sibwp->siblings) sibwp = sibwp->siblings; /* * Now unlink the window and relink it in at the end of the * sibling chain. */ if (prevwp == wp) wp->parent->children = wp->siblings; else prevwp->siblings = wp->siblings; sibwp->siblings = wp; wp->siblings = NULL; /* * Finally redraw the sibling windows which this window covered * if they overlapped our window. */ while (expwp && (expwp != wp)) { if (GsCheckOverlap(wp, expwp)) { GsExposeArea(expwp, wp->x - wp->bordersize, wp->y - wp->bordersize, wp->width + wp->bordersize * 2, wp->height + wp->bordersize * 2, NULL); } expwp = expwp->siblings; } SERVER_UNLOCK();}/* Offset a window position and all children by offx,offy*/static voidOffsetWindow(GR_WINDOW *wp, GR_COORD offx, GR_COORD offy){ GR_WINDOW *cp; wp->x += offx; wp->y += offy; for(cp=wp->children; cp; cp=cp->siblings) OffsetWindow(cp, offx, offy);}/* deliver an update move event to window and all children*/static voidDeliverUpdateMoveEventAndChildren(GR_WINDOW *wp){ GR_WINDOW * childwp; GsDeliverUpdateEvent(wp, GR_UPDATE_MOVE, wp->x, wp->y, wp->width, wp->height); for (childwp = wp->children; childwp; childwp = childwp->siblings) DeliverUpdateMoveEventAndChildren(childwp);}/* * Move the window to the specified position relative to its parent. */voidGrMoveWindow(GR_WINDOW_ID wid, GR_COORD x, GR_COORD y){ GR_WINDOW *wp; /* window structure */ GR_COORD offx, offy; SERVER_LOCK(); wp = GsFindWindow(wid); if (wp == NULL) { SERVER_UNLOCK(); return; } if (wp == rootwp) { GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wid); SERVER_UNLOCK(); return; } x += wp->parent->x; y += wp->parent->y; offx = x - wp->x; offy = y - wp->y; if (wp->x == x && wp->y == y) { SERVER_UNLOCK(); return; } /* * move algorithms not requiring unmap/map ***/#if 1 /* perform screen blit if topmost and mapped - no flicker!*/ if (wp->mapped && wp == wp->parent->children && wp->parent->id == GR_ROOT_WINDOW_ID /* temp don't blit in portrait mode, still buggy*/ /* *&& !(wp->psd->portrait & (MWPORTRAIT_LEFT|MWPORTRAIT_RIGHT))***/ /* don't blit if window has custom frame, background not right*/ && !wp->clipregion ) { int oldx = wp->x; int oldy = wp->y; GR_WINDOW_ID pixid = GrNewPixmap(wp->width, wp->height,NULL); GR_GC_ID gc = GrNewGC(); GR_WINDOW * stopwp = wp; int X, Y, W, H; /* must hide cursor first or GdFixCursor() will show it*/ GdHideCursor(rootwp->psd); /* turn off clipping of root's children*/ GrSetGCMode(gc, GR_MODE_COPY|GR_MODE_EXCLUDECHILDREN); /* copy topmost window contents offscreen*/ GrCopyArea(pixid, gc, 0, 0, wp->width, wp->height, GR_ROOT_WINDOW_ID, oldx, oldy, MWROP_COPY); /* calc new window offsets*/ OffsetWindow(wp, offx, offy); /* force recalc of clip region*/ clipwp = NULL; /* copy window bits to new location*/ GrCopyArea(GR_ROOT_WINDOW_ID, gc, wp->x, wp->y, wp->width, wp->height, pixid, 0, 0, MWROP_COPY); /* * If any portion of the window was offscreen * and is coming onscreen, must send expose events * to this window as well. */ if ((oldx < 0 && wp->x > oldx) || (oldy < 0 && wp->y > oldy) || (oldx+wp->width > rootwp->width && wp->x < oldx) || (oldy+wp->height > rootwp->height && wp->y < oldy)) stopwp = NULL; /* * Calculate bounded exposed area and * redraw anything lower than stopwp window. */ X = MWMIN(oldx, wp->x); Y = MWMIN(oldy, wp->y); W = MWMAX(oldx, wp->x) + wp->width - X; H = MWMAX(oldy, wp->y) + wp->height - Y; GsExposeArea(rootwp, X, Y, W, H, stopwp); GdShowCursor(rootwp->psd); GrDestroyGC(gc); GrDestroyWindow(pixid); DeliverUpdateMoveEventAndChildren(wp); SERVER_UNLOCK(); return; }#endif#if 0 /* perform quick move and expose if topmost and mapped - no blit*/ if (wp->mapped && wp == wp->parent->children) { int oldx = wp->x; int oldy = wp->y; int X, Y, W, H; OffsetWindow(wp, offx, offy); /* force recalc of clip region*/ clipwp = NULL; X = MWMIN(oldx, wp->x); Y = MWMIN(oldy, wp->y); W = MWMAX(oldx, wp->x) + wp->width - X; H = MWMAX(oldy, wp->y) + wp->height - Y; GsExposeArea(rootwp, X, Y, W, H, NULL); DeliverUpdateMoveEventAndChildren(wp); SERVER_UNLOCK(); return; }#endif /* * This method will redraw the window entirely, * resulting in considerable flicker. */ GsWpUnrealizeWindow(wp, GR_TRUE); OffsetWindow(wp, offx, offy); GsWpRealizeWindow(wp, GR_FALSE); DeliverUpdateMoveEventAndChildren(wp); SERVER_UNLOCK(); return;}/* * Resize the window to be the specified size. */voidGrResizeWindow(GR_WINDOW_ID wid, GR_SIZE width, GR_SIZE height){ GR_WINDOW *wp; /* window structure */ SERVER_LOCK(); wp = GsFindWindow(wid); if (wp == NULL) { SERVER_UNLOCK(); return; } if (wp == rootwp) { GsError(GR_ERROR_ILLEGAL_ON_ROOT_WINDOW, wid); SERVER_UNLOCK(); return; } if ((width <= 0) || (height <= 0)) { GsError(GR_ERROR_BAD_WINDOW_SIZE, wid); SERVER_UNLOCK(); return; } if ((wp->width == width) && (wp->height == height)) { SERVER_UNLOCK(); return; } if (!wp->realized || !wp->output) { wp->width = width; wp->height = height; SERVER_UNLOCK(); return; } /* * This should be optimized to not require redrawing of the window * when possible. */ GsWpUnrealizeWindow(wp, GR_TRUE); wp->width = width; wp->height = height; /* send size update before expose event*/ GsDeliverUpdateEvent(wp, GR_UPDATE_SIZE, wp->x, wp->y, width, height);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -