You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1563 lines
47 KiB
Plaintext
1563 lines
47 KiB
Plaintext
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: vtkCocoaRenderWindow.mm
|
|
|
|
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
|
|
All rights reserved.
|
|
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
|
|
|
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
PURPOSE. See the above copyright notice for more information.
|
|
|
|
=========================================================================*/
|
|
|
|
#import <Cocoa/Cocoa.h>
|
|
#import "vtkCocoaMacOSXSDKCompatibility.h" // Needed to support old SDKs
|
|
|
|
#import "vtkCocoaRenderWindow.h"
|
|
#import "vtkRenderWindowInteractor.h"
|
|
#import "vtkCommand.h"
|
|
#import "vtkIdList.h"
|
|
#import "vtkObjectFactory.h"
|
|
#import "vtkRendererCollection.h"
|
|
#import "vtkCocoaGLView.h"
|
|
|
|
#import <sstream>
|
|
|
|
vtkStandardNewMacro(vtkCocoaRenderWindow);
|
|
|
|
//----------------------------------------------------------------------------
|
|
// This is a private class and an implementation detail, do not use it.
|
|
// For fullscreen, an NSWindow that captures key events even when borderless
|
|
@interface vtkCocoaFullScreenWindow : NSWindow
|
|
{
|
|
}
|
|
@end
|
|
|
|
@implementation vtkCocoaFullScreenWindow
|
|
- (BOOL)canBecomeKeyWindow
|
|
{
|
|
return YES;
|
|
}
|
|
@end
|
|
|
|
//----------------------------------------------------------------------------
|
|
// This is a private class and an implementation detail, do not use it.
|
|
// It manages the NSWindow of a "pure VTK application",
|
|
// as opposed to a regular Mac app that happens to use VTK.
|
|
//----------------------------------------------------------------------------
|
|
@interface vtkCocoaServer : NSObject
|
|
{
|
|
@private
|
|
vtkCocoaRenderWindow *_renWin;
|
|
}
|
|
|
|
// Designated initializer
|
|
- (id)initWithRenderWindow:(vtkCocoaRenderWindow *)inRenderWindow;
|
|
|
|
- (void)startObservations;
|
|
- (void)stopObservations;
|
|
|
|
@end
|
|
|
|
//----------------------------------------------------------------------------
|
|
@implementation vtkCocoaServer
|
|
|
|
//----------------------------------------------------------------------------
|
|
- (id)initWithRenderWindow:(vtkCocoaRenderWindow *)inRenderWindow
|
|
{
|
|
self = [super init];
|
|
if (self)
|
|
{
|
|
_renWin = inRenderWindow;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
- (void)startObservations
|
|
{
|
|
assert(_renWin);
|
|
|
|
int windowCreated = _renWin->GetWindowCreated();
|
|
NSWindow *win = reinterpret_cast<NSWindow *>(_renWin->GetRootWindow());
|
|
if (windowCreated && win)
|
|
{
|
|
// Receive notifications of this, and only this, window's closing.
|
|
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
|
|
[nc addObserver:self
|
|
selector:@selector(windowWillClose:)
|
|
name:NSWindowWillCloseNotification
|
|
object:win];
|
|
}
|
|
|
|
NSView *view = reinterpret_cast<NSView *>(_renWin->GetWindowId());
|
|
int viewCreated = _renWin->GetViewCreated();
|
|
if (viewCreated && view)
|
|
{
|
|
// Receive notifications of this, and only this, view's frame changing.
|
|
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
|
|
[nc addObserver:self
|
|
selector:@selector(viewFrameDidChange:)
|
|
name:NSViewFrameDidChangeNotification
|
|
object:view];
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
- (void)stopObservations
|
|
{
|
|
assert(_renWin);
|
|
|
|
int windowCreated = _renWin->GetWindowCreated();
|
|
NSWindow *win = reinterpret_cast<NSWindow *>(_renWin->GetRootWindow());
|
|
if (windowCreated && win)
|
|
{
|
|
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
|
|
[nc removeObserver:self
|
|
name:NSWindowWillCloseNotification
|
|
object:win];
|
|
}
|
|
|
|
NSView *view = reinterpret_cast<NSView *>(_renWin->GetWindowId());
|
|
int viewCreated = _renWin->GetViewCreated();
|
|
if (viewCreated && view)
|
|
{
|
|
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
|
|
[nc removeObserver:self
|
|
name:NSViewFrameDidChangeNotification
|
|
object:view];
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
- (void)windowWillClose:(NSNotification *)aNotification
|
|
{
|
|
// We should only get here if it was us that created the NSWindow.
|
|
assert(_renWin);
|
|
assert(_renWin->GetWindowCreated());
|
|
|
|
// We should only have observed our own NSWindow.
|
|
assert([aNotification object] == _renWin->GetRootWindow());
|
|
(void)aNotification;
|
|
|
|
// Stop observing because the window is closing.
|
|
[self stopObservations];
|
|
|
|
// The NSWindow is closing, so prevent anyone from accidentally using it.
|
|
_renWin->SetRootWindow(NULL);
|
|
|
|
// Tell interactor to stop the NSApplication's run loop
|
|
vtkRenderWindowInteractor *interactor = _renWin->GetInteractor();
|
|
if (interactor)
|
|
{
|
|
interactor->TerminateApp();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
- (void)viewFrameDidChange:(NSNotification *)aNotification
|
|
{
|
|
// We should only get here if it was us that created the NSView.
|
|
assert(_renWin);
|
|
assert(_renWin->GetViewCreated());
|
|
|
|
// We should only have observed our own NSView.
|
|
assert([aNotification object] == _renWin->GetWindowId());
|
|
(void)aNotification;
|
|
|
|
// Retrieve the Interactor.
|
|
vtkRenderWindowInteractor *interactor = _renWin->GetInteractor();
|
|
if (!interactor || !interactor->GetEnabled())
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Get the NSView's new frame size.
|
|
NSView *view = reinterpret_cast<NSView *>(_renWin->GetWindowId());
|
|
assert(view);
|
|
NSRect frameRect = [view frame];
|
|
int width = (int)round(NSWidth(frameRect));
|
|
int height = (int)round(NSHeight(frameRect));
|
|
|
|
// Get the interactor's current cache of the size.
|
|
int size[2];
|
|
interactor->GetSize(size);
|
|
|
|
if (width != size[0] || height != size[1])
|
|
{
|
|
// Send ConfigureEvent from the Interactor.
|
|
interactor->UpdateSize(width, height);
|
|
interactor->InvokeEvent(vtkCommand::ConfigureEvent, NULL);
|
|
}
|
|
}
|
|
|
|
@end
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkCocoaRenderWindow::vtkCocoaRenderWindow()
|
|
{
|
|
// First, create the cocoa objects manager. The dictionary is empty so
|
|
// essentially all objects are initialized to NULL.
|
|
NSMutableDictionary *cocoaManager = [NSMutableDictionary dictionary];
|
|
|
|
// SetCocoaManager works like an Obj-C setter, so do like Obj-C and
|
|
// init the ivar to null first.
|
|
this->CocoaManager = NULL;
|
|
this->SetCocoaManager(reinterpret_cast<void *>(cocoaManager));
|
|
[cocoaManager self]; // prevent premature collection under GC.
|
|
|
|
this->WindowCreated = 0;
|
|
this->ViewCreated = 0;
|
|
this->SetWindowName("Visualization Toolkit - Cocoa");
|
|
this->CursorHidden = 0;
|
|
this->ForceMakeCurrent = 0;
|
|
this->Capabilities = 0;
|
|
this->OnScreenInitialized = 0;
|
|
this->OffScreenInitialized = 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkCocoaRenderWindow::~vtkCocoaRenderWindow()
|
|
{
|
|
if (this->CursorHidden)
|
|
{
|
|
this->ShowCursor();
|
|
}
|
|
this->Finalize();
|
|
|
|
vtkRenderer *ren;
|
|
vtkCollectionSimpleIterator rit;
|
|
this->Renderers->InitTraversal(rit);
|
|
while ( (ren = this->Renderers->GetNextRenderer(rit)) )
|
|
{
|
|
ren->SetRenderWindow(NULL);
|
|
}
|
|
|
|
delete[] this->Capabilities;
|
|
this->Capabilities = 0;
|
|
|
|
this->SetContextId(NULL);
|
|
this->SetPixelFormat(NULL);
|
|
this->SetCocoaServer(NULL);
|
|
this->SetRootWindow(NULL);
|
|
this->SetWindowId(NULL);
|
|
this->SetParentId(NULL);
|
|
|
|
// Release the cocoa object manager.
|
|
this->SetCocoaManager(NULL);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCocoaRenderWindow::Finalize()
|
|
{
|
|
if(this->OffScreenInitialized)
|
|
{
|
|
this->OffScreenInitialized = 0;
|
|
this->DestroyOffScreenWindow();
|
|
}
|
|
if(this->OnScreenInitialized)
|
|
{
|
|
this->OnScreenInitialized = 0;
|
|
this->DestroyWindow();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCocoaRenderWindow::DestroyWindow()
|
|
{
|
|
// finish OpenGL rendering
|
|
if (this->OwnContext && this->GetContextId())
|
|
{
|
|
this->MakeCurrent();
|
|
|
|
// now delete all textures
|
|
glDisable(GL_TEXTURE_2D);
|
|
for (vtkIdType i = 1; i < this->TextureResourceIds->GetNumberOfIds(); i++)
|
|
{
|
|
GLuint txId = (GLuint) this->TextureResourceIds->GetId(i);
|
|
#ifdef GL_VERSION_1_1
|
|
if (glIsTexture(txId))
|
|
{
|
|
glDeleteTextures(1, &txId);
|
|
}
|
|
#else
|
|
if (glIsList(txId))
|
|
{
|
|
glDeleteLists(txId,1);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// tell each of the renderers that this render window/graphics context
|
|
// is being removed (the RendererCollection is removed by vtkRenderWindow's
|
|
// destructor)
|
|
vtkCollectionSimpleIterator rsit;
|
|
vtkRenderer *ren;
|
|
for ( this->Renderers->InitTraversal(rsit);
|
|
(ren = this->Renderers->GetNextRenderer(rsit));)
|
|
{
|
|
ren->SetRenderWindow(NULL);
|
|
ren->SetRenderWindow(this);
|
|
}
|
|
}
|
|
this->SetContextId(NULL);
|
|
this->SetPixelFormat(NULL);
|
|
|
|
vtkCocoaServer *server = (vtkCocoaServer *)this->GetCocoaServer();
|
|
[server stopObservations];
|
|
this->SetCocoaServer(NULL);
|
|
|
|
// If we created it, close the NSWindow.
|
|
if (this->WindowCreated)
|
|
{
|
|
NSWindow *window = (NSWindow*)this->GetRootWindow();
|
|
[window close];
|
|
}
|
|
|
|
this->SetWindowId(NULL);
|
|
this->SetParentId(NULL);
|
|
this->SetRootWindow(NULL);
|
|
this->WindowCreated = 0;
|
|
this->ViewCreated = 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCocoaRenderWindow::SetWindowName( const char * _arg )
|
|
{
|
|
vtkWindow::SetWindowName(_arg);
|
|
if (this->GetRootWindow())
|
|
{
|
|
NSString *winTitleStr = [NSString stringWithUTF8String:_arg];
|
|
|
|
[(NSWindow*)this->GetRootWindow() setTitle:winTitleStr];
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkCocoaRenderWindow::InitializeFromCurrentContext()
|
|
{
|
|
NSOpenGLContext *currentContext = [NSOpenGLContext currentContext];
|
|
if (currentContext != NULL)
|
|
{
|
|
NSView *currentView = [currentContext view];
|
|
if (currentView != NULL)
|
|
{
|
|
NSWindow *window = [currentView window];
|
|
this->SetWindowId(currentView);
|
|
this->SetRootWindow(window);
|
|
this->SetContextId((void*)currentContext);
|
|
this->OpenGLInit();
|
|
this->OwnContext = 0;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkCocoaRenderWindow::GetEventPending()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Initialize the rendering process.
|
|
void vtkCocoaRenderWindow::Start()
|
|
{
|
|
this->Initialize();
|
|
|
|
// set the current window
|
|
this->MakeCurrent();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCocoaRenderWindow::MakeCurrent()
|
|
{
|
|
if (this->GetContextId())
|
|
{
|
|
[(NSOpenGLContext*)this->GetContextId() makeCurrentContext];
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Description:
|
|
// Tells if this window is the current OpenGL context for the calling thread.
|
|
bool vtkCocoaRenderWindow::IsCurrent()
|
|
{
|
|
bool result=false;
|
|
if(this->GetContextId()!=0)
|
|
{
|
|
result=static_cast<NSOpenGLContext *>(this->GetContextId())==
|
|
[NSOpenGLContext currentContext];
|
|
}
|
|
return result;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkCocoaRenderWindow::IsDrawable()
|
|
{
|
|
// you must initialize it first
|
|
// else it always evaluates false
|
|
this->Initialize();
|
|
|
|
// first check that window is valid
|
|
NSView *theView = (NSView*)this->GetWindowId();
|
|
bool win =[[theView window] windowNumber]>0;
|
|
|
|
// then check that the drawable is valid
|
|
NSOpenGLContext *context = (NSOpenGLContext *)this->GetContextId();
|
|
bool ok = [context view] != nil;
|
|
return win && ok;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCocoaRenderWindow::UpdateContext()
|
|
{
|
|
if (this->GetContextId())
|
|
{
|
|
[(NSOpenGLContext*)this->GetContextId() update];
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
const char* vtkCocoaRenderWindow::ReportCapabilities()
|
|
{
|
|
this->MakeCurrent();
|
|
|
|
const char* glVendor = (const char*) glGetString(GL_VENDOR);
|
|
const char* glRenderer = (const char*) glGetString(GL_RENDERER);
|
|
const char* glVersion = (const char*) glGetString(GL_VERSION);
|
|
const char* glExtensions = (const char*) glGetString(GL_EXTENSIONS);
|
|
|
|
std::ostringstream strm;
|
|
strm << "OpenGL vendor string: " << glVendor
|
|
<< "\nOpenGL renderer string: " << glRenderer
|
|
<< "\nOpenGL version string: " << glVersion
|
|
<< "\nOpenGL extensions: " << glExtensions << endl;
|
|
|
|
// Obtain the OpenGL context in order to keep track of the current screen.
|
|
NSOpenGLContext* context = (NSOpenGLContext*)this->GetContextId();
|
|
GLint currentScreen = [context currentVirtualScreen];
|
|
|
|
// The NSOpenGLPixelFormat can only be queried for one particular
|
|
// attribute at a time. Just make repeated queries to get the
|
|
// pertinent settings.
|
|
NSOpenGLPixelFormat* pixelFormat = (NSOpenGLPixelFormat*)this->GetPixelFormat();
|
|
strm << "PixelFormat Descriptor:" << endl;
|
|
GLint pfd = 0;
|
|
[pixelFormat getValues: &pfd forAttribute: NSOpenGLPFAColorSize forVirtualScreen: currentScreen];
|
|
strm << " colorSize: " << pfd << endl;
|
|
|
|
[pixelFormat getValues: &pfd forAttribute: NSOpenGLPFAAlphaSize forVirtualScreen: currentScreen];
|
|
strm << " alphaSize: " << pfd << endl;
|
|
|
|
[pixelFormat getValues: &pfd forAttribute: NSOpenGLPFAStencilSize forVirtualScreen: currentScreen];
|
|
strm << " stencilSize: " << pfd << endl;
|
|
|
|
[pixelFormat getValues: &pfd forAttribute: NSOpenGLPFADepthSize forVirtualScreen: currentScreen];
|
|
strm << " depthSize: " << pfd << endl;
|
|
|
|
[pixelFormat getValues: &pfd forAttribute: NSOpenGLPFAAccumSize forVirtualScreen: currentScreen];
|
|
strm << " accumSize: " << pfd << endl;
|
|
|
|
[pixelFormat getValues: &pfd forAttribute: NSOpenGLPFADoubleBuffer forVirtualScreen: currentScreen];
|
|
strm << " double buffer: " << (pfd == 0 ? "No" : "Yes") << endl;
|
|
|
|
// "NSOpenGLPFAStereo" is deprecated in the 10.12 SDK, suppress warning about its use.
|
|
// No explanation is given for the deprecation, and no alternative is suggested.
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
|
[pixelFormat getValues: &pfd forAttribute: NSOpenGLPFAStereo forVirtualScreen: currentScreen];
|
|
strm << " stereo: " << (pfd == 0 ? "No" : "Yes") << endl;
|
|
#pragma clang diagnostic pop
|
|
|
|
[pixelFormat getValues: &pfd forAttribute: NSOpenGLPFAStencilSize forVirtualScreen: currentScreen];
|
|
strm << " stencil: " << pfd << endl;
|
|
|
|
[pixelFormat getValues: &pfd forAttribute: NSOpenGLPFAAccelerated forVirtualScreen: currentScreen];
|
|
strm << " hardware acceleration:: " << (pfd == 0 ? "No" : "Yes") << endl;
|
|
|
|
delete[] this->Capabilities;
|
|
|
|
size_t len = strm.str().length() + 1;
|
|
this->Capabilities = new char[len];
|
|
strlcpy(this->Capabilities, strm.str().c_str(), len);
|
|
|
|
return this->Capabilities;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkCocoaRenderWindow::SupportsOpenGL()
|
|
{
|
|
this->MakeCurrent();
|
|
if (!this->GetContextId() || !this->GetPixelFormat())
|
|
{
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkCocoaRenderWindow::IsDirect()
|
|
{
|
|
this->MakeCurrent();
|
|
if (!this->GetContextId() || !this->GetPixelFormat())
|
|
{
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCocoaRenderWindow::SetSize(int* a)
|
|
{
|
|
this->SetSize( a[0], a[1] );
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCocoaRenderWindow::SetSize(int x, int y)
|
|
{
|
|
static int resizing = 0;
|
|
|
|
if ((this->Size[0] != x) || (this->Size[1] != y) || (this->GetParentId()))
|
|
{
|
|
this->Superclass::SetSize(x, y);
|
|
if (this->GetParentId() && this->GetWindowId() && this->Mapped)
|
|
{
|
|
// Set the NSView size, not the window size.
|
|
if (!resizing)
|
|
{
|
|
resizing = 1;
|
|
NSView *theView = (NSView*)this->GetWindowId();
|
|
NSRect viewRect = [theView frame];
|
|
CGFloat oldHeight = NSHeight(viewRect);
|
|
CGFloat height = (CGFloat)y;
|
|
CGFloat width = (CGFloat)x;
|
|
CGFloat xpos = NSMinX(viewRect);
|
|
CGFloat ypos = NSMinY(viewRect) - (height - oldHeight);
|
|
NSRect theRect = NSMakeRect(xpos, ypos, width, height);
|
|
[theView setFrame:theRect];
|
|
[theView setNeedsDisplay:YES];
|
|
resizing = 0;
|
|
}
|
|
}
|
|
else if (this->GetRootWindow() && this->Mapped)
|
|
{
|
|
if (!resizing)
|
|
{
|
|
resizing = 1;
|
|
NSSize theSize = NSMakeSize((CGFloat)x, (CGFloat)y);
|
|
[(NSWindow*)this->GetRootWindow() setContentSize:theSize];
|
|
resizing = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCocoaRenderWindow::SetForceMakeCurrent()
|
|
{
|
|
this->ForceMakeCurrent = 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCocoaRenderWindow::SetPosition(int* a)
|
|
{
|
|
this->SetPosition( a[0], a[1] );
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCocoaRenderWindow::SetPosition(int x, int y)
|
|
{
|
|
static int resizing = 0;
|
|
|
|
if ((this->Position[0] != x) || (this->Position[1] != y)
|
|
|| (this->GetParentId()))
|
|
{
|
|
this->Modified();
|
|
this->Position[0] = x;
|
|
this->Position[1] = y;
|
|
if (this->GetParentId() && this->GetWindowId() && this->Mapped)
|
|
{
|
|
// Set the NSView position relative to the parent
|
|
if (!resizing)
|
|
{
|
|
resizing = 1;
|
|
NSRect parentRect = [(NSView*)this->GetParentId() frame];
|
|
NSView *theView = (NSView*)this->GetWindowId();
|
|
NSRect viewRect = [theView frame];
|
|
CGFloat parentHeight = NSHeight(parentRect);
|
|
CGFloat height = NSHeight(viewRect);
|
|
CGFloat xpos = (CGFloat)x;
|
|
CGFloat ypos = parentHeight - height - (CGFloat)y;
|
|
NSPoint origin = NSMakePoint(xpos,ypos);
|
|
[theView setFrameOrigin:origin];
|
|
[theView setNeedsDisplay:YES];
|
|
resizing = 0;
|
|
}
|
|
}
|
|
else if (this->GetRootWindow() && this->Mapped)
|
|
{
|
|
if (!resizing)
|
|
{
|
|
resizing = 1;
|
|
NSPoint origin = NSMakePoint((CGFloat)x, (CGFloat)y);
|
|
[(NSWindow*)this->GetRootWindow() setFrameOrigin:origin];
|
|
resizing = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// End the rendering process and display the image.
|
|
void vtkCocoaRenderWindow::Frame()
|
|
{
|
|
this->MakeCurrent();
|
|
|
|
if (!this->AbortRender && this->DoubleBuffer && this->SwapBuffers)
|
|
{
|
|
[(NSOpenGLContext*)this->GetContextId() flushBuffer];
|
|
}
|
|
else
|
|
{
|
|
glFlush();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Update system if needed due to stereo rendering.
|
|
void vtkCocoaRenderWindow::StereoUpdate()
|
|
{
|
|
// if stereo is on and it wasn't before
|
|
if (this->StereoRender && (!this->StereoStatus))
|
|
{
|
|
switch (this->StereoType)
|
|
{
|
|
case VTK_STEREO_CRYSTAL_EYES:
|
|
this->StereoStatus = 1;
|
|
break;
|
|
case VTK_STEREO_RED_BLUE:
|
|
this->StereoStatus = 1;
|
|
break;
|
|
case VTK_STEREO_ANAGLYPH:
|
|
this->StereoStatus = 1;
|
|
break;
|
|
case VTK_STEREO_DRESDEN:
|
|
this->StereoStatus = 1;
|
|
break;
|
|
case VTK_STEREO_INTERLACED:
|
|
this->StereoStatus = 1;
|
|
break;
|
|
case VTK_STEREO_CHECKERBOARD:
|
|
this->StereoStatus = 1;
|
|
break;
|
|
case VTK_STEREO_SPLITVIEWPORT_HORIZONTAL:
|
|
this->StereoStatus = 1;
|
|
break;
|
|
}
|
|
}
|
|
else if ((!this->StereoRender) && this->StereoStatus)
|
|
{
|
|
switch (this->StereoType)
|
|
{
|
|
case VTK_STEREO_CRYSTAL_EYES:
|
|
this->StereoStatus = 0;
|
|
break;
|
|
case VTK_STEREO_RED_BLUE:
|
|
this->StereoStatus = 0;
|
|
break;
|
|
case VTK_STEREO_ANAGLYPH:
|
|
this->StereoStatus = 0;
|
|
break;
|
|
case VTK_STEREO_DRESDEN:
|
|
this->StereoStatus = 0;
|
|
break;
|
|
case VTK_STEREO_INTERLACED:
|
|
this->StereoStatus = 0;
|
|
break;
|
|
case VTK_STEREO_CHECKERBOARD:
|
|
this->StereoStatus = 0;
|
|
break;
|
|
case VTK_STEREO_SPLITVIEWPORT_HORIZONTAL:
|
|
this->StereoStatus = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Specify various window parameters.
|
|
void vtkCocoaRenderWindow::WindowConfigure()
|
|
{
|
|
// this is all handled by the desiredVisualInfo method
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCocoaRenderWindow::SetupPixelFormat(void*, void*, int, int, int)
|
|
{
|
|
vtkErrorMacro(<< "vtkCocoaRenderWindow::SetupPixelFormat - IMPLEMENT");
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCocoaRenderWindow::SetupPalette(void*)
|
|
{
|
|
vtkErrorMacro(<< "vtkCocoaRenderWindow::SetupPalette - IMPLEMENT");
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Initialize the window for rendering.
|
|
void vtkCocoaRenderWindow::CreateAWindow()
|
|
{
|
|
static unsigned count = 1;
|
|
|
|
// As vtk is both crossplatform and a library, we don't know if it is being
|
|
// used in a 'regular Cocoa application' or as a 'pure vtk application'.
|
|
// By the former I mean a regular Cocoa application that happens to have
|
|
// a vtkCocoaGLView, by the latter I mean an application that only uses
|
|
// vtk APIs (which happen to use Cocoa as an implementation detail).
|
|
// Specifically, we can't know if NSApplicationMain() was ever called
|
|
// (which is usually done in main()), nor whether the NSApplication exists.
|
|
//
|
|
// So here we call +sharedApplication which will create the NSApplication
|
|
// if it does not exist. If it does exist, this does nothing.
|
|
// This call is intentionally delayed until this CreateAWindow call
|
|
// to prevent Cocoa-window related stuff from happening in scenarios
|
|
// where vtkRenderWindows are created but never shown.
|
|
NSApplication* app = [NSApplication sharedApplication];
|
|
|
|
// create an NSWindow only if neither an NSView nor an NSWindow have
|
|
// been specified already. This is the case for a 'pure vtk application'.
|
|
// If you are using vtk in a 'regular Mac application' you should call
|
|
// SetRootWindow() and SetWindowId() so that a window is not created here.
|
|
if (!this->GetRootWindow() && !this->GetWindowId() && !this->GetParentId())
|
|
{
|
|
// Ordinarily, only .app bundles get proper mouse and keyboard interaction,
|
|
// but here we change the 'activation policy' to behave as if we were a
|
|
// .app bundle (which we may or may not be).
|
|
(void)[app setActivationPolicy:NSApplicationActivationPolicyRegular];
|
|
|
|
NSWindow* theWindow = nil;
|
|
|
|
NSScreen *screen = [NSScreen mainScreen];
|
|
if (this->FullScreen && screen)
|
|
{
|
|
NSRect ctRect = [screen frame];
|
|
this->Size[0] = (int)round(NSWidth(ctRect));
|
|
this->Size[1] = (int)round(NSHeight(ctRect));
|
|
|
|
theWindow = [[vtkCocoaFullScreenWindow alloc]
|
|
initWithContentRect:ctRect
|
|
styleMask:NSWindowStyleMaskBorderless
|
|
backing:NSBackingStoreBuffered
|
|
defer:NO];
|
|
|
|
// This will hide the menu and the dock
|
|
[theWindow setLevel:NSMainMenuWindowLevel+1];
|
|
// This will show the menu and the dock
|
|
//[theWindow setLevel:NSFloatingWindowLevel];
|
|
}
|
|
else
|
|
{
|
|
if ((this->Size[0]+this->Size[1]) == 0)
|
|
{
|
|
this->Size[0] = 300;
|
|
this->Size[1] = 300;
|
|
}
|
|
if ((this->Position[0]+this->Position[1]) == 0)
|
|
{
|
|
this->Position[0] = 50;
|
|
this->Position[1] = 50;
|
|
}
|
|
|
|
NSRect ctRect = NSMakeRect((CGFloat)this->Position[0],
|
|
(CGFloat)this->Position[1],
|
|
(CGFloat)this->Size[0],
|
|
(CGFloat)this->Size[1]);
|
|
|
|
theWindow = [[NSWindow alloc]
|
|
initWithContentRect:ctRect
|
|
styleMask:NSWindowStyleMaskTitled |
|
|
NSWindowStyleMaskClosable |
|
|
NSWindowStyleMaskMiniaturizable |
|
|
NSWindowStyleMaskResizable
|
|
backing:NSBackingStoreBuffered
|
|
defer:NO];
|
|
}
|
|
|
|
if (!theWindow)
|
|
{
|
|
vtkErrorMacro("Could not create window, serious error!");
|
|
return;
|
|
}
|
|
|
|
this->SetRootWindow(theWindow);
|
|
this->WindowCreated = 1;
|
|
|
|
// makeKeyAndOrderFront: will show the window
|
|
// we don't want this if offscreen was requested
|
|
if(!this->OffScreenRendering)
|
|
{
|
|
[theWindow makeKeyAndOrderFront:nil];
|
|
[theWindow setAcceptsMouseMovedEvents:YES];
|
|
}
|
|
}
|
|
// create a view if one has not been specified
|
|
if (!this->GetWindowId())
|
|
{
|
|
if (this->GetParentId())
|
|
{
|
|
NSView *parent = (NSView*)this->GetParentId();
|
|
NSRect parentRect = [parent frame];
|
|
CGFloat parentHeight = NSHeight(parentRect);
|
|
CGFloat parentWidth = NSWidth(parentRect);
|
|
CGFloat width = (CGFloat)this->Size[0];
|
|
CGFloat height = (CGFloat)this->Size[1];
|
|
CGFloat x = (CGFloat)this->Position[0];
|
|
CGFloat y = parentHeight - height - (CGFloat)this->Position[1];
|
|
|
|
// A whole bunch of sanity checks: frame must be inside parent
|
|
if (x > parentWidth - 1) { x = parentWidth - 1; };
|
|
if (y > parentHeight - 1) { y = parentHeight - 1; };
|
|
if (x < 0.0) { x = 0.0; }
|
|
if (y < 0.0) { y = 0.0; }
|
|
if (x + width > parentWidth) { width = parentWidth - x; }
|
|
if (y + height > parentWidth) { height = parentHeight - y; }
|
|
|
|
// Don't use vtkCocoaGLView, because if we are in Tk (which is what
|
|
// SetParentId() was added for) then the Tk superview handles the events.
|
|
NSRect glRect = NSMakeRect(x, y, width, height);
|
|
NSView *glView = [[NSView alloc] initWithFrame:glRect];
|
|
[parent addSubview:glView];
|
|
this->SetWindowId(glView);
|
|
this->ViewCreated = 1;
|
|
#if !VTK_OBJC_IS_ARC
|
|
[glView release];
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
NSRect glRect = NSMakeRect(0.0, 0.0,
|
|
(CGFloat)this->Size[0],
|
|
(CGFloat)this->Size[1]);
|
|
|
|
// Create a vtkCocoaGLView.
|
|
vtkCocoaGLView *glView = [[vtkCocoaGLView alloc] initWithFrame:glRect];
|
|
[(NSWindow*)this->GetRootWindow() setContentView:glView];
|
|
this->SetWindowId(glView);
|
|
this->ViewCreated = 1;
|
|
[glView setVTKRenderWindow:this];
|
|
#if !VTK_OBJC_IS_ARC
|
|
[glView release];
|
|
#endif
|
|
}
|
|
}
|
|
|
|
this->CreateGLContext();
|
|
|
|
// Change the window title, but only if it was created by vtk
|
|
if (this->WindowCreated)
|
|
{
|
|
NSString *winName = [NSString stringWithFormat:@"Visualization Toolkit - Cocoa #%u", count++];
|
|
this->SetWindowName([winName cStringUsingEncoding:NSASCIIStringEncoding]);
|
|
}
|
|
|
|
// the error "invalid drawable" in the console from this call can appear
|
|
// but only early in the app's lifetime (ie sometime during launch)
|
|
// IMPORTANT: this is necessary to update the context here in case of
|
|
// hardware offscreen rendering
|
|
NSOpenGLContext* context = (NSOpenGLContext*)this->GetContextId();
|
|
[context setView:(NSView*)this->GetWindowId()];
|
|
|
|
[context update];
|
|
|
|
this->MakeCurrent();
|
|
|
|
// wipe out any existing display lists
|
|
vtkRenderer *renderer = NULL;
|
|
vtkCollectionSimpleIterator rsit;
|
|
|
|
for ( this->Renderers->InitTraversal(rsit);
|
|
(renderer = this->Renderers->GetNextRenderer(rsit));)
|
|
{
|
|
renderer->SetRenderWindow(0);
|
|
renderer->SetRenderWindow(this);
|
|
}
|
|
this->OpenGLInit();
|
|
this->Mapped = 1;
|
|
|
|
// Now that the NSView and NSWindow exist, the vtkCocoaServer can start its observations.
|
|
vtkCocoaServer *server = [[vtkCocoaServer alloc] initWithRenderWindow:this];
|
|
this->SetCocoaServer(reinterpret_cast<void *>(server));
|
|
[server startObservations];
|
|
#if !VTK_OBJC_IS_ARC
|
|
[server release];
|
|
#endif
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCocoaRenderWindow::CreateGLContext()
|
|
{
|
|
// keep trying to get different pixelFormats until successful
|
|
NSOpenGLPixelFormat *pixelFormat = nil;
|
|
while (pixelFormat == nil)
|
|
{
|
|
int i = 0;
|
|
NSOpenGLPixelFormatAttribute attribs[20];
|
|
|
|
attribs[i++] = NSOpenGLPFAAccelerated;
|
|
attribs[i++] = NSOpenGLPFADepthSize;
|
|
attribs[i++] = (NSOpenGLPixelFormatAttribute)32;
|
|
|
|
if (this->MultiSamples != 0)
|
|
{
|
|
attribs[i++] = NSOpenGLPFASampleBuffers;
|
|
attribs[i++] = (NSOpenGLPixelFormatAttribute)1;
|
|
attribs[i++] = NSOpenGLPFASamples;
|
|
attribs[i++] = (NSOpenGLPixelFormatAttribute)(this->MultiSamples);
|
|
attribs[i++] = NSOpenGLPFAMultisample;
|
|
}
|
|
|
|
if (this->DoubleBuffer != 0)
|
|
{
|
|
attribs[i++] = NSOpenGLPFADoubleBuffer;
|
|
}
|
|
|
|
if (this->StencilCapable)
|
|
{
|
|
attribs[i++] = NSOpenGLPFAStencilSize;
|
|
attribs[i++] = (NSOpenGLPixelFormatAttribute)8;
|
|
}
|
|
|
|
attribs[i++] = (NSOpenGLPixelFormatAttribute)0;
|
|
|
|
// make sure that size of array was not exceeded
|
|
assert(sizeof(NSOpenGLPixelFormatAttribute)*i < sizeof(attribs));
|
|
|
|
pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
|
|
|
|
if (pixelFormat == nil)
|
|
{
|
|
if (this->MultiSamples == 0)
|
|
{
|
|
// after trying with no multisamples, we are done
|
|
break;
|
|
}
|
|
else if (this->MultiSamples < 4)
|
|
{
|
|
// next time try with no multisamples
|
|
this->MultiSamples = 0;
|
|
}
|
|
else
|
|
{
|
|
this->MultiSamples /= 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
NSOpenGLContext *context = [[NSOpenGLContext alloc]
|
|
initWithFormat:pixelFormat
|
|
shareContext:nil];
|
|
|
|
// This syncs the OpenGL context to the VBL to prevent tearing
|
|
GLint one = 1;
|
|
[context setValues:&one forParameter:NSOpenGLCPSwapInterval];
|
|
|
|
this->SetPixelFormat((void*)pixelFormat);
|
|
this->SetContextId((void*)context);
|
|
|
|
[pixelFormat self]; // prevent premature collection under GC.
|
|
[context self]; // prevent premature collection under GC.
|
|
|
|
#if !VTK_OBJC_IS_ARC
|
|
[pixelFormat release];
|
|
[context release];
|
|
#endif
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Initialize the rendering window.
|
|
void vtkCocoaRenderWindow::Initialize ()
|
|
{
|
|
if(this->OffScreenRendering)
|
|
{
|
|
// destroy on screen
|
|
if(this->OnScreenInitialized)
|
|
{
|
|
this->DestroyWindow();
|
|
this->OnScreenInitialized = 0;
|
|
}
|
|
// create off screen
|
|
if(!this->OffScreenInitialized)
|
|
{
|
|
int width=((this->Size[0]>0) ? this->Size[0] : 300);
|
|
int height=((this->Size[1]>0) ? this->Size[1] : 300);
|
|
if(!this->CreateHardwareOffScreenWindow(width,height))
|
|
{
|
|
// no other offscreen mode available, do on screen rendering
|
|
this->CreateAWindow();
|
|
}
|
|
this->OffScreenInitialized = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// destroy off screen
|
|
if(this->OffScreenInitialized)
|
|
{
|
|
this->DestroyOffScreenWindow();
|
|
}
|
|
// create on screen
|
|
if(!this->OnScreenInitialized)
|
|
{
|
|
this->OnScreenInitialized = 1;
|
|
this->CreateAWindow();
|
|
}
|
|
}
|
|
if((this->OnScreenInitialized) && (this->Mapped))
|
|
{
|
|
// the error "invalid drawable" in the console from this call can appear
|
|
// but only early in the app's lifetime (ie sometime during launch)
|
|
// IMPORTANT: this is necessary to update the context here in case of
|
|
// onscreen rendering
|
|
NSOpenGLContext* context = (NSOpenGLContext*)this->GetContextId();
|
|
[context setView:(NSView*)this->GetWindowId()];
|
|
|
|
[context update];
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkCocoaRenderWindow::DestroyOffScreenWindow()
|
|
{
|
|
if(this->OffScreenUseFrameBuffer)
|
|
{
|
|
this->DestroyHardwareOffScreenWindow();
|
|
}
|
|
else
|
|
{
|
|
// on screen
|
|
this->DestroyWindow();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Get the current size of the window.
|
|
int *vtkCocoaRenderWindow::GetSize()
|
|
{
|
|
// if we aren't mapped then just return the ivar
|
|
if (!this->Mapped)
|
|
{
|
|
return this->Superclass::GetSize();
|
|
}
|
|
|
|
// We want to return the size of 'the window'. But the term 'window'
|
|
// is overloaded. It's really the NSView that vtk draws into, so we
|
|
// return its size.
|
|
NSView* view = (NSView*)this->GetWindowId();
|
|
if (view)
|
|
{
|
|
NSRect frameRect = [view frame];
|
|
this->Size[0] = (int)round(NSWidth(frameRect));
|
|
this->Size[1] = (int)round(NSHeight(frameRect));
|
|
}
|
|
return this->Superclass::GetSize();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Get the current size of the screen in pixels.
|
|
int *vtkCocoaRenderWindow::GetScreenSize()
|
|
{
|
|
NSOpenGLContext* context = (NSOpenGLContext*)this->GetContextId();
|
|
GLint currentScreen = [context currentVirtualScreen];
|
|
|
|
NSScreen* screen = [[NSScreen screens] objectAtIndex:currentScreen];
|
|
NSRect screenRect = [screen frame];
|
|
|
|
this->Size[0] = (int)round(NSWidth(screenRect));
|
|
this->Size[1] = (int)round(NSHeight(screenRect));
|
|
|
|
return this->Size;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Get the position in screen coordinates of the window.
|
|
int *vtkCocoaRenderWindow::GetPosition()
|
|
{
|
|
// if we aren't mapped then just return the ivar
|
|
if (!this->Mapped)
|
|
{
|
|
return this->Position;
|
|
}
|
|
|
|
if (this->GetParentId() && this->GetWindowId())
|
|
{
|
|
// Get display position of the NSView within its parent
|
|
NSRect parentRect = [(NSView*)this->GetParentId() frame];
|
|
NSRect viewFrameRect = [(NSView*)this->GetWindowId() frame];
|
|
this->Position[0] = int(round(NSMinX(viewFrameRect)));
|
|
this->Position[1] = int(round((NSHeight(parentRect)
|
|
- NSHeight(viewFrameRect)
|
|
- NSMinY(viewFrameRect))));
|
|
}
|
|
else
|
|
{
|
|
// We want to return the position of 'the window'. But the term 'window'
|
|
// is overloaded. In this case, it's the position of the NSWindow itself
|
|
// on the screen that we return. We don't much care where the NSView is
|
|
// within the NSWindow.
|
|
NSWindow *window = (NSWindow*)this->GetRootWindow();
|
|
if (window)
|
|
{
|
|
NSRect winFrameRect = [window frame];
|
|
this->Position[0] = (int)NSMinX(winFrameRect);
|
|
this->Position[1] = (int)NSMinY(winFrameRect);
|
|
}
|
|
}
|
|
|
|
return this->Position;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Change the window to fill the entire screen.
|
|
void vtkCocoaRenderWindow::SetFullScreen(int arg)
|
|
{
|
|
if (this->FullScreen == arg)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!this->Mapped)
|
|
{
|
|
this->FullScreen = arg;
|
|
return;
|
|
}
|
|
|
|
// set the mode
|
|
this->FullScreen = arg;
|
|
if (this->FullScreen <= 0)
|
|
{
|
|
this->Position[0] = this->OldScreen[0];
|
|
this->Position[1] = this->OldScreen[1];
|
|
this->Size[0] = this->OldScreen[2];
|
|
this->Size[1] = this->OldScreen[3];
|
|
this->Borders = this->OldScreen[4];
|
|
}
|
|
else
|
|
{
|
|
// if window already up get its values
|
|
if (this->GetRootWindow())
|
|
{
|
|
int* pos = this->GetPosition();
|
|
this->OldScreen[0] = pos[0];
|
|
this->OldScreen[1] = pos[1];
|
|
|
|
this->OldScreen[4] = this->Borders;
|
|
this->PrefFullScreen();
|
|
}
|
|
}
|
|
|
|
// remap the window
|
|
this->WindowRemap();
|
|
|
|
this->Modified();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Set the variable that indicates that we want a stereo capable window
|
|
// be created. This method can only be called before a window is realized.
|
|
//
|
|
void vtkCocoaRenderWindow::SetStereoCapableWindow(int capable)
|
|
{
|
|
if (this->GetContextId() == 0)
|
|
{
|
|
vtkRenderWindow::SetStereoCapableWindow(capable);
|
|
}
|
|
else
|
|
{
|
|
vtkWarningMacro(<< "Requesting a StereoCapableWindow must be performed "
|
|
<< "before the window is realized, i.e. before a render.");
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Set the preferred window size to full screen.
|
|
void vtkCocoaRenderWindow::PrefFullScreen()
|
|
{
|
|
int *size = this->GetScreenSize();
|
|
vtkWarningMacro(<< "Can only set FullScreen before showing window: "
|
|
<< size[0] << 'x' << size[1] << ".");
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Remap the window.
|
|
void vtkCocoaRenderWindow::WindowRemap()
|
|
{
|
|
vtkWarningMacro(<< "Can't remap the window.");
|
|
// Acquire the display and capture the screen.
|
|
// Create the full-screen window.
|
|
// Add the context.
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCocoaRenderWindow::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os,indent);
|
|
|
|
os << indent << "MultiSamples: " << this->MultiSamples << endl;
|
|
os << indent << "CocoaManager: " << this->GetCocoaManager() << endl;
|
|
os << indent << "RootWindow (NSWindow): " << this->GetRootWindow() << endl;
|
|
os << indent << "WindowId (NSView): " << this->GetWindowId() << endl;
|
|
os << indent << "ParentId: " << this->GetParentId() << endl;
|
|
os << indent << "ContextId: " << this->GetContextId() << endl;
|
|
os << indent << "PixelFormat: " << this->GetPixelFormat() << endl;
|
|
os << indent << "WindowCreated: " << (this->GetWindowCreated() ? "Yes" : "No") << endl;
|
|
os << indent << "ViewCreated: " << (this->GetViewCreated() ? "Yes" : "No") << endl;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkCocoaRenderWindow::GetDepthBufferSize()
|
|
{
|
|
if ( this->Mapped )
|
|
{
|
|
GLint size = 0;
|
|
glGetIntegerv( GL_DEPTH_BITS, &size );
|
|
return (int) size;
|
|
}
|
|
else
|
|
{
|
|
vtkDebugMacro(<< "Window is not mapped yet!" );
|
|
return 24;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Returns the NSWindow* associated with this vtkRenderWindow.
|
|
void *vtkCocoaRenderWindow::GetRootWindow()
|
|
{
|
|
NSMutableDictionary *manager =
|
|
reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
|
|
return reinterpret_cast<void *>([manager objectForKey:@"RootWindow"]);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Sets the NSWindow* associated with this vtkRenderWindow.
|
|
void vtkCocoaRenderWindow::SetRootWindow(void *arg)
|
|
{
|
|
if (arg != NULL)
|
|
{
|
|
NSMutableDictionary *manager =
|
|
reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
|
|
[manager setObject:reinterpret_cast<id>(arg)
|
|
forKey:@"RootWindow"];
|
|
}
|
|
else
|
|
{
|
|
NSMutableDictionary *manager =
|
|
reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
|
|
[manager removeObjectForKey:@"RootWindow"];
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Returns the NSView* associated with this vtkRenderWindow.
|
|
void *vtkCocoaRenderWindow::GetWindowId()
|
|
{
|
|
NSMutableDictionary *manager =
|
|
reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
|
|
return reinterpret_cast<void *>([manager objectForKey:@"WindowId"]);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Sets the NSView* associated with this vtkRenderWindow.
|
|
void vtkCocoaRenderWindow::SetWindowId(void *arg)
|
|
{
|
|
if (arg != NULL)
|
|
{
|
|
NSMutableDictionary *manager =
|
|
reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
|
|
[manager setObject:reinterpret_cast<id>(arg)
|
|
forKey:@"WindowId"];
|
|
}
|
|
else
|
|
{
|
|
NSMutableDictionary *manager =
|
|
reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
|
|
[manager removeObjectForKey:@"WindowId"];
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Returns the NSView* that is the parent of this vtkRenderWindow.
|
|
void *vtkCocoaRenderWindow::GetParentId()
|
|
{
|
|
NSMutableDictionary *manager =
|
|
reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
|
|
return reinterpret_cast<void *>([manager objectForKey:@"ParentId"]);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Sets the NSView* that this vtkRenderWindow should use as a parent.
|
|
void vtkCocoaRenderWindow::SetParentId(void *arg)
|
|
{
|
|
if (arg != NULL)
|
|
{
|
|
NSMutableDictionary *manager =
|
|
reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
|
|
[manager setObject:reinterpret_cast<id>(arg)
|
|
forKey:@"ParentId"];
|
|
}
|
|
else
|
|
{
|
|
NSMutableDictionary *manager =
|
|
reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
|
|
[manager removeObjectForKey:@"ParentId"];
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Sets the NSOpenGLContext* associated with this vtkRenderWindow.
|
|
void vtkCocoaRenderWindow::SetContextId(void *contextId)
|
|
{
|
|
if (contextId != NULL)
|
|
{
|
|
NSMutableDictionary *manager =
|
|
reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
|
|
[manager setObject:reinterpret_cast<id>(contextId)
|
|
forKey:@"ContextId"];
|
|
}
|
|
else
|
|
{
|
|
NSMutableDictionary *manager =
|
|
reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
|
|
[manager removeObjectForKey:@"ContextId"];
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Returns the NSOpenGLContext* associated with this vtkRenderWindow.
|
|
void *vtkCocoaRenderWindow::GetContextId()
|
|
{
|
|
NSMutableDictionary *manager =
|
|
reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
|
|
return reinterpret_cast<void *>([manager objectForKey:@"ContextId"]);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Sets the NSOpenGLPixelFormat* associated with this vtkRenderWindow.
|
|
void vtkCocoaRenderWindow::SetPixelFormat(void *pixelFormat)
|
|
{
|
|
if (pixelFormat != NULL)
|
|
{
|
|
NSMutableDictionary *manager =
|
|
reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
|
|
[manager setObject:reinterpret_cast<id>(pixelFormat)
|
|
forKey:@"PixelFormat"];
|
|
}
|
|
else
|
|
{
|
|
NSMutableDictionary *manager =
|
|
reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
|
|
[manager removeObjectForKey:@"PixelFormat"];
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Returns the NSOpenGLPixelFormat* associated with this vtkRenderWindow.
|
|
void *vtkCocoaRenderWindow::GetPixelFormat()
|
|
{
|
|
NSMutableDictionary *manager =
|
|
reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
|
|
return reinterpret_cast<void *>([manager objectForKey:@"PixelFormat"]);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCocoaRenderWindow::SetCocoaServer(void *server)
|
|
{
|
|
if (server != NULL)
|
|
{
|
|
NSMutableDictionary *manager =
|
|
reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
|
|
[manager setObject:reinterpret_cast<vtkCocoaServer *>(server)
|
|
forKey:@"CocoaServer"];
|
|
}
|
|
else
|
|
{
|
|
NSMutableDictionary *manager =
|
|
reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
|
|
[manager removeObjectForKey:@"CocoaServer"];
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void *vtkCocoaRenderWindow::GetCocoaServer()
|
|
{
|
|
NSMutableDictionary *manager =
|
|
reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
|
|
return reinterpret_cast<void *>([manager objectForKey:@"CocoaServer"]);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCocoaRenderWindow::SetCocoaManager(void *manager)
|
|
{
|
|
NSMutableDictionary *currentCocoaManager =
|
|
reinterpret_cast<NSMutableDictionary *>(this->CocoaManager);
|
|
NSMutableDictionary *newCocoaManager =
|
|
reinterpret_cast<NSMutableDictionary *>(manager);
|
|
|
|
if (currentCocoaManager != newCocoaManager)
|
|
{
|
|
// Why not use Cocoa's retain and release? Without garbage collection
|
|
// (GC), the two are equivalent anyway because of 'toll free bridging',
|
|
// so no problem there. With GC, retain and release do nothing, but
|
|
// CFRetain and CFRelease still manipulate the internal reference count.
|
|
// We need that, since we are not using strong references (we don't want
|
|
// it collected out from under us!).
|
|
if (currentCocoaManager)
|
|
{
|
|
CFRelease(currentCocoaManager);
|
|
}
|
|
if (newCocoaManager)
|
|
{
|
|
this->CocoaManager = const_cast<void *>(CFRetain (newCocoaManager));
|
|
}
|
|
else
|
|
{
|
|
this->CocoaManager = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCocoaRenderWindow::SetWindowInfo(char *info)
|
|
{
|
|
// The paramater is an ASCII string of a decimal number representing
|
|
// a pointer to the window. Convert it back to a pointer.
|
|
ptrdiff_t tmp = 0;
|
|
if (info)
|
|
{
|
|
(void)sscanf(info, "%tu", &tmp);
|
|
}
|
|
|
|
this->SetWindowId (reinterpret_cast<void *>(tmp));
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCocoaRenderWindow::SetParentInfo(char *info)
|
|
{
|
|
// The paramater is an ASCII string of a decimal number representing
|
|
// a pointer to the window. Convert it back to a pointer.
|
|
ptrdiff_t tmp = 0;
|
|
if (info)
|
|
{
|
|
(void)sscanf(info, "%tu", &tmp);
|
|
}
|
|
|
|
this->SetParentId (reinterpret_cast<void *>(tmp));
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void *vtkCocoaRenderWindow::GetCocoaManager()
|
|
{
|
|
return this->CocoaManager;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCocoaRenderWindow::HideCursor()
|
|
{
|
|
if (this->CursorHidden)
|
|
{
|
|
return;
|
|
}
|
|
this->CursorHidden = 1;
|
|
|
|
[NSCursor hide];
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCocoaRenderWindow::ShowCursor()
|
|
{
|
|
if (!this->CursorHidden)
|
|
{
|
|
return;
|
|
}
|
|
this->CursorHidden = 0;
|
|
|
|
[NSCursor unhide];
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
int vtkCocoaRenderWindow::GetViewCreated()
|
|
{
|
|
return this->ViewCreated;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
int vtkCocoaRenderWindow::GetWindowCreated()
|
|
{
|
|
return this->WindowCreated;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCocoaRenderWindow::SetCursorPosition(int x, int y)
|
|
{
|
|
// The given coordinates are from the bottom left of the view.
|
|
NSPoint newViewPoint = NSMakePoint (x, y);
|
|
|
|
// Convert to screen coordinates.
|
|
NSView *view = (NSView *)this->GetWindowId();
|
|
if (view)
|
|
{
|
|
NSPoint screenPoint = [view convertPoint:newViewPoint toView:nil];
|
|
CGPoint newCursorPosition = NSPointToCGPoint(screenPoint);
|
|
|
|
// Move the cursor there.
|
|
(void)CGWarpMouseCursorPosition (newCursorPosition);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkCocoaRenderWindow::SetCurrentCursor(int shape)
|
|
{
|
|
if (this->InvokeEvent(vtkCommand::CursorChangedEvent, &shape))
|
|
{
|
|
return;
|
|
}
|
|
this->Superclass::SetCurrentCursor(shape);
|
|
NSCursor* cursor = nil;
|
|
switch (shape)
|
|
{
|
|
case VTK_CURSOR_DEFAULT:
|
|
case VTK_CURSOR_ARROW:
|
|
cursor = [NSCursor arrowCursor];
|
|
break;
|
|
case VTK_CURSOR_SIZENS:
|
|
cursor = [NSCursor resizeUpDownCursor];
|
|
break;
|
|
case VTK_CURSOR_SIZEWE:
|
|
cursor = [NSCursor resizeLeftRightCursor];
|
|
break;
|
|
case VTK_CURSOR_HAND:
|
|
cursor = [NSCursor pointingHandCursor];
|
|
break;
|
|
case VTK_CURSOR_CROSSHAIR:
|
|
cursor = [NSCursor crosshairCursor];
|
|
break;
|
|
|
|
// NSCursor does not have cursors for these.
|
|
case VTK_CURSOR_SIZENE:
|
|
case VTK_CURSOR_SIZESW:
|
|
case VTK_CURSOR_SIZENW:
|
|
case VTK_CURSOR_SIZESE:
|
|
case VTK_CURSOR_SIZEALL:
|
|
cursor = [NSCursor arrowCursor];
|
|
break;
|
|
}
|
|
|
|
[cursor set];
|
|
}
|