Reorganize top-level view handling and implement -gui-managed window decorations.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@19687 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
alexm 2004-07-06 20:20:31 +00:00
parent b0adad8c30
commit 2ca7818d89
10 changed files with 1152 additions and 267 deletions

View file

@ -1,3 +1,25 @@
2004-07-06 22:15 Alexander Malmberg <alexander@malmberg.org>
* Headers/Additions/GNUstepGUI/GSDisplayServer.h: Add
-handlesWindowDecorations.
* Headers/AppKit/NSWindow.h: Document _frame ivar and add update
for -gui-managed window decorations.
(+minFrameWidthWithTitle:styleMask:): Change return type to float.
* Source/GNUmakefile: Add GSWindowDecorationView.m and
GSStandardWindowDecorationView.m .
* Source/GSDisplayServer.m (-handlesWindowDecorations): Provide a
default implementation.
* Source/NSPanel.m (-sendEvent:): Reimplement using
-_sendEvent:becomesKeyOnlyIfNeeded: .
(setControl): Only call -setStringValue: on the cell if it doesn't
respond to -setTitle: .
* Source/NSWindow.m: Reorganize management of the top-level view.
Implement -gui-managed window decorations.
(-_sendEvent:becomesKeyOnlyIfNeeded:): New method.
(-sendEvent:): Reimplement using -_sendEvent:becomesKeyOnlyIfNeeded: .
* Source/GSWindowDecorationView.h, Source/GSWindowDecorationView.m,
Source/GSStandardWindowDecorationView.m: New files.
2004-07-05 Gregory John Casamento <greg_casamento@yahoo.com> 2004-07-05 Gregory John Casamento <greg_casamento@yahoo.com>
* Source/NSToolbar.m: [NSToolbar _setWindow:] added logic * Source/NSToolbar.m: [NSToolbar _setWindow:] added logic

View file

@ -72,6 +72,8 @@ APPKIT_EXPORT NSString * GSScreenNumber;
- glContextClass; - glContextClass;
- glPixelFormatClass; - glPixelFormatClass;
- (BOOL) handlesWindowDecorations;
/* Drag and drop support. */ /* Drag and drop support. */
+ (BOOL) addDragTypes: (NSArray*)types toWindow: (NSWindow *)win; + (BOOL) addDragTypes: (NSArray*)types toWindow: (NSWindow *)win;
+ (BOOL) removeDragTypes: (NSArray*)types fromWindow: (NSWindow *)win; + (BOOL) removeDragTypes: (NSArray*)types fromWindow: (NSWindow *)win;
@ -109,7 +111,10 @@ APPKIT_EXPORT NSString * GSScreenNumber;
- (int) window: (NSRect)frame : (NSBackingStoreType)type : (unsigned int)style - (int) window: (NSRect)frame : (NSBackingStoreType)type : (unsigned int)style
: (int)screen; : (int)screen;
- (void) termwindow: (int) win; - (void) termwindow: (int) win;
/* Only if handlesWindowDecorations returns YES. */
- (void) stylewindow: (unsigned int) style : (int) win; - (void) stylewindow: (unsigned int) style : (int) win;
- (void) windowbacking: (NSBackingStoreType)type : (int) win; - (void) windowbacking: (NSBackingStoreType)type : (int) win;
- (void) titlewindow: (NSString *) window_title : (int) win; - (void) titlewindow: (NSString *) window_title : (int) win;
- (void) miniwindow: (int) win; - (void) miniwindow: (int) win;

View file

