1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2000-2006 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
39 //---------------------------------------------------------------------------
41 //---------------------------------------------------------------------------
46 #include "OSGConfig.h"
49 #import <Cocoa/Cocoa.h>
55 #include "OSGCSMNativeWindow.h"
56 #include "OSGCSMDrawManager.h"
57 #include "OSGCSMDrawer.h"
58 #include "OSGComplexSceneManager.h"
59 #include "OSGShaderCache.h"
60 #include "OSGGLFuncProtos.h"
62 /***************************************************************************\
63 * local support classes *
64 \***************************************************************************/
66 @interface CSMOpenGLView: NSOpenGLView
68 OSG::CSMNativeWindow *_pWin;
70 - (BOOL) acceptsFirstResponder;
72 - (void) keyDown: (NSEvent*) event;
74 - (void) handleMouseEvent: (NSEvent*) event;
76 - (void) mouseDown: (NSEvent*) event;
77 - (void) mouseDragged: (NSEvent*) event;
78 - (void) mouseUp: (NSEvent*) event;
79 - (void) rightMouseDown: (NSEvent*) event;
80 - (void) rightMouseDragged: (NSEvent*) event;
81 - (void) rightMouseUp: (NSEvent*) event;
82 - (void) otherMouseDown: (NSEvent*) event;
83 - (void) otherMouseDragged: (NSEvent*) event;
84 - (void) otherMouseUp: (NSEvent*) event;
87 - (void) setWindow: (OSG::CSMNativeWindow *) pWin;
90 - (void) drawRect: (NSRect) bounds;
92 - (void) frame: (id) userInfo;
96 @implementation CSMOpenGLView
98 - (BOOL) acceptsFirstResponder
103 - (void) keyDown: (NSEvent*) event
105 if ([[event characters] length] != 1)
108 switch ([[event characters] characterAtIndex: 0])
114 OSG::ComplexSceneManager::the()->key(
117 OSG::CSMKeyData::ButtonDown,
118 [[event characters] characterAtIndex: 0]);
123 - (void) handleMouseEvent: (NSEvent*) event
125 int buttonNumber = [event buttonNumber];
126 unsigned int modifierFlags = [event modifierFlags];
128 // Traditionally, Apple mice just have one button. It is common practice
129 // to simulate the middle and the right button by pressing the option or
132 if(buttonNumber == 0)
134 if(modifierFlags & NSAlternateKeyMask)
137 if(modifierFlags & NSControlKeyMask)
141 NSPoint location = [event locationInWindow];
143 OSG::UInt32 uiHeight = _pWin->getWindow()->getHeight();
145 switch ([event type])
147 case NSLeftMouseDown:
148 case NSRightMouseDown:
149 case NSOtherMouseDown:
151 switch (buttonNumber)
153 case 0: // left button
154 _pWin->mouse(OSG::MouseData::LeftButton,
155 OSG::MouseData::ButtonDown,
156 OSG::MouseData::NoModifier,
158 uiHeight - location.y);
160 case 1: // right button
161 _pWin->mouse(OSG::MouseData::RightButton,
162 OSG::MouseData::ButtonDown,
163 OSG::MouseData::NoModifier,
165 uiHeight - location.y);
167 case 2: // middle button
168 _pWin->mouse(OSG::MouseData::MiddleButton,
169 OSG::MouseData::ButtonDown,
170 OSG::MouseData::NoModifier,
172 uiHeight - location.y);
182 switch (buttonNumber)
184 case 0: // left button
185 _pWin->mouse(OSG::MouseData::LeftButton,
186 OSG::MouseData::ButtonUp,
187 OSG::MouseData::NoModifier,
189 uiHeight - location.y);
191 case 1: // right button
192 _pWin->mouse(OSG::MouseData::RightButton,
193 OSG::MouseData::ButtonUp,
194 OSG::MouseData::NoModifier,
196 uiHeight - location.y);
198 case 2: // middle button
199 _pWin->mouse(OSG::MouseData::MiddleButton,
200 OSG::MouseData::ButtonUp,
201 OSG::MouseData::NoModifier,
203 uiHeight - location.y);
209 case NSLeftMouseDragged:
210 case NSRightMouseDragged:
211 case NSOtherMouseDragged:
213 _pWin->motion(location.x, uiHeight - location.y, 0);
223 - (void) mouseDown: (NSEvent*) event
225 [self handleMouseEvent: event];
228 - (void) mouseDragged: (NSEvent*) event
230 [self handleMouseEvent: event];
233 - (void) mouseUp: (NSEvent*) event
235 [self handleMouseEvent: event];
238 - (void) rightMouseDown: (NSEvent*) event
240 [self handleMouseEvent: event];
243 - (void) rightMouseDragged: (NSEvent*) event
245 [self handleMouseEvent: event];
248 - (void) rightMouseUp: (NSEvent*) event
250 [self handleMouseEvent: event];
253 - (void) otherMouseDown: (NSEvent*) event
255 [self handleMouseEvent: event];
258 - (void) otherMouseDragged: (NSEvent*) event
260 [self handleMouseEvent: event];
263 - (void) otherMouseUp: (NSEvent*) event
265 [self handleMouseEvent: event];
268 - (void) setWindow: (OSG::CSMNativeWindow *) pWin
277 NSRect frame = [self bounds];
279 _pWin->reshape(static_cast<int>(frame.size.width),
280 static_cast<int>(frame.size.height));
283 - (void) drawRect: (NSRect) bounds
288 - (void) frame: (id) userInfo
290 if(OSG::CSMNativeWindow::isRunning() == true)
292 OSG::ComplexSceneManager::the()->frame();
294 OSG::Thread::getCurrentChangeList()->commitChangesAndClear();
302 // Documentation for this class is emitted in the
303 // OSGCSMNativeWindowBase.cpp file.
304 // To modify it, please change the .fcd file (OSGCSMNativeWindow.fcd) and
305 // regenerate the base file.
307 /***************************************************************************\
309 \***************************************************************************/
311 NSAutoreleasePool *CSMNativeWindow::_pPool = NULL;
312 bool CSMNativeWindow::_bRun = false;
314 /***************************************************************************\
316 \***************************************************************************/
318 void CSMNativeWindow::initMethod(InitPhase ePhase)
320 Inherited::initMethod(ePhase);
322 if(ePhase == TypeObject::SystemPost)
327 void CSMNativeWindow::cocoaMainLoop(void)
335 ComplexSceneManager::the()->terminate();
340 /***************************************************************************\
342 \***************************************************************************/
344 /*-------------------------------------------------------------------------*\
346 \*-------------------------------------------------------------------------*/
348 /*----------------------- constructors & destructors ----------------------*/
350 CSMNativeWindow::CSMNativeWindow(void) :
352 _pCocoaWindow (NULL),
357 CSMNativeWindow::CSMNativeWindow(const CSMNativeWindow &source) :
359 _pCocoaWindow (NULL ),
364 CSMNativeWindow::~CSMNativeWindow(void)
368 /*----------------------------- class specific ----------------------------*/
370 void CSMNativeWindow::changed(ConstFieldMaskArg whichField,
374 Inherited::changed(whichField, origin, details);
377 void CSMNativeWindow::dump( UInt32 ,
378 const BitVector ) const
380 SLOG << "Dump CSMNativeWindow NI" << std::endl;
383 void CSMNativeWindow::resolveLinks(void)
385 if(_pCocoaWindow != NULL)
387 _pCocoaWindow->setContext(NULL);
390 _pCocoaWindow = NULL;
392 Inherited::resolveLinks();
395 void CSMNativeWindow::terminateGLContext(void)
397 if(_pCocoaWindow != NULL)
399 _pCocoaWindow->terminate();
405 // A magic method that allows applications to react to events even
406 // when they are not organized in a bundle
407 static void osx_AllowForeground(void)
409 ProcessSerialNumber psn = { 0, kCurrentProcess };
410 TransformProcessType(&psn, kProcessTransformToForegroundApplication);
411 SetFrontProcess(&psn);
414 bool CSMNativeWindow::init(void)
416 osx_AllowForeground();
420 // Create application
421 [NSApplication sharedApplication];
423 _pPool = [[NSAutoreleasePool alloc] init];
433 if(this->getXPos() > 0.f && this->getYPos() > 0.f)
435 iXPos = Int32(this->getXPos());
436 iYPos = Int32(this->getYPos());
439 if(this->getXSize() >= 1.f)
441 uiWidth = UInt32(this->getXSize());
443 else if(this->getXSize() <= 0.f)
445 uiWidth = 300; //DisplayWidth(_pDisplay, vi->screen);
449 uiWidth = 300; //UInt32(Real32(DisplayWidth(_pDisplay, vi->screen)) *
450 // this->getXSize());
453 if(this->getYSize() >= 1.f)
455 uiHeight = UInt32(this->getYSize());
457 else if(this->getYSize() <= 0.f)
459 uiHeight = 300; //DisplayHeight(_pDisplay, vi->screen);
463 uiHeight = 300; //UInt32(Real32(DisplayHeight(_pDisplay, vi->screen)) *
464 // this->getYSize());
467 NSRect nsScreenRect = [[NSScreen mainScreen] frame];
469 iYPos = nsScreenRect.size.height - iYPos - uiHeight;
472 NSWindow *window = [NSWindow alloc];
473 NSRect rect = { { 0, 0 }, { 300, 300 } };
475 rect.origin.x = iXPos;
476 rect.origin.y = iYPos;
478 rect.size.height = uiHeight;
479 rect.size.width = uiWidth;
481 [window initWithContentRect: rect
482 styleMask: (NSTitledWindowMask |
483 NSClosableWindowMask |
484 NSMiniaturizableWindowMask |
485 NSResizableWindowMask)
486 backing: NSBackingStoreBuffered
489 [window setTitle: @"OpenSG - CSM"];
490 [window setReleasedWhenClosed: NO];
492 _pGLView = [[CSMOpenGLView alloc] autorelease];
497 [_pGLView initWithFrame: rect];
498 [_pGLView setAutoresizingMask: (NSViewMaxXMargin |
501 NSViewHeightSizable )];
503 [[window contentView] addSubview: _pGLView];
505 std::vector<NSOpenGLPixelFormatAttribute> attrs;
507 attrs.push_back(NSOpenGLPFAWindow);
508 attrs.push_back(NSOpenGLPFADoubleBuffer);
510 attrs.push_back(NSOpenGLPFADepthSize);
511 attrs.push_back(NSOpenGLPixelFormatAttribute(16));
514 if(_sfRequestSamples.getValue() > 0)
516 attrs.push_back(NSOpenGLPFAMultisample);
518 attrs.push_back(NSOpenGLPFASampleBuffers);
521 attrs.push_back(NSOpenGLPFASamples);
523 NSOpenGLPixelFormatAttribute(_sfRequestSamples.getValue()));
526 if(this->requestStereoVisual() == true)
528 fprintf(stderr, "Choose stereo format\n");
529 attrs.push_back(NSOpenGLPFAStereo);
533 attrs.push_back(NSOpenGLPixelFormatAttribute(0));
535 NSOpenGLPixelFormat *pixFmt =
536 [[NSOpenGLPixelFormat alloc] initWithAttributes: &(attrs.front())];
540 fprintf(stderr, "no RGB visual with depth buffer : :0.0");
545 [_pGLView setPixelFormat: pixFmt];
548 // Create OpenSG window
549 CocoaWindowUnrecPtr pCocoaWindow = CocoaWindow::create();
551 pCocoaWindow->setContext([_pGLView openGLContext]);
552 pCocoaWindow->init ( );
553 pCocoaWindow->resize (uiWidth, uiHeight );
555 _pCocoaWindow = pCocoaWindow;
556 _pWindow = pCocoaWindow;
558 [_pGLView setWindow: this];
561 [window makeKeyAndOrderFront: nil];
562 [window makeFirstResponder:_pGLView];
565 NSTimer *timer = [NSTimer timerWithTimeInterval: 0.0f
567 selector: @selector( frame: )
571 [[NSRunLoop currentRunLoop] addTimer: timer
572 forMode: NSDefaultRunLoopMode];
576 if(ComplexSceneManager::the() != NULL)
578 ComplexSceneManager::the()->setMainloop(
579 &CSMNativeWindow::cocoaMainLoop);
587 void CSMNativeWindow::initWindowSystemThreading(void)
591 void CSMNativeWindow::reshape(Int32 w,
594 Inherited::reshape(w, h);
597 void CSMNativeWindow::mouse(Int32 iButton,
603 Inherited::mouse(iButton, iState, iModifier, x, y);
606 void CSMNativeWindow::motion (Int32 x,
610 Inherited::motion(x, y, iModifier);