/*
|
/*
|
* Copyright (c) 1999 Greg Haerr <greg@censoft.com>
|
* Copyright (c) 1999 Greg Haerr <greg@censoft.com>
|
* Portions Copyright (c) 1991 David I. Bell
|
* Portions Copyright (c) 1991 David I. Bell
|
*
|
*
|
* Non-Win32 API helper routines for window showing/hiding/exposing
|
* Non-Win32 API helper routines for window showing/hiding/exposing
|
*/
|
*/
|
#include "windows.h"
|
#include "windows.h"
|
#include "wintern.h"
|
#include "wintern.h"
|
#include <stdlib.h>
|
#include <stdlib.h>
|
|
|
/* Redraw all windows*/
|
/* Redraw all windows*/
|
void
|
void
|
MwRedrawScreen(void)
|
MwRedrawScreen(void)
|
{
|
{
|
/* redraw all windows except desktop window*/
|
/* redraw all windows except desktop window*/
|
MwExposeArea(rootwp, 0, 0, rootwp->winrect.right,
|
MwExposeArea(rootwp, 0, 0, rootwp->winrect.right,
|
rootwp->winrect.bottom);
|
rootwp->winrect.bottom);
|
|
|
/* redraw desktop window*/
|
/* redraw desktop window*/
|
PostMessage(rootwp, WM_PAINT, 0, 0L);
|
PostMessage(rootwp, WM_PAINT, 0, 0L);
|
}
|
}
|
|
|
/*
|
/*
|
* Hide the window to make it and its children invisible on the screen.
|
* Hide the window to make it and its children invisible on the screen.
|
* This is a recursive routine which increments the unmapcount values for
|
* This is a recursive routine which increments the unmapcount values for
|
* this window and all of its children, and causes exposure events for
|
* this window and all of its children, and causes exposure events for
|
* windows which are newly uncovered.
|
* windows which are newly uncovered.
|
*/
|
*/
|
void
|
void
|
MwHideWindow(HWND hwnd,BOOL bChangeFocus, BOOL bSendMsg)
|
MwHideWindow(HWND hwnd,BOOL bChangeFocus, BOOL bSendMsg)
|
{
|
{
|
HWND wp = hwnd;
|
HWND wp = hwnd;
|
HWND pwp; /* parent window */
|
HWND pwp; /* parent window */
|
HWND sibwp; /* sibling window */
|
HWND sibwp; /* sibling window */
|
HWND childwp; /* child window */
|
HWND childwp; /* child window */
|
|
|
if (wp == rootwp)
|
if (wp == rootwp)
|
return;
|
return;
|
|
|
++mwpaintNC; /* experimental NC paint handling*/
|
++mwpaintNC; /* experimental NC paint handling*/
|
|
|
/* send hide message if currently visible*/
|
/* send hide message if currently visible*/
|
if(bSendMsg && wp->unmapcount == 0)
|
if(bSendMsg && wp->unmapcount == 0)
|
SendMessage(wp, WM_SHOWWINDOW, FALSE, 0L);
|
SendMessage(wp, WM_SHOWWINDOW, FALSE, 0L);
|
|
|
wp->unmapcount++;
|
wp->unmapcount++;
|
|
|
for (childwp = wp->children; childwp; childwp = childwp->siblings)
|
for (childwp = wp->children; childwp; childwp = childwp->siblings)
|
MwHideWindow(childwp, bChangeFocus, bSendMsg);
|
MwHideWindow(childwp, bChangeFocus, bSendMsg);
|
|
|
if (wp == mousewp) {
|
if (wp == mousewp) {
|
MwCheckMouseWindow();
|
MwCheckMouseWindow();
|
MwCheckCursor();
|
MwCheckCursor();
|
}
|
}
|
|
|
if (bChangeFocus && wp == focuswp)
|
if (bChangeFocus && wp == focuswp)
|
SetFocus(rootwp->children? rootwp->children: rootwp);
|
SetFocus(rootwp->children? rootwp->children: rootwp);
|
|
|
/*
|
/*
|
* If the parent window is still unmapped, then we are all done.
|
* If the parent window is still unmapped, then we are all done.
|
*/
|
*/
|
if (wp->parent->unmapcount)
|
if (wp->parent->unmapcount)
|
return;
|
return;
|
|
|
/*
|
/*
|
* Clear the area in the parent for this window, causing an
|
* Clear the area in the parent for this window, causing an
|
* exposure event for it.
|
* exposure event for it.
|
*/
|
*/
|
pwp = wp->parent;
|
pwp = wp->parent;
|
MwClearWindow(pwp, wp->winrect.left - pwp->winrect.left,
|
MwClearWindow(pwp, wp->winrect.left - pwp->winrect.left,
|
wp->winrect.top - pwp->winrect.top,
|
wp->winrect.top - pwp->winrect.top,
|
wp->winrect.right - wp->winrect.left,
|
wp->winrect.right - wp->winrect.left,
|
wp->winrect.bottom - wp->winrect.top, TRUE);
|
wp->winrect.bottom - wp->winrect.top, TRUE);
|
|
|
/*
|
/*
|
* Finally clear and redraw all parts of our lower sibling
|
* Finally clear and redraw all parts of our lower sibling
|
* windows that were covered by this window.
|
* windows that were covered by this window.
|
*/
|
*/
|
sibwp = wp;
|
sibwp = wp;
|
while (sibwp->siblings) {
|
while (sibwp->siblings) {
|
sibwp = sibwp->siblings;
|
sibwp = sibwp->siblings;
|
MwExposeArea(sibwp, wp->winrect.left, wp->winrect.top,
|
MwExposeArea(sibwp, wp->winrect.left, wp->winrect.top,
|
wp->winrect.right - wp->winrect.left,
|
wp->winrect.right - wp->winrect.left,
|
wp->winrect.bottom - wp->winrect.top);
|
wp->winrect.bottom - wp->winrect.top);
|
}
|
}
|
}
|
}
|
|
|
/*
|
/*
|
* Map the window to possibly make it and its children visible on the screen.
|
* 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 is a recursive routine which decrements the unmapcount values for
|
* this window and all of its children, and causes exposure events for
|
* this window and all of its children, and causes exposure events for
|
* those windows which become visible.
|
* those windows which become visible.
|
*/
|
*/
|
void
|
void
|
MwShowWindow(HWND hwnd, BOOL bSendMsg)
|
MwShowWindow(HWND hwnd, BOOL bSendMsg)
|
{
|
{
|
HWND wp = hwnd;
|
HWND wp = hwnd;
|
|
|
if (wp == rootwp)
|
if (wp == rootwp)
|
return;
|
return;
|
|
|
++mwpaintNC; /* experimental NC paint handling*/
|
++mwpaintNC; /* experimental NC paint handling*/
|
|
|
if (wp->unmapcount)
|
if (wp->unmapcount)
|
wp->unmapcount--;
|
wp->unmapcount--;
|
|
|
if (wp->unmapcount == 0) {
|
if (wp->unmapcount == 0) {
|
SendMessage(wp, WM_SHOWWINDOW, TRUE, 0L);
|
SendMessage(wp, WM_SHOWWINDOW, TRUE, 0L);
|
MwCheckMouseWindow();
|
MwCheckMouseWindow();
|
MwCheckCursor();
|
MwCheckCursor();
|
}
|
}
|
|
|
/*
|
/*
|
* If the window just became visible,
|
* If the window just became visible,
|
* then draw its border, clear it to the background color, and
|
* then draw its border, clear it to the background color, and
|
* generate an exposure event.
|
* generate an exposure event.
|
*/
|
*/
|
if (wp->unmapcount == 0) {
|
if (wp->unmapcount == 0) {
|
/*MwDrawBorder(wp);*/
|
/*MwDrawBorder(wp);*/
|
MwClearWindow(wp, 0, 0, wp->winrect.right - wp->winrect.left,
|
MwClearWindow(wp, 0, 0, wp->winrect.right - wp->winrect.left,
|
wp->winrect.bottom - wp->winrect.top, TRUE);
|
wp->winrect.bottom - wp->winrect.top, TRUE);
|
}
|
}
|
|
|
/*
|
/*
|
* Do the same thing for the children.
|
* Do the same thing for the children.
|
*/
|
*/
|
for (wp = wp->children; wp; wp = wp->siblings)
|
for (wp = wp->children; wp; wp = wp->siblings)
|
MwShowWindow(wp, bSendMsg);
|
MwShowWindow(wp, bSendMsg);
|
}
|
}
|
|
|
/*
|
/*
|
* Raise a window to the highest level among its siblings.
|
* Raise a window to the highest level among its siblings.
|
*/
|
*/
|
void
|
void
|
MwRaiseWindow(HWND hwnd)
|
MwRaiseWindow(HWND hwnd)
|
{
|
{
|
HWND wp = hwnd;
|
HWND wp = hwnd;
|
HWND prevwp;
|
HWND prevwp;
|
BOOL overlap;
|
BOOL overlap;
|
|
|
if (!wp || wp == rootwp)
|
if (!wp || wp == rootwp)
|
return;
|
return;
|
|
|
++mwpaintNC; /* experimental NC paint handling*/
|
++mwpaintNC; /* experimental NC paint handling*/
|
|
|
/*
|
/*
|
* If this is already the highest window then we are done.
|
* If this is already the highest window then we are done.
|
*/
|
*/
|
prevwp = wp->parent->children;
|
prevwp = wp->parent->children;
|
if (prevwp == wp)
|
if (prevwp == wp)
|
return;
|
return;
|
|
|
/*
|
/*
|
* Find the sibling just before this window so we can unlink it.
|
* Find the sibling just before this window so we can unlink it.
|
* Also, determine if any sibling ahead of us overlaps the window.
|
* Also, determine if any sibling ahead of us overlaps the window.
|
* Remember that for exposure events.
|
* Remember that for exposure events.
|
*/
|
*/
|
overlap = FALSE;
|
overlap = FALSE;
|
while (prevwp->siblings != wp) {
|
while (prevwp->siblings != wp) {
|
overlap |= MwCheckOverlap(prevwp, wp);
|
overlap |= MwCheckOverlap(prevwp, wp);
|
prevwp = prevwp->siblings;
|
prevwp = prevwp->siblings;
|
}
|
}
|
overlap |= MwCheckOverlap(prevwp, wp);
|
overlap |= MwCheckOverlap(prevwp, wp);
|
|
|
/*
|
/*
|
* Now unlink the window and relink it in at the front of the
|
* Now unlink the window and relink it in at the front of the
|
* sibling chain.
|
* sibling chain.
|
*/
|
*/
|
prevwp->siblings = wp->siblings;
|
prevwp->siblings = wp->siblings;
|
wp->siblings = wp->parent->children;
|
wp->siblings = wp->parent->children;
|
wp->parent->children = wp;
|
wp->parent->children = wp;
|
|
|
/*
|
/*
|
* Finally redraw the window if necessary.
|
* Finally redraw the window if necessary.
|
*/
|
*/
|
if (overlap) {
|
if (overlap) {
|
/*MwDrawBorder(wp);*/
|
/*MwDrawBorder(wp);*/
|
MwExposeArea(wp, wp->winrect.left, wp->winrect.top,
|
MwExposeArea(wp, wp->winrect.left, wp->winrect.top,
|
wp->winrect.right - wp->winrect.left,
|
wp->winrect.right - wp->winrect.left,
|
wp->winrect.bottom - wp->winrect.top);
|
wp->winrect.bottom - wp->winrect.top);
|
}
|
}
|
}
|
}
|
|
|
/*
|
/*
|
* Lower a window to the lowest level among its siblings.
|
* Lower a window to the lowest level among its siblings.
|
*/
|
*/
|
void
|
void
|
MwLowerWindow(HWND hwnd)
|
MwLowerWindow(HWND hwnd)
|
{
|
{
|
HWND wp = hwnd;
|
HWND wp = hwnd;
|
HWND prevwp;
|
HWND prevwp;
|
HWND sibwp; /* sibling window */
|
HWND sibwp; /* sibling window */
|
HWND expwp; /* siblings being exposed */
|
HWND expwp; /* siblings being exposed */
|
|
|
if (!wp || wp == rootwp || !wp->siblings)
|
if (!wp || wp == rootwp || !wp->siblings)
|
return;
|
return;
|
|
|
++mwpaintNC; /* experimental NC paint handling*/
|
++mwpaintNC; /* experimental NC paint handling*/
|
|
|
/*
|
/*
|
* Find the sibling just before this window so we can unlink us.
|
* Find the sibling just before this window so we can unlink us.
|
*/
|
*/
|
prevwp = wp->parent->children;
|
prevwp = wp->parent->children;
|
if (prevwp != wp) {
|
if (prevwp != wp) {
|
while (prevwp->siblings != wp)
|
while (prevwp->siblings != wp)
|
prevwp = prevwp->siblings;
|
prevwp = prevwp->siblings;
|
}
|
}
|
|
|
/*
|
/*
|
* Remember the first sibling that is after us, so we can
|
* Remember the first sibling that is after us, so we can
|
* generate exposure events for the remaining siblings. Then
|
* generate exposure events for the remaining siblings. Then
|
* walk down the sibling chain looking for the last sibling.
|
* walk down the sibling chain looking for the last sibling.
|
*/
|
*/
|
expwp = wp->siblings;
|
expwp = wp->siblings;
|
sibwp = wp;
|
sibwp = wp;
|
while (sibwp->siblings)
|
while (sibwp->siblings)
|
sibwp = sibwp->siblings;
|
sibwp = sibwp->siblings;
|
|
|
/*
|
/*
|
* Now unlink the window and relink it in at the end of the
|
* Now unlink the window and relink it in at the end of the
|
* sibling chain.
|
* sibling chain.
|
*/
|
*/
|
if (prevwp == wp)
|
if (prevwp == wp)
|
wp->parent->children = wp->siblings;
|
wp->parent->children = wp->siblings;
|
else
|
else
|
prevwp->siblings = wp->siblings;
|
prevwp->siblings = wp->siblings;
|
sibwp->siblings = wp;
|
sibwp->siblings = wp;
|
|
|
wp->siblings = NULL;
|
wp->siblings = NULL;
|
|
|
/*
|
/*
|
* Finally redraw the sibling windows which this window covered
|
* Finally redraw the sibling windows which this window covered
|
* if they overlapped our window.
|
* if they overlapped our window.
|
*/
|
*/
|
while (expwp && (expwp != wp)) {
|
while (expwp && (expwp != wp)) {
|
if (MwCheckOverlap(wp, expwp))
|
if (MwCheckOverlap(wp, expwp))
|
MwExposeArea(expwp, wp->winrect.left, wp->winrect.top,
|
MwExposeArea(expwp, wp->winrect.left, wp->winrect.top,
|
wp->winrect.right - wp->winrect.left,
|
wp->winrect.right - wp->winrect.left,
|
wp->winrect.bottom - wp->winrect.top);
|
wp->winrect.bottom - wp->winrect.top);
|
expwp = expwp->siblings;
|
expwp = expwp->siblings;
|
}
|
}
|
}
|
}
|
|
|
/*
|
/*
|
* Check to see if the first window overlaps the second window.
|
* Check to see if the first window overlaps the second window.
|
*/
|
*/
|
BOOL
|
BOOL
|
MwCheckOverlap(HWND topwp, HWND botwp)
|
MwCheckOverlap(HWND topwp, HWND botwp)
|
{
|
{
|
MWCOORD minx1;
|
MWCOORD minx1;
|
MWCOORD miny1;
|
MWCOORD miny1;
|
MWCOORD maxx1;
|
MWCOORD maxx1;
|
MWCOORD maxy1;
|
MWCOORD maxy1;
|
MWCOORD minx2;
|
MWCOORD minx2;
|
MWCOORD miny2;
|
MWCOORD miny2;
|
MWCOORD maxx2;
|
MWCOORD maxx2;
|
MWCOORD maxy2;
|
MWCOORD maxy2;
|
|
|
if (topwp->unmapcount || botwp->unmapcount)
|
if (topwp->unmapcount || botwp->unmapcount)
|
return FALSE;
|
return FALSE;
|
|
|
minx1 = topwp->winrect.left;
|
minx1 = topwp->winrect.left;
|
miny1 = topwp->winrect.top;
|
miny1 = topwp->winrect.top;
|
maxx1 = topwp->winrect.right - 1;
|
maxx1 = topwp->winrect.right - 1;
|
maxy1 = topwp->winrect.bottom - 1;
|
maxy1 = topwp->winrect.bottom - 1;
|
|
|
minx2 = botwp->winrect.left;
|
minx2 = botwp->winrect.left;
|
miny2 = botwp->winrect.top;
|
miny2 = botwp->winrect.top;
|
maxx2 = botwp->winrect.right - 1;
|
maxx2 = botwp->winrect.right - 1;
|
maxy2 = botwp->winrect.bottom - 1;
|
maxy2 = botwp->winrect.bottom - 1;
|
|
|
if (minx1 > maxx2 || minx2 > maxx1 || miny1 > maxy2 || miny2 > maxy1)
|
if (minx1 > maxx2 || minx2 > maxx1 || miny1 > maxy2 || miny2 > maxy1)
|
return FALSE;
|
return FALSE;
|
|
|
return TRUE;
|
return TRUE;
|
}
|
}
|
|
|
/*
|
/*
|
* Clear the specified area of a window and possibly make an exposure event.
|
* Clear the specified area of a window and possibly make an exposure event.
|
* This sets the area window to its background color. If the exposeflag is
|
* This sets the area window to its background color. If the exposeflag is
|
* nonzero, then this also creates an exposure event for the window.
|
* nonzero, then this also creates an exposure event for the window.
|
*/
|
*/
|
void
|
void
|
MwClearWindow(HWND wp, MWCOORD x, MWCOORD y, MWCOORD width, MWCOORD height,
|
MwClearWindow(HWND wp, MWCOORD x, MWCOORD y, MWCOORD width, MWCOORD height,
|
BOOL exposeflag)
|
BOOL exposeflag)
|
{
|
{
|
if (wp->unmapcount)
|
if (wp->unmapcount)
|
return;
|
return;
|
|
|
/*
|
/*
|
* Reduce the arguments so that they actually lie within the window.
|
* Reduce the arguments so that they actually lie within the window.
|
*/
|
*/
|
if (x < 0) {
|
if (x < 0) {
|
width += x;
|
width += x;
|
x = 0;
|
x = 0;
|
}
|
}
|
if (y < 0) {
|
if (y < 0) {
|
height += y;
|
height += y;
|
y = 0;
|
y = 0;
|
}
|
}
|
if (x + width > wp->winrect.right - wp->winrect.left)
|
if (x + width > wp->winrect.right - wp->winrect.left)
|
width = (wp->winrect.right - wp->winrect.left) - x;
|
width = (wp->winrect.right - wp->winrect.left) - x;
|
if (y + height > wp->winrect.bottom - wp->winrect.top)
|
if (y + height > wp->winrect.bottom - wp->winrect.top)
|
height = (wp->winrect.bottom - wp->winrect.top) - y;
|
height = (wp->winrect.bottom - wp->winrect.top) - y;
|
|
|
/*
|
/*
|
* Now see if the region is really in the window. If not, then
|
* Now see if the region is really in the window. If not, then
|
* do nothing.
|
* do nothing.
|
*/
|
*/
|
if (x >= (wp->winrect.right - wp->winrect.left) ||
|
if (x >= (wp->winrect.right - wp->winrect.left) ||
|
y >= (wp->winrect.bottom - wp->winrect.top) ||
|
y >= (wp->winrect.bottom - wp->winrect.top) ||
|
width <= 0 || height <= 0)
|
width <= 0 || height <= 0)
|
return;
|
return;
|
|
|
/*
|
/*
|
* Now do the exposure if required.
|
* Now do the exposure if required.
|
*/
|
*/
|
if (exposeflag)
|
if (exposeflag)
|
MwDeliverExposureEvent(wp, x, y, width, height);
|
MwDeliverExposureEvent(wp, x, y, width, height);
|
}
|
}
|
|
|
/*
|
/*
|
* Handle the exposing of the specified absolute region of the screen,
|
* Handle the exposing of the specified absolute region of the screen,
|
* starting with the specified window. That window and all of its
|
* starting with the specified window. That window and all of its
|
* children will be redrawn and/or exposure events generated if they
|
* children will be redrawn and/or exposure events generated if they
|
* overlap the specified area. This is a recursive routine.
|
* overlap the specified area. This is a recursive routine.
|
*/
|
*/
|
void
|
void
|
MwExposeArea(HWND wp, MWCOORD rootx, MWCOORD rooty, MWCOORD width,
|
MwExposeArea(HWND wp, MWCOORD rootx, MWCOORD rooty, MWCOORD width,
|
MWCOORD height)
|
MWCOORD height)
|
{
|
{
|
if (wp->unmapcount)
|
if (wp->unmapcount)
|
return;
|
return;
|
|
|
++mwpaintNC; /* experimental NC paint handling*/
|
++mwpaintNC; /* experimental NC paint handling*/
|
|
|
/*
|
/*
|
* First see if the area overlaps the window including the border.
|
* First see if the area overlaps the window including the border.
|
* If not, then there is nothing more to do.
|
* If not, then there is nothing more to do.
|
*/
|
*/
|
if (rootx >= wp->winrect.right || rooty >= wp->winrect.bottom ||
|
if (rootx >= wp->winrect.right || rooty >= wp->winrect.bottom ||
|
(rootx + width) <= wp->winrect.left ||
|
(rootx + width) <= wp->winrect.left ||
|
(rooty + height) <= wp->winrect.top)
|
(rooty + height) <= wp->winrect.top)
|
return;
|
return;
|
|
|
#if 0
|
#if 0
|
/*
|
/*
|
* The area does overlap the window. See if the area overlaps
|
* The area does overlap the window. See if the area overlaps
|
* the border, and if so, then redraw it.
|
* the border, and if so, then redraw it.
|
*/
|
*/
|
if (rootx < wp->winrect.left || rooty < wp->winrect.top ||
|
if (rootx < wp->winrect.left || rooty < wp->winrect.top ||
|
(rootx + width) > wp->winrect.right ||
|
(rootx + width) > wp->winrect.right ||
|
(rooty + height) > wp->winrect.bottom)
|
(rooty + height) > wp->winrect.bottom)
|
MwDrawBorder(wp);
|
MwDrawBorder(wp);
|
#endif
|
#endif
|
|
|
/*
|
/*
|
* Now clear the window itself in the specified area,
|
* Now clear the window itself in the specified area,
|
* which might cause an exposure event.
|
* which might cause an exposure event.
|
*/
|
*/
|
MwClearWindow(wp, rootx - wp->winrect.left, rooty - wp->winrect.top,
|
MwClearWindow(wp, rootx - wp->winrect.left, rooty - wp->winrect.top,
|
width, height, TRUE);
|
width, height, TRUE);
|
|
|
/*
|
/*
|
* Now do the same for all the children.
|
* Now do the same for all the children.
|
*/
|
*/
|
for (wp = wp->children; wp; wp = wp->siblings)
|
for (wp = wp->children; wp; wp = wp->siblings)
|
MwExposeArea(wp, rootx, rooty, width, height);
|
MwExposeArea(wp, rootx, rooty, width, height);
|
}
|
}
|
|
|