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 #include "OSGCSMNativeWindow.h"
50 #include "OSGCSMDrawManager.h"
51 #include "OSGCSMDrawer.h"
52 #include "OSGComplexSceneManager.h"
53 #include "OSGShaderCache.h"
54 #include "OSGGLFuncProtos.h"
58 // Documentation for this class is emitted in the
59 // OSGCSMNativeWindowBase.cpp file.
60 // To modify it, please change the .fcd file (OSGCSMNativeWindow.fcd) and
61 // regenerate the base file.
63 /***************************************************************************\
65 \***************************************************************************/
67 bool CSMNativeWindow::_bRun
= false;
69 /***************************************************************************\
71 \***************************************************************************/
73 void CSMNativeWindow::initMethod(InitPhase ePhase
)
75 Inherited::initMethod(ePhase
);
77 if(ePhase
== TypeObject::SystemPost
)
82 OSStatus
CSMNativeWindow::handleMouseEvent(EventHandlerCallRef nextHandler
,
89 err
= GetEventParameter(event
,
92 sizeof(window
), 0, &window
);
97 // Get the window rectangle
99 GetWindowPortBounds(window
, &portRect
);
101 // Get the pressed mouse button
102 EventMouseButton mouseButton
;
103 err
= GetEventParameter(event
,
104 kEventParamMouseButton
,
106 sizeof(mouseButton
), 0, &mouseButton
);
111 // Get the modifier keys
112 ::UInt32 modifierKeys
;
113 err
= GetEventParameter(event
,
114 kEventParamKeyModifiers
,
116 sizeof(modifierKeys
), 0, &modifierKeys
);
121 // Traditionally, Apple mice just have one button. It is common practice
122 // to simulate the middle and the right button by pressing the option or
125 if(mouseButton
== kEventMouseButtonPrimary
)
127 if(modifierKeys
& optionKey
)
128 mouseButton
= kEventMouseButtonTertiary
;
130 if(modifierKeys
& controlKey
)
131 mouseButton
= kEventMouseButtonSecondary
;
134 // Get the location of the mouse pointer
136 err
= GetEventParameter(event
,
137 kEventParamMouseLocation
,
139 sizeof(location
), 0, &location
);
144 // The location of the mouse pointer is in screen coordinates, so
145 // we have to transform it into the local coordinate system of the
146 // window content area.
147 SetPortWindowPort(window
);
148 GlobalToLocal (&location
);
150 // Handle the different kinds of events
151 ::UInt32 eventKind
= GetEventKind(event
);
155 // mouse button pressed
156 case kEventMouseDown
:
160 case kEventMouseButtonPrimary
: // left button
161 this->mouse(MouseData::LeftButton
,
162 MouseData::ButtonDown
,
167 case kEventMouseButtonSecondary
: // right button
168 this->mouse(MouseData::RightButton
,
169 MouseData::ButtonDown
,
174 case kEventMouseButtonTertiary
: // middle button
175 this->mouse(MouseData::MiddleButton
,
176 MouseData::ButtonDown
,
185 // mouse button released
190 case kEventMouseButtonPrimary
: // left button
191 this->mouse(MouseData::LeftButton
,
197 case kEventMouseButtonSecondary
: // right button
198 this->mouse(MouseData::RightButton
,
204 case kEventMouseButtonTertiary
: // middle button
205 this->mouse(MouseData::MiddleButton
,
215 // mouse moved while a button is pressed
216 case kEventMouseDragged
:
218 this->motion(location
.h
, location
.v
, 0);
220 // Redraw the whole window
221 InvalWindowRect(window
, &portRect
);
226 // We have to return eventNotHandledErr, otherwise the system is
227 // not able to operate the menu and the window border
228 return eventNotHandledErr
;
231 OSStatus
CSMNativeWindow::handleKeyEvent(EventHandlerCallRef nextHandler
,
236 // Try to determine the size of the text input
239 err
= GetEventParameter(event
,
240 kEventParamTextInputSendText
,
241 typeUnicodeText
, 0, 0, &actualSize
, 0);
246 // The input can actually consist of more than one character.
247 // We are only interested in single character input
248 if (actualSize
== sizeof(UniChar
))
250 // Get the character unicode
253 err
= GetEventParameter(event
,
254 kEventParamTextInputSendText
,
256 sizeof(UniChar
), 0, &c
);
263 case kEscapeCharCode
:
264 //QuitApplicationEventLoop();
269 ComplexSceneManager::the()->key(
272 CSMKeyData::ButtonDown
,
281 OSStatus
CSMNativeWindow::handleWindowEvent(EventHandlerCallRef nextHandler
,
289 err
= GetEventParameter(event
,
290 kEventParamDirectObject
,
291 typeWindowRef
, 0, sizeof(window
), 0, &window
);
296 // Handle the different kinds of events
297 ::UInt32 eventKind
= GetEventKind(event
);
301 // Quit the application when the user closes the window
302 case kEventWindowClose
:
303 //QuitApplicationEventLoop();
307 // Draw the contents of the window
308 case kEventWindowDrawContent
:
309 //ComplexSceneManager::the()->frame();
311 //Thread::getCurrentChangeList()->commitChangesAndClear();
314 case kEventWindowBoundsChanged
:
316 // Update the GL context
317 // WARNING this crap might crash later
318 aglUpdateContext(_pCarbWindow
->getContext());
320 // Find out if we have a move or a resize situation
322 GetEventParameter(event
,
323 kEventParamAttributes
,
330 if ((attributes
& kWindowBoundsChangeSizeChanged
) != 0)
332 // Get the new bounds of the window
334 GetEventParameter(event
,
335 kEventParamCurrentBounds
,
342 // Resize the OpenSG Window
343 GLsizei width
= bounds
.right
- bounds
.left
;
344 GLsizei height
= bounds
.bottom
- bounds
.top
;
346 this->reshape(width
, height
);
348 // Redraw the whole window
350 GetWindowPortBounds(window
, &portRect
);
351 InvalWindowRect (window
, &portRect
);
358 return eventNotHandledErr
;
362 static pascal OSStatus
eventHandler(EventHandlerCallRef nextHandler
,
366 ::UInt32 eventClass
= GetEventClass(event
);
368 CSMNativeWindow
*pWin
= reinterpret_cast<CSMNativeWindow
*>(userData
);
370 OSG_ASSERT(pWin
!= NULL
);
375 case kEventClassMouse
:
376 return pWin
->handleMouseEvent(nextHandler
, event
);
379 case kEventClassTextInput
:
380 return pWin
->handleKeyEvent(nextHandler
, event
);
383 case kEventClassWindow
:
384 return pWin
->handleWindowEvent(nextHandler
, event
);
387 return eventNotHandledErr
;
391 void CSMNativeWindow::carbonMainLoop(void)
394 EventTargetRef pTarget
= GetEventDispatcherTarget();
398 while(ReceiveNextEvent(0,
400 0, //kEventDurationForever,
404 SendEventToEventTarget(pEvent
, pTarget
);
405 ReleaseEvent (pEvent
);
408 ComplexSceneManager::the()->frame();
410 Thread::getCurrentChangeList()->commitChangesAndClear();
413 ComplexSceneManager::the()->terminate();
417 static UInt32
mapModifier(int iState
)
419 if(0x0000 != (iState
& ShiftMask
))
421 return MouseData::ShiftActive
;
423 else if(0x0000 != (iState
& ControlMask
))
425 return MouseData::CtrlActive
;
427 else if(0x0000 != (iState
& Mod1Mask
))
429 return MouseData::AltActive
;
436 /***************************************************************************\
438 \***************************************************************************/
440 /*-------------------------------------------------------------------------*\
442 \*-------------------------------------------------------------------------*/
444 /*----------------------- constructors & destructors ----------------------*/
446 CSMNativeWindow::CSMNativeWindow(void) :
450 _pLocalWindow (NULL
),
456 CSMNativeWindow::CSMNativeWindow(const CSMNativeWindow
&source
) :
458 _pCarbWindow (NULL
),
460 _pLocalWindow (NULL
),
461 _pEventHandler(NULL
)
465 CSMNativeWindow::~CSMNativeWindow(void)
469 /*----------------------------- class specific ----------------------------*/
471 void CSMNativeWindow::changed(ConstFieldMaskArg whichField
,
475 Inherited::changed(whichField
, origin
, details
);
478 void CSMNativeWindow::dump( UInt32
,
479 const BitVector
) const
481 SLOG
<< "Dump CSMNativeWindow NI" << std::endl
;
484 void CSMNativeWindow::resolveLinks(void)
486 if(_pCarbWindow
!= NULL
)
488 _pCarbWindow
->setContext(NULL
);
491 if(_pContext
!= NULL
)
492 aglDestroyContext(_pContext
);
494 if(_pLocalWindow
!= NULL
)
495 DisposeWindow(_pLocalWindow
);
497 if(_pEventHandler
!= NULL
)
498 DisposeEventHandlerUPP(_pEventHandler
);
500 Inherited::resolveLinks();
503 void CSMNativeWindow::terminateGLContext(void)
507 // A magic method that allows applications to react to events even
508 // when they are not organized in a bundle
509 static void osx_AllowForeground(void)
511 ProcessSerialNumber psn
= { 0, kCurrentProcess
};
512 TransformProcessType(&psn
, kProcessTransformToForegroundApplication
);
513 SetFrontProcess(&psn
);
516 bool CSMNativeWindow::init(void)
518 osx_AllowForeground();
520 CSMDrawer
*pDrawer
= this->getParent();
522 CarbonWindowUnrecPtr pCarbonWindow
= OSG::CarbonWindow::create();
523 AGLPixelFormat pixelFormat
= NULL
;
525 std::vector
<int> pfForm
;
527 pfForm
.push_back(AGL_RGBA
);
528 pfForm
.push_back(AGL_DEPTH_SIZE
);
529 pfForm
.push_back(16);
530 pfForm
.push_back(AGL_DOUBLEBUFFER
);
532 if(_sfRequestSamples
.getValue() > 0)
534 pfForm
.push_back(AGL_SAMPLE_BUFFERS_ARB
);
537 pfForm
.push_back(AGL_SAMPLES_ARB
);
538 pfForm
.push_back(_sfRequestSamples
.getValue());
541 if(this->requestStereoVisual() == true)
543 fprintf(stderr
, "Choose stereo format\n");
544 pfForm
.push_back(AGL_STEREO
);
547 pfForm
.push_back(AGL_NONE
);
549 pixelFormat
= aglChoosePixelFormat(NULL
, 0, &(pfForm
.front()));
551 fprintf(stderr
, "Got pf : %p\n", pixelFormat
);
553 if(pixelFormat
== NULL
)
555 fprintf(stderr
, "no RGB visual with depth buffer : :0.0");
560 _pContext
= aglCreateContext(pixelFormat
, 0);
562 aglDestroyPixelFormat(pixelFormat
);
571 if(this->getXPos() > 0.f
&& this->getYPos() > 0.f
)
573 iXPos
= Int32(this->getXPos());
574 iYPos
= Int32(this->getYPos());
577 if(this->getXSize() >= 1.f
)
579 uiWidth
= UInt32(this->getXSize());
581 else if(this->getXSize() <= 0.f
)
583 uiWidth
= 300; //DisplayWidth(_pDisplay, vi->screen);
587 uiWidth
= 300; //UInt32(Real32(DisplayWidth(_pDisplay, vi->screen)) *
588 // this->getXSize());
591 if(this->getYSize() >= 1.f
)
593 uiHeight
= UInt32(this->getYSize());
595 else if(this->getYSize() <= 0.f
)
597 uiHeight
= 300; //DisplayHeight(_pDisplay, vi->screen);
601 uiHeight
= 300; //UInt32(Real32(DisplayHeight(_pDisplay, vi->screen)) *
602 // this->getYSize());
605 WindowAttributes windowAttrs
= (kWindowStandardDocumentAttributes
|
606 kWindowLiveResizeAttribute
|
607 kWindowStandardHandlerAttribute
);
609 SetRect(&contentRect
, iXPos
, iYPos
, iXPos
+ uiWidth
, iYPos
+ uiHeight
);
611 CreateNewWindow(kDocumentWindowClass
, windowAttrs
, &contentRect
,
614 SetWindowTitleWithCFString(_pLocalWindow
, CFSTR("OpenSG - CSM"));
616 // Install event handler
617 _pEventHandler
= NewEventHandlerUPP(eventHandler
);
619 EventTypeSpec eventList
[] =
621 { kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent
},
622 { kEventClassMouse
, kEventMouseDown
},
623 { kEventClassMouse
, kEventMouseUp
},
624 { kEventClassMouse
, kEventMouseDragged
},
625 { kEventClassWindow
, kEventWindowClose
},
626 { kEventClassWindow
, kEventWindowDrawContent
},
627 { kEventClassWindow
, kEventWindowBoundsChanged
}
630 InstallWindowEventHandler(_pLocalWindow
, _pEventHandler
,
631 GetEventTypeCount(eventList
),
634 aglSetWindowRef(_pContext
, _pLocalWindow
);
636 _pCarbWindow
= pCarbonWindow
;
638 _pCarbWindow
->setContext(_pContext
);
639 _pCarbWindow
->init ( );
640 _pCarbWindow
->resize ( uiWidth
,
643 std::string
windowName(" OpenSG - CSM - ");
645 _pCarbWindow
->activate();
647 windowName
+= reinterpret_cast<const char *>(glGetString(GL_VERSION
));
649 windowName
+= reinterpret_cast<const char *>(glGetString(GL_RENDERER
));
651 _pCarbWindow
->deactivate();
653 SetWTitle(_pLocalWindow
,
654 reinterpret_cast<const unsigned char *>(windowName
.c_str()));
657 RepositionWindow(_pLocalWindow
, 0, kWindowCascadeOnMainScreen
);
658 ShowWindow (_pLocalWindow
);
660 if(ComplexSceneManager::the() != NULL
&&
661 this->getRegisterMainLoop() == true )
663 ComplexSceneManager::the()->setMainloop(
664 &CSMNativeWindow::carbonMainLoop
);
667 _pWindow
= _pCarbWindow
;
676 void CSMNativeWindow::initWindowSystemThreading(void)