fixups for implementation of window levels support

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@26218 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2008-03-06 06:19:02 +00:00
parent 28d61c7a23
commit 78ee5962c6
3 changed files with 192 additions and 106 deletions

View file

@ -1,3 +1,13 @@
2008-03-06 Richard Frith-Macdonald <rfm@gnu.org>
* Source\win32\WIN32Server.m: Improve window level code ... when moving
a window to the top of a level, jump it right to the top of the window
z-order so that it is above any non-gnustep windows.
* Source\win32\w32_movesize.m: If a window is jumped to the top of the
z-order and hence breaks the level rules, use a bubble sort to get
the windows back in level order by raising any windows which are
lower than they should be.
2008-03-05 Richard Frith-Macdonald <rfm@gnu.org>
* Headers\win32\WIN32Server.h: Add fields to track window level/ordering

View file

@ -1036,6 +1036,11 @@ NSLog(@"Callback");
}
}
flag = SW_SHOW;
if (IsIconic((HWND)winNum))
flag = SW_RESTORE;
ShowWindow((HWND)winNum, flag);
win = (WIN_INTERN *)GetWindowLong((HWND)winNum, GWL_USERDATA);
if (op == NSWindowOut)
@ -1080,11 +1085,6 @@ NSLog(@"Callback");
}
}
flag = SW_SHOW;
if (IsIconic((HWND)winNum))
flag = SW_RESTORE;
ShowWindow((HWND)winNum, flag);
if (win->level <= NSDesktopWindowLevel)
{
// For desktop level, put this at the bottom of the z-order
@ -1135,9 +1135,27 @@ NSLog(@"Callback");
otherWin, other->level);
if (other->level >= win->level)
{
if (other->level > win->level
|| op == NSWindowBelow
|| foreground == otherWin)
if (other->level > win->level)
{
/* On windows, there is no notion of levels, so
* native apps will automatically move to the
* very top of the stack (above our alert panels etc)
*
* So to cope with this, when we move to the top
* of a level, we assume there may be native apps
* above us and we set otherWin=0 to move to the
* very top of the stack past them.
*
* We rely on the fact that we have code in the
* window positioning notification to rearrange
* (sort) all the windows into level order if
* moving this window to the top messes up the
* level ordering.
*/
otherWin = 0;
break;
}
if (op == NSWindowBelow || foreground == otherWin)
{
break;
}
@ -1167,37 +1185,38 @@ NSLog(@"Callback");
SetWindowPos((HWND)winNum, (HWND)otherWin, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
#if 1
{
NSString *s = @"Window list:\n";
otherWin = (int)GetDesktopWindow();
otherWin = (int)GetWindow((HWND)otherWin, GW_CHILD);
if (otherWin > 0)
/* For debug log window stack.
*/
if (GSDebugSet(@"WTrace") == YES)
{
otherWin = (int)GetWindow((HWND)otherWin, GW_HWNDLAST);
}
while (otherWin > 0)
{
TCHAR buf[32];
NSString *s = @"Window list:\n";
otherWin = (int)GetNextWindow((HWND)otherWin, GW_HWNDPREV);
if (otherWin > 0 && otherWin != winNum
&& GetClassName((HWND)otherWin, buf, 32) == 18
&& strncmp(buf, "GNUstepWindowClass", 18) == 0)
otherWin = (int)GetDesktopWindow();
otherWin = (int)GetWindow((HWND)otherWin, GW_CHILD);
if (otherWin > 0)
{
other = (WIN_INTERN *)GetWindowLong((HWND)otherWin, GWL_USERDATA);
if (other->orderedIn == YES)
otherWin = (int)GetWindow((HWND)otherWin, GW_HWNDLAST);
}
while (otherWin > 0)
{
TCHAR buf[32];
otherWin = (int)GetNextWindow((HWND)otherWin, GW_HWNDPREV);
if (otherWin > 0
&& GetClassName((HWND)otherWin, buf, 32) == 18
&& strncmp(buf, "GNUstepWindowClass", 18) == 0)
{
s = [s stringByAppendingFormat:
@"%d (%d)\n", otherWin, other->level];
other = (WIN_INTERN *)GetWindowLong((HWND)otherWin, GWL_USERDATA);
if (other->orderedIn == YES)
{
s = [s stringByAppendingFormat:
@"%d (%d)\n", otherWin, other->level];
}
}
}
NSDebugLLog(@"WTrace", @"orderwindow: %@", s);
}
NSDebugLLog(@"WTrace", @"orderwindow: %@", s);
}
#endif
}
- (void) movewindow: (NSPoint)loc : (int)winNum

View file

@ -252,84 +252,141 @@
- (void) decodeWM_WINDOWPOSCHANGEDParams: (WPARAM)wParam : (LPARAM)lParam : (HWND)hwnd
{
#if 0
/* FIXME we really want to ensure that windows stay in the correct
* level order. When we change ordering programmatically using
* orderwindow::: that's OK, but if someone else reorders our
* windows, how do we cope?
* Perhaps we should veto/adjust ordering before it happens, or
* perhaps we should re-order here?
*/
if ((inf->flags & SWP_NOZORDER) == 0)
{
/* If this window has been moved to the front, we need to move
* any other higher level windows to follow it.
*/
win = (WIN_INTERN *)GetWindowLong(hwnd, GWL_USERDATA);
if (win->level > NSDesktopWindowLevel)
{
int otherWin;
int levelToMove = NSDesktopWindowlevel;
/* Start searching from bottom of window list...
* The last child of the desktop.
*/
otherWin = (int)GetDesktopWindow();
otherWin = (int)GetWindow((HWND)otherWin, GW_CHILD);
if (otherWin > 0)
{
otherWin = (int)GetWindow((HWND)otherWin, GW_HWNDLAST);
}
while (otherWin > 0)
{
TCHAR buf[32];
otherWin = (int)GetNextWindow((HWND)otherWin, GW_HWNDPREV);
if (otherWin == 0 || otherWin == (int)hwnd)
{
break; // No higher level windows below this
}
if (GetClassName((HWND)otherWin, buf, 32) == 18
&& strncmp(buf, "GNUstepWindowClass", 18) == 0)
{
other = (WIN_INTERN *)GetWindowLong((HWND)otherWin,
GWL_USERDATA);
if (other->orderedIn == YES)
{
BOOL moveThisWindow = NO;
if (levelToMove > NSDesktopWindowLevel)
{
if (other->level == levelToMove)
{
moveThisWindow = YES;
}
}
else if (other->level > win->level)
{
levelToMove = other->level;
moveThisWindow = YES;
}
if (moveThisWidnow == YES)
{
SetWindowPos((HWND)otherWin, HWND_TOP, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
}
}
}
}
}
}
#endif
}
- (void) decodeWM_WINDOWPOSCHANGINGParams: (WPARAM)wParam : (LPARAM)lParam : (HWND)hwnd
{
WIN_INTERN *win;
WINDOWPOS *inf = (WINDOWPOS*)lParam;
if ((inf->flags & SWP_NOZORDER) == 0)
{
HWND hi;
HWND lo;
WIN_INTERN *hInf;
WIN_INTERN *lInf;
/* For debugging, log current window stack.
*/
if (GSDebugSet(@"WTrace") == YES)
{
NSString *s = @"Window list:\n";
hi = GetDesktopWindow();
hi = GetWindow(hi, GW_CHILD);
if (hi > 0)
{
hi = GetWindow(hi, GW_HWNDLAST);
}
while (hi > 0)
{
TCHAR buf[32];
hi = GetNextWindow(hi, GW_HWNDPREV);
if (hi > 0
&& GetClassName(hi, buf, 32) == 18
&& strncmp(buf, "GNUstepWindowClass", 18) == 0)
{
hInf = (WIN_INTERN *)GetWindowLong(hi, GWL_USERDATA);
if (hInf->orderedIn == YES)
{
s = [s stringByAppendingFormat:
@"%d (%d)\n", hi, hInf->level];
}
}
}
NSLog(@"window pos changed: %@", s);
}
/* This window has changed its z-order, so we take the opportunity
* to check that all the GNUstep windows are in the correct order
* of their levels.
* We do this as a simple bubble sort ...swapping over a pait of
* windows if we find any pair in the list which are in the wrong
* order. This sort has the virtue of being simple and of
* maintaining window order within a level. ... but may be too slow.
*/
hi = GetDesktopWindow();
hi = GetWindow(hi, GW_CHILD);
while (hi > 0)
{
TCHAR buf[32];
/* Find a GNUstep window which is ordered in and above desktop
*/
while (hi > 0)
{
if (GetClassName(hi, buf, 32) == 18
&& strncmp(buf, "GNUstepWindowClass", 18) == 0
&& (hInf = (WIN_INTERN *)GetWindowLong(hi, GWL_USERDATA))
&& hInf->level > NSDesktopWindowLevel
&& hInf->orderedIn == YES)
{
break;
}
hi = GetNextWindow(hi, GW_HWNDNEXT);
}
if (hi > 0)
{
NSDebugLLog(@"WTrace", @"sort hi %d (%d)", hi, hInf->level);
/* Find the next (lower in z-order) GNUstep window which
* is ordered in and above desktop
*/
lo = GetNextWindow(hi, GW_HWNDNEXT);
while (lo > 0)
{
if (GetClassName(lo, buf, 32) == 18
&& strncmp(buf, "GNUstepWindowClass", 18) == 0
&& (lInf = (WIN_INTERN *)GetWindowLong(lo, GWL_USERDATA))
&& lInf->level > NSDesktopWindowLevel
&& lInf->orderedIn == YES)
{
break;
}
lo = GetNextWindow(lo, GW_HWNDNEXT);
}
if (lo > 0)
{
NSDebugLLog(@"WTrace", @"sort lo %d (%d)", lo, lInf->level);
/* Check to see if the higher of the two windows should
* actually be lower.
*/
if (hInf->level < lInf->level)
{
HWND higher;
/* Insert the low window before the high one.
* ie after the window preceding the high one.
*/
higher = GetNextWindow(hi, GW_HWNDPREV);
if (higher == 0)
{
higher = HWND_TOP;
}
NSDebugLLog(@"WTrace", @"swap %d (%d) with %d (%d)",
hi, hInf->level, lo, lInf->level);
SetWindowPos(lo, higher, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
/* Done this iteration of the sort ... the next
* iteration takes place when we get notified
* that the swap we have just donew is complete.
*/
break;
}
}
hi = lo;
}
}
}
}
- (void) decodeWM_WINDOWPOSCHANGINGParams: (WPARAM)wParam : (LPARAM)lParam : (HWND)hwnd
{
WINDOWPOS *inf = (WINDOWPOS*)lParam;
if ((inf->flags & SWP_NOZORDER) == 0)
{
WIN_INTERN *win;
/* desktop level windows should stay at the bottom of the
* window list, so we can simply override any re-ordering
* to ensure that they are at the bottom unless another