mirror of
https://github.com/darlinghq/darling-glut.git
synced 2024-11-27 06:01:15 +00:00
676 lines
21 KiB
Objective-C
676 lines
21 KiB
Objective-C
|
|
/* Copyright (c) Dietmar Planitzer, 1998, 2002 - 2003 */
|
|
|
|
/* This program is freely distributable without licensing fees
|
|
and is provided without guarantee or warrantee expressed or
|
|
implied. This program is -not- in the public domain. */
|
|
|
|
#import "macx_glut.h"
|
|
#import "GLUTWindow.h"
|
|
#import "GLUTView.h"
|
|
#import "GLUTApplication.h"
|
|
|
|
|
|
NSString *GLUTWindowFrame = @"GLUTWindowFrame";
|
|
|
|
|
|
@interface GLUTView(GLUTPrivate)
|
|
- (void)_commonReshape;
|
|
@end
|
|
|
|
|
|
@interface GLUTWindow(GLUTPrivate)
|
|
- (id)_initWithContentRect: (NSRect)rect styleMask: (unsigned int)mask contentView: (GLUTView *)aView;
|
|
- (id)_initWithWindow: (GLUTWindow *)aWindow operation: (int)op arguments: (NSDictionary *)operands;
|
|
- (NSWindow *)_windowWithTIFFInsideRect: (NSRect)rect;
|
|
- (NSData *)_dataWithTIFFOfContentView;
|
|
- (NSData *)_dataWithRTFDOfContentView;
|
|
@end
|
|
|
|
|
|
/////////////////////////////////////////////
|
|
#pragma mark -
|
|
|
|
|
|
@implementation GLUTWindow
|
|
|
|
static BOOL gInitialized = NO;
|
|
static NSArray * gServicesTypes = nil;
|
|
|
|
|
|
+ (void)initialize
|
|
{
|
|
if(!gInitialized) {
|
|
gInitialized = YES;
|
|
|
|
gServicesTypes = [[NSArray arrayWithObjects: NSTIFFPboardType, NSRTFDPboardType, nil] retain];
|
|
[NSApp registerServicesMenuSendTypes: gServicesTypes returnTypes: nil];
|
|
}
|
|
}
|
|
|
|
+ (id)windowByMorphingWindow: (GLUTWindow *)aWindow operation: (int)op arguments: (NSDictionary *)dict
|
|
{
|
|
return [[[self alloc] _initWithWindow: aWindow operation: op arguments: dict] autorelease];
|
|
}
|
|
|
|
|
|
/* Designated initializer */
|
|
- (id)_initWithContentRect: (NSRect)rect styleMask: (unsigned int)mask contentView: (GLUTView *)aView
|
|
{
|
|
if((self = [super initWithContentRect: rect styleMask: mask backing: NSBackingStoreBuffered defer: NO]) != nil) {
|
|
[self setReleasedWhenClosed: NO];
|
|
[self setMinSize: NSMakeSize(80.0, 80.0)];
|
|
[self setShowsResizeIndicator:NO]; // turn off the grow box.
|
|
[self setContentView: aView];
|
|
[self makeFirstResponder: aView];
|
|
[self setDelegate: self];
|
|
return self;
|
|
}
|
|
return nil;
|
|
}
|
|
|
|
- (id)initWithContentRect: (NSRect)rect pixelFormat: (NSOpenGLPixelFormat *)pixelFormat
|
|
windowID: (int)winid gameMode: (BOOL)gameMode fullscreenStereo: (BOOL)pfStereo treatAsSingle: (BOOL)treatAsSingle
|
|
{
|
|
unsigned int mask;
|
|
GLUTView * view = nil;
|
|
|
|
if(gameMode) { // set to fill screen
|
|
float offsetY = 0.0f;
|
|
/* XXX NSScreen BUG WORKAROUND
|
|
The purpose of the following code is to workaround a bug in the NSScreen class.
|
|
The problem is that this class doesn't realize that we switched from the original
|
|
screen mode to another mode via the CGDisplaySwitchToMode() function and thus
|
|
keeps on reporting now out-dated screen attributes like screen width & height.
|
|
This however has the unfortunate consequence that our NSWindow would be positioned
|
|
incorrectly if the new mode has a smaller Y resolution than the old one. I.e.
|
|
if the old Y res was 870 and the new is 480 the window would be placed by 390 pixels
|
|
too far below.
|
|
*/
|
|
NSScreen * screen = [[NSScreen screens] objectAtIndex: 0];
|
|
NSSize screenSize = [screen frame].size;
|
|
|
|
if(screenSize.height - rect.size.height > 0.0f)
|
|
offsetY = screenSize.height - rect.size.height;
|
|
rect.origin.y = offsetY;
|
|
mask = NSBorderlessWindowMask;
|
|
} else {
|
|
mask = (NSTitledWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask);
|
|
}
|
|
|
|
/* create and configure content view */
|
|
view = [[[GLUTView alloc] initWithFrame: rect
|
|
pixelFormat: pixelFormat
|
|
windowID: winid
|
|
treatAsSingle: treatAsSingle
|
|
isSubwindow: NO
|
|
fullscreenStereo:pfStereo
|
|
isVBLSynced: __glutSyncToVBL] autorelease];
|
|
if(view)
|
|
return [self _initWithContentRect: rect styleMask: mask contentView: view];
|
|
else
|
|
return nil;
|
|
}
|
|
|
|
- (id)_initWithWindow: (GLUTWindow *)aWindow operation: (int)op arguments: (NSDictionary *)dict
|
|
{
|
|
GLUTView * contentView = nil;
|
|
NSResponder * savedFirstResponder;
|
|
NSRect rect = {{0.0f, 0.0f}, {0.0f, 0.0f}};
|
|
unsigned int mask = 0;
|
|
int level = 0;
|
|
|
|
switch(op) {
|
|
case kGLUTMorphOperationFullscreen:
|
|
/* Make a fullscreen window */
|
|
if (NO == __glutUseExtendedDesktop) {
|
|
rect = [[aWindow screen] frame];
|
|
} else { // look at all screens
|
|
NSEnumerator *enumerator = [[NSScreen screens] objectEnumerator];
|
|
NSScreen * screen = nil;
|
|
while (nil != (screen = (NSScreen *)[enumerator nextObject])) {
|
|
if([screen frame].origin.x < rect.origin.x)
|
|
rect.origin.x = [screen frame].origin.x;
|
|
if([screen frame].origin.y < rect.origin.y)
|
|
rect.origin.y = [screen frame].origin.y;
|
|
if(([screen frame].origin.x + [screen frame].size.width - rect.origin.x) > rect.size.width)
|
|
rect.size.width = [screen frame].origin.x + [screen frame].size.width - rect.origin.x;
|
|
if(([screen frame].origin.y + [screen frame].size.height - rect.origin.y) > rect.size.height)
|
|
rect.size.height = [screen frame].origin.y + [screen frame].size.height - rect.origin.y;
|
|
}
|
|
}
|
|
mask = NSBorderlessWindowMask;
|
|
level = GLUT_FULLSCREEN_LEVEL;
|
|
|
|
break;
|
|
|
|
case kGLUTMorphOperationRegular:
|
|
/* Make a standard window */
|
|
rect = [[dict objectForKey: GLUTWindowFrame] rectValue];
|
|
mask = (NSTitledWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask);
|
|
level = GLUT_NORMAL_LEVEL;
|
|
break;
|
|
}
|
|
|
|
savedFirstResponder = [aWindow firstResponder];
|
|
contentView = (GLUTView *) [[aWindow contentView] retain];
|
|
[contentView recursiveWillBeginMorph: op];
|
|
[aWindow setContentView: nil];
|
|
|
|
if((self = [self _initWithContentRect: rect styleMask: mask contentView: contentView]) != nil) {
|
|
[self setLevel: level];
|
|
|
|
switch(op) {
|
|
case kGLUTMorphOperationFullscreen: // new window is full screen
|
|
_isFullscreen = YES;
|
|
/* put window on fullscreen window list */
|
|
_nextFullscreenWindow = __glutFullscreenWindows;
|
|
__glutFullscreenWindows = self;
|
|
break;
|
|
case kGLUTMorphOperationRegular: // new window is not full screen
|
|
_isFullscreen = NO;
|
|
break;
|
|
}
|
|
|
|
|
|
_imagePath = [aWindow->_imagePath copy];
|
|
_enabledMouseMovedEvents = aWindow->_enabledMouseMovedEvents;
|
|
if(_enabledMouseMovedEvents > 0)
|
|
[self setAcceptsMouseMovedEvents: YES];
|
|
[contentView recursiveDidEndMorph: op];
|
|
[self makeFirstResponder: savedFirstResponder];
|
|
// Call _commonReshape on the window's content view in order
|
|
// to simulate a resize event (we don't automatically get one
|
|
// because we just moved the content view from one window to
|
|
// to another one...)
|
|
[contentView _commonReshape];
|
|
[contentView release];
|
|
|
|
return self;
|
|
}
|
|
return nil;
|
|
}
|
|
|
|
- (void)dealloc
|
|
{
|
|
// remove from full screen window list
|
|
if(_isFullscreen) {
|
|
GLUTWindow * prev = nil;
|
|
GLUTWindow * cur = __glutFullscreenWindows;
|
|
|
|
while(cur != nil && cur != self) {
|
|
prev = cur;
|
|
cur = cur->_nextFullscreenWindow;
|
|
}
|
|
|
|
if(prev)
|
|
prev->_nextFullscreenWindow = _nextFullscreenWindow;
|
|
else
|
|
__glutFullscreenWindows = _nextFullscreenWindow;
|
|
}
|
|
|
|
[super dealloc];
|
|
}
|
|
|
|
- (void)finalize
|
|
{
|
|
if(_isFullscreen) {
|
|
GLUTWindow * prev = nil;
|
|
GLUTWindow * cur = __glutFullscreenWindows;
|
|
while(cur != nil && cur != self) {
|
|
prev = cur;
|
|
cur = cur->_nextFullscreenWindow;
|
|
}
|
|
if(prev)
|
|
prev->_nextFullscreenWindow = _nextFullscreenWindow;
|
|
else
|
|
__glutFullscreenWindows = _nextFullscreenWindow;
|
|
}
|
|
[super finalize];
|
|
}
|
|
|
|
- (BOOL)isFullscreen
|
|
{
|
|
return _isFullscreen;
|
|
}
|
|
|
|
/* Returns YES if the window 'me' is either above or below the frame rectangle
|
|
of any fullscreen window and NO otherwise */
|
|
- (BOOL)isAffectedByFullscreenWindow
|
|
{
|
|
NSRect frame = [self frame];
|
|
GLUTWindow * cur = __glutFullscreenWindows;
|
|
|
|
while(cur != nil) {
|
|
NSRect othFrame = [cur frame];
|
|
|
|
if(NSContainsRect(othFrame, frame) ||
|
|
NSEqualRects(othFrame, frame) ||
|
|
NSIntersectsRect(othFrame, frame))
|
|
return YES;
|
|
|
|
cur = cur->_nextFullscreenWindow;
|
|
}
|
|
return NO;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////
|
|
#pragma mark -
|
|
#pragma mark Events
|
|
#pragma mark -
|
|
|
|
|
|
- (void)enableMouseMovedEvents
|
|
{
|
|
_enabledMouseMovedEvents++;
|
|
if(_enabledMouseMovedEvents == 1)
|
|
[self setAcceptsMouseMovedEvents: YES];
|
|
}
|
|
|
|
- (void)disableMouseMovedEvents
|
|
{
|
|
NSAssert(_enabledMouseMovedEvents >= 0, @"bogus -disableMouseMovedEvents");
|
|
_enabledMouseMovedEvents--;
|
|
if(_enabledMouseMovedEvents == 0)
|
|
[self setAcceptsMouseMovedEvents: NO];
|
|
}
|
|
|
|
- (BOOL)canBecomeKeyWindow
|
|
{
|
|
return (!__glutGameModeWindow && !_isFullscreen) ? [super canBecomeKeyWindow] : YES;
|
|
}
|
|
|
|
- (void)sendEvent: (NSEvent *)event
|
|
{
|
|
[super sendEvent: event];
|
|
if(__glutMappedMenu) {
|
|
/* use mapped menu to determine if menu finishing needs to be done, regardless of button */
|
|
__glutFinishMenu([NSEvent mouseLocation]); /* sets mapped menu to nil */
|
|
__glutMenuWindow = nil;
|
|
}
|
|
}
|
|
|
|
- (BOOL)validateMenuItem: (NSMenuItem *)menuItem
|
|
{
|
|
SEL action = [menuItem action];
|
|
|
|
if(action == @selector(save:) || action == @selector(saveAs:))
|
|
return (!__glutDisableGrabbing) ? [self isDocumentEdited] : NO;
|
|
|
|
if(action == @selector(copy:))
|
|
return (!__glutDisableGrabbing);
|
|
|
|
if(__glutDisablePrinting) {
|
|
if(action == @selector(runPageLayout:) || action == @selector(print:))
|
|
return NO;
|
|
}
|
|
return [super validateMenuItem: menuItem];
|
|
}
|
|
|
|
- (IBAction)save: (id)sender
|
|
{
|
|
if(_imagePath) {
|
|
NSData * data = [self contentsAsDataOfType: NSTIFFPboardType];
|
|
|
|
if(!data || !__glutWriteDataToFile(data, _imagePath, 'TIFF')) {
|
|
NSBundle * bdl = __glutGetFrameworkBundle();
|
|
|
|
NSRunCriticalAlertPanel(NSLocalizedStringFromTableInBundle(@"Save Error", @"GLUTUI",
|
|
bdl, @"Save Error"),
|
|
NSLocalizedStringFromTableInBundle(@"Unable to save current window contents.", @"GLUTUI",
|
|
bdl, @"Unable to save current window contents."),
|
|
@"OK", nil, nil);
|
|
}
|
|
[self setDocumentEdited: NO];
|
|
} else {
|
|
[self saveAs: sender];
|
|
}
|
|
}
|
|
|
|
/* Save As */
|
|
- (void)savePanelDidEnd: (NSWindow *)sheet returnCode: (int)returnCode contextInfo: (id)savePanel
|
|
{
|
|
if(returnCode == NSOKButton) {
|
|
NSData * data = [self contentsAsDataOfType: NSTIFFPboardType];
|
|
|
|
[_imagePath release];
|
|
_imagePath = [[savePanel filename] copy];
|
|
|
|
if(!data || !__glutWriteDataToFile(data, _imagePath, 'TIFF')) {
|
|
NSBundle * bdl = __glutGetFrameworkBundle();
|
|
|
|
NSRunCriticalAlertPanel(NSLocalizedStringFromTableInBundle(@"Save Error", @"GLUTUI",
|
|
bdl, @"Save Error"),
|
|
NSLocalizedStringFromTableInBundle(@"Unable to save current window contents.", @"GLUTUI",
|
|
bdl, @"Unable to save current window contents."),
|
|
@"OK", nil, nil);
|
|
}
|
|
|
|
[self setDocumentEdited: NO];
|
|
}
|
|
}
|
|
|
|
- (IBAction)saveAs: (id)sender
|
|
{
|
|
NSSavePanel * savePanel = [NSSavePanel savePanel];
|
|
NSString * imageDirectory, *imageName;
|
|
|
|
if(!_imagePath) {
|
|
_imagePath = [[[NSFileManager defaultManager] currentDirectoryPath] copy];
|
|
imageDirectory = _imagePath;
|
|
imageName = @"";
|
|
} else {
|
|
imageDirectory = _imagePath;
|
|
imageName = [[_imagePath lastPathComponent] stringByDeletingPathExtension];
|
|
}
|
|
|
|
[savePanel setCanSelectHiddenExtension: YES];
|
|
[savePanel setRequiredFileType: @"tiff"];
|
|
[savePanel beginSheetForDirectory: imageDirectory
|
|
file: imageName
|
|
modalForWindow: self
|
|
modalDelegate: self
|
|
didEndSelector: @selector(savePanelDidEnd:returnCode:contextInfo:)
|
|
contextInfo: savePanel];
|
|
}
|
|
|
|
- (IBAction)copy: (id)sender
|
|
{
|
|
NSString * type = NSTIFFPboardType;
|
|
NSData * imageData = [self contentsAsDataOfType: type];
|
|
|
|
if(imageData) {
|
|
NSPasteboard * generalPboard = [NSPasteboard generalPasteboard];
|
|
|
|
[generalPboard declareTypes: [NSArray arrayWithObjects: type, nil] owner: nil];
|
|
[generalPboard setData: imageData forType: type];
|
|
}
|
|
}
|
|
|
|
/* Page Layout */
|
|
- (void)pageLayoutDidEnd: (NSPageLayout *)pageLayout returnCode: (int)returnCode contextInfo: (id)printInfo
|
|
{
|
|
if(returnCode == NSOKButton) {
|
|
[NSPrintInfo setSharedPrintInfo: printInfo];
|
|
}
|
|
}
|
|
|
|
- (void)runPageLayout: (id)sender
|
|
{
|
|
NSPageLayout * pageLayout = [NSPageLayout pageLayout];
|
|
NSPrintInfo * printInfo = [NSPrintInfo sharedPrintInfo];
|
|
|
|
[pageLayout beginSheetWithPrintInfo: printInfo
|
|
modalForWindow: self
|
|
delegate: self
|
|
didEndSelector: @selector(pageLayoutDidEnd:returnCode:contextInfo:)
|
|
contextInfo: printInfo];
|
|
}
|
|
|
|
/* Print Panel */
|
|
- (void)printOperationDidRun: (NSPrintOperation *)printOperation success: (BOOL)success contextInfo: (id)window
|
|
{
|
|
[window release];
|
|
}
|
|
|
|
- (void)print: (id)sender
|
|
{
|
|
NSWindow * window = [[self _windowWithTIFFInsideRect: NSZeroRect] retain];
|
|
|
|
if(window) {
|
|
NSPrintOperation * printOperation = [NSPrintOperation printOperationWithView: [window contentView]];
|
|
|
|
[printOperation runOperationModalForWindow: self
|
|
delegate: self
|
|
didRunSelector: @selector(printOperationDidRun:success:contextInfo:)
|
|
contextInfo: window];
|
|
} else {
|
|
NSBundle * bdl = __glutGetFrameworkBundle();
|
|
|
|
NSRunCriticalAlertPanel(NSLocalizedStringFromTableInBundle(@"Print Error", @"GLUTUI",
|
|
bdl, @"Print Error"),
|
|
NSLocalizedStringFromTableInBundle(@"Could not generate PDF data for printing.", @"GLUTUI",
|
|
bdl, @"Could not generate PDF data for printing."),
|
|
@"OK", nil, nil);
|
|
}
|
|
}
|
|
|
|
- (void)zoom:(id)sender
|
|
{
|
|
NSMutableSet * views = [NSMutableSet set];
|
|
GLUTView * view = (GLUTView *) [self contentView];
|
|
|
|
[views unionSet: [view coveredViews]];
|
|
[views addObject: view];
|
|
|
|
[super zoom: sender];
|
|
|
|
[views unionSet: [view coveredViews]];
|
|
[GLUTView evaluateVisibilityOfViews: views];
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////
|
|
#pragma mark -
|
|
#pragma mark Services
|
|
#pragma mark -
|
|
|
|
|
|
- (id)validRequestorForSendType:(NSString *)sendType returnType:(NSString *)returnType
|
|
{
|
|
if([gServicesTypes containsObject: sendType])
|
|
return self;
|
|
|
|
return [super validRequestorForSendType: sendType returnType: returnType];
|
|
}
|
|
|
|
- (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard types:(NSArray *)types
|
|
{
|
|
unsigned i, count = [types count];
|
|
|
|
for(i = 0; i < count; i++) {
|
|
NSString * pboardType = [types objectAtIndex: i];
|
|
NSData * imageData = [self contentsAsDataOfType: pboardType];
|
|
|
|
if(imageData) {
|
|
[pboard declareTypes: [NSArray arrayWithObject: pboardType] owner: nil];
|
|
[pboard setData: imageData forType: pboardType];
|
|
return YES;
|
|
}
|
|
}
|
|
|
|
return NO;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////
|
|
#pragma mark -
|
|
#pragma mark Image Data Creation
|
|
#pragma mark -
|
|
|
|
|
|
- (NSWindow *)_windowWithTIFFInsideRect: (NSRect)rect
|
|
{
|
|
NSImage * image = nil;
|
|
NSImageView * imageView = nil;
|
|
NSWindow * window = nil;
|
|
GLUTView * view = (GLUTView *) [self contentView];
|
|
|
|
if(NSIsEmptyRect(rect))
|
|
rect = [view bounds];
|
|
|
|
if((imageView = [[NSImageView alloc] initWithFrame: rect]) == nil)
|
|
return nil;
|
|
|
|
if((window = [[NSWindow alloc] initWithContentRect: rect
|
|
styleMask: NSBorderlessWindowMask
|
|
backing: NSBackingStoreNonretained
|
|
defer: NO]) == nil) {
|
|
[imageView release];
|
|
return nil;
|
|
}
|
|
|
|
[window setContentView: imageView];
|
|
[imageView release];
|
|
|
|
if((image = [view imageWithTIFFInsideRect: rect]) == nil) {
|
|
[window release];
|
|
return nil;
|
|
}
|
|
[imageView setImage: image];
|
|
|
|
return [window autorelease];
|
|
}
|
|
|
|
- (NSData *)_dataWithTIFFOfContentView
|
|
{
|
|
NSImage * image = [(GLUTView *) [self contentView] imageWithTIFFInsideRect: NSZeroRect];
|
|
NSData * data = nil;
|
|
|
|
if(image != nil) {
|
|
data = [image TIFFRepresentation];
|
|
}
|
|
return data;
|
|
}
|
|
|
|
- (NSData *)_dataWithRTFDOfContentView
|
|
{
|
|
static int generationCounter = 1;
|
|
NSAttributedString * myString = nil;
|
|
NSFileWrapper * myFileWrapper = nil;
|
|
NSTextAttachment * myTextAttachment = nil;
|
|
NSData * tiffData = [self _dataWithTIFFOfContentView];
|
|
|
|
// create file wrapper
|
|
if((myFileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents: tiffData]) == nil)
|
|
return nil;
|
|
[myFileWrapper setPreferredFilename: [NSString stringWithFormat: @"GLUT Picture No.%d.tiff", generationCounter++]];
|
|
|
|
// create the text attachment
|
|
if((myTextAttachment = [[NSTextAttachment alloc] initWithFileWrapper: myFileWrapper]) == nil) {
|
|
[myFileWrapper release];
|
|
return nil;
|
|
}
|
|
[myFileWrapper release];
|
|
|
|
// create the attributed string
|
|
if((myString = [NSAttributedString attributedStringWithAttachment: myTextAttachment]) == nil) {
|
|
[myTextAttachment release];
|
|
return nil;
|
|
}
|
|
[myTextAttachment release];
|
|
|
|
// return the flattend data
|
|
return [myString RTFDFromRange: NSMakeRange(0, [myString length]) documentAttributes: nil];
|
|
}
|
|
|
|
/* Returns a data object containing the current contents of the receiving window */
|
|
- (NSData *)contentsAsDataOfType: (NSString *)pboardType
|
|
{
|
|
NSData * data = nil;
|
|
|
|
if([pboardType isEqualToString: NSTIFFPboardType] == YES) {
|
|
data = [self _dataWithTIFFOfContentView];
|
|
} else if([pboardType isEqualToString: NSRTFDPboardType] == YES) {
|
|
data = [self _dataWithRTFDOfContentView];
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////
|
|
#pragma mark -
|
|
#pragma mark Delegate
|
|
#pragma mark -
|
|
|
|
|
|
- (BOOL)windowShouldClose: (id)sender
|
|
{
|
|
GLUTView * view = (GLUTView *) [self contentView];
|
|
GLUTwmcloseCB closeFunc = [view wmCloseCallback];
|
|
|
|
/* Enable special behavior of glutDestroyWindow() while we're here */
|
|
__glutInsideWindowShouldClose = YES;
|
|
__glutShouldWindowClose = NO;
|
|
__glutSetWindow(view);
|
|
closeFunc();
|
|
__glutInsideWindowShouldClose = NO;
|
|
|
|
/* Only return with YES, if the application called glutDestroyWindow().
|
|
Return NO otherwise. */
|
|
return __glutShouldWindowClose;
|
|
}
|
|
|
|
/* Update the window status of the receiver and all of it's sub windows. */
|
|
- (void)windowWillMiniaturize:(NSNotification *)notification
|
|
{
|
|
GLUTView * view = (GLUTView *) [self contentView];
|
|
|
|
/* Miniaturizing a window with an OpenGL content view in it is a bit tricky,
|
|
because the OpenGL graphics is drawn in its own surface which floats above
|
|
the Quartz window and thus is not directly accessible to the latter.
|
|
In order to get around this, we tell our GLUTView to copy its OpenGL pixels
|
|
from its associated surface into its Quartz context. The copied pixels will
|
|
finally end up in the window's backing store where they can be easily
|
|
grabbed from by the window minaturization engine. */
|
|
[view prepareForMiniaturization];
|
|
_viewStorage = [[NSMutableSet alloc] init];
|
|
[_viewStorage unionSet: [view coveredViews]];
|
|
[_viewStorage addObject: view];
|
|
}
|
|
|
|
- (void)windowDidMiniaturize:(NSNotification *)notification
|
|
{
|
|
[GLUTView evaluateVisibilityOfViews: _viewStorage];
|
|
[_viewStorage release];
|
|
_viewStorage = nil;
|
|
[(GLUTView *) [self contentView] setShown: NO];
|
|
}
|
|
|
|
- (void)windowWillMove:(NSNotification *)notification
|
|
{
|
|
GLUTView * view = (GLUTView *) [self contentView];
|
|
|
|
_viewStorage = [[NSMutableSet alloc] init];
|
|
[_viewStorage unionSet: [view coveredViews]];
|
|
[_viewStorage addObject: view];
|
|
}
|
|
|
|
- (void)windowDidMove:(NSNotification *)notification
|
|
{
|
|
[_viewStorage unionSet: [(GLUTView *) [self contentView] coveredViews]];
|
|
[GLUTView evaluateVisibilityOfViews: _viewStorage];
|
|
[_viewStorage release];
|
|
_viewStorage = nil;
|
|
}
|
|
|
|
- (void)orderWindow:(NSWindowOrderingMode)place relativeTo:(int)otherWin
|
|
{
|
|
GLUTView * view = (GLUTView *) [self contentView];
|
|
|
|
if(view != nil) {
|
|
NSMutableSet * views = [NSMutableSet set];
|
|
|
|
if(place == NSWindowOut) {
|
|
[views unionSet: [view coveredViews]];
|
|
[views addObject: view];
|
|
}
|
|
|
|
[view setShown: (place != NSWindowOut)];
|
|
[super orderWindow: place relativeTo: otherWin];
|
|
|
|
if(place != NSWindowOut) {
|
|
[views unionSet: [view coveredViews]];
|
|
[view recursiveCollectViewsIntoSet: views];
|
|
}
|
|
|
|
[GLUTView evaluateVisibilityOfViews: views];
|
|
} else {
|
|
[super orderWindow: place relativeTo: otherWin];
|
|
}
|
|
}
|
|
|
|
@end
|