@ -60,6 +60,8 @@
@class NSWindowController; @class NSWindowController;
@class NSCachedImageRep; @class NSCachedImageRep;
@class GSWindowDecorationView;
/* /*
* Window levels are taken from MacOS-X * Window levels are taken from MacOS-X
* NSDesktopWindowLevel is copied from Window maker and is intended to be * NSDesktopWindowLevel is copied from Window maker and is intended to be
@ -101,12 +103,39 @@ APPKIT_EXPORT NSSize NSTokenSize;
@interface NSWindow : NSResponder <NSCoding> @interface NSWindow : NSResponder <NSCoding>
{ {
/*
A window really has three interesting frames:
The screen frame. This is the frame of the _entire_ window on the screen,
including all decorations and borders (regardless of where they come from).
(On X, we can only guess what the screen frame is.)
The window frame. This is the frame of the backend window for this window,
and is thus the base of the coordinate system for the window. IOW, it's
the frame of the area we can draw into.
The contect rect. This is the frame of the content view.
Wrt. size, ScreenFrame >= WindowFrame >= ContentRect. When -gui doesn't
manage the window decorations, WindowFrame == ContentRect. When -gui does
manage the window decorations, WindowFrame will include the decorations,
and ScreenFrame == WindowFrame.
To get coordinate transforms and stuff right wrt. OpenStep, we really want
the window frame here. However, for hysterical reasons, _frame is actually
the screen frame. (The other rectangles/sizes passed around in NSWindow
methods are likely a mix of screen and window frames.) Only if -gui manages
decorations will this match the semantics properly.
*/
NSRect _frame; NSRect _frame;
NSSize _minimumSize; NSSize _minimumSize;
NSSize _maximumSize; NSSize _maximumSize;
NSSize _increments; NSSize _increments;
NSString *_autosaveName; NSString *_autosaveName;
id _wv; GSWindowDecorationView *_wv;
id _contentView; id _contentView;
id _firstResponder; id _firstResponder;
id _futureFirstResponder; id _futureFirstResponder;
@ -193,8 +222,8 @@ APPKIT_EXPORT NSSize NSTokenSize;
+ (NSRect) frameRectForContentRect: (NSRect)aRect + (NSRect) frameRectForContentRect: (NSRect)aRect
styleMask: (unsigned int)aStyle; styleMask: (unsigned int)aStyle;
+ (NSRect) minFrameWidthWithTitle: (NSString *)aTitle + (float) minFrameWidthWithTitle: (NSString *)aTitle
styleMask: (unsigned int)aStyle; styleMask: (unsigned int)aStyle;
/* /*

View file

@ -186,7 +186,9 @@ GSNibTemplates.m \
GSNibCompatibility.m \ GSNibCompatibility.m \
GSTitleView.m \ GSTitleView.m \
GSToolbar.m \ GSToolbar.m \
GSToolbarView.m GSToolbarView.m \
GSStandardWindowDecorationView.m \
GSWindowDecorationView.m
# Turn off NSMenuItem warning that NSMenuItem conforms to <NSObject>, # Turn off NSMenuItem warning that NSMenuItem conforms to <NSObject>,
# but does not implement <NSObject>'s methods itself (it inherits # but does not implement <NSObject>'s methods itself (it inherits

View file

@ -278,6 +278,12 @@ GSCurrentServer(void)
} }
- (BOOL) handlesWindowDecorations
{
return YES;
}
/* Drag and drop support. */ /* Drag and drop support. */
/** Convienience method that calls -addDragTypes:toWindow: using the /** Convienience method that calls -addDragTypes:toWindow: using the
server that controls win. server that controls win.

View file

@ -0,0 +1,549 @@
/** <title>GSStandardWindowDecorationView</title>
Copyright (C) 2004 Free Software Foundation, Inc.
Author: Alexander Malmberg <alexander@malmberg.org>
Date: 2004-03-24
This file is part of the GNUstep GUI Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "GSWindowDecorationView.h"
#include <Foundation/NSException.h>
#include "AppKit/NSApplication.h"
#include "AppKit/NSButton.h"
#include "AppKit/NSImage.h"
#include "AppKit/NSScreen.h"
#include "AppKit/NSStringDrawing.h"
#include "AppKit/NSWindow.h"
#include "AppKit/PSOperators.h"
#include "GNUstepGUI/GSDisplayServer.h"
@implementation GSStandardWindowDecorationView
/* These include the black border. */
#define TITLE_HEIGHT 23.0
#define RESIZE_HEIGHT 9.0
+(void) offsets: (float *)l : (float *)r : (float *)t : (float *)b
forStyleMask: (unsigned int)style
{
if (style
& (NSTitledWindowMask | NSClosableWindowMask
| NSMiniaturizableWindowMask | NSResizableWindowMask))
*l = *r = *t = *b = 1.0;
else
*l = *r = *t = *b = 0.0;
if (style
& (NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask))
{
*t = TITLE_HEIGHT;
}
if (style & NSResizableWindowMask)
{
*b = RESIZE_HEIGHT;
}
}
+ (float) minFrameWidthWithTitle: (NSString *)aTitle
styleMask: (unsigned int)aStyle
{
float l, r, t, b, width;
[self offsets: &l : &r : &t : &b
forStyleMask: aStyle];
width = l + r;
if (aStyle & NSTitledWindowMask)
width += [aTitle sizeWithAttributes: nil].width;
return width;
}
static NSDictionary *titleTextAttributes[3];
static NSColor *titleColor[3];
-(void) updateRects
{
if (hasTitleBar)
titleBarRect = NSMakeRect(0.0, _frame.size.height - TITLE_HEIGHT,
_frame.size.width, TITLE_HEIGHT);
if (hasResizeBar)
resizeBarRect = NSMakeRect(0.0, 0.0, _frame.size.width, RESIZE_HEIGHT);
if (hasCloseButton)
{
closeButtonRect = NSMakeRect(
_frame.size.width - 15 - 4, _frame.size.height - 15 - 4, 15, 15);
[closeButton setFrame: closeButtonRect];
}
if (hasMiniaturizeButton)
{
miniaturizeButtonRect = NSMakeRect(4, _frame.size.height - 15 - 4,
15, 15);
[miniaturizeButton setFrame: miniaturizeButtonRect];
}
}
- initWithFrame: (NSRect)frame
window: (NSWindow *)w
{
if (!titleTextAttributes[0])
{
titleTextAttributes[0] = [[NSMutableDictionary alloc]
initWithObjectsAndKeys:
[NSFont titleBarFontOfSize: 0], NSFontAttributeName,
[NSColor windowFrameTextColor], NSForegroundColorAttributeName,
nil];
titleTextAttributes[1] = [[NSMutableDictionary alloc]
initWithObjectsAndKeys:
[NSFont titleBarFontOfSize: 0], NSFontAttributeName,
[NSColor blackColor], NSForegroundColorAttributeName, /* TODO: need a named color for this */
nil];
titleTextAttributes[2] = [[NSMutableDictionary alloc]
initWithObjectsAndKeys:
[NSFont titleBarFontOfSize: 0], NSFontAttributeName,
[NSColor windowFrameTextColor], NSForegroundColorAttributeName,
nil];
titleColor[0] = RETAIN([NSColor windowFrameColor]);
titleColor[1] = RETAIN([NSColor lightGrayColor]);
titleColor[2] = RETAIN([NSColor darkGrayColor]);
}
self = [super initWithFrame: frame
window: w];
if (!self) return nil;
if ([w styleMask]
& (NSTitledWindowMask | NSClosableWindowMask
| NSMiniaturizableWindowMask))
{
hasTitleBar = YES;
}
if ([w styleMask] & NSTitledWindowMask)
isTitled = YES;
if ([w styleMask] & NSClosableWindowMask)
{
hasCloseButton = YES;
closeButton = [[NSButton alloc] init];
[closeButton setRefusesFirstResponder: YES];
[closeButton setButtonType: NSMomentaryChangeButton];
[closeButton setImagePosition: NSImageOnly];
[closeButton setBordered: YES];
[closeButton setImage: [NSImage imageNamed: @"common_Close"]];
[closeButton setAlternateImage: [NSImage imageNamed: @"common_CloseH"]];
[closeButton setTarget: window];
/* TODO: -performClose: should (but doesn't currently) highlight the
button, which is wrong here. When -performClose: is fixed, we'll need a
different method here. */
[closeButton setAction: @selector(performClose:)];
[self addSubview: closeButton];
RELEASE(closeButton);
}
if ([w styleMask] & NSMiniaturizableWindowMask)
{
hasMiniaturizeButton = YES;
miniaturizeButton = [[NSButton alloc] init];
[miniaturizeButton setRefusesFirstResponder: YES];
[miniaturizeButton setButtonType: NSMomentaryChangeButton];
[miniaturizeButton setImagePosition: NSImageOnly];
[miniaturizeButton setBordered: YES];
[miniaturizeButton setImage:
[NSImage imageNamed: @"common_Miniaturize"]];
[miniaturizeButton setAlternateImage:
[NSImage imageNamed: @"common_MiniaturizeH"]];
[miniaturizeButton setTarget: window];
/* TODO: -performMiniaturize: should (but doesn't currently) highlight
the button, which is wrong here, just like -performClose: above. */
[miniaturizeButton setAction: @selector(performMiniaturize:)];
[self addSubview: miniaturizeButton];
RELEASE(miniaturizeButton);
}
if ([w styleMask] & NSResizableWindowMask)
hasResizeBar = YES;
[self updateRects];
return self;
}
-(void) drawTitleBar
{
static const NSRectEdge edges[4] = {NSMinXEdge, NSMaxYEdge,
NSMaxXEdge, NSMinYEdge};
float grays[3][4] =
{{NSLightGray, NSLightGray, NSDarkGray, NSDarkGray},
{NSWhite, NSWhite, NSDarkGray, NSDarkGray},
{NSLightGray, NSLightGray, NSBlack, NSBlack}};
NSRect workRect;
NSString *title = [window title];
/*
Draw the black border towards the rest of the window. (The outer black
border is drawn in -drawRect: since it might be drawn even if we don't have
a title bar.
*/
[[NSColor blackColor] set];
PSmoveto(0, NSMinY(titleBarRect) + 0.5);
PSrlineto(titleBarRect.size.width, 0);
PSstroke();
/*
Draw the button-like border.
*/
workRect = titleBarRect;
workRect.origin.x += 1;
workRect.origin.y += 1;
workRect.size.width -= 2;
workRect.size.height -= 2;
workRect = NSDrawTiledRects(workRect, workRect, edges, grays[inputState], 4);
/*
Draw the background.
*/
[titleColor[inputState] set];
NSRectFill(workRect);
/* Draw the title. */
if (isTitled)
{
NSSize titleSize;
if (hasMiniaturizeButton)
{
workRect.origin.x += 17;
workRect.size.width -= 17;
}
if (hasCloseButton)
{
workRect.size.width -= 17;
}
titleSize = [title sizeWithAttributes: titleTextAttributes[inputState]];
if (titleSize.width <= workRect.size.width)
workRect.origin.x += NSMidX(workRect) - titleSize.width / 2;
workRect.origin.y = NSMidY(workRect) - titleSize.height / 2;
workRect.size.height = titleSize.height;
[title drawInRect: workRect
withAttributes: titleTextAttributes[inputState]];
}
}
-(void) drawResizeBar
{
[[NSColor lightGrayColor] set];
PSrectfill(1.0, 1.0, resizeBarRect.size.width - 2.0, RESIZE_HEIGHT - 3.0);
PSsetlinewidth(1.0);
[[NSColor blackColor] set];
PSmoveto(0.0, 0.5);
PSlineto(resizeBarRect.size.width, 0.5);
PSstroke();
[[NSColor darkGrayColor] set];
PSmoveto(1.0, RESIZE_HEIGHT - 0.5);
PSlineto(resizeBarRect.size.width - 1.0, RESIZE_HEIGHT - 0.5);
PSstroke();
[[NSColor whiteColor] set];
PSmoveto(1.0, RESIZE_HEIGHT - 1.5);
PSlineto(resizeBarRect.size.width - 1.0, RESIZE_HEIGHT - 1.5);
PSstroke();
/* Only draw the notches if there's enough space. */
if (resizeBarRect.size.width < 30 * 2)
return;
[[NSColor darkGrayColor] set];
PSmoveto(27.5, 1.0);
PSlineto(27.5, RESIZE_HEIGHT - 2.0);
PSmoveto(resizeBarRect.size.width - 28.5, 1.0);
PSlineto(resizeBarRect.size.width - 28.5, RESIZE_HEIGHT - 2.0);
PSstroke();
[[NSColor whiteColor] set];
PSmoveto(28.5, 1.0);
PSlineto(28.5, RESIZE_HEIGHT - 2.0);
PSmoveto(resizeBarRect.size.width - 27.5, 1.0);
PSlineto(resizeBarRect.size.width - 27.5, RESIZE_HEIGHT - 2.0);
PSstroke();
}
-(void) drawRect: (NSRect)rect
{
if (hasTitleBar && NSIntersectsRect(rect, titleBarRect))
{
[self drawTitleBar];
}
if (hasResizeBar && NSIntersectsRect(rect, resizeBarRect))
{
[self drawResizeBar];
}
if (hasResizeBar || hasTitleBar)
{
PSsetlinewidth(1.0);
[[NSColor blackColor] set];
if (NSMinX(rect) < 1.0)
{
PSmoveto(0.5, 0.0);
PSlineto(0.5, _frame.size.height);
PSstroke();
}
if (NSMaxX(rect) > _frame.size.width - 1.0)
{
PSmoveto(_frame.size.width - 0.5, 0.0);
PSlineto(_frame.size.width - 0.5, _frame.size.height);
PSstroke();
}
if (NSMaxY(rect) > _frame.size.height - 1.0)
{
PSmoveto(0.0, _frame.size.height - 0.5);
PSlineto(_frame.size.width, _frame.size.height - 0.5);
PSstroke();
}
if (NSMinY(rect) < 1.0)
{
PSmoveto(0.0, 0.5);
PSlineto(_frame.size.width, 0.5);
PSstroke();
}
}
[super drawRect: rect];
}
-(void) setTitle: (NSString *)newTitle
{
if (isTitled)
[self setNeedsDisplayInRect: titleBarRect];
}
-(void) setInputState: (int)state
{
NSAssert(state >= 0 && state <= 2, @"Invalid state!");
[super setInputState: state];
if (hasTitleBar)
[self setNeedsDisplayInRect: titleBarRect];
}
-(void) setDocumentEdited: (BOOL)flag
{
if (flag)
{
[closeButton setImage: [NSImage imageNamed: @"common_CloseBroken"]];
[closeButton setAlternateImage:
[NSImage imageNamed: @"common_CloseBrokenH"]];
}
else
{
[closeButton setImage: [NSImage imageNamed: @"common_Close"]];
[closeButton setAlternateImage:
[NSImage imageNamed: @"common_CloseH"]];
}
}
-(NSPoint) mouseLocationOnScreenOutsideOfEventStream
{
int screen = [[window screen] screenNumber];
return [GSServerForWindow(window) mouseLocationOnScreen: screen
window: NULL];
}
-(void) moveWindowStartingWithEvent: (NSEvent *)event
{
unsigned int mask = NSLeftMouseDraggedMask | NSLeftMouseUpMask;
NSEvent *currentEvent = event;
NSDate *distantPast = [NSDate distantPast];
NSPoint delta, point;
delta = [event locationInWindow];
[window _captureMouse: nil];
do
{
while (currentEvent && [currentEvent type] != NSLeftMouseUp)
{
currentEvent = [_window nextEventMatchingMask: mask
untilDate: distantPast
inMode: NSEventTrackingRunLoopMode
dequeue: YES];
}
point = [self mouseLocationOnScreenOutsideOfEventStream];
[window setFrameOrigin: NSMakePoint(point.x - delta.x,
point.y - delta.y)];
if (currentEvent && [currentEvent type] == NSLeftMouseUp)
break;
currentEvent = [_window nextEventMatchingMask: mask
untilDate: nil
inMode: NSEventTrackingRunLoopMode
dequeue: YES];
} while ([currentEvent type] != NSLeftMouseUp);
[window _releaseMouse: nil];
}
static NSRect calc_new_frame(NSRect frame, NSPoint point, NSPoint firstPoint,
int mode, NSSize minSize, NSSize maxSize)
{
NSRect newFrame = frame;
newFrame.origin.y = point.y - firstPoint.y;
newFrame.size.height = NSMaxY(frame) - newFrame.origin.y;
if (newFrame.size.height < minSize.height)
{
newFrame.size.height = minSize.height;
newFrame.origin.y = NSMaxY(frame) - newFrame.size.height;
}
if (mode == 0)
{
newFrame.origin.x = point.x - firstPoint.x;
newFrame.size.width = NSMaxX(frame) - newFrame.origin.x;
if (newFrame.size.width < minSize.width)
{
newFrame.size.width = minSize.width;
newFrame.origin.x = NSMaxX(frame) - newFrame.size.width;
}
}
else if (mode == 1)
{
newFrame.size.width = point.x - frame.origin.x + frame.size.width
- firstPoint.x;
if (newFrame.size.width < minSize.width)
{
newFrame.size.width = minSize.width;
newFrame.origin.x = frame.origin.x;
}
}
return newFrame;
}
-(void) resizeWindowStartingWithEvent: (NSEvent *)event
{
unsigned int mask = NSLeftMouseDraggedMask | NSLeftMouseUpMask;
NSEvent *currentEvent = event;
NSDate *distantPast = [NSDate distantPast];
NSPoint firstPoint, point;
NSRect newFrame, frame;
NSSize minSize, maxSize;
/*
0 drag lower left corner
1 drag lower right corner
2 drag lower edge
*/
int mode;
firstPoint = [event locationInWindow];
if (resizeBarRect.size.width < 30 * 2
&& firstPoint.x < resizeBarRect.size.width / 2)
mode = 0;
else if (firstPoint.x > resizeBarRect.size.width - 29)
mode = 1;
else if (firstPoint.x < 29)
mode = 0;
else
mode = 2;
frame = [window frame];
minSize = [window minSize];
maxSize = [window maxSize];
[window _captureMouse: nil];
do
{
while (currentEvent && [currentEvent type] != NSLeftMouseUp)
{
currentEvent = [_window nextEventMatchingMask: mask
untilDate: distantPast
inMode: NSEventTrackingRunLoopMode
dequeue: YES];
}
point = [self mouseLocationOnScreenOutsideOfEventStream];
newFrame = calc_new_frame(frame, point, firstPoint, mode, minSize, maxSize);
if (currentEvent && [currentEvent type] == NSLeftMouseUp)
break;
currentEvent = [_window nextEventMatchingMask: mask
untilDate: nil
inMode: NSEventTrackingRunLoopMode
dequeue: YES];
} while ([currentEvent type] != NSLeftMouseUp);
[window _releaseMouse: nil];
[window setFrame: newFrame display: YES];
}
-(BOOL) acceptsFirstMouse: (NSEvent*)theEvent
{
return YES;
}
-(void) mouseDown: (NSEvent *)event
{
NSPoint p = [self convertPoint: [event locationInWindow] fromView: nil];
if (NSPointInRect(p, contentRect))
return;
if (NSPointInRect(p, titleBarRect))
{
[self moveWindowStartingWithEvent: event];
return;
}
if (NSPointInRect(p, resizeBarRect))
{
[self resizeWindowStartingWithEvent: event];
return;
}
}
- (void) setFrame: (NSRect)frameRect
{
[super setFrame: frameRect];
[self updateRects];
}
@end

