📄 srvutil.c
字号:
}
return NULL;
}
GR_TIMER *
GsFindTimer (GR_TIMER_ID timer_id)
{
GR_TIMER *timer;
/*
* See if this is the same graphics context as last time.
*/
if ((timer_id == cache_timer_id) && timer_id)
return cache_timer;
/*
* No, search for it and cache it for future calls.
*/
for (timer = list_timer; timer != NULL; timer = timer->next)
{
if (timer->id == timer_id)
{
cache_timer_id = timer_id;
cache_timer = timer;
return timer;
}
}
return NULL;
}
/*
* 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;
}
/*
* 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;
}
/*
* Find the window which is currently visible for the specified coordinates.
* This just walks down the window tree looking for the deepest mapped
* window which contains the specified point. If the coordinates are
* off the screen, the root window is returned.
*/
GR_WINDOW *GsFindVisibleWindow(GR_COORD x, GR_COORD y)
{
GR_WINDOW *wp; /* current window */
GR_WINDOW *retwp; /* returned window */
wp = rootwp;
retwp = wp;
while (wp) {
if ((wp->unmapcount == 0) && (wp->x <= x) && (wp->y <= y) &&
(wp->x + wp->width > x) && (wp->y + wp->height > y))
{
retwp = wp;
wp = wp->children;
continue;
}
wp = wp->siblings;
}
return retwp;
}
/*
* Check to see if the cursor shape is the correct shape for its current
* location. If not, its shape is changed.
*/
void GsCheckCursor(void)
{
GR_WINDOW *wp; /* window cursor is in */
GR_CURSOR *cp; /* cursor definition */
/*
* Get the cursor at its current position, and if it is not the
* currently defined one, then set the new cursor. However,
* if the pointer is currently grabbed, then leave it alone.
*/
wp = grabbuttonwp;
if (wp == NULL)
wp = mousewp;
cp = GsFindCursor(wp->cursorid);
if (!cp)
cp = stdcursor;
if (cp == curcursor)
return;
/*
* It needs redefining, so do it.
*/
curcursor = cp;
GdMoveCursor(cursorx - cp->cursor.hotx, cursory - cp->cursor.hoty);
GdSetCursor(&cp->cursor);
}
/*
* Check to see if the window the mouse is currently in has changed.
* If so, generate enter and leave events as required. The newest
* mouse window is remembered in mousewp. However, do not change the
* window while it is grabbed.
*/
void GsCheckMouseWindow(void)
{
GR_WINDOW *wp; /* newest window for mouse */
wp = grabbuttonwp;
if (wp == NULL)
wp = GsFindVisibleWindow(cursorx, cursory);
if (wp == mousewp)
return;
GsDeliverGeneralEvent(mousewp, GR_EVENT_TYPE_MOUSE_EXIT, NULL);
mousewp = wp;
GsDeliverGeneralEvent(wp, GR_EVENT_TYPE_MOUSE_ENTER, NULL);
}
/*
* Determine the current focus window for the current mouse coordinates.
* The mouse coordinates only matter if the focus is not fixed. Otherwise,
* the selected window is dependant on the window which wants keyboard
* events. This also sets the current focus for that found window.
* The window with focus is remembered in focuswp.
*/
void GsCheckFocusWindow(void)
{
GR_WINDOW *wp; /* current window */
GR_EVENT_CLIENT *ecp; /* current event client */
GR_EVENT_MASK eventmask; /* event mask */
if (focusfixed)
return;
eventmask = GR_EVENT_MASK_KEY_DOWN;
/*
* Walk upwards from the current window containing the mouse
* looking for the first window which would accept a keyboard event.
*/
for (wp = mousewp; ;wp = wp->parent) {
if (wp->props & GR_WM_PROPS_NOFOCUS)
continue;
for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
if (ecp->eventmask & eventmask) {
GsWpSetFocus(wp);
return;
}
}
if ((wp == rootwp) || (wp->nopropmask & eventmask)) {
GsWpSetFocus(rootwp);
return;
}
}
}
/* Send an update activate event to top level window of passed window*/
static void
GsWpNotifyActivate(GR_WINDOW *wp)
{
GR_WINDOW *pwp;
for (pwp=wp; pwp->parent; pwp=pwp->parent)
if (pwp->parent->id == GR_ROOT_WINDOW_ID)
break;
if (pwp->id != GR_ROOT_WINDOW_ID)
GsDeliverUpdateEvent(pwp, GR_UPDATE_ACTIVATE, 0, 0, 0, 0);
}
/*
* Set the input focus to the specified window.
* This generates focus out and focus in events as necessary.
*/
void GsWpSetFocus(GR_WINDOW *wp)
{
GR_WINDOW *oldfocus;
if (wp == focuswp)
return;
GsDeliverGeneralEvent(focuswp, GR_EVENT_TYPE_FOCUS_OUT, wp);
GsWpNotifyActivate(focuswp);
oldfocus = focuswp;
focuswp = wp;
GsDeliverGeneralEvent(wp, GR_EVENT_TYPE_FOCUS_IN, oldfocus);
GsWpNotifyActivate(focuswp);
}
/*
* Set dynamic portrait mode and redraw screen.
*/
void
GsSetPortraitMode(int mode)
{
GdSetPortraitMode(&scrdev, mode);
GdRestrictMouse(0, 0, scrdev.xvirtres - 1, scrdev.yvirtres - 1);
/* reset clip and root window size*/
clipwp = NULL;
rootwp->width = scrdev.xvirtres;
rootwp->height = scrdev.yvirtres;
/* deliver portrait changed event to all windows selecting it*/
GsDeliverPortraitChangedEvent();
/* redraw screen - apps may redraw/resize again causing flicker*/
GsRedrawScreen();
}
/*
* Check mouse coordinates and possibly set indicated portrait
* mode from mouse position.
*/
void
GsSetPortraitModeFromXY(GR_COORD rootx, GR_COORD rooty)
{
int newmode;
if (rootx == 0) {
/* rotate left*/
switch (scrdev.portrait) {
case MWPORTRAIT_NONE:
default:
newmode = MWPORTRAIT_LEFT;
break;
case MWPORTRAIT_LEFT:
newmode = MWPORTRAIT_DOWN;
break;
case MWPORTRAIT_DOWN:
newmode = MWPORTRAIT_RIGHT;
break;
case MWPORTRAIT_RIGHT:
newmode = MWPORTRAIT_NONE;
break;
}
GsSetPortraitMode(newmode);
GrMoveCursor(5, rooty);
GdMoveMouse(5, rooty);
} else if (rootx == scrdev.xvirtres-1) {
/* rotate right*/
switch (scrdev.portrait) {
case MWPORTRAIT_NONE:
default:
newmode = MWPORTRAIT_RIGHT;
break;
case MWPORTRAIT_LEFT:
newmode = MWPORTRAIT_NONE;
break;
case MWPORTRAIT_DOWN:
newmode = MWPORTRAIT_LEFT;
break;
case MWPORTRAIT_RIGHT:
newmode = MWPORTRAIT_DOWN;
break;
}
GsSetPortraitMode(newmode);
GrMoveCursor(scrdev.xvirtres-5, rooty);
GdMoveMouse(scrdev.xvirtres-5, rooty);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -