1/*=========================================================================
2
3Program:   Visualization Toolkit
4Module:    vtkCocoaRenderWindow.mm
5
6Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7All rights reserved.
8See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10This software is distributed WITHOUT ANY WARRANTY; without even
11the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12PURPOSE.  See the above copyright notice for more information.
13
14=========================================================================*/
15
16#include "vtkOpenGLRenderWindow.h"
17#import <Cocoa/Cocoa.h>
18#import "vtkCocoaMacOSXSDKCompatibility.h" // Needed to support old SDKs
19
20#import "vtkCocoaRenderWindow.h"
21#import "vtkRenderWindowInteractor.h"
22#import "vtkCommand.h"
23#import "vtkIdList.h"
24#import "vtkObjectFactory.h"
25#import "vtkRendererCollection.h"
26#import "vtkCocoaGLView.h"
27
28#import <vtksys/ios/sstream>
29
30vtkStandardNewMacro(vtkCocoaRenderWindow);
31
32//----------------------------------------------------------------------------
33// This is a private class and an implementation detail, do not use it.
34// For fullscreen, an NSWindow that captures key events even when borderless
35@interface vtkCocoaFullScreenWindow : NSWindow
36{
37}
38@end
39
40@implementation vtkCocoaFullScreenWindow
41- (BOOL)canBecomeKeyWindow
42{
43  return YES;
44}
45@end
46
47//----------------------------------------------------------------------------
48// This is a private class and an implementation detail, do not use it.
49// It manages the NSWindow of a "pure VTK application",
50// as opposed to a regular Mac app that happens to use VTK.
51//----------------------------------------------------------------------------
52@interface vtkCocoaServer : NSObject
53{
54  @private
55  vtkCocoaRenderWindow *_renWin;
56}
57
58// Designated initializer
59- (id)initWithRenderWindow:(vtkCocoaRenderWindow *)inRenderWindow;
60
61- (void)startObservations;
62- (void)stopObservations;
63
64@end
65
66//----------------------------------------------------------------------------
67@implementation vtkCocoaServer
68
69//----------------------------------------------------------------------------
70- (id)initWithRenderWindow:(vtkCocoaRenderWindow *)inRenderWindow
71{
72  self = [super init];
73  if (self)
74    {
75    _renWin = inRenderWindow;
76    }
77  return self;
78}
79
80//----------------------------------------------------------------------------
81- (void)startObservations
82{
83  assert(_renWin);
84
85  int windowCreated = _renWin->GetWindowCreated();
86  NSWindow *win = reinterpret_cast<NSWindow *>(_renWin->GetRootWindow());
87  if (windowCreated && win)
88    {
89    // Receive notifications of this, and only this, window's closing.
90    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
91    [nc addObserver:self
92           selector:@selector(windowWillClose:)
93               name:NSWindowWillCloseNotification
94             object:win];
95    }
96
97  NSView *view = reinterpret_cast<NSView *>(_renWin->GetWindowId());
98  int viewCreated = _renWin->GetViewCreated();
99  if (viewCreated && view)
100    {
101    // Receive notifications of this, and only this, view's frame changing.
102    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
103    [nc addObserver:self
104           selector:@selector(viewFrameDidChange:)
105               name:NSViewFrameDidChangeNotification
106             object:view];
107    }
108}
109
110//----------------------------------------------------------------------------
111- (void)stopObservations
112{
113  assert(_renWin);
114
115  int windowCreated = _renWin->GetWindowCreated();
116  NSWindow *win = reinterpret_cast<NSWindow *>(_renWin->GetRootWindow());
117  if (windowCreated && win)
118    {
119    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
120    [nc removeObserver:self
121                  name:NSWindowWillCloseNotification
122                object:win];
123    }
124
125  NSView *view = reinterpret_cast<NSView *>(_renWin->GetWindowId());
126  int viewCreated = _renWin->GetViewCreated();
127  if (viewCreated && view)
128    {
129    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
130    [nc removeObserver:self
131                  name:NSViewFrameDidChangeNotification
132                object:view];
133    }
134}
135
136//----------------------------------------------------------------------------
137- (void)windowWillClose:(NSNotification *)aNotification
138{
139  // We should only get here if it was us that created the NSWindow.
140  assert(_renWin);
141  assert(_renWin->GetWindowCreated());
142
143  // We should only have observed our own NSWindow.
144  assert([aNotification object] == _renWin->GetRootWindow());
145  (void)aNotification;
146
147  // Stop observing because the window is closing.
148  [self stopObservations];
149
150  // The NSWindow is closing, so prevent anyone from accidentally using it.
151  _renWin->SetRootWindow(NULL);
152
153  // Tell interactor to stop the NSApplication's run loop
154  vtkRenderWindowInteractor *interactor = _renWin->GetInteractor();
155  if (interactor)
156    {
157    interactor->TerminateApp();
158    }
159}
160
161//----------------------------------------------------------------------------
162- (void)viewFrameDidChange:(NSNotification *)aNotification
163{
164  // We should only get here if it was us that created the NSView.
165  assert(_renWin);
166  assert(_renWin->GetViewCreated());
167
168  // We should only have observed our own NSView.
169  assert([aNotification object] == _renWin->GetWindowId());
170  (void)aNotification;
171
172  // Retrieve the Interactor.
173  vtkRenderWindowInteractor *interactor = _renWin->GetInteractor();
174  if (!interactor || !interactor->GetEnabled())
175    {
176    return;
177    }
178
179  // Get the NSView's new frame size.
180  NSView *view = reinterpret_cast<NSView *>(_renWin->GetWindowId());
181  assert(view);
182  NSRect frameRect = [view frame];
183  int width = (int)round(NSWidth(frameRect));
184  int height = (int)round(NSHeight(frameRect));
185
186  // Get the interactor's current cache of the size.
187  int size[2];
188  interactor->GetSize(size);
189
190  if (width != size[0] || height != size[1])
191    {
192    // Send ConfigureEvent from the Interactor.
193    interactor->UpdateSize(width, height);
194    interactor->InvokeEvent(vtkCommand::ConfigureEvent, NULL);
195    }
196}
197
198@end
199
200//----------------------------------------------------------------------------
201vtkCocoaRenderWindow::vtkCocoaRenderWindow()
202{
203  // First, create the cocoa objects manager. The dictionary is empty so
204  // essentially all objects are initialized to NULL.
205  NSMutableDictionary *cocoaManager = [NSMutableDictionary dictionary];
206
207  // SetCocoaManager works like an Obj-C setter, so do like Obj-C and
208  // init the ivar to null first.
209  this->CocoaManager = NULL;
210  this->SetCocoaManager(reinterpret_cast<void *>(cocoaManager));
211  [cocoaManager self]; // prevent premature collection under GC.
212
213  this->WindowCreated = 0;
214  this->ViewCreated = 0;
215  this->SetWindowName("Visualization Toolkit - Cocoa");
216  this->CursorHidden = 0;
217  this->ForceMakeCurrent = 0;
218  this->Capabilities = 0;
219  this->OnScreenInitialized = 0;
220  this->OffScreenInitialized = 0;
221}
222
223//----------------------------------------------------------------------------
224vtkCocoaRenderWindow::~vtkCocoaRenderWindow()
225{
226  if (this->CursorHidden)
227    {
228    this->ShowCursor();
229    }
230  this->Finalize();
231
232  vtkRenderer *ren;
233  vtkCollectionSimpleIterator rit;
234  this->Renderers->InitTraversal(rit);
235  while ( (ren = this->Renderers->GetNextRenderer(rit)) )
236    {
237    ren->SetRenderWindow(NULL);
238    }
239
240  delete[] this->Capabilities;
241  this->Capabilities = 0;
242
243  this->SetContextId(NULL);
244  this->SetPixelFormat(NULL);
245  this->SetCocoaServer(NULL);
246  this->SetRootWindow(NULL);
247  this->SetWindowId(NULL);
248  this->SetParentId(NULL);
249
250  // Release the cocoa object manager.
251  this->SetCocoaManager(NULL);
252}
253
254//----------------------------------------------------------------------------
255void vtkCocoaRenderWindow::Finalize()
256{
257  if(this->OffScreenInitialized)
258    {
259    this->OffScreenInitialized = 0;
260    this->DestroyOffScreenWindow();
261    }
262  if(this->OnScreenInitialized)
263    {
264    this->OnScreenInitialized = 0;
265    this->DestroyWindow();
266    }
267}
268
269//----------------------------------------------------------------------------
270void vtkCocoaRenderWindow::DestroyWindow()
271{
272  // finish OpenGL rendering
273  if (this->OwnContext && this->GetContextId())
274    {
275    this->MakeCurrent();
276
277    // tell each of the renderers that this render window/graphics context
278    // is being removed (the RendererCollection is removed by vtkRenderWindow's
279    // destructor)
280    vtkCollectionSimpleIterator rsit;
281    vtkRenderer *ren;
282    for ( this->Renderers->InitTraversal(rsit);
283          (ren = this->Renderers->GetNextRenderer(rsit));)
284      {
285      ren->SetRenderWindow(NULL);
286      ren->SetRenderWindow(this);
287      }
288  }
289  this->SetContextId(NULL);
290  this->SetPixelFormat(NULL);
291
292  vtkCocoaServer *server = (vtkCocoaServer *)this->GetCocoaServer();
293  [server stopObservations];
294  this->SetCocoaServer(NULL);
295
296  // If we created it, close the NSWindow.
297  if (this->WindowCreated)
298    {
299    NSWindow *window = (NSWindow*)this->GetRootWindow();
300    [window close];
301    }
302
303  this->SetWindowId(NULL);
304  this->SetParentId(NULL);
305  this->SetRootWindow(NULL);
306  this->WindowCreated = 0;
307  this->ViewCreated = 0;
308}
309
310//----------------------------------------------------------------------------
311void vtkCocoaRenderWindow::SetWindowName( const char * _arg )
312{
313  vtkWindow::SetWindowName(_arg);
314  if (this->GetRootWindow())
315    {
316    NSString *winTitleStr = [NSString stringWithUTF8String:_arg];
317
318    [(NSWindow*)this->GetRootWindow() setTitle:winTitleStr];
319    }
320}
321
322//----------------------------------------------------------------------------
323bool vtkCocoaRenderWindow::InitializeFromCurrentContext()
324{
325  NSOpenGLContext *currentContext = [NSOpenGLContext currentContext];
326  if (currentContext != NULL)
327    {
328    NSView *currentView = [currentContext view];
329    if (currentView != NULL)
330      {
331      NSWindow *window = [currentView window];
332      this->SetWindowId(currentView);
333      this->SetRootWindow(window);
334      this->SetContextId((void*)currentContext);
335      this->OpenGLInit();
336      this->OwnContext = 0;
337      return true;
338      }
339    }
340  return false;
341}
342
343//----------------------------------------------------------------------------
344int vtkCocoaRenderWindow::GetEventPending()
345{
346  return 0;
347}
348
349//----------------------------------------------------------------------------
350// Initialize the rendering process.
351void vtkCocoaRenderWindow::Start()
352{
353  this->Initialize();
354
355  // set the current window
356  this->MakeCurrent();
357}
358
359//----------------------------------------------------------------------------
360void vtkCocoaRenderWindow::MakeCurrent()
361{
362  if (this->GetContextId())
363    {
364    [(NSOpenGLContext*)this->GetContextId() makeCurrentContext];
365    }
366}
367
368// ----------------------------------------------------------------------------
369// Description:
370// Tells if this window is the current OpenGL context for the calling thread.
371bool vtkCocoaRenderWindow::IsCurrent()
372{
373  bool result=false;
374  if(this->GetContextId()!=0)
375    {
376    result=static_cast<NSOpenGLContext *>(this->GetContextId())==
377      [NSOpenGLContext currentContext];
378    }
379  return result;
380}
381
382//----------------------------------------------------------------------------
383bool vtkCocoaRenderWindow::IsDrawable()
384{
385  // you must initialize it first
386  // else it always evaluates false
387  this->Initialize();
388
389  // first check that window is valid
390  NSView *theView = (NSView*)this->GetWindowId();
391  bool win =[[theView window] windowNumber]>0;
392
393  // then check that the drawable is valid
394  NSOpenGLContext *context = (NSOpenGLContext *)this->GetContextId();
395  bool ok  = [context view] != nil;
396  return win && ok;
397}
398
399//----------------------------------------------------------------------------
400void vtkCocoaRenderWindow::UpdateContext()
401{
402  if (this->GetContextId())
403    {
404    [(NSOpenGLContext*)this->GetContextId() update];
405    }
406}
407
408//----------------------------------------------------------------------------
409const char* vtkCocoaRenderWindow::ReportCapabilities()
410{
411  this->MakeCurrent();
412
413  const char* glVendor = (const char*) glGetString(GL_VENDOR);
414  const char* glRenderer = (const char*) glGetString(GL_RENDERER);
415  const char* glVersion = (const char*) glGetString(GL_VERSION);
416  const char* glExtensions = (const char*) glGetString(GL_EXTENSIONS);
417
418  vtksys_ios::ostringstream strm;
419  strm << "OpenGL vendor string:  " << glVendor
420       << "\nOpenGL renderer string:  " << glRenderer
421       << "\nOpenGL version string:  " << glVersion
422       << "\nOpenGL extensions:  " << glExtensions << endl;
423
424  // Obtain the OpenGL context in order to keep track of the current screen.
425  NSOpenGLContext* context = (NSOpenGLContext*)this->GetContextId();
426  GLint currentScreen = [context currentVirtualScreen];
427
428  // The NSOpenGLPixelFormat can only be queried for one particular
429  // attribute at a time. Just make repeated queries to get the
430  // pertinent settings.
431  NSOpenGLPixelFormat* pixelFormat = (NSOpenGLPixelFormat*)this->GetPixelFormat();
432  strm << "PixelFormat Descriptor:" << endl;
433  GLint pfd = 0;
434  [pixelFormat getValues: &pfd forAttribute: NSOpenGLPFAColorSize forVirtualScreen: currentScreen];
435  strm  << "  colorSize:  " << pfd << endl;
436
437  [pixelFormat getValues: &pfd forAttribute: NSOpenGLPFAAlphaSize forVirtualScreen: currentScreen];
438  strm  << "  alphaSize:  " << pfd << endl;
439
440  [pixelFormat getValues: &pfd forAttribute: NSOpenGLPFAStencilSize forVirtualScreen: currentScreen];
441  strm  << "  stencilSize:  " << pfd << endl;
442
443  [pixelFormat getValues: &pfd forAttribute: NSOpenGLPFADepthSize forVirtualScreen: currentScreen];
444  strm  << "  depthSize:  " << pfd << endl;
445
446  [pixelFormat getValues: &pfd forAttribute: NSOpenGLPFAAccumSize forVirtualScreen: currentScreen];
447  strm  << "  accumSize:  " << pfd << endl;
448
449  [pixelFormat getValues: &pfd forAttribute: NSOpenGLPFADoubleBuffer forVirtualScreen: currentScreen];
450  strm  << "  double buffer:  " << (pfd == 0 ? "No" : "Yes") << endl;
451
452  [pixelFormat getValues: &pfd forAttribute: NSOpenGLPFAStereo forVirtualScreen: currentScreen];
453  strm  << "  stereo:  " << (pfd == 0 ? "No" : "Yes") << endl;
454
455  [pixelFormat getValues: &pfd forAttribute: NSOpenGLPFAStencilSize forVirtualScreen: currentScreen];
456  strm  << "  stencil:  " << pfd << endl;
457
458  [pixelFormat getValues: &pfd forAttribute: NSOpenGLPFAAccelerated forVirtualScreen: currentScreen];
459  strm  << "  hardware acceleration::  " << (pfd == 0 ? "No" : "Yes") << endl;
460
461  delete[] this->Capabilities;
462
463  size_t len = strm.str().length() + 1;
464  this->Capabilities = new char[len];
465  strlcpy(this->Capabilities, strm.str().c_str(), len);
466
467  return this->Capabilities;
468}
469
470//----------------------------------------------------------------------------
471int vtkCocoaRenderWindow::SupportsOpenGL()
472{
473  this->MakeCurrent();
474  if (!this->GetContextId() || !this->GetPixelFormat())
475    {
476    return 0;
477    }
478  return 1;
479}
480
481//----------------------------------------------------------------------------
482int vtkCocoaRenderWindow::IsDirect()
483{
484  this->MakeCurrent();
485  if (!this->GetContextId() || !this->GetPixelFormat())
486    {
487    return 0;
488    }
489  return 1;
490}
491
492//----------------------------------------------------------------------------
493void vtkCocoaRenderWindow::SetSize(int* a)
494{
495  this->SetSize( a[0], a[1] );
496}
497
498//----------------------------------------------------------------------------
499void vtkCocoaRenderWindow::SetSize(int x, int y)
500{
501  static int resizing = 0;
502
503  if ((this->Size[0] != x) || (this->Size[1] != y) || (this->GetParentId()))
504    {
505    this->Modified();
506    this->Size[0] = x;
507    this->Size[1] = y;
508    if (this->GetParentId() && this->GetWindowId() && this->Mapped)
509      {
510      // Set the NSView size, not the window size.
511      if (!resizing)
512        {
513        resizing = 1;
514        NSView *theView = (NSView*)this->GetWindowId();
515        NSRect viewRect = [theView frame];
516        CGFloat oldHeight = NSHeight(viewRect);
517        CGFloat height = (CGFloat)y;
518        CGFloat width = (CGFloat)x;
519        CGFloat xpos = NSMinX(viewRect);
520        CGFloat ypos = NSMinY(viewRect) - (height - oldHeight);
521        NSRect theRect = NSMakeRect(xpos, ypos, width, height);
522        [theView setFrame:theRect];
523        [theView setNeedsDisplay:YES];
524        resizing = 0;
525        }
526      }
527    else if (this->GetRootWindow() && this->Mapped)
528      {
529      if (!resizing)
530        {
531        resizing = 1;
532        NSSize theSize = NSMakeSize((CGFloat)x, (CGFloat)y);
533        [(NSWindow*)this->GetRootWindow() setContentSize:theSize];
534        resizing = 0;
535        }
536      }
537    }
538}
539
540//----------------------------------------------------------------------------
541void vtkCocoaRenderWindow::SetForceMakeCurrent()
542{
543  this->ForceMakeCurrent = 1;
544}
545
546//----------------------------------------------------------------------------
547void vtkCocoaRenderWindow::SetPosition(int* a)
548{
549  this->SetPosition( a[0], a[1] );
550}
551
552//----------------------------------------------------------------------------
553void vtkCocoaRenderWindow::SetPosition(int x, int y)
554{
555  static int resizing = 0;
556
557  if ((this->Position[0] != x) || (this->Position[1] != y)
558      || (this->GetParentId()))
559    {
560    this->Modified();
561    this->Position[0] = x;
562    this->Position[1] = y;
563    if (this->GetParentId() && this->GetWindowId() && this->Mapped)
564      {
565      // Set the NSView position relative to the parent
566      if (!resizing)
567        {
568        resizing = 1;
569        NSRect parentRect = [(NSView*)this->GetParentId() frame];
570        NSView *theView = (NSView*)this->GetWindowId();
571        NSRect viewRect = [theView frame];
572        CGFloat parentHeight = NSHeight(parentRect);
573        CGFloat height = NSHeight(viewRect);
574        CGFloat xpos = (CGFloat)x;
575        CGFloat ypos = parentHeight - height - (CGFloat)y;
576        NSPoint origin = NSMakePoint(xpos,ypos);
577        [theView setFrameOrigin:origin];
578        [theView setNeedsDisplay:YES];
579        resizing = 0;
580        }
581      }
582    else if (this->GetRootWindow() && this->Mapped)
583      {
584      if (!resizing)
585        {
586        resizing = 1;
587        NSPoint origin = NSMakePoint((CGFloat)x, (CGFloat)y);
588        [(NSWindow*)this->GetRootWindow() setFrameOrigin:origin];
589        resizing = 0;
590        }
591      }
592    }
593}
594
595//----------------------------------------------------------------------------
596// End the rendering process and display the image.
597void vtkCocoaRenderWindow::Frame()
598{
599  this->MakeCurrent();
600
601  if (!this->AbortRender && this->DoubleBuffer && this->SwapBuffers)
602    {
603    [(NSOpenGLContext*)this->GetContextId() flushBuffer];
604    }
605   else
606    {
607    glFlush();
608    }
609}
610
611//----------------------------------------------------------------------------
612// Update system if needed due to stereo rendering.
613void vtkCocoaRenderWindow::StereoUpdate()
614{
615  // if stereo is on and it wasn't before
616  if (this->StereoRender && (!this->StereoStatus))
617    {
618    switch (this->StereoType)
619      {
620      case VTK_STEREO_CRYSTAL_EYES:
621        this->StereoStatus = 1;
622        break;
623      case VTK_STEREO_RED_BLUE:
624        this->StereoStatus = 1;
625        break;
626      case VTK_STEREO_ANAGLYPH:
627        this->StereoStatus = 1;
628        break;
629      case VTK_STEREO_DRESDEN:
630        this->StereoStatus = 1;
631        break;
632      case VTK_STEREO_INTERLACED:
633        this->StereoStatus = 1;
634        break;
635      case VTK_STEREO_CHECKERBOARD:
636        this->StereoStatus = 1;
637        break;
638      case VTK_STEREO_SPLITVIEWPORT_HORIZONTAL:
639        this->StereoStatus = 1;
640        break;
641      }
642    }
643  else if ((!this->StereoRender) && this->StereoStatus)
644    {
645    switch (this->StereoType)
646      {
647      case VTK_STEREO_CRYSTAL_EYES:
648        this->StereoStatus = 0;
649        break;
650      case VTK_STEREO_RED_BLUE:
651        this->StereoStatus = 0;
652        break;
653      case VTK_STEREO_ANAGLYPH:
654        this->StereoStatus = 0;
655        break;
656      case VTK_STEREO_DRESDEN:
657        this->StereoStatus = 0;
658        break;
659      case VTK_STEREO_INTERLACED:
660        this->StereoStatus = 0;
661        break;
662      case VTK_STEREO_CHECKERBOARD:
663        this->StereoStatus = 0;
664        break;
665      case VTK_STEREO_SPLITVIEWPORT_HORIZONTAL:
666        this->StereoStatus = 0;
667        break;
668      }
669    }
670}
671
672//----------------------------------------------------------------------------
673// Specify various window parameters.
674void vtkCocoaRenderWindow::WindowConfigure()
675{
676  // this is all handled by the desiredVisualInfo method
677}
678
679//----------------------------------------------------------------------------
680void vtkCocoaRenderWindow::SetupPixelFormat(void*, void*, int, int, int)
681{
682  vtkErrorMacro(<< "vtkCocoaRenderWindow::SetupPixelFormat - IMPLEMENT");
683}
684
685//----------------------------------------------------------------------------
686void vtkCocoaRenderWindow::SetupPalette(void*)
687{
688  vtkErrorMacro(<< "vtkCocoaRenderWindow::SetupPalette - IMPLEMENT");
689}
690
691//----------------------------------------------------------------------------
692// Initialize the window for rendering.
693void vtkCocoaRenderWindow::CreateAWindow()
694{
695  static unsigned count = 1;
696
697  // As vtk is both crossplatform and a library, we don't know if it is being
698  // used in a 'regular Cocoa application' or as a 'pure vtk application'.
699  // By the former I mean a regular Cocoa application that happens to have
700  // a vtkCocoaGLView, by the latter I mean an application that only uses
701  // vtk APIs (which happen to use Cocoa as an implementation detail).
702  // Specifically, we can't know if NSApplicationMain() was ever called
703  // (which is usually done in main()), nor whether the NSApplication exists.
704  //
705  // So here we call +sharedApplication which will create the NSApplication
706  // if it does not exist.  If it does exist, this does nothing.
707  // We are not actually interested in the return value.
708  // This call is intentionally delayed until this CreateAWindow call
709  // to prevent Cocoa-window related stuff from happening in scenarios
710  // where vtkRenderWindows are created but never shown.
711  (void)[NSApplication sharedApplication];
712
713  // create an NSWindow only if neither an NSView nor an NSWindow have
714  // been specified already.  This is the case for a 'pure vtk application'.
715  // If you are using vtk in a 'regular Mac application' you should call
716  // SetRootWindow() and SetWindowId() so that a window is not created here.
717  if (!this->GetRootWindow() && !this->GetWindowId() && !this->GetParentId())
718    {
719    NSWindow* theWindow = nil;
720
721#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
722    NSScreen *screen = [NSScreen mainScreen];
723    if (this->FullScreen && screen)
724      {
725      NSRect ctRect = [screen frame];
726      this->Size[0] = (int)round(NSWidth(ctRect));
727      this->Size[1] = (int)round(NSHeight(ctRect));
728
729      theWindow = [[vtkCocoaFullScreenWindow alloc]
730                   initWithContentRect:ctRect
731                             styleMask:NSBorderlessWindowMask
732                               backing:NSBackingStoreBuffered
733                                 defer:NO];
734
735      // This will hide the menu and the dock
736      [theWindow setLevel:NSMainMenuWindowLevel+1];
737      // This will show the menu and the dock
738      //[theWindow setLevel:NSFloatingWindowLevel];
739      }
740    else
741#endif
742      {
743      if ((this->Size[0]+this->Size[1]) == 0)
744        {
745        this->Size[0] = 300;
746        this->Size[1] = 300;
747        }
748      if ((this->Position[0]+this->Position[1]) == 0)
749        {
750        this->Position[0] = 50;
751        this->Position[1] = 50;
752        }
753
754      NSRect ctRect = NSMakeRect((CGFloat)this->Position[0],
755                                 (CGFloat)this->Position[1],
756                                 (CGFloat)this->Size[0],
757                                 (CGFloat)this->Size[1]);
758
759      theWindow = [[NSWindow alloc]
760                   initWithContentRect:ctRect
761                             styleMask:NSTitledWindowMask |
762                                       NSClosableWindowMask |
763                                       NSMiniaturizableWindowMask |
764                                       NSResizableWindowMask
765                               backing:NSBackingStoreBuffered
766                                 defer:NO];
767      }
768
769    if (!theWindow)
770      {
771      vtkErrorMacro("Could not create window, serious error!");
772      return;
773      }
774
775    this->SetRootWindow(theWindow);
776    this->WindowCreated = 1;
777
778    // makeKeyAndOrderFront: will show the window
779    // we don't want this if offscreen was requested
780    if(!this->OffScreenRendering)
781      {
782      [theWindow makeKeyAndOrderFront:nil];
783      [theWindow setAcceptsMouseMovedEvents:YES];
784      }
785  }
786  // create a view if one has not been specified
787  if (!this->GetWindowId())
788    {
789    if (this->GetParentId())
790      {
791      NSView *parent = (NSView*)this->GetParentId();
792      NSRect parentRect = [parent frame];
793      CGFloat parentHeight = NSHeight(parentRect);
794      CGFloat parentWidth = NSWidth(parentRect);
795      CGFloat width = (CGFloat)this->Size[0];
796      CGFloat height = (CGFloat)this->Size[1];
797      CGFloat x = (CGFloat)this->Position[0];
798      CGFloat y = parentHeight - height - (CGFloat)this->Position[1];
799
800      // A whole bunch of sanity checks: frame must be inside parent
801      if (x > parentWidth - 1) { x = parentWidth - 1; };
802      if (y > parentHeight - 1) { y = parentHeight - 1; };
803      if (x < 0.0) { x = 0.0; }
804      if (y < 0.0) { y = 0.0; }
805      if (x + width > parentWidth) { width = parentWidth - x; }
806      if (y + height > parentWidth) { height = parentHeight - y; }
807
808      // Don't use vtkCocoaGLView, because if we are in Tk (which is what
809      // SetParentId() was added for) then the Tk superview handles the events.
810      NSRect glRect = NSMakeRect(x, y, width, height);
811      NSView *glView = [[NSView alloc] initWithFrame:glRect];
812      [parent addSubview:glView];
813      this->SetWindowId(glView);
814      this->ViewCreated = 1;
815#if VTK_OBJC_IS_MRR
816      [glView release];
817#endif
818      }
819    else
820      {
821      NSRect glRect = NSMakeRect(0.0, 0.0,
822                                 (CGFloat)this->Size[0],
823                                 (CGFloat)this->Size[1]);
824
825      // Create a vtkCocoaGLView.
826      vtkCocoaGLView *glView = [[vtkCocoaGLView alloc] initWithFrame:glRect];
827      [(NSWindow*)this->GetRootWindow() setContentView:glView];
828      this->SetWindowId(glView);
829      this->ViewCreated = 1;
830      [glView setVTKRenderWindow:this];
831#if VTK_OBJC_IS_MRR
832      [glView release];
833#endif
834      }
835    }
836
837  this->CreateGLContext();
838
839  // Change the window title, but only if it was created by vtk
840  if (this->WindowCreated)
841    {
842    NSString *winName = [NSString stringWithFormat:@"Visualization Toolkit - Cocoa #%u", count++];
843    this->SetWindowName([winName cStringUsingEncoding:NSASCIIStringEncoding]);
844    }
845
846  // the error "invalid drawable" in the console from this call can appear
847  // but only early in the app's lifetime (ie sometime during launch)
848  // IMPORTANT: this is necessary to update the context here in case of
849  // hardware offscreen rendering
850  NSOpenGLContext* context = (NSOpenGLContext*)this->GetContextId();
851  [context setView:(NSView*)this->GetWindowId()];
852
853  [context update];
854
855  this->MakeCurrent();
856
857  // wipe out any existing display lists
858  vtkRenderer *renderer = NULL;
859  vtkCollectionSimpleIterator rsit;
860
861  for ( this->Renderers->InitTraversal(rsit);
862        (renderer = this->Renderers->GetNextRenderer(rsit));)
863    {
864    renderer->SetRenderWindow(0);
865    renderer->SetRenderWindow(this);
866    }
867  this->OpenGLInit();
868  this->Mapped = 1;
869
870  // Now that the NSView and NSWindow exist, the vtkCocoaServer can start its observations.
871  vtkCocoaServer *server = [[vtkCocoaServer alloc] initWithRenderWindow:this];
872  this->SetCocoaServer(reinterpret_cast<void *>(server));
873  [server startObservations];
874#if VTK_OBJC_IS_MRR
875  [server release];
876#endif
877}
878
879//----------------------------------------------------------------------------
880void vtkCocoaRenderWindow::CreateGLContext()
881{
882  // keep trying to get different pixelFormats until successful
883  NSOpenGLPixelFormat *pixelFormat = nil;
884  while (pixelFormat == nil)
885    {
886    int i = 0;
887    NSOpenGLPixelFormatAttribute attribs[20];
888
889    attribs[i++] = NSOpenGLPFAAccelerated;
890    attribs[i++] = NSOpenGLPFADepthSize;
891    attribs[i++] = (NSOpenGLPixelFormatAttribute)32;
892
893    if (this->MultiSamples != 0)
894      {
895      attribs[i++] = NSOpenGLPFASampleBuffers;
896      attribs[i++] = (NSOpenGLPixelFormatAttribute)1;
897      attribs[i++] = NSOpenGLPFASamples;
898      attribs[i++] = (NSOpenGLPixelFormatAttribute)(this->MultiSamples);
899      attribs[i++] = NSOpenGLPFAMultisample;
900      }
901
902    if (this->DoubleBuffer != 0)
903      {
904      attribs[i++] = NSOpenGLPFADoubleBuffer;
905      }
906
907    attribs[i++] = (NSOpenGLPixelFormatAttribute)0;
908
909    // make sure that size of array was not exceeded
910    assert(sizeof(NSOpenGLPixelFormatAttribute)*i < sizeof(attribs));
911
912    pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
913
914    if (pixelFormat == nil)
915      {
916      if (this->MultiSamples == 0)
917        {
918        // after trying with no multisamples, we are done
919        break;
920        }
921      else if (this->MultiSamples < 4)
922        {
923        // next time try with no multisamples
924        this->MultiSamples = 0;
925        }
926      else
927        {
928        this->MultiSamples /= 2;
929        }
930      }
931    }
932
933  NSOpenGLContext *context = [[NSOpenGLContext alloc]
934                              initWithFormat:pixelFormat
935                                shareContext:nil];
936
937  // This syncs the OpenGL context to the VBL to prevent tearing
938  GLint one = 1;
939  [context setValues:&one forParameter:NSOpenGLCPSwapInterval];
940
941  this->SetPixelFormat((void*)pixelFormat);
942  this->SetContextId((void*)context);
943
944  [pixelFormat self]; // prevent premature collection under GC.
945  [context self]; // prevent premature collection under GC.
946
947#if VTK_OBJC_IS_MRR
948  [pixelFormat release];
949  [context release];
950#endif
951}
952
953//----------------------------------------------------------------------------
954// Initialize the rendering window.
955void vtkCocoaRenderWindow::Initialize ()
956{
957  if(this->OffScreenRendering)
958    {
959    // destroy on screen
960    if(this->OnScreenInitialized)
961      {
962      this->DestroyWindow();
963      this->OnScreenInitialized = 0;
964      }
965    // create off screen
966    if(!this->OffScreenInitialized)
967      {
968      int width=((this->Size[0]>0) ? this->Size[0] : 300);
969      int height=((this->Size[1]>0) ? this->Size[1] : 300);
970      if(!this->CreateHardwareOffScreenWindow(width,height))
971        {
972        // no other offscreen mode available, do on screen rendering
973        this->CreateAWindow();
974        }
975      this->OffScreenInitialized = 1;
976      }
977    }
978  else
979    {
980    // destroy off screen
981    if(this->OffScreenInitialized)
982      {
983      this->DestroyOffScreenWindow();
984      }
985    // create on screen
986    if(!this->OnScreenInitialized)
987      {
988      this->OnScreenInitialized = 1;
989      this->CreateAWindow();
990      }
991    }
992  if((this->OnScreenInitialized) && (this->Mapped))
993    {
994    // the error "invalid drawable" in the console from this call can appear
995    // but only early in the app's lifetime (ie sometime during launch)
996    // IMPORTANT: this is necessary to update the context here in case of
997    // onscreen rendering
998    NSOpenGLContext* context = (NSOpenGLContext*)this->GetContextId();
999    [context setView:(NSView*)this->GetWindowId()];
1000
1001    [context update];
1002    }
1003}
1004
1005//-----------------------------------------------------------------------------
1006void vtkCocoaRenderWindow::DestroyOffScreenWindow()
1007{
1008  if(this->OffScreenUseFrameBuffer)
1009    {
1010    this->DestroyHardwareOffScreenWindow();
1011    }
1012  else
1013    {
1014    // on screen
1015    this->DestroyWindow();
1016    }
1017}
1018
1019//----------------------------------------------------------------------------
1020// Get the current size of the window.
1021int *vtkCocoaRenderWindow::GetSize()
1022{
1023  // if we aren't mapped then just return the ivar
1024  if (!this->Mapped)
1025    {
1026    return this->Superclass::GetSize();
1027    }
1028
1029  // We want to return the size of 'the window'.  But the term 'window'
1030  // is overloaded. It's really the NSView that vtk draws into, so we
1031  // return its size.
1032  NSView* view = (NSView*)this->GetWindowId();
1033  if (view)
1034    {
1035    NSRect frameRect = [view frame];
1036    this->Size[0] = (int)round(NSWidth(frameRect));
1037    this->Size[1] = (int)round(NSHeight(frameRect));
1038    }
1039  return this->Superclass::GetSize();
1040}
1041
1042//----------------------------------------------------------------------------
1043// Get the current size of the screen in pixels.
1044int *vtkCocoaRenderWindow::GetScreenSize()
1045{
1046  NSOpenGLContext* context = (NSOpenGLContext*)this->GetContextId();
1047  GLint currentScreen = [context currentVirtualScreen];
1048
1049  NSScreen* screen = [[NSScreen screens] objectAtIndex:currentScreen];
1050  NSRect screenRect = [screen frame];
1051
1052  this->Size[0] = (int)round(NSWidth(screenRect));
1053  this->Size[1] = (int)round(NSHeight(screenRect));
1054
1055  return this->Size;
1056}
1057
1058//----------------------------------------------------------------------------
1059// Get the position in screen coordinates of the window.
1060int *vtkCocoaRenderWindow::GetPosition()
1061{
1062  // if we aren't mapped then just return the ivar
1063  if (!this->Mapped)
1064    {
1065    return this->Position;
1066    }
1067
1068  if (this->GetParentId() && this->GetWindowId())
1069    {
1070    // Get display position of the NSView within its parent
1071    NSRect parentRect = [(NSView*)this->GetParentId() frame];
1072    NSRect viewFrameRect = [(NSView*)this->GetWindowId() frame];
1073    this->Position[0] = int(round(NSMinX(viewFrameRect)));
1074    this->Position[1] = int(round((NSHeight(parentRect)
1075                                   - NSHeight(viewFrameRect)
1076                                   - NSMinY(viewFrameRect))));
1077    }
1078  else
1079    {
1080    // We want to return the position of 'the window'.  But the term 'window'
1081    // is overloaded. In this case, it's the position of the NSWindow itself
1082    // on the screen that we return. We don't much care where the NSView is
1083    // within the NSWindow.
1084    NSWindow *window = (NSWindow*)this->GetRootWindow();
1085    if (window)
1086      {
1087      NSRect winFrameRect = [window frame];
1088      this->Position[0] = (int)NSMinX(winFrameRect);
1089      this->Position[1] = (int)NSMinY(winFrameRect);
1090      }
1091    }
1092
1093  return this->Position;
1094}
1095
1096//----------------------------------------------------------------------------
1097// Change the window to fill the entire screen.
1098void vtkCocoaRenderWindow::SetFullScreen(int arg)
1099{
1100  if (this->FullScreen == arg)
1101    {
1102    return;
1103    }
1104
1105  if (!this->Mapped)
1106    {
1107    this->FullScreen = arg;
1108    return;
1109    }
1110
1111  // set the mode
1112  this->FullScreen = arg;
1113  if (this->FullScreen <= 0)
1114    {
1115    this->Position[0] = this->OldScreen[0];
1116    this->Position[1] = this->OldScreen[1];
1117    this->Size[0] = this->OldScreen[2];
1118    this->Size[1] = this->OldScreen[3];
1119    this->Borders = this->OldScreen[4];
1120    }
1121  else
1122    {
1123    // if window already up get its values
1124    if (this->GetRootWindow())
1125      {
1126      int* pos = this->GetPosition();
1127      this->OldScreen[0] = pos[0];
1128      this->OldScreen[1] = pos[1];
1129
1130      this->OldScreen[4] = this->Borders;
1131      this->PrefFullScreen();
1132      }
1133    }
1134
1135  // remap the window
1136  this->WindowRemap();
1137
1138  this->Modified();
1139}
1140
1141//----------------------------------------------------------------------------
1142//
1143// Set the variable that indicates that we want a stereo capable window
1144// be created. This method can only be called before a window is realized.
1145//
1146void vtkCocoaRenderWindow::SetStereoCapableWindow(int capable)
1147{
1148  if (this->GetContextId() == 0)
1149    {
1150    vtkRenderWindow::SetStereoCapableWindow(capable);
1151    }
1152  else
1153    {
1154    vtkWarningMacro(<< "Requesting a StereoCapableWindow must be performed "
1155                    << "before the window is realized, i.e. before a render.");
1156    }
1157}
1158
1159//----------------------------------------------------------------------------
1160// Set the preferred window size to full screen.
1161void vtkCocoaRenderWindow::PrefFullScreen()
1162{
1163  int *size = this->GetScreenSize();
1164  vtkWarningMacro(<< "Can only set FullScreen before showing window: "
1165                  << size[0] << 'x' << size[1] << ".");
1166}
1167
1168//----------------------------------------------------------------------------
1169// Remap the window.
1170void vtkCocoaRenderWindow::WindowRemap()
1171{
1172  vtkWarningMacro(<< "Can't remap the window.");
1173  // Acquire the display and capture the screen.
1174  // Create the full-screen window.
1175  // Add the context.
1176}
1177
1178//----------------------------------------------------------------------------
1179void vtkCocoaRenderWindow::PrintSelf(ostream& os, vtkIndent indent)
1180{
1181  this->Superclass::PrintSelf(os,indent);
1182
1183  os << indent << "MultiSamples: " << this->MultiSamples << endl;
1184  os << indent << "CocoaManager: " << this->GetCocoaManager() << endl;
1185  os << indent << "RootWindow (NSWindow): " << this->GetRootWindow() << endl;
1186  os << indent << "WindowId (NSView): " << this->GetWindowId() << endl;
1187  os << indent << "ParentId: " << this->GetParentId() << endl;
1188  os << indent << "ContextId: " << this->GetContextId() << endl;
1189  os << indent << "PixelFormat: " << this->GetPixelFormat() << endl;
1190  os << indent << "WindowCreated: " << (this->GetWindowCreated() ? "Yes" : "No") << endl;
1191  os << indent << "ViewCreated: " << (this->GetViewCreated() ? "Yes" : "No") << endl;
1192}
1193
1194//----------------------------------------------------------------------------
1195int vtkCocoaRenderWindow::GetDepthBufferSize()
1196{
1197  if ( this->Mapped )
1198    {
1199    GLint size = 0;
1200    glGetIntegerv( GL_DEPTH_BITS, &size );
1201    return (int) size;
1202    }
1203  else
1204    {
1205    vtkDebugMacro(<< "Window is not mapped yet!" );
1206    return 24;
1207    }
1208}
1209
1210//----------------------------------------------------------------------------
1211// Returns the NSWindow* associated with this vtkRenderWindow.
1212void *vtkCocoaRenderWindow::GetRootWindow()
1213{
1214  NSMutableDictionary *manager =
1215    reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
1216  return reinterpret_cast<void *>([manager objectForKey:@"RootWindow"]);
1217}
1218
1219//----------------------------------------------------------------------------
1220// Sets the NSWindow* associated with this vtkRenderWindow.
1221void vtkCocoaRenderWindow::SetRootWindow(void *arg)
1222{
1223  if (arg != NULL)
1224    {
1225    NSMutableDictionary *manager =
1226      reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
1227    [manager setObject:reinterpret_cast<id>(arg)
1228                forKey:@"RootWindow"];
1229    }
1230  else
1231    {
1232    NSMutableDictionary *manager =
1233      reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
1234    [manager removeObjectForKey:@"RootWindow"];
1235    }
1236}
1237
1238//----------------------------------------------------------------------------
1239// Returns the NSView* associated with this vtkRenderWindow.
1240void *vtkCocoaRenderWindow::GetWindowId()
1241{
1242  NSMutableDictionary *manager =
1243    reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
1244  return reinterpret_cast<void *>([manager objectForKey:@"WindowId"]);
1245}
1246
1247//----------------------------------------------------------------------------
1248// Sets the NSView* associated with this vtkRenderWindow.
1249void vtkCocoaRenderWindow::SetWindowId(void *arg)
1250{
1251  if (arg != NULL)
1252    {
1253    NSMutableDictionary *manager =
1254      reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
1255    [manager setObject:reinterpret_cast<id>(arg)
1256                forKey:@"WindowId"];
1257    }
1258  else
1259    {
1260    NSMutableDictionary *manager =
1261      reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
1262    [manager removeObjectForKey:@"WindowId"];
1263    }
1264}
1265
1266//----------------------------------------------------------------------------
1267// Returns the NSView* that is the parent of this vtkRenderWindow.
1268void *vtkCocoaRenderWindow::GetParentId()
1269{
1270  NSMutableDictionary *manager =
1271    reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
1272  return reinterpret_cast<void *>([manager objectForKey:@"ParentId"]);
1273}
1274
1275//----------------------------------------------------------------------------
1276// Sets the NSView* that this vtkRenderWindow should use as a parent.
1277void vtkCocoaRenderWindow::SetParentId(void *arg)
1278{
1279  if (arg != NULL)
1280    {
1281    NSMutableDictionary *manager =
1282      reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
1283    [manager setObject:reinterpret_cast<id>(arg)
1284                forKey:@"ParentId"];
1285    }
1286  else
1287    {
1288    NSMutableDictionary *manager =
1289      reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
1290    [manager removeObjectForKey:@"ParentId"];
1291    }
1292}
1293
1294//----------------------------------------------------------------------------
1295// Sets the NSOpenGLContext* associated with this vtkRenderWindow.
1296void vtkCocoaRenderWindow::SetContextId(void *contextId)
1297{
1298  if (contextId != NULL)
1299    {
1300    NSMutableDictionary *manager =
1301      reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
1302    [manager setObject:reinterpret_cast<id>(contextId)
1303                forKey:@"ContextId"];
1304    }
1305  else
1306    {
1307    NSMutableDictionary *manager =
1308      reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
1309    [manager removeObjectForKey:@"ContextId"];
1310    }
1311}
1312
1313//----------------------------------------------------------------------------
1314// Returns the NSOpenGLContext* associated with this vtkRenderWindow.
1315void *vtkCocoaRenderWindow::GetContextId()
1316{
1317  NSMutableDictionary *manager =
1318    reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
1319  return reinterpret_cast<void *>([manager objectForKey:@"ContextId"]);
1320}
1321
1322//----------------------------------------------------------------------------
1323// Sets the NSOpenGLPixelFormat* associated with this vtkRenderWindow.
1324void vtkCocoaRenderWindow::SetPixelFormat(void *pixelFormat)
1325{
1326  if (pixelFormat != NULL)
1327    {
1328    NSMutableDictionary *manager =
1329      reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
1330    [manager setObject:reinterpret_cast<id>(pixelFormat)
1331                forKey:@"PixelFormat"];
1332    }
1333  else
1334    {
1335    NSMutableDictionary *manager =
1336      reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
1337    [manager removeObjectForKey:@"PixelFormat"];
1338    }
1339}
1340
1341//----------------------------------------------------------------------------
1342// Returns the NSOpenGLPixelFormat* associated with this vtkRenderWindow.
1343void *vtkCocoaRenderWindow::GetPixelFormat()
1344{
1345  NSMutableDictionary *manager =
1346    reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
1347  return reinterpret_cast<void *>([manager objectForKey:@"PixelFormat"]);
1348}
1349
1350//----------------------------------------------------------------------------
1351void vtkCocoaRenderWindow::SetCocoaServer(void *server)
1352{
1353  if (server != NULL)
1354    {
1355    NSMutableDictionary *manager =
1356      reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
1357    [manager setObject:reinterpret_cast<vtkCocoaServer *>(server)
1358                forKey:@"CocoaServer"];
1359    }
1360  else
1361    {
1362    NSMutableDictionary *manager =
1363      reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
1364    [manager removeObjectForKey:@"CocoaServer"];
1365    }
1366}
1367
1368//----------------------------------------------------------------------------
1369void *vtkCocoaRenderWindow::GetCocoaServer()
1370{
1371  NSMutableDictionary *manager =
1372    reinterpret_cast<NSMutableDictionary *>(this->GetCocoaManager());
1373  return reinterpret_cast<void *>([manager objectForKey:@"CocoaServer"]);
1374}
1375
1376//----------------------------------------------------------------------------
1377void vtkCocoaRenderWindow::SetCocoaManager(void *manager)
1378{
1379  NSMutableDictionary *currentCocoaManager =
1380    reinterpret_cast<NSMutableDictionary *>(this->CocoaManager);
1381  NSMutableDictionary *newCocoaManager =
1382    reinterpret_cast<NSMutableDictionary *>(manager);
1383
1384  if (currentCocoaManager != newCocoaManager)
1385    {
1386    // Why not use Cocoa's retain and release?  Without garbage collection
1387    // (GC), the two are equivalent anyway because of 'toll free bridging',
1388    // so no problem there.  With GC, retain and release do nothing, but
1389    // CFRetain and CFRelease still manipulate the internal reference count.
1390    // We need that, since we are not using strong references (we don't want
1391    // it collected out from under us!).
1392    if (currentCocoaManager)
1393      {
1394      CFRelease(currentCocoaManager);
1395      }
1396    if (newCocoaManager)
1397      {
1398      this->CocoaManager = const_cast<void *>(CFRetain (newCocoaManager));
1399      }
1400    else
1401      {
1402      this->CocoaManager = NULL;
1403      }
1404    }
1405}
1406
1407//----------------------------------------------------------------------------
1408void vtkCocoaRenderWindow::SetWindowInfo(char *info)
1409{
1410  // The paramater is an ASCII string of a decimal number representing
1411  // a pointer to the window. Convert it back to a pointer.
1412  ptrdiff_t tmp = 0;
1413  if (info)
1414    {
1415    (void)sscanf(info, "%tu", &tmp);
1416    }
1417
1418  this->SetWindowId (reinterpret_cast<void *>(tmp));
1419}
1420
1421//----------------------------------------------------------------------------
1422void vtkCocoaRenderWindow::SetParentInfo(char *info)
1423{
1424  // The paramater is an ASCII string of a decimal number representing
1425  // a pointer to the window. Convert it back to a pointer.
1426  ptrdiff_t tmp = 0;
1427  if (info)
1428    {
1429    (void)sscanf(info, "%tu", &tmp);
1430    }
1431
1432  this->SetParentId (reinterpret_cast<void *>(tmp));
1433}
1434
1435//----------------------------------------------------------------------------
1436void *vtkCocoaRenderWindow::GetCocoaManager()
1437{
1438  return this->CocoaManager;
1439}
1440
1441//----------------------------------------------------------------------------
1442void vtkCocoaRenderWindow::HideCursor()
1443{
1444  if (this->CursorHidden)
1445    {
1446    return;
1447    }
1448  this->CursorHidden = 1;
1449
1450  [NSCursor hide];
1451}
1452
1453//----------------------------------------------------------------------------
1454void vtkCocoaRenderWindow::ShowCursor()
1455{
1456  if (!this->CursorHidden)
1457    {
1458    return;
1459    }
1460  this->CursorHidden = 0;
1461
1462  [NSCursor unhide];
1463}
1464
1465// ---------------------------------------------------------------------------
1466int vtkCocoaRenderWindow::GetViewCreated()
1467{
1468  return this->ViewCreated;
1469}
1470
1471// ---------------------------------------------------------------------------
1472int vtkCocoaRenderWindow::GetWindowCreated()
1473{
1474  return this->WindowCreated;
1475}
1476
1477//----------------------------------------------------------------------------
1478void vtkCocoaRenderWindow::SetCursorPosition(int x, int y)
1479{
1480  // The given coordinates are from the bottom left of the view.
1481  NSPoint newViewPoint = NSMakePoint (x, y);
1482
1483  // Convert to screen coordinates.
1484  NSView *view = (NSView *)this->GetWindowId();
1485  if (view)
1486    {
1487    NSPoint screenPoint = [view convertPoint:newViewPoint toView:nil];
1488    CGPoint newCursorPosition = NSPointToCGPoint(screenPoint);
1489
1490    // Move the cursor there.
1491    (void)CGWarpMouseCursorPosition (newCursorPosition);
1492    }
1493}
1494
1495//----------------------------------------------------------------------------
1496void vtkCocoaRenderWindow::SetCurrentCursor(int shape)
1497{
1498  if (this->InvokeEvent(vtkCommand::CursorChangedEvent, &shape))
1499    {
1500    return;
1501    }
1502  this->Superclass::SetCurrentCursor(shape);
1503  NSCursor* cursor = nil;
1504  switch (shape)
1505    {
1506    case VTK_CURSOR_DEFAULT:
1507    case VTK_CURSOR_ARROW:
1508      cursor = [NSCursor arrowCursor];
1509      break;
1510    case VTK_CURSOR_SIZENS:
1511      cursor = [NSCursor resizeUpDownCursor];
1512      break;
1513    case VTK_CURSOR_SIZEWE:
1514      cursor = [NSCursor resizeLeftRightCursor];
1515      break;
1516    case VTK_CURSOR_HAND:
1517      cursor = [NSCursor pointingHandCursor];
1518      break;
1519    case VTK_CURSOR_CROSSHAIR:
1520      cursor = [NSCursor crosshairCursor];
1521      break;
1522
1523    // NSCursor does not have cursors for these.
1524    case VTK_CURSOR_SIZENE:
1525    case VTK_CURSOR_SIZESW:
1526    case VTK_CURSOR_SIZENW:
1527    case VTK_CURSOR_SIZESE:
1528    case VTK_CURSOR_SIZEALL:
1529      cursor = [NSCursor arrowCursor];
1530      break;
1531    }
1532
1533  [cursor set];
1534}
1535