View file

@ -0,0 +1,100 @@
/** <title>GSWindowDecorationView</title>
Copyright (C) 2004 Free Software Foundation, Inc.
Author: Alexander Malmberg <alexander@malmberg.org>
Date: 2004-03-24
This file is part of the GNUstep GUI Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _GNUstep_H_GSWindowDecorationView
#define _GNUstep_H_GSWindowDecorationView
#include <Foundation/NSGeometry.h>
#include "AppKit/NSView.h"
@class NSWindow;
@protocol GSWindowDecorator
- (id) newWindowDecorationViewWithFrame: (NSRect)frame
window: (NSWindow *)window;
- (NSRect) contentRectForFrameRect: (NSRect)aRect
styleMask: (unsigned int)aStyle;
- (NSRect) frameRectForContentRect: (NSRect)aRect
styleMask: (unsigned int)aStyle;
- (float) minFrameWidthWithTitle: (NSString *)aTitle
styleMask: (unsigned int)aStyle;
@end
/*
Abstract superclass for the top-level view in each window. This view is
responsible for managing window decorations. Concrete subclasses may do
this, either directly, or indirectly (by using the backend).
*/
@interface GSWindowDecorationView : NSView
{
NSWindow *window; /* not retained */
int windowNumber;
NSRect contentRect;
int inputState;
BOOL documentEdited;
}
+(id<GSWindowDecorator>) windowDecorator;
- initWithFrame: (NSRect)frame
window: (NSWindow *)w;
-(void) setContentView: (NSView *)contentView;
/*
Called when the backend window is created or destroyed. When it's destroyed,
windowNumber will be 0.
*/
-(void) setWindowNumber: (int)windowNumber;
-(void) setTitle: (NSString *)title;
-(void) setInputState: (int)state;
-(void) setDocumentEdited: (BOOL)flag;
@end
/*
Standard OPENSTEP-ish window decorations.
*/
@class NSButton;
@interface GSStandardWindowDecorationView : GSWindowDecorationView
{
BOOL hasTitleBar, hasResizeBar, hasCloseButton, hasMiniaturizeButton;
BOOL isTitled;
NSRect titleBarRect;
NSRect resizeBarRect;
NSRect closeButtonRect;
NSRect miniaturizeButtonRect;
NSButton *closeButton, *miniaturizeButton;
}
@end
#endif

