858 lines
22 KiB
C
858 lines
22 KiB
C
/* windMove.c -
|
|
*
|
|
* This file contains the functions which move windows around on
|
|
* the screen. It does not contain the functions that change the
|
|
* contents of the windows.
|
|
*
|
|
* *********************************************************************
|
|
* * Copyright (C) 1985, 1990 Regents of the University of California. *
|
|
* * Permission to use, copy, modify, and distribute this *
|
|
* * software and its documentation for any purpose and without *
|
|
* * fee is hereby granted, provided that the above copyright *
|
|
* * notice appear in all copies. The University of California *
|
|
* * makes no representations about the suitability of this *
|
|
* * software for any purpose. It is provided "as is" without *
|
|
* * express or implied warranty. Export of this software outside *
|
|
* * of the United States of America may require an export license. *
|
|
* *********************************************************************
|
|
*/
|
|
|
|
#ifndef lint
|
|
static char rcsid[] __attribute__ ((unused)) = "$Header$";
|
|
#endif /* not lint */
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "utils/magic.h"
|
|
#include "textio/textio.h"
|
|
#include "utils/geometry.h"
|
|
#include "windows/windows.h"
|
|
#include "graphics/graphics.h"
|
|
#include "graphics/glyphs.h"
|
|
#include "windows/windInt.h"
|
|
#include "tiles/tile.h"
|
|
#include "utils/hash.h"
|
|
#include "database/database.h"
|
|
#include "utils/malloc.h"
|
|
|
|
/* The following own variable is used to pass information between
|
|
* WindReframe and windFindUnobscured.
|
|
*/
|
|
|
|
static MagWindow *sharedW;
|
|
|
|
/*
|
|
* By default, new windows have scroll bars, border, a title caption,
|
|
* and allow standard window commands.
|
|
*/
|
|
int WindDefaultFlags = WIND_SCROLLBARS | WIND_CAPTION |
|
|
WIND_BORDER | WIND_COMMANDS |
|
|
WIND_SCROLLABLE;
|
|
|
|
/*
|
|
* A mask of the current window IDs, as well as a limit on the number of
|
|
* windows we can create.
|
|
*/
|
|
|
|
int windWindowMask = 0; /* One bit per window ID */
|
|
int windMaxWindows = 32; /* May be decreased via the WIND_MAX_WINDOWS() macro */
|
|
int windCurNumWindows = 0;
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
* windUnlink --
|
|
*
|
|
* Unlink a window from the doubly linked list of windows.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* The window is unlinked.
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
windUnlink(w)
|
|
MagWindow *w;
|
|
{
|
|
ASSERT(w != (MagWindow *) NULL, "windUnlink");
|
|
ASSERT(windTopWindow != (MagWindow *) NULL, "windUnlink");
|
|
ASSERT(windBottomWindow != (MagWindow *) NULL, "windUnlink");
|
|
ASSERT(windTopWindow->w_prevWindow == (MagWindow *) NULL, "windUnlink");
|
|
ASSERT(windBottomWindow->w_nextWindow == (MagWindow *) NULL, "windUnlink");
|
|
|
|
if ( (windTopWindow == w) || (windBottomWindow == w) )
|
|
{
|
|
if (windTopWindow == w)
|
|
{
|
|
windTopWindow = w->w_nextWindow;
|
|
if (windTopWindow != (MagWindow *) NULL)
|
|
windTopWindow->w_prevWindow = (MagWindow *) NULL;
|
|
}
|
|
if (windBottomWindow == w)
|
|
{
|
|
windBottomWindow = w->w_prevWindow;
|
|
if (windBottomWindow != (MagWindow *) NULL)
|
|
windBottomWindow->w_nextWindow = (MagWindow *) NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
w->w_nextWindow->w_prevWindow = w->w_prevWindow;
|
|
w->w_prevWindow->w_nextWindow = w->w_nextWindow;
|
|
}
|
|
|
|
w->w_nextWindow = (MagWindow *) NULL;
|
|
w->w_prevWindow = (MagWindow *) NULL;
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* windFree --
|
|
*
|
|
* This local procedure does the dirty work of freeing up
|
|
* memory in a window.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* All storage associated with w is returned to the free pool.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
windFree(w)
|
|
MagWindow *w;
|
|
{
|
|
windWindowMask &= ~(1 << w->w_wid);
|
|
windCurNumWindows--;
|
|
if (w->w_caption != (char *) NULL) freeMagic(w->w_caption);
|
|
if (w->w_iconname != (char *) NULL) freeMagic(w->w_iconname);
|
|
if (GrFreeBackingStorePtr != NULL) (*GrFreeBackingStorePtr)(w);
|
|
if (w->w_redrawAreas != (ClientData) NULL) {
|
|
DBFreePaintPlane( (Plane *) w->w_redrawAreas);
|
|
TiFreePlane( (Plane *) w->w_redrawAreas);
|
|
}
|
|
freeMagic( (char *) w);
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
* WindSetWindowAreas --
|
|
*
|
|
* Given the location of the window on the screen, compute w->w_allArea
|
|
* and w->w_screenArea in the window's own coordinate system.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Modifies w->w_allArea and w->w_screenArea.
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
WindSetWindowAreas(w)
|
|
MagWindow *w;
|
|
{
|
|
switch ( WindPackageType )
|
|
{
|
|
case WIND_X_WINDOWS:
|
|
/* Windows have origin at lower-left corner */
|
|
w->w_allArea.r_xbot = w->w_allArea.r_ybot = 0;
|
|
w->w_allArea.r_xtop = w->w_frameArea.r_xtop - w->w_frameArea.r_xbot;
|
|
w->w_allArea.r_ytop = w->w_frameArea.r_ytop - w->w_frameArea.r_ybot;
|
|
break;
|
|
|
|
default:
|
|
/* Windows are all in the same coordinate system */
|
|
w->w_allArea = w->w_frameArea;
|
|
}
|
|
WindOutToIn(w, &w->w_allArea, &w->w_screenArea);
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
* windSetWindowPosition --
|
|
*
|
|
* (deprecated function)
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* None.
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
windSetWindowPosition(w)
|
|
MagWindow *w;
|
|
{
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
* WindDelete --
|
|
*
|
|
* Delete a window.
|
|
*
|
|
* Results:
|
|
* TRUE if the window was deleted, FALSE otherwise.
|
|
*
|
|
* Side effects:
|
|
* The window disappears from the sreen. The window's client is notified
|
|
* that this is about to happen, and it may refuse to let it happen.
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
bool
|
|
WindDelete(w)
|
|
MagWindow *w;
|
|
{
|
|
clientRec *cr;
|
|
|
|
ASSERT(w != (MagWindow *) NULL, "WindDelete");
|
|
|
|
cr = (clientRec *) w->w_client;
|
|
if ( (cr->w_delete == NULL) || (*(cr->w_delete))(w) )
|
|
{
|
|
WindAreaChanged(w, &(w->w_allArea) );
|
|
if (GrDeleteWindowPtr != NULL) (*GrDeleteWindowPtr)(w);
|
|
windUnlink(w);
|
|
windReClip();
|
|
windFree(w);
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
* WindCreate --
|
|
*
|
|
* Create a new window for the specified client.
|
|
*
|
|
* Results:
|
|
* A pointer to the new window, or NULL if one couldn't be created.
|
|
*
|
|
* Side effects:
|
|
* An empty window is created, and it is displayed.
|
|
* The new window is place on top of all the other
|
|
* windows.
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
MagWindow *
|
|
WindCreate(client, frameArea, isHint, argc, argv)
|
|
WindClient client; /* The client that will control this window */
|
|
Rect *frameArea; /* The area that the window is to occupy */
|
|
bool isHint; /* TRUE if the above rectangle is only a
|
|
* hint and it is OK for a window package to
|
|
* override it to maintain a consistent
|
|
* user interface.
|
|
*/
|
|
int argc; /* Passed to the client */
|
|
char *argv[];
|
|
{
|
|
MagWindow *w;
|
|
clientRec *cr;
|
|
bool OK;
|
|
int id;
|
|
|
|
if (windCurNumWindows + 1 > windMaxWindows) {
|
|
TxError("Can't have more than %d windows.\n", windMaxWindows);
|
|
return NULL;
|
|
}
|
|
windCurNumWindows++;
|
|
|
|
cr = (clientRec *) client;
|
|
|
|
/* initialize the window */
|
|
w = (MagWindow *) mallocMagic( sizeof(MagWindow) );
|
|
w->w_client = client;
|
|
w->w_flags = WindDefaultFlags;
|
|
w->w_clipAgainst = (LinkedRect *) NULL;
|
|
w->w_caption = (char *) NULL;
|
|
w->w_stippleOrigin.p_x = 0;
|
|
w->w_stippleOrigin.p_y = 0;
|
|
w->w_bbox = NULL;
|
|
w->w_grdata = (ClientData) NULL;
|
|
w->w_grdata2 = (ClientData) NULL;
|
|
w->w_backingStore = (ClientData)NULL;
|
|
w->w_redrawAreas = (ClientData) NULL;
|
|
w->w_surfaceID = (ClientData) NULL;
|
|
w->w_iconname = NULL;
|
|
for (id = 0; ((1 << id) & windWindowMask) != 0; id++) /* advance id */ ;
|
|
windWindowMask |= (1 << id);
|
|
w->w_wid = id;
|
|
|
|
/* locate window on the screen */
|
|
if (frameArea == (Rect *) NULL)
|
|
{
|
|
switch ( WindPackageType )
|
|
{
|
|
case WIND_X_WINDOWS:
|
|
/*
|
|
* Create default size window in upper left corner
|
|
* of screen.
|
|
*/
|
|
w->w_frameArea.r_xbot = GrScreenRect.r_xbot;
|
|
w->w_frameArea.r_ytop = GrScreenRect.r_ytop;
|
|
w->w_frameArea.r_xtop =
|
|
(GrScreenRect.r_xtop - GrScreenRect.r_xbot) / 2;
|
|
w->w_frameArea.r_ybot =
|
|
(GrScreenRect.r_ytop - GrScreenRect.r_ybot) / 2;
|
|
break;
|
|
|
|
default:
|
|
w->w_frameArea = GrScreenRect;
|
|
}
|
|
}
|
|
else
|
|
w->w_frameArea = *frameArea;
|
|
|
|
WindSetWindowAreas(w);
|
|
|
|
/* now link the window in on top */
|
|
w->w_nextWindow = windTopWindow;
|
|
w->w_prevWindow = (MagWindow *) NULL;
|
|
if (windTopWindow == (MagWindow *) NULL)
|
|
windBottomWindow = w;
|
|
else
|
|
windTopWindow->w_prevWindow = w;
|
|
windTopWindow = w;
|
|
|
|
/* notify the client */
|
|
OK = ((cr->w_create == NULL) || (*(cr->w_create))(w, argc, argv));
|
|
|
|
#ifdef THREE_D
|
|
if (strcmp(cr->w_clientName, "wind3d"))
|
|
#endif
|
|
|
|
if (OK && (GrCreateWindowPtr != NULL))
|
|
OK = (*GrCreateWindowPtr)(w, (argc > 1) ? argv[1] : NULL);
|
|
|
|
if (OK)
|
|
{
|
|
WindSetWindowAreas(w);
|
|
windSetWindowPosition(w);
|
|
WindAreaChanged(w, &(w->w_allArea));
|
|
}
|
|
else
|
|
{
|
|
/* the client refused the new window */
|
|
windUnlink(w);
|
|
windFree(w);
|
|
w = (MagWindow *) NULL;
|
|
}
|
|
windReClip();
|
|
if ((GrCreateBackingStorePtr != NULL) && (w != NULL) &&
|
|
(!(w->w_flags & WIND_OBSCURED)))
|
|
(*GrCreateBackingStorePtr)(w);
|
|
|
|
return w;
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* WindOutToIn and WindInToOut --
|
|
*
|
|
* The two procedures on this page translate from window inside
|
|
* area (the area used to display the surface) to window
|
|
* outside area (the total area of the window including caption),
|
|
* and vice versa.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Each procedure modifies its third parameter. WindOutToIn
|
|
* fills in the third parameter with the inside area of the
|
|
* window whose outside area is out, and WindInToOut does the
|
|
* opposite.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
WindOutToIn(w, out, in)
|
|
MagWindow *w; /* Window under consideration */
|
|
Rect *out; /* Pointer to rectangle of outside area of
|
|
* a window.
|
|
*/
|
|
Rect *in; /* Pointer to rectangle to be filled in with
|
|
* inside area corresponding to out.
|
|
*/
|
|
{
|
|
*in = *out;
|
|
in->r_xbot += LEFT_BORDER(w);
|
|
in->r_xtop -= RIGHT_BORDER(w);
|
|
in->r_ybot += BOT_BORDER(w);
|
|
in->r_ytop -= TOP_BORDER(w);
|
|
}
|
|
|
|
void WindInToOut(w, in, out)
|
|
MagWindow *w; /* Window under consideration */
|
|
Rect *in; /* Pointer to rectangle of outside area of
|
|
* a window.
|
|
*/
|
|
Rect *out; /* Pointer to rectangle to be filled in with
|
|
* inside area corresponding to out.
|
|
*/
|
|
{
|
|
*out = *in;
|
|
out->r_xbot -= LEFT_BORDER(w);
|
|
out->r_xtop += RIGHT_BORDER(w);
|
|
out->r_ybot -= BOT_BORDER(w);
|
|
out->r_ytop += TOP_BORDER(w);
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
* WindUnder --
|
|
*
|
|
* Move a window underneath the rest.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* The window is moved so that it is underneath the rest. This will
|
|
* cause portions of uncovered windows to be redisplayed.
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
WindUnder(w)
|
|
MagWindow *w; /* the window to be moved */
|
|
{
|
|
Rect area;
|
|
MagWindow *w2;
|
|
|
|
switch ( WindPackageType )
|
|
{
|
|
case WIND_X_WINDOWS:
|
|
if ( GrUnderWindowPtr )
|
|
(*GrUnderWindowPtr)(w);
|
|
break;
|
|
default:
|
|
/* Mark for redisplay all the areas that this window
|
|
* currently obscures.
|
|
*/
|
|
|
|
for (w2 = w->w_nextWindow; w2 != NULL; w2 = w2->w_nextWindow)
|
|
{
|
|
area = w2->w_allArea;
|
|
GeoClip(&area, &w->w_allArea);
|
|
if ((area.r_xbot <= area.r_xtop) && (area.r_ybot <= area.r_ytop))
|
|
WindAreaChanged(w, &area);
|
|
}
|
|
|
|
/* take the window out of the linked list */
|
|
windUnlink(w);
|
|
|
|
/* now link it back in at the bottom */
|
|
w->w_prevWindow = windBottomWindow;
|
|
if (windBottomWindow != (MagWindow *) NULL)
|
|
windBottomWindow->w_nextWindow = w;
|
|
else
|
|
windTopWindow = w;
|
|
windBottomWindow = w;
|
|
|
|
windReClip();
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
* WindOver --
|
|
*
|
|
* Move a window so that it is over (on top of) the other windows.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* The window is moved to the top. This may obscure some other windows.
|
|
* The window that is moved will be redisplayed.
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
WindOver(w)
|
|
MagWindow *w; /* the window to be moved */
|
|
{
|
|
LinkedRect *r;
|
|
Rect area;
|
|
|
|
switch ( WindPackageType )
|
|
{
|
|
case WIND_X_WINDOWS:
|
|
if ( GrOverWindowPtr )
|
|
(*GrOverWindowPtr)(w);
|
|
break;
|
|
|
|
default:
|
|
/* Mark for redisplay all of the areas of the screen that
|
|
* currently obscure this window.
|
|
*/
|
|
|
|
for (r = w->w_clipAgainst; r != NULL; r = r->r_next)
|
|
{
|
|
area = r->r_r;
|
|
GeoClip(&area, &w->w_frameArea);
|
|
if ((area.r_xbot <= area.r_xtop) && (area.r_ybot <= area.r_ytop))
|
|
WindAreaChanged((MagWindow *) NULL, &area);
|
|
}
|
|
|
|
/* take the window out of the linked list */
|
|
windUnlink(w);
|
|
|
|
/* now link it back in at the top */
|
|
w->w_nextWindow = windTopWindow;
|
|
if (windTopWindow != (MagWindow *) NULL)
|
|
windTopWindow->w_prevWindow = w;
|
|
else
|
|
windBottomWindow = w;
|
|
windTopWindow = w;
|
|
|
|
windReClip();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* windFindUnobscured --
|
|
*
|
|
* Locates one portion of a rectangle that is unobscured, if
|
|
* any part of the rectangle is unobscured. Used only by
|
|
* WindReframe.
|
|
*
|
|
* Results:
|
|
* Always returns TRUE.
|
|
*
|
|
* Side effects:
|
|
* The caller must place in the shared variable sharedW the
|
|
* name of a window, or NULL. That window, and all windows
|
|
* above it, are checked to see if any obscure area. If
|
|
* there is any unobscured part of area, it is placed in
|
|
* okArea. If several distinct parts of area are unobscured,
|
|
* one, but only one, of them will be placed in okArea.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
bool
|
|
windFindUnobscured(area, okArea)
|
|
Rect *area; /* Area that may be obscured. */
|
|
Rect *okArea; /* Modified to contain one of the
|
|
* unobscured areas.
|
|
*/
|
|
{
|
|
MagWindow *w;
|
|
w = sharedW;
|
|
if (w == NULL)
|
|
{
|
|
*okArea = *area;
|
|
return FALSE;
|
|
}
|
|
sharedW = w->w_prevWindow;
|
|
(void) GeoDisjoint(area, &w->w_frameArea,
|
|
windFindUnobscured, (ClientData) okArea);
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
* WindReframe --
|
|
*
|
|
* Change the size or location of a window.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* The window is moved, and areas of the screen are marked for
|
|
* redisplay. This routine tries to be tricky in order to avoid
|
|
* massive redisplay for small changes.
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
WindReframe(w, r, inside, move)
|
|
MagWindow *w; /* the window to be reframed */
|
|
Rect *r; /* the new location in screen coordinates */
|
|
bool inside; /* TRUE if the rectangle is the screen location of
|
|
* the inside of the window, FALSE if the above
|
|
* rectangle includes border areas.
|
|
*/
|
|
bool move; /* Move the coordinate system of the window the same
|
|
* amount as the lower left corner of the window?
|
|
*/
|
|
{
|
|
Rect newFrameArea; /* New w_frameArea. */
|
|
Rect dontRedisplay; /* Used to record an area that does
|
|
* not have to be redisplayed.
|
|
*/
|
|
int xmove, ymove; /* Distance window is moving. */
|
|
extern bool windReframeFunc(); /* Forward declaration. */
|
|
clientRec *cr;
|
|
|
|
cr = (clientRec *) w->w_client;
|
|
|
|
/* Ensure that the new window size is not inside out and has some size to
|
|
* it. Compute the new w_frameArea (in newFrameArea).
|
|
*/
|
|
|
|
GeoCanonicalRect(r, &newFrameArea);
|
|
if (inside) WindInToOut(w, &newFrameArea, &newFrameArea);
|
|
|
|
if ((w->w_flags & WIND_ISICONIC) == 0) {
|
|
/* Not iconic -- enforce a minimum size */
|
|
newFrameArea.r_xtop = MAX(newFrameArea.r_xtop,
|
|
newFrameArea.r_xbot + WIND_MIN_WIDTH);
|
|
newFrameArea.r_ytop = MAX(newFrameArea.r_ytop,
|
|
newFrameArea.r_ybot + WIND_MIN_HEIGHT);
|
|
}
|
|
|
|
/* Give the client a chance to modify the change. */
|
|
if (cr->w_reposition != NULL)
|
|
(*(cr->w_reposition))(w, &newFrameArea, FALSE);
|
|
|
|
|
|
/* If the window coordinates are moving, update the transform
|
|
* so that the lower-left corner of the window remains at the
|
|
* same location in surface coordinates.
|
|
*/
|
|
|
|
if (move)
|
|
{
|
|
xmove = newFrameArea.r_xbot - w->w_frameArea.r_xbot;
|
|
w->w_origin.p_x += xmove << SUBPIXELBITS;
|
|
ymove = newFrameArea.r_ybot - w->w_frameArea.r_ybot;
|
|
w->w_origin.p_y += ymove << SUBPIXELBITS;
|
|
w->w_stippleOrigin.p_x += xmove;
|
|
w->w_stippleOrigin.p_y += ymove;
|
|
}
|
|
|
|
switch ( WindPackageType )
|
|
{
|
|
case WIND_X_WINDOWS:
|
|
break;
|
|
|
|
default:
|
|
/* Now comes the tricky part: figuring out what to redisplay.
|
|
* The simple way out is to force redisplay at both the old and
|
|
* new window positions. Naturally this code is going to be more
|
|
* ambitious. There are two steps. First, figure out what piece
|
|
* of the old window must be redisplayed, then move the window,
|
|
* then figure out what pieces of the new window must be redisplayed.
|
|
* If the window coordinates aren't moving, then any screen area
|
|
* common to the old and new positions needn't be redisplayed,
|
|
* since its contents won't change.
|
|
*/
|
|
|
|
if (!move)
|
|
{
|
|
/* Compute the intersection of the old and new areas in
|
|
* dontRedisplay. Mark old areas outside of this common area as
|
|
* needing to be redisplayed.
|
|
*/
|
|
WindOutToIn(w, &newFrameArea, &dontRedisplay);
|
|
GeoClip(&dontRedisplay, &w->w_screenArea);
|
|
(void) GeoDisjoint(&w->w_frameArea, &dontRedisplay, windReframeFunc,
|
|
(ClientData) w);
|
|
}
|
|
else
|
|
{
|
|
/* Record the entire old area as needing to be redisplayed. */
|
|
|
|
WindAreaChanged(w, &w->w_allArea);
|
|
dontRedisplay = w->w_allArea;
|
|
}
|
|
}
|
|
|
|
/* At this point, we've recorded any old area that needs to be
|
|
* redisplayed.
|
|
*/
|
|
|
|
w->w_frameArea = newFrameArea;
|
|
WindSetWindowAreas(w);
|
|
windSetWindowPosition(w);
|
|
windFixSurfaceArea(w);
|
|
windReClip();
|
|
|
|
switch (WindPackageType)
|
|
{
|
|
case WIND_X_WINDOWS:
|
|
/* Regenerate backing store, if enabled */
|
|
if ((GrCreateBackingStorePtr != NULL) &&
|
|
(!(w->w_flags & WIND_OBSCURED)))
|
|
(*GrCreateBackingStorePtr)(w);
|
|
break;
|
|
|
|
default:
|
|
/* Now that the window has been moved, record any of the new area that
|
|
* has to be redisplayed.
|
|
*/
|
|
|
|
(void) GeoDisjoint(&w->w_allArea, &dontRedisplay, windReframeFunc,
|
|
(ClientData) w);
|
|
}
|
|
|
|
/* Give the client a chance to do things like windMove().
|
|
*/
|
|
if (cr->w_reposition != NULL)
|
|
(*(cr->w_reposition))(w, &newFrameArea, TRUE);
|
|
}
|
|
|
|
bool
|
|
windReframeFunc(area, w)
|
|
Rect *area; /* Area to redisplay. */
|
|
MagWindow *w; /* Window in which to redisplay. */
|
|
|
|
{
|
|
WindAreaChanged(w, area);
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* WindFullScreen --
|
|
*
|
|
* This procedure blows a window up so it's on top of all the others
|
|
* and is full-screen. Or, if the window was already full-screen,
|
|
* it is put back where it came from before it was made full-screen.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* The window's size and location are changed.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
WindFullScreen(w)
|
|
MagWindow *w; /* Window to be blown up or shrunk back. */
|
|
{
|
|
int i;
|
|
MagWindow *w2;
|
|
Rect newFrameArea;
|
|
clientRec *cr;
|
|
int newDepth;
|
|
|
|
cr = (clientRec *) w->w_client;
|
|
|
|
/* Compute default new location. */
|
|
|
|
if (w->w_flags & WIND_FULLSCREEN)
|
|
newFrameArea = w->w_oldArea;
|
|
else
|
|
newFrameArea = GrScreenRect;
|
|
|
|
/* Give the client a chance to modify newFrameArea. */
|
|
|
|
if (cr->w_reposition != NULL)
|
|
(*(cr->w_reposition))(w, &newFrameArea, FALSE);
|
|
|
|
/*
|
|
* Now, actually modify the window and its position.
|
|
*/
|
|
|
|
/* Compute new stuff. */
|
|
|
|
if (w->w_flags & WIND_FULLSCREEN)
|
|
{
|
|
newDepth = w->w_oldDepth;
|
|
w->w_flags &= ~WIND_FULLSCREEN;
|
|
}
|
|
else
|
|
{
|
|
newDepth = 0;
|
|
w->w_flags |= WIND_FULLSCREEN;
|
|
|
|
/* Record old depth and area. */
|
|
|
|
w->w_oldArea = w->w_frameArea;
|
|
w->w_oldDepth = 0;
|
|
for (w2 = windTopWindow; w2 != w; w2 = w2->w_nextWindow)
|
|
{
|
|
ASSERT(w2 != (MagWindow *) NULL, "WindFullScreen");
|
|
w->w_oldDepth += 1;
|
|
}
|
|
}
|
|
|
|
|
|
/* Change the view and screen location. */
|
|
w->w_frameArea = newFrameArea;
|
|
WindSetWindowAreas(w);
|
|
windSetWindowPosition(w);
|
|
WindMove(w, &w->w_surfaceArea);
|
|
|
|
/* Move the window to the proper depth. */
|
|
if (windTopWindow != (MagWindow *) NULL)
|
|
{
|
|
if (newDepth == 0)
|
|
{
|
|
switch ( WindPackageType )
|
|
{
|
|
case WIND_X_WINDOWS:
|
|
break;
|
|
|
|
default:
|
|
WindOver(w);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
windUnlink(w);
|
|
w2 = windTopWindow;
|
|
for (i=1; i<newDepth; i++)
|
|
if (w2->w_nextWindow != NULL) w2 = w2->w_nextWindow;
|
|
w->w_nextWindow = w2->w_nextWindow;
|
|
w->w_prevWindow = w2;
|
|
w2->w_nextWindow = w;
|
|
if (w->w_nextWindow == NULL)
|
|
windBottomWindow = w;
|
|
else
|
|
w->w_nextWindow->w_prevWindow = w;
|
|
windReClip();
|
|
}
|
|
}
|
|
|
|
/* Notify the client. */
|
|
if (cr->w_reposition != NULL)
|
|
(*(cr->w_reposition))(w, &newFrameArea, TRUE);
|
|
|
|
/* Record new display areas. */
|
|
switch (WindPackageType)
|
|
{
|
|
case WIND_X_WINDOWS:
|
|
if (GrConfigureWindowPtr != NULL)
|
|
(*GrConfigureWindowPtr)(w);
|
|
if (GrCreateBackingStorePtr != NULL &&
|
|
(!(w->w_flags & WIND_OBSCURED)))
|
|
(*GrCreateBackingStorePtr)(w);
|
|
break;
|
|
default:
|
|
WindAreaChanged((MagWindow *) NULL, (Rect *) NULL);
|
|
}
|
|
}
|