818 lines
21 KiB
C
818 lines
21 KiB
C
#ifndef lint
|
|
static char sccsid[] = "@(#)wintree.c 1.1 94/10/31 Copyr 1985 Sun Micro";
|
|
#endif
|
|
|
|
/*
|
|
* Copyright (c) 1985 by Sun Microsystems, Inc.
|
|
*/
|
|
|
|
/*
|
|
* SunWindows window tree primitives.
|
|
*/
|
|
|
|
#include <sunwindowdev/wintree.h>
|
|
#include <sunwindow/win_ioctl.h>
|
|
#include <sys/vmmeter.h>
|
|
#include <sys/kmem_alloc.h>
|
|
|
|
#define MAX_RNSDAMAGED 20
|
|
|
|
static void wt_bump_clippingid();
|
|
|
|
|
|
wt_install(win)
|
|
register struct window *win;
|
|
{
|
|
register struct window *parent;
|
|
struct window *youngest;
|
|
|
|
if (win->w_flags & WF_INSTALLED)
|
|
return (EBUSY);
|
|
if (wt_badchildren(win))
|
|
return (EINVAL);
|
|
parent = win->w_link[WL_PARENT];
|
|
if (parent == NULL)
|
|
return (EINVAL);
|
|
TryAgain:
|
|
if (parent->w_link[WL_OLDESTCHILD] == NULL &&
|
|
parent->w_link[WL_YOUNGESTCHILD] == NULL) {
|
|
if (win->w_link[WL_OLDERSIB] || win->w_link[WL_YOUNGERSIB]) {
|
|
#ifdef HARSH_CHECKING
|
|
return (EINVAL);
|
|
#else HARSH_CHECKING
|
|
/* Adjust windows siblings */
|
|
win->w_link[WL_OLDERSIB] = win->w_link[WL_YOUNGERSIB] =
|
|
NULL;
|
|
#endif HARSH_CHECKING
|
|
}
|
|
parent->w_link[WL_OLDESTCHILD] =
|
|
parent->w_link[WL_YOUNGESTCHILD] = win;
|
|
} else if (win->w_link[WL_OLDERSIB] == NULL) {
|
|
win->w_link[WL_YOUNGERSIB] = parent->w_link[WL_OLDESTCHILD];
|
|
win->w_link[WL_YOUNGERSIB]->w_link[WL_OLDERSIB] = win;
|
|
parent->w_link[WL_OLDESTCHILD] = win;
|
|
} else if (win->w_link[WL_YOUNGERSIB] == NULL) {
|
|
/*
|
|
* check WUF_WMGR4 of top window to see if current
|
|
* window can go on top of it.
|
|
*/
|
|
youngest = parent->w_link[WL_YOUNGESTCHILD];
|
|
if (youngest->w_userflags & WUF_WMGR4) {
|
|
win->w_link[WL_YOUNGERSIB] = youngest;
|
|
win->w_link[WL_OLDERSIB] = youngest->w_link[WL_OLDERSIB];
|
|
if (youngest->w_link[WL_OLDERSIB])
|
|
youngest->w_link[WL_OLDERSIB]->w_link[WL_YOUNGERSIB] = win;
|
|
youngest->w_link[WL_OLDERSIB] = win;
|
|
}
|
|
else
|
|
{
|
|
win->w_link[WL_OLDERSIB] = parent->w_link[WL_YOUNGESTCHILD];
|
|
win->w_link[WL_OLDERSIB]->w_link[WL_YOUNGERSIB] = win;
|
|
parent->w_link[WL_YOUNGESTCHILD] = win;
|
|
}
|
|
} else {
|
|
if ((win->w_link[WL_OLDERSIB]->w_flags & WF_INSTALLED) == 0 ||
|
|
(win->w_link[WL_YOUNGERSIB]->w_flags & WF_INSTALLED) == 0 ||
|
|
win->w_link[WL_YOUNGERSIB]->w_link[WL_OLDERSIB] !=
|
|
win->w_link[WL_OLDERSIB] ||
|
|
win->w_link[WL_OLDERSIB]->w_link[WL_YOUNGERSIB] !=
|
|
win->w_link[WL_YOUNGERSIB]) {
|
|
#ifdef HARSH_CHECKING
|
|
return (EINVAL);
|
|
#else HARSH_CHECKING
|
|
/* Just place it on the bottom of sibling pile */
|
|
win->w_link[WL_YOUNGERSIB] = win->w_link[WL_OLDERSIB] =
|
|
NULL;
|
|
goto TryAgain;
|
|
#endif HARSH_CHECKING
|
|
}
|
|
win->w_link[WL_OLDERSIB]->w_link[WL_YOUNGERSIB] = win;
|
|
win->w_link[WL_YOUNGERSIB]->w_link[WL_OLDERSIB] = win;
|
|
}
|
|
win->w_flags |= WF_INSTALLED;
|
|
{
|
|
int wt_initclipping();
|
|
wt_enumeratechildren(wt_initclipping, win, (struct rect *)0);
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
wt_badchildren(win)
|
|
register struct window *win;
|
|
{
|
|
register struct window *child;
|
|
|
|
if (child = win->w_link[WL_OLDESTCHILD])
|
|
if ((child->w_flags & WF_INSTALLED) == 0 ||
|
|
child->w_link[WL_PARENT] != win ||
|
|
child->w_link[WL_OLDERSIB])
|
|
return (-1);
|
|
if (child = win->w_link[WL_YOUNGESTCHILD])
|
|
if ((child->w_flags & WF_INSTALLED) == 0 ||
|
|
child->w_link[WL_PARENT] != win ||
|
|
child->w_link[WL_YOUNGERSIB])
|
|
return (-1);
|
|
return (0);
|
|
}
|
|
|
|
wt_remove(win)
|
|
register struct window *win;
|
|
{
|
|
register struct window *parent = win->w_link[WL_PARENT];
|
|
|
|
if ((win->w_flags & WF_INSTALLED) == 0)
|
|
return (EINVAL);
|
|
win->w_flags &= ~WF_INSTALLED;
|
|
if (parent->w_link[WL_OLDESTCHILD] == win)
|
|
parent->w_link[WL_OLDESTCHILD] = win->w_link[WL_YOUNGERSIB];
|
|
if (parent->w_link[WL_YOUNGESTCHILD] == win)
|
|
parent->w_link[WL_YOUNGESTCHILD] = win->w_link[WL_OLDERSIB];
|
|
if (win->w_link[WL_OLDERSIB])
|
|
win->w_link[WL_OLDERSIB]->w_link[WL_YOUNGERSIB] =
|
|
win->w_link[WL_YOUNGERSIB];
|
|
if (win->w_link[WL_YOUNGERSIB])
|
|
win->w_link[WL_YOUNGERSIB]->w_link[WL_OLDERSIB] =
|
|
win->w_link[WL_OLDERSIB];
|
|
{
|
|
int wt_nullclipping();
|
|
wt_enumeratechildren(wt_nullclipping, win, (struct rect *)0);
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* Walk the tree (including win) in layering order direction.
|
|
* Note: Currently not called from anywhere, so commented out.
|
|
*/
|
|
wt_enumerate(function, direction, win)
|
|
int (*function)();
|
|
int direction;
|
|
struct window *win;
|
|
{
|
|
if (direction==WT_BOTTOMTOTOP) {
|
|
(*function)(win);
|
|
if (win->WL_BOTTOMCHILD!=NULL)
|
|
wt_enumerate(function, direction, win->WL_BOTTOMCHILD);
|
|
if (win->WL_COVERING!=NULL)
|
|
wt_enumerate(function, direction, win->WL_COVERING);
|
|
} else {
|
|
/*
|
|
* Assume WT_TOPTOBOTTOM
|
|
*/
|
|
if (win->WL_TOPCHILD!=NULL)
|
|
wt_enumerate(function, direction, win->WL_TOPCHILD);
|
|
(*function)(win);
|
|
if (win->WL_COVERED!=NULL)
|
|
wt_enumerate(function, direction, win->WL_COVERED);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Enumerate the children of win (including win).
|
|
*/
|
|
wt_enumeratechildren(function, win, rect)
|
|
int (*function)();
|
|
struct window *win;
|
|
struct rect *rect;
|
|
{
|
|
register struct window *wchild;
|
|
|
|
if (win)
|
|
(*function)(win, rect);
|
|
else
|
|
return;
|
|
for (wchild = win->w_link[WL_YOUNGESTCHILD]; wchild;
|
|
wchild = wchild->w_link[WL_OLDERSIB]) {
|
|
if (rect)
|
|
rect_passtochild(wchild->w_rect.r_left,
|
|
wchild->w_rect.r_top, rect);
|
|
wt_enumeratechildren(function, wchild, rect);
|
|
if (rect)
|
|
rect_passtoparent(wchild->w_rect.r_left,
|
|
wchild->w_rect.r_top, rect);
|
|
}
|
|
}
|
|
|
|
/* Utilities */
|
|
|
|
wt_numbertowindow(number, aw)
|
|
int number;
|
|
struct window **aw;
|
|
{
|
|
|
|
if (number == WIN_NULLLINK) {
|
|
*aw = NULL;
|
|
return (0);
|
|
}
|
|
if ((unsigned)number >= win_nwindows) {
|
|
return (-1);
|
|
}
|
|
*aw = winfromdev(number);
|
|
if (!((*aw)->w_flags & WF_OPEN))
|
|
return (-1);
|
|
return (0);
|
|
}
|
|
|
|
wt_windowtonumber(w, anumber)
|
|
register struct window *w;
|
|
register int *anumber;
|
|
{
|
|
register int wi;
|
|
|
|
*anumber = WIN_NULLLINK;
|
|
if (w == NULL)
|
|
return;
|
|
for (wi = 0; wi < win_nwindows; wi++) {
|
|
/* Linear search - hope we're not called often! */
|
|
if (w == winbufs[wi]) {
|
|
*anumber = wi;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* This routine should initially be called when winthis is a root.
|
|
* This routine can't generally be initially be called with winthis at
|
|
* any level of the window tree. However, a special case allows the
|
|
* first level in the window heirarchy to be used as the initial
|
|
* winthis.
|
|
*/
|
|
wt_setclipping(winthis, rlaffected)
|
|
register struct window *winthis;
|
|
register struct rectlist *rlaffected; /* Self relative */
|
|
{
|
|
register struct window *w;
|
|
register struct rectnode *rn;
|
|
struct rect rparent, rintersect;
|
|
struct rectlist rlfix;
|
|
int rnsdamaged;
|
|
|
|
rlfix = rl_null;
|
|
/*
|
|
* Save the current clipping and init clipping to null.
|
|
*/
|
|
rl_copy(&winthis->w_rlexposed, &winthis->w_rlexposedold);
|
|
rl_free(&winthis->w_rlexposed);
|
|
if (winthis->w_link[WL_PARENT] == NULL) {
|
|
/*
|
|
* Initialize the root clipping with its entire rectangle
|
|
*/
|
|
rl_initwithrect(&winthis->w_rect, &winthis->w_rlexposed);
|
|
winthis->w_screenx =
|
|
winthis->w_desktop->dt_screen.scr_rect.r_left;
|
|
winthis->w_screeny =
|
|
winthis->w_desktop->dt_screen.scr_rect.r_top;
|
|
/*
|
|
* Initialize the root fixup with entire rlaffected
|
|
*/
|
|
rl_copy(rlaffected, &rlfix);
|
|
} else {
|
|
/*
|
|
* Make data parent relative
|
|
*/
|
|
rl_passtoparent(winthis->w_rect.r_left, winthis->w_rect.r_top,
|
|
rlaffected);
|
|
rparent = winthis->w_link[WL_PARENT]->w_rect;
|
|
rparent.r_left = rparent.r_top = 0;
|
|
/*
|
|
* Initialize the window clipping to intersection of parent
|
|
* window and self.
|
|
*/
|
|
rect_intersection(&winthis->w_rect, &rparent, &rintersect);
|
|
rl_initwithrect(&rintersect, &winthis->w_rlexposed);
|
|
winthis->w_screenx = winthis->w_link[WL_PARENT]->w_screenx+
|
|
winthis->w_rect.r_left;
|
|
winthis->w_screeny = winthis->w_link[WL_PARENT]->w_screeny+
|
|
winthis->w_rect.r_top;
|
|
/*
|
|
* Remove ansector opaque portions from clipping.
|
|
* At this point the parent's clipping only includes the
|
|
* parent's ansector and sibling clipping, no child clipping.
|
|
*/
|
|
if (winthis->w_link[WL_PARENT]->w_link[WL_PARENT] != NULL)
|
|
/*
|
|
* Don't need to do this computation if one level down.
|
|
*/
|
|
rl_intersection(&winthis->w_rlexposed,
|
|
&winthis->w_link[WL_PARENT]->w_rlexposed,
|
|
&winthis->w_rlexposed);
|
|
/*
|
|
* Remove covering siblings from clipping.
|
|
*/
|
|
for (w = winthis->WL_COVERING; w != NULL; w = w->WL_COVERING) {
|
|
rl_rectdifference(&w->w_rect, &winthis->w_rlexposed,
|
|
&winthis->w_rlexposed);
|
|
}
|
|
/*
|
|
* Initialize the window fixup with intersection of initial
|
|
* clipping and rlaffected.
|
|
*/
|
|
rl_rectintersection(&rintersect, rlaffected, &rlfix);
|
|
/*
|
|
* Make data self relative
|
|
*/
|
|
rl_passtochild(winthis->w_rect.r_left, winthis->w_rect.r_top,
|
|
rlaffected);
|
|
rl_passtochild(winthis->w_rect.r_left, winthis->w_rect.r_top,
|
|
&winthis->w_rlexposed);
|
|
rl_passtochild(winthis->w_rect.r_left, winthis->w_rect.r_top,
|
|
&rlfix);
|
|
}
|
|
/*
|
|
* Make sure clipping and fixup have 0 offsets
|
|
*/
|
|
rl_normalize(&winthis->w_rlexposed);
|
|
rl_normalize(&rlfix);
|
|
/*
|
|
* Allow children to find clipping.
|
|
* Make rlaffected relative to w before call wt_setclipping.
|
|
*/
|
|
for (w = winthis->WL_BOTTOMCHILD; w != NULL; w = w->WL_COVERING) {
|
|
rl_passtochild(w->w_rect.r_left, w->w_rect.r_top, rlaffected);
|
|
wt_setclipping(w, rlaffected);
|
|
rl_passtoparent(w->w_rect.r_left, w->w_rect.r_top, rlaffected);
|
|
}
|
|
/*
|
|
* Remove covering children.
|
|
*/
|
|
for (w = winthis->WL_BOTTOMCHILD; w != NULL; w = w->WL_COVERING) {
|
|
rl_rectdifference(&w->w_rect, &winthis->w_rlexposed,
|
|
&winthis->w_rlexposed);
|
|
}
|
|
rl_coalesce(&winthis->w_rlexposed);
|
|
if (!(winthis->w_flags&WF_DTOPPOSCHANGED)) {
|
|
/*
|
|
* Remove what was already exposed from what needs to be
|
|
* repaired.
|
|
*/
|
|
rl_difference(&rlfix, &winthis->w_rlexposedold, &rlfix);
|
|
} else {
|
|
/*
|
|
* Don't try to optimize because bits on dtop must move.
|
|
*/
|
|
}
|
|
/*
|
|
* Add what needs to be repaired this time to what was leftover from
|
|
* previous clipping recomputations.
|
|
*/
|
|
rl_union(&rlfix, &winthis->w_rlfixup, &rlfix);
|
|
/*
|
|
* Remember if had unfinished fixup in case try to do partial repair.
|
|
*/
|
|
if (!rl_empty(&winthis->w_rlfixup))
|
|
winthis->w_flags |= WF_PREVIOUSDAMAGED;
|
|
else
|
|
winthis->w_flags &= ~WF_PREVIOUSDAMAGED;
|
|
/*
|
|
* Reduce what needs to be repaired by intersecting with what's exposed.
|
|
*/
|
|
rl_intersection(&rlfix, &winthis->w_rlexposed, &rlfix);
|
|
/*
|
|
* Simplify rls as much as possible.
|
|
*/
|
|
rl_coalesce(&rlfix);
|
|
/*
|
|
* If damaged area is "too" complex then replace by total exposed area.
|
|
* This is mainly to prevent too much damage from accumulating.
|
|
* Exposed could still have more parts then damaged,
|
|
* but this is the degenerate case.
|
|
*/
|
|
rnsdamaged = 0;
|
|
for (rn = rlfix.rl_head; rn; rn = rn->rn_next)
|
|
rnsdamaged++;
|
|
if (rnsdamaged >= MAX_RNSDAMAGED) {
|
|
rl_free(&rlfix);
|
|
rl_copy(&winthis->w_rlexposed, &rlfix);
|
|
}
|
|
/*
|
|
* Bump clippingid if exposed part has changed.
|
|
*/
|
|
if (!rl_equal(&winthis->w_rlexposed, &winthis->w_rlexposedold)) {
|
|
wt_bump_clippingid(winthis);
|
|
#ifndef PRE_FLAMINGO
|
|
if (winthis->w_flags & WF_NOTIFYALLCHANGES)
|
|
winthis->w_flags |= WF_CLIPPINGCHANGED;
|
|
#endif
|
|
}
|
|
/*
|
|
* Bump clippingid if fixup different.
|
|
* OK to bump this second time.
|
|
*/
|
|
if (!rl_equal(&rlfix, &winthis->w_rlfixup)) {
|
|
rl_free(&winthis->w_rlfixup);
|
|
rl_copy(&rlfix, &winthis->w_rlfixup);
|
|
wt_bump_clippingid(winthis);
|
|
}
|
|
rl_free(&rlfix);
|
|
}
|
|
|
|
wt_partialrepair(window, rectok)
|
|
struct window *window;
|
|
struct rect *rectok;
|
|
{
|
|
|
|
if (!(window->w_flags&WF_PREVIOUSDAMAGED)) {
|
|
rl_rectdifference(
|
|
rectok, &window->w_rlfixup, &window->w_rlfixup);
|
|
}
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
wt_positionchanged(window, rectnotused)
|
|
struct window *window;
|
|
struct rect *rectnotused;
|
|
{
|
|
|
|
window->w_flags |= WF_DTOPPOSCHANGED;
|
|
}
|
|
|
|
bool
|
|
wt_isindisplaytree(window)
|
|
register struct window *window;
|
|
{
|
|
register struct window *w, *wparent, *wchild;
|
|
|
|
/*
|
|
* window is in a display tree if the there are full links from window
|
|
* up the tree to its root.
|
|
*/
|
|
for (w = window; w; w = w->w_link[WL_PARENT]) {
|
|
wparent = w->w_link[WL_PARENT];
|
|
if (wparent==NULL) {
|
|
if (w==window->w_desktop->dt_rootwin) {
|
|
/*
|
|
* Made it up the correct display tree OK
|
|
*/
|
|
return (TRUE);
|
|
} else
|
|
break;
|
|
}
|
|
/*
|
|
* w must be among parent's children
|
|
*/
|
|
for (wchild = wparent->w_link[WL_OLDESTCHILD]; wchild;
|
|
wchild = wchild->w_link[WL_YOUNGERSIB]) {
|
|
if (w==wchild)
|
|
break;
|
|
}
|
|
/*
|
|
* See if broke out of above loop or didn't find w
|
|
*/
|
|
if (wchild==NULL)
|
|
return (FALSE);
|
|
}
|
|
return (FALSE);
|
|
}
|
|
|
|
wt_passrltoancestor(rl, winfrom, winto)
|
|
struct rectlist *rl;
|
|
struct window *winfrom, *winto;
|
|
{
|
|
register struct window *w;
|
|
|
|
for (w = winfrom; w != winto; w = w->w_link[WL_PARENT]) {
|
|
rl_passtoparent(w->w_rect.r_left, w->w_rect.r_top, rl);
|
|
}
|
|
|
|
}
|
|
|
|
struct winnotify wnlist; /* window notify list */
|
|
#ifdef WINDEVDEBUG
|
|
int winnotify_debug = 0;
|
|
#endif
|
|
int winnotify_inorder = 1;
|
|
int winnotify_starttimer = 1;
|
|
|
|
/*ARGSUSED*/
|
|
wt_add_to_notifyqueue(w, rectnotused)
|
|
register struct window *w;
|
|
struct rect *rectnotused;
|
|
{
|
|
register struct winnotify *wp;
|
|
register struct winnotify *newwp;
|
|
|
|
int s, pos_ch = 0;
|
|
|
|
extern wtsigwnchtimeout;
|
|
extern wtsigwnchtimeoutpending;
|
|
extern wt_sigwnch_timeout();
|
|
|
|
if (w->w_flags&WF_DTOPPOSCHANGED) {
|
|
wt_bump_clippingid(w);
|
|
if (w->w_flags & WF_NOTIFYALLCHANGES)
|
|
pos_ch = 1;
|
|
}
|
|
if (w->w_flags&WF_SIZECHANGED)
|
|
wt_bump_clippingid(w); /* OK to bump more than once */
|
|
|
|
s = spl6(); /* this is probably not needed */
|
|
|
|
if ((w->w_flags&WF_SIZECHANGED) || (!rl_empty(&w->w_rlfixup))
|
|
|| (pos_ch)) {
|
|
for (wp = &wnlist; wp->wn_next != NULL; wp = wp->wn_next) {
|
|
if (wp->wn_window &&
|
|
wp->wn_window->w_pid == w->w_pid) {
|
|
#ifdef WINDEVDEBUG
|
|
if (winnotify_debug)
|
|
printf("Ignoring 0x%x\n", w);
|
|
#endif
|
|
(void) splx(s);
|
|
return;
|
|
}
|
|
}
|
|
newwp = (struct winnotify *)new_kmem_alloc(
|
|
sizeof (struct winnotify), KMEM_SLEEP);
|
|
newwp->wn_next = NULL;
|
|
newwp->wn_window = w;
|
|
#ifdef WINDEVDEBUG
|
|
if (winnotify_debug)
|
|
printf("Queue for 0x%x after 0x%x\n", w, (wp)->wn_window);
|
|
#endif
|
|
(wp)->wn_next = newwp;
|
|
w->w_flags &= ~WF_SIZECHANGED;
|
|
}
|
|
|
|
/*
|
|
* Start the timer if it's not going already.
|
|
*/
|
|
if (winnotify_starttimer && wtsigwnchtimeoutpending == 0) {
|
|
wtsigwnchtimeoutpending++;
|
|
timeout(wt_sigwnch_timeout, (caddr_t)0, wtsigwnchtimeout);
|
|
}
|
|
(void)splx(s);
|
|
}
|
|
|
|
int wtsigwnchtimeoutpending;
|
|
int wtsigwnchtimeout = 5; /* timeout in ticks */
|
|
int maxtimeout = 10; /* do it anyway after 20 ticks */
|
|
int totaltimeout; /* time we've waited so far */
|
|
int maxdiskwaiters = 1; /* max allowable disk waiters */
|
|
int wttoomuchiocount;
|
|
int wtsigwnchtimeoutcount;
|
|
#ifdef WINDEVDEBUG
|
|
int wtsigwnchdebug = 0;
|
|
#endif
|
|
|
|
/*ARGSUSED*/
|
|
wt_sigwnch_timeout()
|
|
{
|
|
wtsigwnchtimeoutpending--;
|
|
wt_sigwnch_nextwin(); /* do next in the queue */
|
|
wtsigwnchtimeoutcount++;
|
|
|
|
#ifdef WINDEVDEBUG
|
|
if (wtsigwnchdebug) {
|
|
printf("wt_sigwnch_timeout called %d. times\n",
|
|
wtsigwnchtimeoutcount);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
wt_sigwnch_untimeout()
|
|
{
|
|
register struct winnotify *wp;
|
|
register int s;
|
|
|
|
s = spl6();
|
|
|
|
if (wtsigwnchtimeoutpending) {
|
|
wtsigwnchtimeoutpending = 0;
|
|
untimeout(wt_sigwnch_timeout, (caddr_t)0);
|
|
}
|
|
|
|
while ((wp = wnlist.wn_next) != NULL) {
|
|
wnlist.wn_next = wp->wn_next; /* remove from the queue */
|
|
kmem_free((caddr_t)wp, sizeof (struct winnotify));
|
|
}
|
|
|
|
(void)splx(s);
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
wt_sigwnch_nextwin()
|
|
{
|
|
register struct winnotify *wp;
|
|
register int s;
|
|
register struct proc *p;
|
|
|
|
int dwaiters;
|
|
|
|
extern hz;
|
|
|
|
s = spl6(); /* this is probably not needed */
|
|
|
|
if ((wp = wnlist.wn_next) != NULL) {
|
|
dwaiters = 0;
|
|
|
|
for (p = allproc; p != NULL; p = p->p_nxt) {
|
|
if (p->p_flag & SSYS)
|
|
continue;
|
|
|
|
if (p->p_stat == SSLEEP || p->p_stat == SSTOP) {
|
|
if ((p->p_flag & SLOAD) && p->p_pri <= PZERO) {
|
|
if (++dwaiters > maxdiskwaiters)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (dwaiters <= maxdiskwaiters || totaltimeout > maxtimeout) {
|
|
totaltimeout = 0;
|
|
wnlist.wn_next = wp->wn_next; /* remove from queue */
|
|
wt_notifychanged(wp->wn_window, (struct rect *)NULL);
|
|
/*
|
|
* Need to set lock go_to_kernel field.
|
|
*/
|
|
if (wp->wn_window->w_desktop &&
|
|
wp->wn_window->w_desktop->shared_info)
|
|
wp->wn_window->w_desktop->shared_info->go_to_kernel = 1;
|
|
|
|
kmem_free((caddr_t)wp, sizeof (struct winnotify));
|
|
} else {
|
|
totaltimeout += wtsigwnchtimeout;
|
|
wttoomuchiocount++;
|
|
#ifdef WINDEVDEBUG
|
|
if (wtsigwnchdebug)
|
|
printf("wt_sigwnch_nextwin not called. too much io\n");
|
|
#endif
|
|
}
|
|
}
|
|
/*
|
|
* If there are still requests on the list, then
|
|
* start a timer so that we'll eventually flush the queue.
|
|
*/
|
|
if (wnlist.wn_next != NULL) {
|
|
if (wtsigwnchtimeoutpending == 0) {
|
|
wtsigwnchtimeoutpending++;
|
|
timeout(wt_sigwnch_timeout, (caddr_t)0, wtsigwnchtimeout);
|
|
}
|
|
} else if (wtsigwnchtimeoutpending) {
|
|
wtsigwnchtimeoutpending = 0;
|
|
untimeout(wt_sigwnch_timeout, (caddr_t)0);
|
|
}
|
|
(void) splx(s);
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
wt_notifychanged(w, rectnotused)
|
|
register struct window *w;
|
|
struct rect *rectnotused;
|
|
{
|
|
if (winnotify_inorder == 0) {
|
|
#ifndef PRE_FLAMINGO
|
|
if (w->w_flags&WF_DTOPPOSCHANGED) {
|
|
w->w_flags &= ~WF_DTOPPOSCHANGED;
|
|
if (w->w_flags & WF_NOTIFYALLCHANGES)
|
|
w->w_flags |= WF_CLIPPINGCHANGED;
|
|
wt_bump_clippingid(w);
|
|
}
|
|
if (w->w_flags&WF_SIZECHANGED)
|
|
wt_bump_clippingid(w); /* OK to bump more than once */
|
|
if (w->w_flags & WF_NOTIFYALLCHANGES)
|
|
w->w_flags |= WF_CLIPPINGCHANGED;
|
|
if ((w->w_flags&WF_SIZECHANGED) || !rl_empty(&w->w_rlfixup)) {
|
|
winsignal(w, SIGWINCH);
|
|
w->w_flags &= ~WF_SIZECHANGED;
|
|
}
|
|
} else {
|
|
/* If the client wants to be notified of all changes */
|
|
/* set clipping changed if size or posion has changed */
|
|
if ((w->w_flags & WF_DTOPPOSCHANGED ||
|
|
w->w_flags&WF_SIZECHANGED) &&
|
|
(w->w_flags & WF_NOTIFYALLCHANGES)) {
|
|
w->w_flags |= WF_CLIPPINGCHANGED;
|
|
wt_bump_clippingid(w); /* OK to bump more than once */
|
|
}
|
|
winsignal(w, SIGWINCH);
|
|
w->w_flags &=
|
|
~(WF_SIZECHANGED|WF_DTOPPOSCHANGED|WF_CLIPPINGCHANGED);
|
|
#ifdef WINDEVDEBUG
|
|
if (winnotify_debug)
|
|
printf("Deliver to 0x%x\n", w);
|
|
#endif /* WINDEVDEBUG */
|
|
|
|
#else /* !PRE_FLAMINGO */
|
|
if (w->w_flags&WF_DTOPPOSCHANGED) {
|
|
w->w_flags &= ~WF_DTOPPOSCHANGED;
|
|
wt_bump_clippingid(w);
|
|
}
|
|
if (w->w_flags&WF_SIZECHANGED)
|
|
wt_bump_clippingid(w); /* OK to bump more than once */
|
|
if ((w->w_flags&WF_SIZECHANGED) || !rl_empty(&w->w_rlfixup)) {
|
|
winsignal(w, SIGWINCH);
|
|
w->w_flags &= ~WF_SIZECHANGED;
|
|
}
|
|
} else {
|
|
winsignal(w, SIGWINCH);
|
|
#ifdef WINDEVDEBUG
|
|
if (winnotify_debug)
|
|
printf("Deliver to 0x%x\n", w);
|
|
#endif /* WINDEVDEBUG */
|
|
#endif /* PRE_FLAMINGO */
|
|
}
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
wt_initclipping(win, rectnotused)
|
|
struct window *win;
|
|
struct rect *rectnotused;
|
|
{
|
|
/*
|
|
* This routines handles the case of a window
|
|
* being removed and then reinstalled into the tree when,
|
|
* at the time of removal, there was unresolved damage.
|
|
* At the user level this might be a move followed by a top command.
|
|
* Removal cleared the damage,
|
|
* installing generated a new exposed list and damaged list,
|
|
* wt_partialrepair then clears the damaged list because the
|
|
* WF_PREVIOUSDAMAGED flag is not on.
|
|
*/
|
|
if (win->w_flags & WF_PREVIOUSDAMAGED) {
|
|
/*
|
|
* Since don't remember exactly want damage was there when
|
|
* removed, repaint the entire window.
|
|
* W_rlfixup will get trimmed to exposed area when set clipping.
|
|
*/
|
|
rl_initwithrect(&win->w_rect, &win->w_rlfixup);
|
|
}
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
wt_nullclipping(win, rectnotused)
|
|
struct window *win;
|
|
struct rect *rectnotused;
|
|
{
|
|
|
|
rl_free(&win->w_rlexposed);
|
|
rl_free(&win->w_rlexposedold);
|
|
rl_free(&win->w_rlfixup);
|
|
/*
|
|
* So that window wouldn't write to screen when removed,
|
|
* bump clippingid.
|
|
*/
|
|
wt_bump_clippingid(win);
|
|
}
|
|
|
|
struct window *
|
|
wt_intersected(winthis, x, y)
|
|
struct window *winthis;
|
|
coord x, y;
|
|
{
|
|
register struct window *w, *winintersect;
|
|
struct rect rect;
|
|
|
|
rect = winthis->w_rect;
|
|
rect.r_left = winthis->w_screenx;
|
|
rect.r_top = winthis->w_screeny;
|
|
if (!rect_includespoint(&rect, x, y))
|
|
return (NULL);
|
|
for (w = winthis->WL_TOPCHILD; w; w = w->WL_COVERED)
|
|
if (winintersect = wt_intersected(w, x, y))
|
|
return (winintersect);
|
|
return (winthis);
|
|
}
|
|
|
|
#ifdef WINDEVDEBUG
|
|
wt_printwindow(w, tag)
|
|
struct window *w;
|
|
char *tag;
|
|
{
|
|
printf(tag);
|
|
if (w==NULL)
|
|
return;
|
|
printf("w: %X, Flags: %X ", w, w->w_flags);
|
|
printf("parent: %X \n", w->w_link[WL_PARENT]);
|
|
printf("link[WL_OLDERSIB]: %X ", w->w_link[WL_OLDERSIB]);
|
|
printf("link[WL_YOUNGERSIB]: %X \n", w->w_link[WL_YOUNGERSIB]);
|
|
printf("link[WL_OLDESTCHILD]: %X ", w->w_link[WL_OLDESTCHILD]);
|
|
printf("link[WL_YOUNGESTCHILD]: %X \n", w->w_link[WL_YOUNGESTCHILD]);
|
|
printf("Window Rect: ");
|
|
rect_print(&w->w_rect);
|
|
printf("\n");
|
|
printf("Saved Rect: ");
|
|
rect_print(&w->w_rectsaved);
|
|
printf("\n");
|
|
printf("ScreenOffsets: x=%d y=%d ClippingID=%d\n",
|
|
w->w_screenx, w->w_screeny, w->w_clippingid);
|
|
rl_print(&w->w_rlexposed, "w_rlexposed");
|
|
rl_print(&w->w_rlexposedold, "w_rlexposedold");
|
|
rl_print(&w->w_rlfixup, "w_rlfixup");
|
|
}
|
|
#endif
|
|
|
|
|
|
static void
|
|
wt_bump_clippingid(w)
|
|
register struct window *w;
|
|
{
|
|
int win_number;
|
|
|
|
w->w_clippingid++;
|
|
/*
|
|
* get the window number.
|
|
*/
|
|
wt_windowtonumber(w, &win_number);
|
|
w->w_desktop->shared_info->clip_ids[win_number] = w->w_clippingid;
|
|
}
|