mirror of
https://github.com/gnustep/libs-back.git
synced 2025-02-24 20:31:44 +00:00
* Source/win32/WIN32Server.m: * Source/win32/w32_movesize.m: Fix a rather serious error where the extra window data was allocated in two places (allocated with objc_malloc in the WM_CREATE handler, and also allocated by Windows using the cbWndExtra field of the window class structure). Sometimes the window level was accessed from one memory area and sometimes from the other. This is a quick fix that leaves the level and ordered properties in the cbWndExtra area, and the rest is left in the WIN_INTERN structure. This fixes the problem where window ordering was broken when running apps in gdb. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@31198 72102866-910b-0410-8b05-ffd578937521
379 lines
10 KiB
Objective-C
379 lines
10 KiB
Objective-C
/* WIN32Server - Implements window handling for MSWindows
|
|
|
|
Copyright (C) 2005 Free Software Foundation, Inc.
|
|
|
|
Written by: Tom MacSween <macsweent@sympatico.ca>
|
|
Date August 2005
|
|
|
|
This file is part of the GNU Objective C User Interface Library.
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; see the file COPYING.LIB.
|
|
If not, see <http://www.gnu.org/licenses/> or write to the
|
|
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
|
Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include <AppKit/NSEvent.h>
|
|
#include <AppKit/NSWindow.h>
|
|
#include "win32/WIN32Server.h"
|
|
#include "win32/WIN32Geometry.h"
|
|
|
|
@implementation WIN32Server (w32_movesize)
|
|
|
|
- (LRESULT) decodeWM_MOVEParams:(HWND)hwnd : (WPARAM)wParam : (LPARAM)lParam
|
|
{
|
|
NSPoint eventLocation;
|
|
NSRect rect;
|
|
RECT r;
|
|
NSEvent *ev = nil;
|
|
|
|
GetWindowRect(hwnd, &r);
|
|
rect = MSScreenRectToGS(r);
|
|
eventLocation = rect.origin;
|
|
|
|
ev = [NSEvent otherEventWithType: NSAppKitDefined
|
|
location: eventLocation
|
|
modifierFlags: 0
|
|
timestamp: 0
|
|
windowNumber: (int)hwnd
|
|
context: GSCurrentContext()
|
|
subtype: GSAppKitWindowMoved
|
|
data1: rect.origin.x
|
|
data2: rect.origin.y];
|
|
|
|
|
|
//need native code here?
|
|
[EVENT_WINDOW(hwnd) sendEvent: ev];
|
|
|
|
return 0;
|
|
}
|
|
|
|
- (LRESULT) decodeWM_SIZEParams:(HWND)hwnd : (WPARAM)wParam : (LPARAM)lParam
|
|
{
|
|
switch ((int)wParam)
|
|
{
|
|
case SIZE_MAXHIDE:
|
|
{
|
|
// stubbed for future development
|
|
}
|
|
break;
|
|
|
|
case SIZE_MAXSHOW:
|
|
{
|
|
// stubbed for future development
|
|
}
|
|
break;
|
|
|
|
case SIZE_MINIMIZED:
|
|
{
|
|
if (flags.HOLD_MINI_FOR_SIZE == TRUE) // this is fix for [5, 25 bug]
|
|
break;
|
|
|
|
[EVENT_WINDOW(hwnd) miniaturize: self];
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case SIZE_MAXIMIZED:
|
|
case SIZE_RESTORED:
|
|
{
|
|
NSPoint eventLocation;
|
|
NSRect rect;
|
|
RECT r;
|
|
NSEvent *ev =nil;
|
|
|
|
GetWindowRect(hwnd, &r);
|
|
rect = MSScreenRectToGS(r);
|
|
eventLocation = rect.origin;
|
|
|
|
// make event
|
|
ev = [NSEvent otherEventWithType: NSAppKitDefined
|
|
location: eventLocation
|
|
modifierFlags: 0
|
|
timestamp: 0
|
|
windowNumber: (int)hwnd
|
|
context: GSCurrentContext()
|
|
subtype: GSAppKitWindowResized
|
|
data1: rect.size.width
|
|
data2: rect.size.height];
|
|
|
|
[EVENT_WINDOW(hwnd) sendEvent: ev];
|
|
[self resizeBackingStoreFor: hwnd];
|
|
// fixes part one of bug [5, 25] see notes
|
|
if ([self usesNativeTaskbar])
|
|
[EVENT_WINDOW(hwnd) deminiaturize:self];
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
flags.HOLD_MINI_FOR_SIZE = FALSE;
|
|
|
|
return 0;
|
|
}
|
|
|
|
- (void) decodeWM_NCCALCSIZEParams: (WPARAM)wParam : (LPARAM)lParam : (HWND)hwnd
|
|
{
|
|
// stub for future dev
|
|
|
|
/*NCCALCSIZE_PARAMS * newRects;
|
|
|
|
NSPoint eventLocation;
|
|
NSRect rect;
|
|
RECT drect;
|
|
NSEvent *ev =nil;
|
|
|
|
if (wParam == TRUE)
|
|
{
|
|
// get first rect from NCCALCSIZE_PARAMS Structure
|
|
newRects=(NCCALCSIZE_PARAMS *)lParam;
|
|
// get rect 1 from array
|
|
drect=newRects->rgrc[1];
|
|
|
|
//create a size event and send it to the window
|
|
rect = MSScreenRectToGS(drect);
|
|
eventLocation = rect.origin;
|
|
|
|
// make event
|
|
ev = [NSEvent otherEventWithType: NSAppKitDefined
|
|
location: eventLocation
|
|
modifierFlags: 0
|
|
timestamp: 0
|
|
windowNumber: (int)hwnd
|
|
context: GSCurrentContext()
|
|
subtype: GSAppKitWindowResized
|
|
data1: rect.size.width
|
|
data2: rect.size.height];
|
|
|
|
[EVENT_WINDOW(hwnd) sendEvent:ev];*/
|
|
//[[EVENT_WINDOW(hwnd) contentView] display];
|
|
//[self resizeBackingStoreFor:hwnd];
|
|
|
|
|
|
/* ev = [NSEvent otherEventWithType: NSAppKitDefined
|
|
location: eventLocation
|
|
modifierFlags: 0
|
|
timestamp: 0
|
|
windowNumber: (int)hwnd
|
|
context: GSCurrentContext()
|
|
subtype: GSAppKitWindowMoved
|
|
data1: rect.origin.x
|
|
data2: rect.origin.y];
|
|
|
|
[EVENT_WINDOW(hwnd) sendEvent:ev];
|
|
|
|
//printf(" Rect 1 =\n%s", [[self MSRectDetails:drect] cString]);
|
|
|
|
}
|
|
|
|
//printf("wParam is %s\n", wParam ? "TRUE" : "FALSE");*/
|
|
}
|
|
|
|
- (void) decodeWM_WINDOWPOSCHANGEDParams: (WPARAM)wParam : (LPARAM)lParam : (HWND)hwnd
|
|
{
|
|
WINDOWPOS *inf = (WINDOWPOS*)lParam;
|
|
|
|
if ((inf->flags & SWP_NOZORDER) == 0)
|
|
{
|
|
HWND hi;
|
|
HWND lo;
|
|
int hl;
|
|
int ll;
|
|
|
|
/* 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)
|
|
{
|
|
if (GetWindowLong(hi, OFF_ORDERED) == 1)
|
|
{
|
|
hl = GetWindowLong(hi, OFF_LEVEL);
|
|
s = [s stringByAppendingFormat: @"%d (%d)\n", hi, hl];
|
|
}
|
|
}
|
|
}
|
|
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
|
|
&& GetWindowLong(hi, OFF_ORDERED) == 1
|
|
&& (hl = GetWindowLong(hi, OFF_LEVEL))
|
|
> NSDesktopWindowLevel)
|
|
{
|
|
break;
|
|
}
|
|
hi = GetNextWindow(hi, GW_HWNDNEXT);
|
|
}
|
|
|
|
if (hi > 0)
|
|
{
|
|
NSDebugLLog(@"WTrace", @"sort hi %d (%d)", hi, hl);
|
|
/* 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
|
|
&& GetWindowLong(lo, OFF_ORDERED) == 1
|
|
&& (ll = GetWindowLong(lo, OFF_LEVEL))
|
|
> NSDesktopWindowLevel)
|
|
{
|
|
break;
|
|
}
|
|
lo = GetNextWindow(lo, GW_HWNDNEXT);
|
|
}
|
|
|
|
if (lo > 0)
|
|
{
|
|
NSDebugLLog(@"WTrace", @"sort lo %d (%d)", lo, ll);
|
|
/* Check to see if the higher of the two windows should
|
|
* actually be lower.
|
|
*/
|
|
if (hl < ll)
|
|
{
|
|
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, hl, lo, ll);
|
|
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)
|
|
{
|
|
/* 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
|
|
* desktop level window is inserted below them.
|
|
*/
|
|
if (GetWindowLong(hwnd, OFF_LEVEL) <= NSDesktopWindowLevel)
|
|
{
|
|
inf->hwndInsertAfter = HWND_BOTTOM;
|
|
}
|
|
}
|
|
}
|
|
|
|
- (LRESULT) decodeWM_GETMINMAXINFOParams: (WPARAM)wParam : (LPARAM)lParam : (HWND)hwnd
|
|
{
|
|
// reused from original author (added debug code)
|
|
WIN_INTERN *win = (WIN_INTERN *)GetWindowLong(hwnd, GWL_USERDATA);
|
|
MINMAXINFO *mm;
|
|
|
|
if (win != NULL)
|
|
{
|
|
mm = (MINMAXINFO*)lParam;
|
|
mm->ptMinTrackSize = win->minmax.ptMinTrackSize;
|
|
mm->ptMaxTrackSize = win->minmax.ptMaxTrackSize;
|
|
return 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
- (LRESULT) decodeWM_EXITSIZEMOVEParams: (WPARAM)wParam : (LPARAM)lParam : (HWND)hwnd
|
|
{
|
|
// may have a small bug here note it for follow up
|
|
/*
|
|
decodeWM_MOVE and decodeWM_SIZE will send event if they have one.
|
|
no posting is needed.
|
|
*/
|
|
[self resizeBackingStoreFor: hwnd];
|
|
[self decodeWM_MOVEParams:hwnd :wParam :lParam];
|
|
[self decodeWM_SIZEParams:hwnd :wParam :lParam];
|
|
|
|
//Make sure DefWindowProc gets called
|
|
return 0;
|
|
}
|
|
|
|
- (LRESULT) decodeWM_SIZINGParams:(HWND)hwnd : (WPARAM)wParam : (LPARAM)lParam
|
|
{
|
|
[EVENT_WINDOW(hwnd) displayIfNeeded];
|
|
return TRUE;
|
|
}
|
|
|
|
- (LRESULT) decodeWM_MOVINGParams:(HWND)hwnd : (WPARAM)wParam : (LPARAM)lParam
|
|
{
|
|
// stub for future dev
|
|
[self decodeWM_MOVEParams:(HWND)hwnd : (WPARAM)wParam : (LPARAM)lParam];
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|