View file

@ -0,0 +1,293 @@
/** <title>GSWindowDecorationView</title>
Copyright (C) 2004 Free Software Foundation, Inc.
Author: Alexander Malmberg <alexander@malmberg.org>
Date: 2004-03-24
This file is part of the GNUstep GUI Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "GSWindowDecorationView.h"
#include <Foundation/NSException.h>
#include "AppKit/NSColor.h"
#include "AppKit/NSWindow.h"
#include "GNUstepGUI/GSDisplayServer.h"
struct NSWindow_struct
{
@defs(NSWindow)
};
/*
Manage window decorations by using the backend functions. This only works
on backends that can handle window decorations.
*/
@interface GSBackendWindowDecorationView : GSWindowDecorationView
@end
/*
GSWindowDecorationView implementation.
*/
@implementation GSWindowDecorationView
+(id<GSWindowDecorator>) windowDecorator
{
if ([GSCurrentServer() handlesWindowDecorations])
return [GSBackendWindowDecorationView self];
else
return [GSStandardWindowDecorationView self];
}
+(id) newWindowDecorationViewWithFrame: (NSRect)frame
window: (NSWindow *)aWindow
{
return [[self alloc] initWithFrame: frame
window: aWindow];
}
+(void) offsets: (float *)l : (float *)r : (float *)t : (float *)b
forStyleMask: (unsigned int)style
{
[self subclassResponsibility: _cmd];
}
+ (NSRect) contentRectForFrameRect: (NSRect)aRect
styleMask: (unsigned int)aStyle
{
float t, b, l, r;
[self offsets: &l : &r : &t : &b
forStyleMask: aStyle];
aRect.size.width -= l + r;
aRect.size.height -= t + b;
aRect.origin.x += l;
aRect.origin.y += b;
return aRect;
}
+ (NSRect) frameRectForContentRect: (NSRect)aRect
styleMask: (unsigned int)aStyle
{
float t, b, l, r;
[self offsets: &l : &r : &t : &b
forStyleMask: aStyle];
aRect.size.width += l + r;
aRect.size.height += t + b;
aRect.origin.x -= l;
aRect.origin.y -= b;
return aRect;
}
+ (float) minFrameWidthWithTitle: (NSString *)aTitle
styleMask: (unsigned int)aStyle
{
[self subclassResponsibility: _cmd];
return 0.0;
}
/*
Internal helpers.
Returns the internal window frame rect for a given (screen) frame.
*/
+(NSRect) windowFrameRectForFrameRect: (NSRect)aRect
styleMask: (unsigned int)aStyle
{
aRect.origin = NSZeroPoint;
return aRect;
}
/*
Returns the content rect for a given window frame.
*/
+(NSRect) contentRectForWindowFrameRect: (NSRect)aRect
styleMask: (unsigned int)aStyle
{
return [self contentRectForFrameRect: aRect styleMask: aStyle];
}
- initWithFrame: (NSRect)frame
{
NSAssert(NO, @"Tried to create GSWindowDecorationView without a window!");
return nil;
}
- initWithFrame: (NSRect)frame
window: (NSWindow *)w
{
frame = [isa windowFrameRectForFrameRect: frame
styleMask: [w styleMask]];
self = [super initWithFrame: frame];
if (!self)
return nil;
window = w;
contentRect = frame;
contentRect =
[isa contentRectForWindowFrameRect: contentRect
styleMask: [window styleMask]];
return self;
}
/*
* Special setFrame: implementation - a minimal autoresize mechanism
*/
- (void) setFrame: (NSRect)frameRect
{
NSSize oldSize = _frame.size;
NSView *cv = [_window contentView];
frameRect = [isa windowFrameRectForFrameRect: frameRect
styleMask: [window styleMask]];
_autoresizes_subviews = NO;
[super setFrame: frameRect];
contentRect = [isa contentRectForWindowFrameRect: frameRect
styleMask: [window styleMask]];
// Safety Check.
[cv setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
[cv resizeWithOldSuperviewSize: oldSize];
}
- (void) setContentView: (NSView *)contentView
{
NSSize oldSize;
[contentView setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
[self addSubview: contentView];
oldSize = [contentView frame].size;
oldSize.width += _frame.size.width - contentRect.size.width;
oldSize.height += _frame.size.height - contentRect.size.height;
[contentView resizeWithOldSuperviewSize: oldSize];
[contentView setFrameOrigin: NSMakePoint(contentRect.origin.x,
contentRect.origin.y)];
}
-(void) setWindowNumber: (int)theWindowNumber
{
windowNumber = theWindowNumber;
if (!windowNumber)
return;
[GSServerForWindow(window) titlewindow: [window title] : windowNumber];
[GSServerForWindow(window) setinputstate: inputState : windowNumber];
[GSServerForWindow(window) docedited: documentEdited : windowNumber];
}
-(void) setTitle: (NSString *)title
{
if (windowNumber)
[GSServerForWindow(window) titlewindow: title : windowNumber];
}
-(void) setInputState: (int)state
{
inputState = state;
if (windowNumber)
[GSServerForWindow(window) setinputstate: inputState : windowNumber];
}
-(void) setDocumentEdited: (BOOL)flag
{
documentEdited = flag;
if (windowNumber)
[GSServerForWindow(window) docedited: documentEdited : windowNumber];
}
- (BOOL) isOpaque
{
return YES;
}
- (void) drawRect: (NSRect)rect
{
NSColor *c = [_window backgroundColor];
if (NSIntersectsRect(rect, contentRect))
{
[c set];
NSRectFill(contentRect);
}
}
- initWithCoder: (NSCoder*)aCoder
{
NSAssert(NO, @"The top-level window view should never be encoded.");
return nil;
}
-(void) encodeWithCoder: (NSCoder*)aCoder
{
NSAssert(NO, @"The top-level window view should never be encoded.");
}
@end
@implementation GSBackendWindowDecorationView
+(void) offsets: (float *)l : (float *)r : (float *)t : (float *)b
forStyleMask: (unsigned int)style
{
[GSCurrentServer() styleoffsets: l : r : t : b : style];
}
+ (float) minFrameWidthWithTitle: (NSString *)aTitle
styleMask: (unsigned int)aStyle
{
/* TODO: we could at least guess... */
return 0.0;
}
+(NSRect) windowFrameRectForFrameRect: (NSRect)aRect
styleMask: (unsigned int)aStyle
{
float l, r, t, b;
[self offsets: &l : &r : &t : &b forStyleMask: aStyle];
aRect.size.width -= l + r;
aRect.size.height -= t + b;
return aRect;
}
/*
Returns the content rect for a given window frame.
*/
+(NSRect) contentRectForWindowFrameRect: (NSRect)aRect
styleMask: (unsigned int)aStyle
{
return aRect;
}
@end

View file

@ -194,65 +194,8 @@ static NSString *defaultTitle = @" ";
- (void) sendEvent: (NSEvent*)theEvent - (void) sendEvent: (NSEvent*)theEvent
{ {
/* [self _sendEvent: theEvent
Code shared with [NSWindow -sendEvent:], remember to update both places. becomesKeyOnlyIfNeeded: _becomesKeyOnlyIfNeeded];
*/
NSView *v;
NSEventType type;
type = [theEvent type];
if (type == NSLeftMouseDown)
{
if (_f.visible)
{
BOOL wasKey = _f.is_key;
if (_f.has_closed == NO)
{
v = [_contentView hitTest: [theEvent locationInWindow]];
if (_f.is_key == NO)
{
/* NSPanel modification: check becomesKeyOnlyIfNeeded. */
if (!_becomesKeyOnlyIfNeeded || [v needsPanelToBecomeKey])
[self makeKeyAndOrderFront: self];
}
/* Activate the app *after* making the receiver key, as app
activation tries to make the previous key window key. */
if ([NSApp isActive] == NO
&& (NSWindow*)self != [NSApp iconWindow])
{
[NSApp activateIgnoringOtherApps: YES];
}
if (_firstResponder != v)
{
[self makeFirstResponder: v];
}
if (_lastView)
{
DESTROY(_lastView);
}
if (wasKey == YES || [v acceptsFirstMouse: theEvent] == YES)
{
if ([NSHelpManager isContextHelpModeActive])
{
[v helpRequested: theEvent];
}
else
{
ASSIGN(_lastView, v);
[v mouseDown: theEvent];
}
}
else
{
[self mouseDown: theEvent];
}
}
_lastPoint = [theEvent locationInWindow];
}
return;
}
[super sendEvent: theEvent];
} }
@end /* NSPanel */ @end /* NSPanel */
@ -504,7 +447,7 @@ setControl(NSView* content, id control, NSString *title)
{ {
[control setTitle: title]; [control setTitle: title];
} }
if ([control respondsToSelector: @selector(setStringValue:)]) else if ([control respondsToSelector: @selector(setStringValue:)])
{ {
[control setStringValue: title]; [control setStringValue: title];
} }

View file

@ -47,31 +47,37 @@
#include <Foundation/NSLock.h> #include <Foundation/NSLock.h>
#include <Foundation/NSUserDefaults.h> #include <Foundation/NSUserDefaults.h>
#include "AppKit/NSDocument.h"
#include "AppKit/NSWindow.h"
#include "AppKit/NSWindowController.h"
#include "AppKit/NSApplication.h" #include "AppKit/NSApplication.h"
#include "AppKit/NSButtonCell.h" #include "AppKit/NSButtonCell.h"
#include "AppKit/NSMenu.h"
#include "AppKit/NSImage.h"
#include "AppKit/NSTextFieldCell.h"
#include "AppKit/NSTextField.h"
#include "AppKit/NSFont.h"
#include "AppKit/NSColor.h"
#include "AppKit/NSScreen.h"
#include "AppKit/NSView.h"
#include "AppKit/NSCursor.h"
#include "AppKit/PSOperators.h"
#include "AppKit/NSDragging.h"
#include "AppKit/NSPasteboard.h"
#include "AppKit/NSHelpManager.h"
#include "AppKit/NSGraphics.h"
#include "AppKit/NSCachedImageRep.h" #include "AppKit/NSCachedImageRep.h"
#include "AppKit/NSColor.h"
#include "AppKit/NSColorList.h"
#include "AppKit/NSCursor.h"
#include "AppKit/NSDocument.h"
#include "AppKit/NSDragging.h"
#include "AppKit/NSFont.h"
#include "AppKit/NSGraphics.h"
#include "AppKit/NSHelpManager.h"
#include "AppKit/NSImage.h"
#include "AppKit/NSMenu.h"
#include "AppKit/NSPasteboard.h"
#include "AppKit/NSScreen.h"
#include "AppKit/NSTextField.h"
#include "AppKit/NSTextFieldCell.h"
#include "AppKit/NSToolbar.h" #include "AppKit/NSToolbar.h"
#include "AppKit/NSView.h"
#include "AppKit/NSWindow.h"
#include "AppKit/NSWindowController.h"
#include "AppKit/PSOperators.h"
#include "GNUstepGUI/GSTrackingRect.h" #include "GNUstepGUI/GSTrackingRect.h"
#include "GNUstepGUI/GSDisplayServer.h" #include "GNUstepGUI/GSDisplayServer.h"
#include "GNUstepGUI/GSToolbarView.h" #include "GNUstepGUI/GSToolbarView.h"
#include "GSWindowDecorationView.h"
static id<GSWindowDecorator> windowDecorator;
BOOL GSViewAcceptsDrag(NSView *v, id<NSDraggingInfo> dragInfo); BOOL GSViewAcceptsDrag(NSView *v, id<NSDraggingInfo> dragInfo);
static NSArray *modes = nil; static NSArray *modes = nil;
@ -102,7 +108,7 @@ static NSArray *modes = nil;
/* /*
This method handles all normal displaying. It is set to be run on each This method handles all normal displaying. It is set to be run on each
runloop iteration for each window that's on-screen. The performer is runloop iteration for each window that's on-screen. The performer is
added then the window is ordered in and re-added each time it is run. added when the window is ordered in and re-added each time it is run.
If the window is ordered out, the performer is cancelled. If the window is ordered out, the performer is cancelled.
The reason why this performer is always added, as opposed to adding it The reason why this performer is always added, as opposed to adding it
@ -398,53 +404,6 @@ static NSCell *tileCell = nil;
@interface GSWindowView : NSView
{
}
@end
@implementation GSWindowView
- (BOOL) isOpaque
{
return YES;
}
- (void) drawRect: (NSRect)rect
{
NSColor *c = [[self window] backgroundColor];
NSDebugLLog(@"NSView", @"-drawRect: %@ for %@ in window %p (%@)",
NSStringFromRect(rect), self, _window,
NSStringFromRect([_window frame]));
[c set];
NSRectFill(rect);
}
/*
* Special setFrame: implementation - a minimal autoresize mechanism
*/
- (void) setFrame: (NSRect)frameRect
{
NSSize oldSize = _frame.size;
NSView *cv = [_window contentView];
_autoresizes_subviews = NO;
[super setFrame: frameRect];
// Safety Check.
[cv setAutoresizingMask: (NSViewWidthSizable | NSViewHeightSizable)];
[cv resizeWithOldSuperviewSize: oldSize];
}
- (Class) classForCoder: (NSCoder*)aCoder
{
if ([self class] == [GSWindowView class])
return [super class];
return [self class];
}
@end
/***************************************************************************** /*****************************************************************************
* *
* NSWindow * NSWindow
@ -546,52 +505,31 @@ static NSNotificationCenter *nc = nil;
+ (NSRect) contentRectForFrameRect: (NSRect)aRect + (NSRect) contentRectForFrameRect: (NSRect)aRect
styleMask: (unsigned int)aStyle styleMask: (unsigned int)aStyle
{ {
float t, b, l, r; if (!windowDecorator)
windowDecorator = [GSWindowDecorationView windowDecorator];
[GSCurrentServer() styleoffsets: &l : &r : &t : &b : aStyle]; return [windowDecorator contentRectForFrameRect: aRect
aRect.size.width -= (l + r); styleMask: aStyle];
aRect.size.height -= (t + b);
aRect.origin.x += l;
aRect.origin.y += b;
return aRect;
} }
+ (NSRect) frameRectForContentRect: (NSRect)aRect + (NSRect) frameRectForContentRect: (NSRect)aRect
styleMask: (unsigned int)aStyle styleMask: (unsigned int)aStyle
{ {
float t, b, l, r; if (!windowDecorator)
windowDecorator = [GSWindowDecorationView windowDecorator];
[GSCurrentServer() styleoffsets: &l : &r : &t : &b : aStyle]; return [windowDecorator frameRectForContentRect: aRect
aRect.size.width += (l + r); styleMask: aStyle];
aRect.size.height += (t + b);
aRect.origin.x -= l;
aRect.origin.y -= b;
return aRect;
} }
+ (NSRect) minFrameWidthWithTitle: (NSString*)aTitle + (float) minFrameWidthWithTitle: (NSString *)aTitle
styleMask: (unsigned int)aStyle styleMask: (unsigned int)aStyle
{ {
float t, b, l, r; if (!windowDecorator)
NSRect f = NSZeroRect; windowDecorator = [GSWindowDecorationView windowDecorator];
[GSCurrentServer() styleoffsets: &l : &r : &t : &b : aStyle]; return [windowDecorator minFrameWidthWithTitle: aTitle
f.size.width = l + r; styleMask: aStyle];
f.size.height = t + b;
/*
* Assume that the width of the area needed for a button is equal to
* the height of the title bar.
*/
if (aStyle & NSClosableWindowMask)
f.size.width += t;
if (aStyle & NSMiniaturizableWindowMask)
f.size.width += t;
/*
* FIXME - title width has to be better determined than this.
* need to get correct values from font.
*/
f.size.width += [aTitle length] * 10;
return f;
} }
/* default Screen and window depth */ /* default Screen and window depth */
@ -641,6 +579,7 @@ many times.
if (_windowNum) if (_windowNum)
{ {
[_wv setWindowNumber: 0];
[GSServerForWindow(self) termwindow: _windowNum]; [GSServerForWindow(self) termwindow: _windowNum];
NSMapRemove(windowmaps, (void*)_windowNum); NSMapRemove(windowmaps, (void*)_windowNum);
_windowNum = 0; _windowNum = 0;
@ -680,7 +619,7 @@ many times.
deallocation of the window's views ! - some of them might be deallocation of the window's views ! - some of them might be
retained for some other reason by the programmer or by other retained for some other reason by the programmer or by other
parts of the code */ parts of the code */
TEST_RELEASE(_wv); DESTROY(_wv);
TEST_RELEASE(_fieldEditor); TEST_RELEASE(_fieldEditor);
TEST_RELEASE(_backgroundColor); TEST_RELEASE(_backgroundColor);
TEST_RELEASE(_representedFilename); TEST_RELEASE(_representedFilename);
@ -713,7 +652,7 @@ many times.
[super dealloc]; [super dealloc];
} }
- (void) _initBackendWindow: (NSRect)frame - (void) _initBackendWindow
{ {
int screenNumber; int screenNumber;
NSCountedSet *dragTypes; NSCountedSet *dragTypes;
@ -735,7 +674,12 @@ many times.
} }
screenNumber = [_screen screenNumber]; screenNumber = [_screen screenNumber];
_windowNum = [srv window: frame : _backingType : _styleMask : screenNumber];
_windowNum =
[srv window: _frame
: _backingType
: _styleMask
: screenNumber];
[srv setwindowlevel: [self level] : _windowNum]; [srv setwindowlevel: [self level] : _windowNum];
NSMapInsert (windowmaps, (void*)_windowNum, self); NSMapInsert (windowmaps, (void*)_windowNum, self);
@ -745,9 +689,9 @@ many times.
_gstate = GSDefineGState(context); _gstate = GSDefineGState(context);
DPSgrestore(context); DPSgrestore(context);
frame = [NSWindow contentRectForFrameRect: frame styleMask: _styleMask];
if (NSIsEmptyRect([_wv frame])) if (NSIsEmptyRect([_wv frame]))
{ {
NSRect frame = _frame;
frame.origin = NSZeroPoint; frame.origin = NSZeroPoint;
[_wv setFrame: frame]; [_wv setFrame: frame];
} }
@ -783,8 +727,6 @@ many times.
} }
/* Other stuff we need to do for deferred windows */ /* Other stuff we need to do for deferred windows */
if (_windowTitle != nil)
[srv titlewindow: _windowTitle : _windowNum];
if (!NSEqualSizes(_minimumSize, NSZeroSize)) if (!NSEqualSizes(_minimumSize, NSZeroSize))
[self setMinSize: _minimumSize]; [self setMinSize: _minimumSize];
if (!NSEqualSizes(_maximumSize, NSZeroSize)) if (!NSEqualSizes(_maximumSize, NSZeroSize))
@ -792,7 +734,9 @@ many times.
if (!NSEqualSizes(_increments, NSZeroSize)) if (!NSEqualSizes(_increments, NSZeroSize))
[self setResizeIncrements: _increments]; [self setResizeIncrements: _increments];
NSDebugLLog(@"NSWindow", @"Created NSWindow frame %@", [_wv setWindowNumber: _windowNum];
NSDebugLLog(@"NSWindow", @"Created NSWindow window frame %@",
NSStringFromRect(_frame)); NSStringFromRect(_frame));
} }
@ -868,6 +812,9 @@ many times.
windowmaps = NSCreateMapTable(NSIntMapKeyCallBacks, windowmaps = NSCreateMapTable(NSIntMapKeyCallBacks,
NSNonRetainedObjectMapValueCallBacks, 20); NSNonRetainedObjectMapValueCallBacks, 20);
if (!windowDecorator)
windowDecorator = [GSWindowDecorationView windowDecorator];
/* Initialize attributes and flags */ /* Initialize attributes and flags */
[super init]; [super init];
[self _initDefaults]; [self _initDefaults];
@ -881,7 +828,7 @@ many times.
_frame = [NSWindow frameRectForContentRect: contentRect styleMask: aStyle]; _frame = [NSWindow frameRectForContentRect: contentRect styleMask: aStyle];
_minimumSize = NSMakeSize(_frame.size.width - contentRect.size.width + 1, _minimumSize = NSMakeSize(_frame.size.width - contentRect.size.width + 1,
_frame.size.height - contentRect.size.height + 1); _frame.size.height - contentRect.size.height + 1);
_maximumSize = NSMakeSize (10e4, 10e4); _maximumSize = NSMakeSize (10e4, 10e4);
[self setNextResponder: NSApp]; [self setNextResponder: NSApp];
@ -891,8 +838,9 @@ many times.
/* Create the window view */ /* Create the window view */
cframe.origin = NSZeroPoint; cframe.origin = NSZeroPoint;
cframe.size = contentRect.size; cframe.size = _frame.size;
_wv = [[GSWindowView allocWithZone: [self zone]] initWithFrame: cframe]; _wv = [windowDecorator newWindowDecorationViewWithFrame: cframe
window: self];
[_wv viewWillMoveToWindow: self]; [_wv viewWillMoveToWindow: self];
/* Create the content view */ /* Create the content view */
@ -911,15 +859,28 @@ many times.
if (flag == NO) if (flag == NO)
{ {
NSDebugLLog(@"NSWindow", @"Creating NSWindow\n"); NSDebugLLog(@"NSWindow", @"Creating NSWindow\n");
[self _initBackendWindow: _frame]; [self _initBackendWindow];
} }
else else
NSDebugLLog(@"NSWindow", @"Defering NSWindow creation\n"); NSDebugLLog(@"NSWindow", @"Deferring NSWindow creation\n");
[nc addObserver: self
selector: @selector(colorListChanged:)
name: NSColorListChangedNotification
object: nil];
NSDebugLLog(@"NSWindow", @"NSWindow end of init\n"); NSDebugLLog(@"NSWindow", @"NSWindow end of init\n");
return self; return self;
} }
-(void) colorListChanged:(NSNotification*)notif
{
if ([[notif object] isEqual: [NSColorList colorListNamed:@"System"]])
{
[_wv setNeedsDisplay:YES];
}
}
/* /*
* Accessing the content view * Accessing the content view
*/ */
@ -935,21 +896,18 @@ many times.
{ {
if (aView == nil) if (aView == nil)
{ {
aView = AUTORELEASE([[NSView alloc] initWithFrame: _frame]); aView = AUTORELEASE([[NSView alloc]
initWithFrame:
[NSWindow contentRectForFrameRect: _frame
styleMask: _styleMask]]);
} }
if (_contentView != nil) if (_contentView != nil)
{ {
[_contentView removeFromSuperview]; [_contentView removeFromSuperview];
} }
_contentView = aView; _contentView = aView;
[_contentView setAutoresizingMask: (NSViewWidthSizable
| NSViewHeightSizable)];
[_wv addSubview: _contentView];
[_contentView resizeWithOldSuperviewSize: [_contentView frame].size];
[_contentView setFrameOrigin: [_wv bounds].origin];
NSAssert1 ([[_wv subviews] count] == 1, [_wv setContentView: _contentView];
@"window's view has %d subviews!", [[_wv subviews] count]);
[_contentView setNextResponder: self]; [_contentView setNextResponder: self];
} }
@ -982,14 +940,13 @@ many times.
{ {
if ([_windowTitle isEqual: aString] == NO) if ([_windowTitle isEqual: aString] == NO)
{ {
ASSIGN(_windowTitle, aString); ASSIGNCOPY(_windowTitle, aString);
[self setMiniwindowTitle: aString]; [self setMiniwindowTitle: _windowTitle];
if (_windowNum > 0) [_wv setTitle: _windowTitle];
[GSServerForWindow(self) titlewindow: aString : _windowNum];
if (_f.menu_exclude == NO && _f.has_opened == YES) if (_f.menu_exclude == NO && _f.has_opened == YES)
{ {
[NSApp changeWindowsItem: self [NSApp changeWindowsItem: self
title: aString title: _windowTitle
filename: NO]; filename: NO];
} }
} }
@ -1003,14 +960,13 @@ many times.
[aString stringByDeletingLastPathComponent]]; [aString stringByDeletingLastPathComponent]];
if ([_windowTitle isEqual: aString] == NO) if ([_windowTitle isEqual: aString] == NO)
{ {
ASSIGN(_windowTitle, aString); ASSIGNCOPY(_windowTitle, aString);
[self setMiniwindowTitle: aString]; [self setMiniwindowTitle: _windowTitle];
if (_windowNum > 0) [_wv setTitle: _windowTitle];
[GSServerForWindow(self) titlewindow: aString : _windowNum];
if (_f.menu_exclude == NO && _f.has_opened == YES) if (_f.menu_exclude == NO && _f.has_opened == YES)
{ {
[NSApp changeWindowsItem: self [NSApp changeWindowsItem: self
title: aString title: _windowTitle
filename: YES]; filename: YES];
} }
} }
@ -1241,7 +1197,7 @@ many times.
[_firstResponder becomeKeyWindow]; [_firstResponder becomeKeyWindow];
} }
[GSServerForWindow(self) setinputstate: GSTitleBarKey : _windowNum]; [_wv setInputState: GSTitleBarKey];
[GSServerForWindow(self) setinputfocus: _windowNum]; [GSServerForWindow(self) setinputfocus: _windowNum];
[self resetCursorRects]; [self resetCursorRects];
[nc postNotificationName: NSWindowDidBecomeKeyNotification object: self]; [nc postNotificationName: NSWindowDidBecomeKeyNotification object: self];
@ -1256,7 +1212,7 @@ many times.
_f.is_main = YES; _f.is_main = YES;
if (_f.is_key == NO) if (_f.is_key == NO)
{ {
[GSServerForWindow(self) setinputstate: GSTitleBarMain : _windowNum]; [_wv setInputState: GSTitleBarMain];
} }
[nc postNotificationName: NSWindowDidBecomeMainNotification object: self]; [nc postNotificationName: NSWindowDidBecomeMainNotification object: self];
NSDebugLLog(@"NSWindow", @"%@ is now main window", [self title]); NSDebugLLog(@"NSWindow", @"%@ is now main window", [self title]);
@ -1454,7 +1410,7 @@ many times.
&& [NSApp isHidden] == NO && [NSApp isHidden] == NO
&& _f.visible == NO) && _f.visible == NO)
{ {
NSRect nframe = [self constrainFrameRect: _frame NSRect nframe = [self constrainFrameRect: _frame
toScreen: [self screen]]; toScreen: [self screen]];
if (_windowNum) if (_windowNum)
[self setFrame: nframe display: NO]; [self setFrame: nframe display: NO];
@ -1464,16 +1420,16 @@ many times.
// create deferred window // create deferred window
if (_windowNum == 0) if (_windowNum == 0)
{ {
[self _initBackendWindow: _frame]; [self _initBackendWindow];
display = YES; display = YES;
} }
} }
// Draw content before backend window ordering // Draw content before backend window ordering
if (display) if (display)
[_contentView display]; [_wv display];
else if (place != NSWindowOut) else if (place != NSWindowOut)
[_contentView displayIfNeeded]; [_wv displayIfNeeded];
/* The backend will keep us below the current key window unless we /* The backend will keep us below the current key window unless we
force it not too */ force it not too */
@ -1520,7 +1476,7 @@ many times.
} }
if ([self isKeyWindow] == YES) if ([self isKeyWindow] == YES)
{ {
[srv setinputstate: GSTitleBarKey : _windowNum]; [_wv setInputState: GSTitleBarKey];
[srv setinputfocus: _windowNum]; [srv setinputfocus: _windowNum];
} }
_f.visible = YES; _f.visible = YES;
@ -1543,12 +1499,11 @@ many times.
if (_f.is_main == YES) if (_f.is_main == YES)
{ {
[GSServerForWindow(self) setinputstate: GSTitleBarMain : _windowNum]; [_wv setInputState: GSTitleBarMain];
} }
else else
{ {
[GSServerForWindow(self) setinputstate: GSTitleBarNormal [_wv setInputState: GSTitleBarNormal];
: _windowNum];
} }
[self discardCursorRects]; [self discardCursorRects];
@ -1563,13 +1518,11 @@ many times.
_f.is_main = NO; _f.is_main = NO;
if (_f.is_key == YES) if (_f.is_key == YES)
{ {
[GSServerForWindow(self) setinputstate: GSTitleBarKey [_wv setInputState: GSTitleBarKey];
: _windowNum];
} }
else else
{ {
[GSServerForWindow(self) setinputstate: GSTitleBarNormal [_wv setInputState: GSTitleBarNormal];
: _windowNum];
} }
[nc postNotificationName: NSWindowDidResignMainNotification object: self]; [nc postNotificationName: NSWindowDidResignMainNotification object: self];
} }
@ -1774,8 +1727,6 @@ many times.
else else
{ {
_frame = frameRect; _frame = frameRect;
frameRect = [NSWindow contentRectForFrameRect: frameRect
styleMask: _styleMask];
frameRect.origin = NSZeroPoint; frameRect.origin = NSZeroPoint;
[_wv setFrame: frameRect]; [_wv setFrame: frameRect];
} }
@ -1855,14 +1806,9 @@ many times.
*/ */
- (NSPoint) convertBaseToScreen: (NSPoint)aPoint - (NSPoint) convertBaseToScreen: (NSPoint)aPoint
{ {
GSDisplayServer *srv = GSCurrentServer(); NSPoint screenPoint;
NSPoint screenPoint; screenPoint.x = _frame.origin.x + aPoint.x;
float t, b, l, r; screenPoint.y = _frame.origin.y + aPoint.y;
[srv styleoffsets: &l : &r : &t : &b : _styleMask];
screenPoint.x = _frame.origin.x + aPoint.x + l;
screenPoint.y = _frame.origin.y + aPoint.y + b;
return screenPoint; return screenPoint;
} }
@ -1872,14 +1818,9 @@ many times.
*/ */
- (NSPoint) convertScreenToBase: (NSPoint)aPoint - (NSPoint) convertScreenToBase: (NSPoint)aPoint
{ {
GSDisplayServer *srv = GSCurrentServer(); NSPoint basePoint;
NSPoint basePoint; basePoint.x = aPoint.x - _frame.origin.x;
float t, b, l, r; basePoint.y = aPoint.y - _frame.origin.y;
[srv styleoffsets: &l : &r : &t : &b : _styleMask];
basePoint.x = aPoint.x - _frame.origin.x - l;
basePoint.y = aPoint.y - _frame.origin.y - b;
return basePoint; return basePoint;
} }
@ -2320,7 +2261,7 @@ resetCursorRectsForView(NSView *theView)
/* Make sure we're not defered */ /* Make sure we're not defered */
if (_windowNum == 0) if (_windowNum == 0)
{ {
[self _initBackendWindow: _frame]; [self _initBackendWindow];
} }
/* /*
* Ensure that we have a miniwindow counterpart. * Ensure that we have a miniwindow counterpart.
@ -2460,8 +2401,7 @@ resetCursorRectsForView(NSView *theView)
{ {
[NSApp updateWindowsItem: self]; [NSApp updateWindowsItem: self];
} }
if (_windowNum) [_wv setDocumentEdited: flag];
[GSServerForWindow(self) docedited: flag : _windowNum];
} }
} }
@ -2879,7 +2819,8 @@ resetCursorRectsForView(NSView *theView)
/** Handles mouse and other events sent to the receiver by NSApplication. /** Handles mouse and other events sent to the receiver by NSApplication.
Do not invoke this method directly. Do not invoke this method directly.
*/ */
- (void) sendEvent: (NSEvent*)theEvent - (void) _sendEvent: (NSEvent*)theEvent
becomesKeyOnlyIfNeeded: (BOOL)becomesKeyOnlyIfNeeded
{ {
NSView *v; NSView *v;
NSEventType type; NSEventType type;
@ -2906,18 +2847,17 @@ resetCursorRectsForView(NSView *theView)
switch (type) switch (type)
{ {
case NSLeftMouseDown: case NSLeftMouseDown:
/*
Code shared with [NSPanel -sendEvent:], remember to update both places.
*/
{ {
BOOL wasKey = _f.is_key; BOOL wasKey = _f.is_key;
if (_f.has_closed == NO) if (_f.has_closed == NO)
{ {
v = [_contentView hitTest: [theEvent locationInWindow]]; v = [_wv hitTest: [theEvent locationInWindow]];
if (_f.is_key == NO && _windowLevel != NSDesktopWindowLevel) if (_f.is_key == NO && _windowLevel != NSDesktopWindowLevel)
{ {
[self makeKeyAndOrderFront: self]; /* NSPanel modification: check becomesKeyOnlyIfNeeded. */
if (!becomesKeyOnlyIfNeeded || [v needsPanelToBecomeKey])
[self makeKeyAndOrderFront: self];
} }
/* Activate the app *after* making the receiver key, as app /* Activate the app *after* making the receiver key, as app
activation tries to make the previous key window key. */ activation tries to make the previous key window key. */
@ -2964,27 +2904,27 @@ Code shared with [NSPanel -sendEvent:], remember to update both places.
break; break;
case NSOtherMouseDown: case NSOtherMouseDown:
v = [_contentView hitTest: [theEvent locationInWindow]]; v = [_wv hitTest: [theEvent locationInWindow]];
[v otherMouseDown: theEvent]; [v otherMouseDown: theEvent];
_lastPoint = [theEvent locationInWindow]; _lastPoint = [theEvent locationInWindow];
break; break;
case NSOtherMouseUp: case NSOtherMouseUp:
v = [_contentView hitTest: [theEvent locationInWindow]]; v = [_wv hitTest: [theEvent locationInWindow]];
[v otherMouseUp: theEvent]; [v otherMouseUp: theEvent];
_lastPoint = [theEvent locationInWindow]; _lastPoint = [theEvent locationInWindow];
break; break;
case NSRightMouseDown: case NSRightMouseDown:
{ {
v = [_contentView hitTest: [theEvent locationInWindow]]; v = [_wv hitTest: [theEvent locationInWindow]];
[v rightMouseDown: theEvent]; [v rightMouseDown: theEvent];
_lastPoint = [theEvent locationInWindow]; _lastPoint = [theEvent locationInWindow];
} }
break; break;
case NSRightMouseUp: case NSRightMouseUp:
v = [_contentView hitTest: [theEvent locationInWindow]]; v = [_wv hitTest: [theEvent locationInWindow]];
[v rightMouseUp: theEvent]; [v rightMouseUp: theEvent];
_lastPoint = [theEvent locationInWindow]; _lastPoint = [theEvent locationInWindow];
break; break;
@ -2996,15 +2936,15 @@ Code shared with [NSPanel -sendEvent:], remember to update both places.
switch (type) switch (type)
{ {
case NSLeftMouseDragged: case NSLeftMouseDragged:
v = [_contentView hitTest: [theEvent locationInWindow]]; v = [_wv hitTest: [theEvent locationInWindow]];
[v mouseDragged: theEvent]; [v mouseDragged: theEvent];
break; break;
case NSOtherMouseDragged: case NSOtherMouseDragged:
v = [_contentView hitTest: [theEvent locationInWindow]]; v = [_wv hitTest: [theEvent locationInWindow]];
[v otherMouseDragged: theEvent]; [v otherMouseDragged: theEvent];
break; break;
case NSRightMouseDragged: case NSRightMouseDragged:
v = [_contentView hitTest: [theEvent locationInWindow]]; v = [_wv hitTest: [theEvent locationInWindow]];
[v rightMouseDragged: theEvent]; [v rightMouseDragged: theEvent];
break; break;
default: default:
@ -3014,7 +2954,7 @@ Code shared with [NSPanel -sendEvent:], remember to update both places.
* If the window is set to accept mouse movements, we need to * If the window is set to accept mouse movements, we need to
* forward the mouse movement to the correct view. * forward the mouse movement to the correct view.
*/ */
v = [_contentView hitTest: [theEvent locationInWindow]]; v = [_wv hitTest: [theEvent locationInWindow]];
[v mouseMoved: theEvent]; [v mouseMoved: theEvent];
} }
break; break;
@ -3035,7 +2975,7 @@ Code shared with [NSPanel -sendEvent:], remember to update both places.
* cursor update event. * cursor update event.
*/ */
if (_f.cursor_rects_enabled) if (_f.cursor_rects_enabled)
(*ccImp)(self, ccSel, _contentView, theEvent); (*ccImp)(self, ccSel, _wv, theEvent);
} }
_lastPoint = [theEvent locationInWindow]; _lastPoint = [theEvent locationInWindow];
@ -3074,7 +3014,7 @@ Code shared with [NSPanel -sendEvent:], remember to update both places.
break; break;
case NSScrollWheel: case NSScrollWheel:
v = [_contentView hitTest: [theEvent locationInWindow]]; v = [_wv hitTest: [theEvent locationInWindow]];
[v scrollWheel: theEvent]; [v scrollWheel: theEvent];
break; break;
@ -3113,8 +3053,6 @@ Code shared with [NSPanel -sendEvent:], remember to update both places.
{ {
NSRect rect = _frame; NSRect rect = _frame;
rect = [NSWindow contentRectForFrameRect: rect
styleMask: _styleMask];
rect.origin = NSZeroPoint; rect.origin = NSZeroPoint;
[_wv setFrame: rect]; [_wv setFrame: rect];
[_wv setNeedsDisplay: YES]; [_wv setNeedsDisplay: YES];
@ -3179,7 +3117,7 @@ Code shared with [NSPanel -sendEvent:], remember to update both places.
* to determine if we should send a cursor update * to determine if we should send a cursor update
* event. */ * event. */
if (_f.cursor_rects_enabled) if (_f.cursor_rects_enabled)
(*ccImp)(self, ccSel, _contentView, theEvent); (*ccImp)(self, ccSel, _wv, theEvent);
} }
_lastPoint = NSMakePoint(-1, -1); _lastPoint = NSMakePoint(-1, -1);
@ -3243,7 +3181,7 @@ Code shared with [NSPanel -sendEvent:], remember to update both places.
{ {
BOOL isEntry; BOOL isEntry;
v = [_contentView hitTest: [theEvent locationInWindow]]; v = [_wv hitTest: [theEvent locationInWindow]];
while (v != nil && ((NSViewPtr)v)->_rFlags.has_draginfo == 0) while (v != nil && ((NSViewPtr)v)->_rFlags.has_draginfo == 0)
{ {
v = [v superview]; v = [v superview];
@ -3379,6 +3317,16 @@ Code shared with [NSPanel -sendEvent:], remember to update both places.
} }
} }
/** Handles mouse and other events sent to the receiver by NSApplication.
Do not invoke this method directly.
*/
- (void) sendEvent: (NSEvent*)theEvent
{
[self _sendEvent: theEvent
becomesKeyOnlyIfNeeded: NO];
}
- (BOOL) tryToPerform: (SEL)anAction with: (id)anObject - (BOOL) tryToPerform: (SEL)anAction with: (id)anObject
{ {
if ([super tryToPerform: anAction with: anObject]) if ([super tryToPerform: anAction with: anObject])
@ -3784,24 +3732,24 @@ Code shared with [NSPanel -sendEvent:], remember to update both places.
*/ */
- (NSData *) dataWithEPSInsideRect: (NSRect)rect - (NSData *) dataWithEPSInsideRect: (NSRect)rect
{ {
return [_contentView dataWithEPSInsideRect: return [_wv dataWithEPSInsideRect:
[_contentView convertRect: rect fromView: nil]]; [_wv convertRect: rect fromView: nil]];
} }
- (NSData *)dataWithPDFInsideRect:(NSRect)aRect - (NSData *)dataWithPDFInsideRect:(NSRect)aRect
{ {
return [_contentView dataWithPDFInsideRect: return [_wv dataWithPDFInsideRect:
[_contentView convertRect: aRect fromView: nil]]; [_wv convertRect: aRect fromView: nil]];
} }
- (void) fax: (id)sender - (void) fax: (id)sender
{ {
[_contentView fax: sender]; [_wv fax: sender];
} }
- (void) print: (id)sender - (void) print: (id)sender
{ {
[_contentView print: sender]; [_wv print: sender];
} }
/* /*
@ -4116,18 +4064,6 @@ Code shared with [NSPanel -sendEvent:], remember to update both places.
[GSCurrentServer() releasemouse]; [GSCurrentServer() releasemouse];
} }
- (void) setContentViewSize: (NSSize)aSize
{
NSRect r;
r.origin = NSZeroPoint;
r.size = aSize;
if (_contentView)
{
[_contentView setFrame: r];
}
}
- (void) _setVisible: (BOOL)flag - (void) _setVisible: (BOOL)flag
{ {
_f.visible = flag; _f.visible = flag;