2007-01-09 18:06:20 +08:00
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
*
* This library is open source and may be redistributed and / or modified under
* the terms of the OpenSceneGraph Public License ( OSGPL ) version 0.0 or
* ( at your option ) any later version . The full license is in LICENSE file
* included with this distribution , and on the openscenegraph . org website .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* OpenSceneGraph Public License for more details .
*/
# ifdef __APPLE__
2007-01-13 05:33:19 +08:00
# include <osg/observer_ptr>
2007-07-07 00:54:45 +08:00
2007-06-28 04:44:12 +08:00
# include <osgViewer/api/Carbon/PixelBufferCarbon>
2007-04-10 19:03:37 +08:00
# include <osgViewer/api/Carbon/GraphicsWindowCarbon>
2007-07-07 00:54:45 +08:00
# include <osg/DeleteHandler>
2007-01-09 18:06:20 +08:00
# include <Carbon/Carbon.h>
# include <OpenGL/OpenGL.h>
2008-02-18 23:30:55 +08:00
# include <iostream>
2008-04-01 18:00:39 +08:00
2007-01-09 18:06:20 +08:00
using namespace osgViewer ;
// Carbon-Eventhandler to handle the click in the close-widget and the resize of windows
2007-01-13 05:33:19 +08:00
static pascal OSStatus GraphicsWindowEventHandler ( EventHandlerCallRef nextHandler , EventRef event , void * userData )
2007-01-09 18:06:20 +08:00
{
WindowRef window ;
Rect bounds ;
OSStatus result = eventNotHandledErr ; /* report failure by default */
2008-02-18 23:30:55 +08:00
osg : : notify ( osg : : INFO ) < < " GraphicsWindowEventHandler " < < std : : endl ;
2007-01-09 18:06:20 +08:00
GraphicsWindowCarbon * w = ( GraphicsWindowCarbon * ) userData ;
if ( ! w )
return result ;
GetEventParameter ( event , kEventParamDirectObject , typeWindowRef , NULL ,
sizeof ( window ) , NULL , & window ) ;
2007-01-13 05:33:19 +08:00
switch ( GetEventClass ( event ) )
{
case kEventClassTablet :
case kEventClassMouse :
if ( w - > handleMouseEvent ( event ) )
2007-01-09 18:06:20 +08:00
result = noErr ;
2007-01-13 05:33:19 +08:00
break ;
2008-02-26 00:05:53 +08:00
2007-01-13 05:33:19 +08:00
case kEventClassKeyboard :
if ( w - > handleKeyboardEvent ( event ) )
2007-01-09 18:06:20 +08:00
result = noErr ;
2007-01-13 05:33:19 +08:00
break ;
case kEventClassWindow : {
switch ( GetEventKind ( event ) )
{
case kEventWindowBoundsChanging :
// left the code for live-resizing, but it is not used, because of window-refreshing issues...
GetEventParameter ( event , kEventParamCurrentBounds , typeQDRectangle , NULL , sizeof ( Rect ) , NULL , & bounds ) ;
w - > resized ( bounds . left , bounds . top , bounds . right - bounds . left , bounds . bottom - bounds . top ) ;
w - > getEventQueue ( ) - > windowResize ( bounds . left , bounds . top , bounds . right - bounds . left , bounds . bottom - bounds . top , w - > getEventQueue ( ) - > getTime ( ) ) ;
w - > requestRedraw ( ) ;
result = noErr ;
break ;
case kEventWindowBoundsChanged :
InvalWindowRect ( window , GetWindowPortBounds ( window , & bounds ) ) ;
GetWindowBounds ( window , kWindowContentRgn , & bounds ) ;
w - > resized ( bounds . left , bounds . top , bounds . right - bounds . left , bounds . bottom - bounds . top ) ;
w - > getEventQueue ( ) - > windowResize ( bounds . left , bounds . top , bounds . right - bounds . left , bounds . bottom - bounds . top , w - > getEventQueue ( ) - > getTime ( ) ) ;
result = noErr ;
break ;
2007-07-28 00:48:31 +08:00
case kEventWindowClose :
2007-01-13 05:33:19 +08:00
w - > requestClose ( ) ;
2007-07-28 00:48:31 +08:00
result = noErr ;
2007-01-13 05:33:19 +08:00
break ;
default :
break ;
}
}
default :
2008-02-26 00:05:53 +08:00
//std::cout << "unknown: " << GetEventClass(event) << std::endl;
2007-01-13 05:33:19 +08:00
break ;
}
2007-07-28 00:48:31 +08:00
2008-02-18 23:30:55 +08:00
//if (result == eventNotHandledErr)
// result = CallNextEventHandler (nextHandler, event);
2007-07-28 00:48:31 +08:00
2007-01-09 18:06:20 +08:00
return result ;
}
2008-04-01 18:00:39 +08:00
2007-01-09 18:06:20 +08:00
static bool s_quit_requested = false ;
// Application eventhandler -- listens for a quit-event
static pascal OSStatus ApplicationEventHandler ( EventHandlerCallRef inHandlerCallRef , EventRef inEvent , void * inUserData )
{
HICommand commandStruct ;
OSErr err = eventNotHandledErr ;
GetEventParameter ( inEvent , kEventParamDirectObject , typeHICommand , NULL , sizeof ( HICommand ) , NULL , & commandStruct ) ;
switch ( commandStruct . commandID ) {
case kHICommandQuit :
s_quit_requested = true ;
err = noErr ;
break ;
}
return err ;
}
// AppleEventHandler, listens to the Quit-AppleEvent
static pascal OSErr QuitAppleEventHandler ( const AppleEvent * theAppleEvent , AppleEvent * reply , long handlerRefcon ) {
s_quit_requested = true ;
return ( noErr ) ;
}
namespace osgViewer
{
// small helper class which maps the raw key codes to osgGA::GUIEventAdapter::Keys
class OSXKeyboardMap {
public :
OSXKeyboardMap ( )
{
_keymap [ 53 ] = osgGA : : GUIEventAdapter : : KEY_Escape ;
_keymap [ 115 ] = osgGA : : GUIEventAdapter : : KEY_Home ;
_keymap [ 76 ] = osgGA : : GUIEventAdapter : : KEY_KP_Enter ;
_keymap [ 119 ] = osgGA : : GUIEventAdapter : : KEY_End ;
_keymap [ 36 ] = osgGA : : GUIEventAdapter : : KEY_Return ;
_keymap [ 116 ] = osgGA : : GUIEventAdapter : : KEY_Page_Up ;
_keymap [ 121 ] = osgGA : : GUIEventAdapter : : KEY_Page_Down ;
_keymap [ 123 ] = osgGA : : GUIEventAdapter : : KEY_Left ;
_keymap [ 124 ] = osgGA : : GUIEventAdapter : : KEY_Right ;
_keymap [ 126 ] = osgGA : : GUIEventAdapter : : KEY_Up ;
_keymap [ 125 ] = osgGA : : GUIEventAdapter : : KEY_Down ;
_keymap [ 51 ] = osgGA : : GUIEventAdapter : : KEY_BackSpace ;
_keymap [ 48 ] = osgGA : : GUIEventAdapter : : KEY_Tab ;
_keymap [ 49 ] = osgGA : : GUIEventAdapter : : KEY_Space ;
_keymap [ 117 ] = osgGA : : GUIEventAdapter : : KEY_Delete ;
_keymap [ 122 ] = osgGA : : GUIEventAdapter : : KEY_F1 ;
_keymap [ 120 ] = osgGA : : GUIEventAdapter : : KEY_F2 ;
_keymap [ 99 ] = osgGA : : GUIEventAdapter : : KEY_F3 ;
_keymap [ 118 ] = osgGA : : GUIEventAdapter : : KEY_F4 ;
_keymap [ 96 ] = osgGA : : GUIEventAdapter : : KEY_F5 ;
_keymap [ 97 ] = osgGA : : GUIEventAdapter : : KEY_F6 ;
_keymap [ 98 ] = osgGA : : GUIEventAdapter : : KEY_F7 ;
_keymap [ 100 ] = osgGA : : GUIEventAdapter : : KEY_F8 ;
_keymap [ 101 ] = osgGA : : GUIEventAdapter : : KEY_F9 ;
_keymap [ 109 ] = osgGA : : GUIEventAdapter : : KEY_F10 ;
_keymap [ 103 ] = osgGA : : GUIEventAdapter : : KEY_F11 ;
_keymap [ 111 ] = osgGA : : GUIEventAdapter : : KEY_F12 ;
_keymap [ 75 ] = osgGA : : GUIEventAdapter : : KEY_KP_Divide ;
_keymap [ 67 ] = osgGA : : GUIEventAdapter : : KEY_KP_Multiply ;
_keymap [ 78 ] = osgGA : : GUIEventAdapter : : KEY_KP_Subtract ;
_keymap [ 69 ] = osgGA : : GUIEventAdapter : : KEY_KP_Add ;
_keymap [ 89 ] = osgGA : : GUIEventAdapter : : KEY_KP_Home ;
_keymap [ 91 ] = osgGA : : GUIEventAdapter : : KEY_KP_Up ;
_keymap [ 92 ] = osgGA : : GUIEventAdapter : : KEY_KP_Page_Up ;
_keymap [ 86 ] = osgGA : : GUIEventAdapter : : KEY_KP_Left ;
_keymap [ 87 ] = osgGA : : GUIEventAdapter : : KEY_KP_Begin ;
_keymap [ 88 ] = osgGA : : GUIEventAdapter : : KEY_KP_Right ;
_keymap [ 83 ] = osgGA : : GUIEventAdapter : : KEY_KP_End ;
_keymap [ 84 ] = osgGA : : GUIEventAdapter : : KEY_KP_Down ;
_keymap [ 85 ] = osgGA : : GUIEventAdapter : : KEY_KP_Page_Down ;
_keymap [ 82 ] = osgGA : : GUIEventAdapter : : KEY_KP_Insert ;
_keymap [ 65 ] = osgGA : : GUIEventAdapter : : KEY_KP_Delete ;
}
~ OSXKeyboardMap ( ) {
}
unsigned int remapKey ( unsigned int key , unsigned int rawkey )
{
KeyMap : : iterator itr = _keymap . find ( rawkey ) ;
if ( itr = = _keymap . end ( ) ) return key ;
else return itr - > second ;
}
private :
typedef std : : map < unsigned int , osgGA : : GUIEventAdapter : : KeySymbol > KeyMap ;
KeyMap _keymap ;
} ;
/** remaps a native os x keycode to a GUIEventAdapter-keycode */
static unsigned int remapOSXKey ( unsigned int key , unsigned int rawkey )
{
static OSXKeyboardMap s_OSXKeyboardMap ;
return s_OSXKeyboardMap . remapKey ( key , rawkey ) ;
}
2007-01-13 05:33:19 +08:00
2007-01-09 18:06:20 +08:00
2007-02-07 04:03:13 +08:00
# pragma mark * * * MenubarController * * *
2007-01-13 05:33:19 +08:00
2007-06-12 23:38:09 +08:00
/** the MenubarController class checks all open windows if they intersect with the menubar / dock and hide the menubar/dock if necessary */
2007-01-13 05:33:19 +08:00
class MenubarController : public osg : : Referenced
{
public :
2007-06-12 23:38:09 +08:00
MenubarController ( ) :
osg : : Referenced ( ) ,
_list ( ) ,
2008-04-01 18:00:39 +08:00
_menubarShown ( false ) ,
_mutex ( )
2007-06-12 23:38:09 +08:00
{
2008-04-01 18:00:39 +08:00
// the following code will query the system for the available rect on the main-display (typically the displaying showing the menubar + the dock
2007-01-13 05:33:19 +08:00
GDHandle mainScreenDevice ;
DMGetGDeviceByDisplayID ( ( DisplayIDType ) CGMainDisplayID ( ) , & mainScreenDevice , true ) ;
GetAvailableWindowPositioningBounds ( mainScreenDevice , & _availRect ) ;
// now we need the rect of the main-display including the menubar and the dock
_mainScreenBounds = CGDisplayBounds ( CGMainDisplayID ( ) ) ;
// hide the menubar initially
SetSystemUIMode ( kUIModeAllHidden , kUIOptionAutoShowMenuBar ) ;
}
static MenubarController * instance ( ) ;
void attachWindow ( GraphicsWindowCarbon * win ) ;
void update ( ) ;
void detachWindow ( GraphicsWindowCarbon * win ) ;
private :
typedef std : : list < osg : : observer_ptr < GraphicsWindowCarbon > > WindowList ;
2008-04-01 18:00:39 +08:00
WindowList _list ;
bool _menubarShown ;
Rect _availRect ;
CGRect _mainScreenBounds ;
OpenThreads : : Mutex _mutex ;
2007-01-13 05:33:19 +08:00
} ;
MenubarController * MenubarController : : instance ( )
{
static osg : : ref_ptr < MenubarController > s_menubar_controller = new MenubarController ( ) ;
return s_menubar_controller . get ( ) ;
2007-01-09 18:06:20 +08:00
}
2007-01-13 05:33:19 +08:00
void MenubarController : : attachWindow ( GraphicsWindowCarbon * win )
{
2008-04-01 18:00:39 +08:00
OpenThreads : : ScopedLock < OpenThreads : : Mutex > lock ( _mutex ) ;
2007-01-13 05:33:19 +08:00
_list . push_back ( win ) ;
update ( ) ;
}
void MenubarController : : detachWindow ( GraphicsWindowCarbon * win )
{
2008-04-01 18:00:39 +08:00
OpenThreads : : ScopedLock < OpenThreads : : Mutex > lock ( _mutex ) ;
2007-01-13 05:33:19 +08:00
for ( WindowList : : iterator i = _list . begin ( ) ; i ! = _list . end ( ) ; ) {
if ( ( * i ) . get ( ) = = win )
i = _list . erase ( i ) ;
else
+ + i ;
}
update ( ) ;
}
// iterate through all open windows and check, if they intersect the area occupied by the menubar/dock, and if so, hide the menubar/dock
void MenubarController : : update ( )
{
OSErr error ( noErr ) ;
unsigned int windowsCoveringMenubarArea = 0 ;
unsigned int windowsIntersectingMainScreen = 0 ;
for ( WindowList : : iterator i = _list . begin ( ) ; i ! = _list . end ( ) ; ) {
if ( ( * i ) . valid ( ) ) {
GraphicsWindowCarbon * w = ( * i ) . get ( ) ;
Rect windowBounds ;
error = GetWindowBounds ( w - > getNativeWindowRef ( ) , kWindowStructureRgn , & windowBounds ) ;
bool intersect = ! ( ( _mainScreenBounds . origin . x > windowBounds . right ) | |
( _mainScreenBounds . origin . x + _mainScreenBounds . size . width < windowBounds . left ) | |
( _mainScreenBounds . origin . y > windowBounds . bottom ) | |
( _mainScreenBounds . origin . y + _mainScreenBounds . size . height < windowBounds . top ) ) ;
if ( intersect & & ! error )
{
+ + windowsIntersectingMainScreen ;
// the window intersects the main-screen, does it intersect with the menubar/dock?
if ( ( ( _availRect . top > _mainScreenBounds . origin . y ) & & ( _availRect . top > windowBounds . top ) ) | |
( ( _availRect . left > _mainScreenBounds . origin . x ) & & ( _availRect . left > windowBounds . left ) ) | |
( ( _availRect . right < _mainScreenBounds . origin . x + _mainScreenBounds . size . width ) & & ( _availRect . right < windowBounds . right ) ) | |
( ( _availRect . bottom < _mainScreenBounds . origin . y + _mainScreenBounds . size . height ) & & ( _availRect . bottom < windowBounds . bottom ) ) )
{
+ + windowsCoveringMenubarArea ;
}
}
+ + i ;
}
else
i = _list . erase ( i ) ;
}
// see http://developer.apple.com/technotes/tn2002/tn2062.html for hiding the dock+menubar
if ( windowsCoveringMenubarArea & & _menubarShown )
error = SetSystemUIMode ( kUIModeAllHidden , kUIOptionAutoShowMenuBar ) ;
if ( ! windowsCoveringMenubarArea & & ! _menubarShown )
error = SetSystemUIMode ( kUIModeNormal , 0 ) ;
_menubarShown = ! windowsCoveringMenubarArea ;
// osg::notify(osg::DEBUG_INFO) << "MenubarController:: " << windowsCoveringMenubarArea << " windows covering the menubar/dock area, " << windowsIntersectingMainScreen << " intersecting mainscreen" << std::endl;
}
# pragma mark * * * OSXWindowingSystemInterface * * *
struct OSXCarbonWindowingSystemInterface : public osg : : GraphicsContext : : WindowingSystemInterface
{
/** ctor, get a list of all attached displays */
OSXCarbonWindowingSystemInterface ( ) :
_displayCount ( 0 ) ,
_displayIds ( NULL )
{
2007-02-07 04:03:13 +08:00
ProcessSerialNumber sn = { 0 , kCurrentProcess } ;
TransformProcessType ( & sn , kProcessTransformToForegroundApplication ) ;
SetFrontProcess ( & sn ) ;
2007-01-13 05:33:19 +08:00
if ( CGGetActiveDisplayList ( 0 , NULL , & _displayCount ) ! = CGDisplayNoErr )
osg : : notify ( osg : : WARN ) < < " OSXCarbonWindowingSystemInterface: could not get # of screens " < < std : : endl ;
_displayIds = new CGDirectDisplayID [ _displayCount ] ;
if ( CGGetActiveDisplayList ( _displayCount , _displayIds , & _displayCount ) ! = CGDisplayNoErr )
osg : : notify ( osg : : WARN ) < < " OSXCarbonWindowingSystemInterface: CGGetActiveDisplayList failed " < < std : : endl ;
// register application event handler and AppleEventHandler to get quit-events:
static const EventTypeSpec menueventSpec = { kEventClassCommand , kEventCommandProcess } ;
OSErr status = InstallEventHandler ( GetApplicationEventTarget ( ) , NewEventHandlerUPP ( ApplicationEventHandler ) , 1 , & menueventSpec , 0 , NULL ) ;
status = AEInstallEventHandler ( kCoreEventClass , kAEQuitApplication , NewAEEventHandlerUPP ( QuitAppleEventHandler ) , 0 , false ) ;
}
/** dtor */
2007-07-06 21:08:51 +08:00
~ OSXCarbonWindowingSystemInterface ( )
{
if ( osg : : Referenced : : getDeleteHandler ( ) )
{
osg : : Referenced : : getDeleteHandler ( ) - > setNumFramesToRetainObjects ( 0 ) ;
osg : : Referenced : : getDeleteHandler ( ) - > flushAll ( ) ;
}
if ( _displayIds ) delete [ ] _displayIds ;
2007-01-13 05:33:19 +08:00
_displayIds = NULL ;
}
/** @return a CGDirectDisplayID for a ScreenIdentifier */
inline CGDirectDisplayID getDisplayID ( const osg : : GraphicsContext : : ScreenIdentifier & si ) {
2007-06-08 19:04:30 +08:00
if ( si . screenNum < _displayCount )
return _displayIds [ si . screenNum ] ;
else {
osg : : notify ( osg : : WARN ) < < " GraphicsWindowCarbon :: invalid screen # " < < si . screenNum < < " , returning main-screen instead " < < std : : endl ;
return _displayIds [ 0 ] ;
}
2007-01-13 05:33:19 +08:00
}
/** @return count of attached screens */
virtual unsigned int getNumScreens ( const osg : : GraphicsContext : : ScreenIdentifier & si )
{
return _displayCount ;
}
/** returns the resolution of a specific display */
virtual void getScreenResolution ( const osg : : GraphicsContext : : ScreenIdentifier & si , unsigned int & width , unsigned int & height )
{
CGDirectDisplayID id = getDisplayID ( si ) ;
width = CGDisplayPixelsWide ( id ) ;
height = CGDisplayPixelsHigh ( id ) ;
}
/** return the top left coord of a specific screen in global screen space */
void getScreenTopLeft ( const osg : : GraphicsContext : : ScreenIdentifier & si , int & x , int & y ) {
CGRect bounds = CGDisplayBounds ( getDisplayID ( si ) ) ;
2007-06-04 23:05:59 +08:00
x = static_cast < int > ( bounds . origin . x ) ;
y = static_cast < int > ( bounds . origin . y ) ;
2007-01-13 05:33:19 +08:00
// osg::notify(osg::DEBUG_INFO) << "topleft of screen " << si.screenNum <<" " << bounds.origin.x << "/" << bounds.origin.y << std::endl;
}
2007-05-20 21:42:41 +08:00
/** helper method to get a value out of a CFDictionary */
static double getDictDouble ( CFDictionaryRef refDict , CFStringRef key )
{
double double_value ;
CFNumberRef number_value = ( CFNumberRef ) CFDictionaryGetValue ( refDict , key ) ;
if ( ! number_value ) // if can't get a number for the dictionary
return - 1 ; // fail
if ( ! CFNumberGetValue ( number_value , kCFNumberDoubleType , & double_value ) ) // or if cant convert it
return - 1 ; // fail
return double_value ; // otherwise return the long value
}
/** implementation of setScreenResolution */
virtual bool setScreenResolution ( const osg : : GraphicsContext : : ScreenIdentifier & screenIdentifier , unsigned int width , unsigned int height )
{
CGDirectDisplayID displayID = getDisplayID ( screenIdentifier ) ;
// add next line and on following line replace hard coded depth and refresh rate
CGRefreshRate refresh = getDictDouble ( CGDisplayCurrentMode ( displayID ) , kCGDisplayRefreshRate ) ;
CFDictionaryRef display_mode_values =
CGDisplayBestModeForParametersAndRefreshRate (
displayID ,
CGDisplayBitsPerPixel ( displayID ) ,
width , height ,
refresh ,
NULL ) ;
CGDisplaySwitchToMode ( displayID , display_mode_values ) ;
return true ;
}
/** implementation of setScreenRefreshRate */
virtual bool setScreenRefreshRate ( const osg : : GraphicsContext : : ScreenIdentifier & screenIdentifier , double refreshRate ) {
boolean_t success ( false ) ;
unsigned width , height ;
getScreenResolution ( screenIdentifier , width , height ) ;
CGDirectDisplayID displayID = getDisplayID ( screenIdentifier ) ;
// add next line and on following line replace hard coded depth and refresh rate
CFDictionaryRef display_mode_values =
CGDisplayBestModeForParametersAndRefreshRate (
displayID ,
CGDisplayBitsPerPixel ( displayID ) ,
width , height ,
refreshRate ,
& success ) ;
if ( success )
CGDisplaySwitchToMode ( displayID , display_mode_values ) ;
return ( success ! = 0 ) ;
}
2007-01-13 05:33:19 +08:00
virtual osg : : GraphicsContext * createGraphicsContext ( osg : : GraphicsContext : : Traits * traits )
{
if ( traits - > pbuffer )
{
2007-06-28 04:44:12 +08:00
osg : : ref_ptr < osgViewer : : PixelBufferCarbon > pbuffer = new PixelBufferCarbon ( traits ) ;
2007-01-13 05:33:19 +08:00
if ( pbuffer - > valid ( ) ) return pbuffer . release ( ) ;
else return 0 ;
}
else
{
osg : : ref_ptr < osgViewer : : GraphicsWindowCarbon > window = new GraphicsWindowCarbon ( traits ) ;
if ( window - > valid ( ) ) return window . release ( ) ;
else return 0 ;
}
}
private :
CGDisplayCount _displayCount ;
CGDirectDisplayID * _displayIds ;
} ;
}
# pragma mark * * * GraphicsWindowCarbon * * *
2007-05-20 21:42:41 +08:00
2007-01-09 18:06:20 +08:00
2007-03-27 00:28:26 +08:00
void GraphicsWindowCarbon : : init ( )
2007-01-09 18:06:20 +08:00
{
2007-07-13 19:17:41 +08:00
if ( _initialized ) return ;
2008-06-03 01:34:47 +08:00
// getEventQueue()->setCurrentEventState(osgGA::GUIEventAdapter::getAccumulatedEventState().get());
2008-02-26 00:05:53 +08:00
_lastModifierKeys = 0 ;
2007-05-16 03:32:55 +08:00
_windowTitleHeight = 0 ;
2007-01-09 18:06:20 +08:00
_closeRequested = false ;
2007-05-20 21:42:41 +08:00
_ownsWindow = false ;
2007-01-09 18:06:20 +08:00
_context = NULL ;
_window = NULL ;
2007-06-28 04:44:12 +08:00
_pixelFormat = PixelBufferCarbon : : createPixelFormat ( _traits . get ( ) ) ;
2007-01-09 18:06:20 +08:00
if ( ! _pixelFormat )
osg : : notify ( osg : : WARN ) < < " GraphicsWindowCarbon::init could not create a valid pixelformat " < < std : : endl ;
_valid = ( _pixelFormat ! = NULL ) ;
_initialized = true ;
}
2007-06-11 03:53:18 +08:00
bool GraphicsWindowCarbon : : setWindowDecorationImplementation ( bool flag )
2007-01-09 18:06:20 +08:00
{
2007-05-20 21:42:41 +08:00
_useWindowDecoration = flag ;
2007-06-11 03:53:18 +08:00
if ( _realized )
{
2007-05-20 21:42:41 +08:00
OSErr err = noErr ;
Rect bounds ;
GetWindowBounds ( getNativeWindowRef ( ) , kWindowContentRgn , & bounds ) ;
2007-06-11 03:53:18 +08:00
if ( _useWindowDecoration )
{
2007-05-20 21:42:41 +08:00
err = ChangeWindowAttributes ( getNativeWindowRef ( ) , kWindowStandardDocumentAttributes , kWindowNoTitleBarAttribute | kWindowNoShadowAttribute ) ;
SetWindowBounds ( getNativeWindowRef ( ) , kWindowContentRgn , & bounds ) ;
2007-06-11 03:53:18 +08:00
}
else
{
2007-05-20 21:42:41 +08:00
err = ChangeWindowAttributes ( getNativeWindowRef ( ) , kWindowNoTitleBarAttribute | kWindowNoShadowAttribute , kWindowStandardDocumentAttributes ) ;
2007-06-12 23:38:09 +08:00
SetWindowBounds ( getNativeWindowRef ( ) , kWindowContentRgn , & bounds ) ;
2007-05-20 21:42:41 +08:00
}
2007-01-13 05:33:19 +08:00
2007-06-11 03:53:18 +08:00
if ( err ! = noErr )
{
2007-05-20 21:42:41 +08:00
osg : : notify ( osg : : WARN ) < < " GraphicsWindowCarbon::setWindowDecoration failed with " < < err < < std : : endl ;
2007-06-11 03:53:18 +08:00
return false ;
2007-05-20 21:42:41 +08:00
}
2007-06-12 23:38:09 +08:00
// update titlebar-height
Rect titleRect ;
GetWindowBounds ( _window , kWindowTitleBarRgn , & titleRect ) ;
_windowTitleHeight = abs ( titleRect . bottom - titleRect . top ) ;
// sth: I don't know why I have to reattach the context to the window here, If I don't do this I get blank areas, where the titlebar was.
// InvalWindowRect doesn't help here :-/
aglSetDrawable ( _context , 0 ) ;
aglSetDrawable ( _context , GetWindowPort ( _window ) ) ;
MenubarController : : instance ( ) - > update ( ) ;
2007-01-13 05:33:19 +08:00
}
2007-06-11 03:53:18 +08:00
return true ;
2007-05-20 21:42:41 +08:00
}
2007-06-12 23:38:09 +08:00
2007-05-20 21:42:41 +08:00
WindowAttributes GraphicsWindowCarbon : : computeWindowAttributes ( bool useWindowDecoration , bool supportsResize ) {
WindowAttributes attr ;
2007-01-13 05:33:19 +08:00
2007-05-20 21:42:41 +08:00
if ( useWindowDecoration )
2007-01-13 05:33:19 +08:00
{
2007-05-20 21:42:41 +08:00
if ( supportsResize )
2007-01-09 18:06:20 +08:00
attr = ( kWindowStandardDocumentAttributes | kWindowStandardHandlerAttribute ) ;
else
attr = ( kWindowStandardDocumentAttributes | kWindowStandardHandlerAttribute ) & ~ kWindowResizableAttribute ;
2007-01-13 05:33:19 +08:00
}
2007-02-16 21:33:29 +08:00
else
{
attr = kWindowNoTitleBarAttribute | kWindowNoShadowAttribute | kWindowStandardHandlerAttribute ;
2007-05-20 21:42:41 +08:00
if ( supportsResize )
2007-01-09 18:06:20 +08:00
attr | = kWindowResizableAttribute ;
}
2007-05-20 21:42:41 +08:00
return attr ;
}
void GraphicsWindowCarbon : : installEventHandler ( ) {
2007-02-16 21:33:29 +08:00
2007-01-09 18:06:20 +08:00
// register window event handler to receive resize-events
2007-01-13 05:33:19 +08:00
EventTypeSpec windEventList [ ] = {
{ kEventClassWindow , kEventWindowBoundsChanged } ,
2007-07-28 00:48:31 +08:00
{ kEventClassWindow , kEventWindowClose } ,
2007-01-13 05:33:19 +08:00
{ kEventClassMouse , kEventMouseDown } ,
{ kEventClassMouse , kEventMouseUp } ,
{ kEventClassMouse , kEventMouseMoved } ,
{ kEventClassMouse , kEventMouseDragged } ,
{ kEventClassMouse , kEventMouseWheelMoved } ,
2008-04-22 22:15:24 +08:00
{ kEventClassMouse , 11 /* kEventMouseScroll */ } ,
2007-01-13 05:33:19 +08:00
{ kEventClassKeyboard , kEventRawKeyDown } ,
{ kEventClassKeyboard , kEventRawKeyRepeat } ,
{ kEventClassKeyboard , kEventRawKeyUp } ,
{ kEventClassKeyboard , kEventRawKeyModifiersChanged } ,
{ kEventClassKeyboard , kEventHotKeyPressed } ,
{ kEventClassKeyboard , kEventHotKeyReleased } ,
} ;
InstallWindowEventHandler ( _window , NewEventHandlerUPP ( GraphicsWindowEventHandler ) , GetEventTypeCount ( windEventList ) , windEventList , this , NULL ) ;
2008-02-18 23:30:55 +08:00
}
2007-05-20 21:42:41 +08:00
bool GraphicsWindowCarbon : : realizeImplementation ( )
{
if ( ! _initialized ) init ( ) ;
if ( ! _initialized ) return false ;
if ( ! _traits ) return false ;
2008-02-18 23:30:55 +08:00
osg : : notify ( osg : : INFO ) < < " GraphicsWindowCarbon:: realizeIMplementation " < < std : : endl ;
2007-05-20 21:42:41 +08:00
setWindowDecoration ( _traits - > windowDecoration ) ;
2007-12-17 18:24:20 +08:00
useCursor ( _traits - > useCursor ) ;
2008-01-29 00:38:39 +08:00
2007-05-20 21:42:41 +08:00
// move the window to the right screen
OSXCarbonWindowingSystemInterface * wsi = dynamic_cast < OSXCarbonWindowingSystemInterface * > ( osg : : GraphicsContext : : getWindowingSystemInterface ( ) ) ;
int screenLeft ( 0 ) , screenTop ( 0 ) ;
if ( wsi ) {
wsi - > getScreenTopLeft ( ( * _traits ) , screenLeft , screenTop ) ;
_traits - > y + = screenTop ;
_traits - > x + = screenLeft ;
}
2008-04-01 18:00:39 +08:00
WindowData * windowData = ( _traits . get ( ) & & _traits - > inheritedWindowData . get ( ) ) ? static_cast < osgViewer : : GraphicsWindowCarbon : : WindowData * > ( _traits - > inheritedWindowData . get ( ) ) : 0 ;
2008-02-18 23:30:55 +08:00
2007-05-20 21:42:41 +08:00
_ownsWindow = ( windowData ) ? ( windowData - > getNativeWindowRef ( ) = = NULL ) : true ;
if ( _ownsWindow ) {
// create the window
Rect bounds = { _traits - > y , _traits - > x , _traits - > y + _traits - > height , _traits - > x + _traits - > width } ;
OSStatus err = 0 ;
WindowAttributes attr = computeWindowAttributes ( _useWindowDecoration , _traits - > supportsResize ) ;
err = CreateNewWindow ( kDocumentWindowClass , attr , & bounds , & _window ) ;
if ( err ) {
osg : : notify ( osg : : WARN ) < < " GraphicsWindowCarbon::realizeImplementation() failed creating a window: " < < err < < std : : endl ;
return false ;
} else {
osg : : notify ( osg : : INFO ) < < " GraphicsWindowCarbon::realizeImplementation() - window created with bounds( " < < bounds . top < < " , " < < bounds . left < < " , " < < bounds . bottom < < " , " < < bounds . right < < " ) " < < std : : endl ;
}
}
else {
2008-02-18 23:30:55 +08:00
_window = windowData - > getNativeWindowRef ( ) ;
2007-05-20 21:42:41 +08:00
}
Rect titleRect ;
GetWindowBounds ( _window , kWindowTitleBarRgn , & titleRect ) ;
2007-06-12 16:28:41 +08:00
_windowTitleHeight = abs ( titleRect . bottom - titleRect . top ) ;
2007-05-20 21:42:41 +08:00
if ( ( _ownsWindow ) | | ( windowData & & windowData - > installEventHandler ( ) ) )
installEventHandler ( ) ;
2007-01-09 18:06:20 +08:00
// set the window title
2007-12-17 18:24:20 +08:00
setWindowName ( _traits - > windowName ) ;
2007-01-09 18:06:20 +08:00
// create the context
2007-06-28 04:44:12 +08:00
AGLContext sharedContextCarbon = NULL ;
GraphicsWindowCarbon * graphicsWindowCarbon = dynamic_cast < GraphicsWindowCarbon * > ( _traits - > sharedContext ) ;
if ( graphicsWindowCarbon )
2007-02-15 20:24:04 +08:00
{
2007-06-28 04:44:12 +08:00
sharedContextCarbon = graphicsWindowCarbon - > getAGLContext ( ) ;
2007-02-15 20:24:04 +08:00
}
else
{
2007-06-28 04:44:12 +08:00
PixelBufferCarbon * pixelbuffer = dynamic_cast < PixelBufferCarbon * > ( _traits - > sharedContext ) ;
if ( pixelbuffer ) {
sharedContextCarbon = pixelbuffer - > getAGLContext ( ) ;
}
2007-02-15 20:24:04 +08:00
}
2007-06-28 04:44:12 +08:00
_context = aglCreateContext ( _pixelFormat , sharedContextCarbon ) ;
2007-02-15 20:24:04 +08:00
2007-01-09 18:06:20 +08:00
if ( ! _context ) {
osg : : notify ( osg : : WARN ) < < " GraphicsWindowCarbon::realizeImplementation failed creating a context: " < < aglGetError ( ) < < std : : endl ;
return false ;
}
2008-02-18 23:30:55 +08:00
if ( windowData & & windowData - > getAGLDrawable ( ) ) {
2008-04-01 18:00:39 +08:00
aglSetDrawable ( _context , ( AGLDrawable ) * ( windowData - > getAGLDrawable ( ) ) ) ;
2008-02-18 23:30:55 +08:00
} else {
2008-04-01 18:00:39 +08:00
aglSetDrawable ( _context , GetWindowPort ( _window ) ) ;
ShowWindow ( _window ) ;
2008-02-18 23:30:55 +08:00
MenubarController : : instance ( ) - > attachWindow ( this ) ;
}
2007-01-09 18:06:20 +08:00
makeCurrent ( ) ;
2007-02-16 21:33:29 +08:00
if ( ( _traits - > useMultiThreadedOpenGLEngine ) & & ( OpenThreads : : GetNumberOfProcessors ( ) > 1 ) ) {
2007-02-07 04:03:13 +08:00
// enable Multi-threaded OpenGL Execution:
CGLError cgerr = kCGLNoError ;
CGLContextObj ctx = CGLGetCurrentContext ( ) ;
2007-01-09 18:06:20 +08:00
2007-06-04 19:14:17 +08:00
#if 0
2007-02-07 04:03:13 +08:00
cgerr = CGLEnable ( ctx , kCGLCEMPEngine ) ;
2007-06-04 19:14:17 +08:00
# else
// the above use of kCGLCEMPEngine is not backwards compatible
// so we'll use the raw value of it to keep things compiling on older
// versions of OSX.
cgerr = CGLEnable ( ctx , static_cast < CGLContextEnable > ( 313 ) ) ;
# endif
2007-02-07 04:03:13 +08:00
if ( cgerr ! = kCGLNoError )
{
osg : : notify ( osg : : INFO ) < < " GraphicsWindowCarbon:: Multi-threaded OpenGL Execution not available " < < std : : endl ;
}
2007-02-16 21:33:29 +08:00
}
2008-04-01 18:00:39 +08:00
InitCursor ( ) ;
2007-01-09 18:06:20 +08:00
//enable vsync
if ( _traits - > vsync ) {
GLint swap = 1 ;
aglSetInteger ( _context , AGL_SWAP_INTERVAL , & swap ) ;
}
_realized = true ;
return _realized ;
}
bool GraphicsWindowCarbon : : makeCurrentImplementation ( )
{
return ( aglSetCurrentContext ( _context ) = = GL_TRUE ) ;
}
bool GraphicsWindowCarbon : : releaseContextImplementation ( )
{
if ( ! _realized )
{
osg : : notify ( osg : : NOTICE ) < < " Warning: GraphicsWindow not realized, cannot do makeCurrent. " < < std : : endl ;
return false ;
}
// osg::notify(osg::NOTICE)<<"makeCurrentImplementation "<<this<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
// osg::notify(osg::NOTICE)<<" glXMakeCurrent ("<<_display<<","<<_window<<","<<_glxContext<<std::endl;
return ( aglSetCurrentContext ( NULL ) = = GL_TRUE ) ;
}
void GraphicsWindowCarbon : : closeImplementation ( )
{
2007-07-28 00:48:31 +08:00
// osg::notify(osg::INFO) << "GraphicsWindowCarbon::closeImplementation" << std::endl;
2007-01-09 18:06:20 +08:00
_valid = false ;
_realized = false ;
2008-04-01 18:00:39 +08:00
// there's a possibility that the MenubarController is destructed already, so prevent a crash:
MenubarController * mbc = MenubarController : : instance ( ) ;
if ( mbc ) mbc - > detachWindow ( this ) ;
2007-01-13 05:33:19 +08:00
2007-01-09 18:06:20 +08:00
if ( _pixelFormat )
{
aglDestroyPixelFormat ( _pixelFormat ) ;
_pixelFormat = NULL ;
}
if ( _context )
{
aglSetDrawable ( _context , NULL ) ;
aglSetCurrentContext ( NULL ) ;
aglDestroyContext ( _context ) ;
_context = NULL ;
}
2007-05-20 21:42:41 +08:00
if ( _ownsWindow & & _window ) DisposeWindow ( _window ) ;
2007-01-09 18:06:20 +08:00
_window = NULL ;
}
void GraphicsWindowCarbon : : swapBuffersImplementation ( )
{
aglSwapBuffers ( _context ) ;
}
void GraphicsWindowCarbon : : resizedImplementation ( int x , int y , int width , int height )
{
2007-01-13 05:33:19 +08:00
GraphicsContext : : resizedImplementation ( x , y , width , height ) ;
2007-01-09 18:06:20 +08:00
aglUpdateContext ( _context ) ;
2007-01-13 05:33:19 +08:00
MenubarController : : instance ( ) - > update ( ) ;
2007-01-09 18:06:20 +08:00
}
2007-01-13 05:33:19 +08:00
bool GraphicsWindowCarbon : : handleMouseEvent ( EventRef theEvent )
2007-01-09 18:06:20 +08:00
{
2007-01-13 05:33:19 +08:00
static unsigned int lastEmulatedMouseButton = 0 ;
2007-01-09 18:06:20 +08:00
// mouse down event
Point wheresMyMouse ;
2007-01-13 05:33:19 +08:00
GetEventParameter ( theEvent , kEventParamWindowMouseLocation , typeQDPoint , NULL , sizeof ( wheresMyMouse ) , NULL , & wheresMyMouse ) ;
2007-05-16 03:32:55 +08:00
wheresMyMouse . v - = _windowTitleHeight ;
if ( _useWindowDecoration & & ( wheresMyMouse . v < 0 ) )
return false ;
2007-01-13 05:33:19 +08:00
Point wheresMyMouseGlobal ;
GetEventParameter ( theEvent , kEventParamMouseLocation , typeQDPoint , NULL , sizeof ( wheresMyMouse ) , NULL , & wheresMyMouseGlobal ) ;
2007-01-09 18:06:20 +08:00
EventMouseButton mouseButton = 0 ;
GetEventParameter ( theEvent , kEventParamMouseButton , typeMouseButton , NULL , sizeof ( mouseButton ) , NULL , & mouseButton ) ;
2007-01-13 05:33:19 +08:00
UInt32 modifierKeys ;
GetEventParameter ( theEvent , kEventParamKeyModifiers , typeUInt32 , NULL , sizeof ( modifierKeys ) , NULL , & modifierKeys ) ;
2007-01-09 18:06:20 +08:00
WindowRef win ;
2007-01-13 05:33:19 +08:00
int fwres = FindWindow ( wheresMyMouseGlobal , & win ) ;
2008-04-01 18:00:39 +08:00
// return false when Window is inactive; For enabling click-to-active on window by delegating event to default handler
if ( ( ( fwres ! = inContent ) & & ( fwres > 0 ) & & ( mouseButton > = 1 ) ) | | ! IsWindowActive ( win ) )
2007-01-09 18:06:20 +08:00
{
2007-01-13 05:33:19 +08:00
return false ;
2007-01-09 18:06:20 +08:00
}
else
{
2008-01-29 00:38:39 +08:00
UInt32 clickCount ;
GetEventParameter ( theEvent , kEventParamClickCount , typeUInt32 , NULL , sizeof ( clickCount ) , NULL , & clickCount ) ;
2007-01-09 18:06:20 +08:00
// swap right and middle buttons so that middle button is 2, right button is 3.
if ( mouseButton = = 3 ) mouseButton = 2 ;
else if ( mouseButton = = 2 ) mouseButton = 3 ;
// check tablet pointer device and map it to a musebutton
TabletProximityRec theTabletRecord ; // The Tablet Proximity Record
// Extract the Tablet Proximity reccord from the event.
if ( noErr = = GetEventParameter ( theEvent , kEventParamTabletProximityRec ,
typeTabletProximityRec , NULL ,
sizeof ( TabletProximityRec ) ,
NULL , ( void * ) & theTabletRecord ) )
{
osgGA : : GUIEventAdapter : : TabletPointerType pointerType ;
switch ( theTabletRecord . pointerType )
{
case 1 : // pen
pointerType = osgGA : : GUIEventAdapter : : PEN ;
break ;
case 2 : // puck
pointerType = osgGA : : GUIEventAdapter : : PUCK ;
break ;
case 3 : //eraser
pointerType = osgGA : : GUIEventAdapter : : ERASER ;
break ;
default :
pointerType = osgGA : : GUIEventAdapter : : UNKNOWN ;
break ;
}
getEventQueue ( ) - > penProximity ( pointerType , ( theTabletRecord . enterProximity ! = 0 ) ) ;
}
2008-04-11 21:28:09 +08:00
// get tilt and rotation from the pen
TabletPointRec theTabletPointRecord ;
if ( noErr = = GetEventParameter ( theEvent , kEventParamTabletPointRec , typeTabletPointRec , NULL ,
sizeof ( TabletPointRec ) , NULL , ( void * ) & theTabletPointRecord ) )
{
int penRotation = ( int ) theTabletPointRecord . rotation * 9 / 575 ; //to get angle between 0 to 360 grad
penRotation = - ( ( ( penRotation + 180 ) % 360 ) - 180 ) ; //for same range on all plattforms we need -180 to 180
getEventQueue ( ) - > penOrientation (
theTabletPointRecord . tiltX * 60 / 32767.0f , //multiply with 60 to get angle between -60 to 60 grad
- theTabletPointRecord . tiltY * 60 / 32767.0f , //multiply with 60 to get angle between -60 to 60 grad
penRotation
) ;
}
2007-01-09 18:06:20 +08:00
switch ( GetEventKind ( theEvent ) )
{
case kEventMouseDown :
{
float mx = wheresMyMouse . h ;
float my = wheresMyMouse . v ;
transformMouseXY ( mx , my ) ;
2007-01-13 05:33:19 +08:00
lastEmulatedMouseButton = 0 ;
if ( mouseButton = = 1 )
{
if ( modifierKeys & cmdKey )
{
mouseButton = lastEmulatedMouseButton = 3 ;
}
else if ( modifierKeys & optionKey )
{
mouseButton = lastEmulatedMouseButton = 2 ;
}
}
2008-01-29 00:38:39 +08:00
if ( clickCount > 1 )
getEventQueue ( ) - > mouseDoubleButtonPress ( mx , my , mouseButton ) ;
else
getEventQueue ( ) - > mouseButtonPress ( mx , my , mouseButton ) ;
2007-01-09 18:06:20 +08:00
}
break ;
case kEventMouseUp :
{
float mx = wheresMyMouse . h ;
float my = wheresMyMouse . v ;
transformMouseXY ( mx , my ) ;
2007-01-13 05:33:19 +08:00
if ( lastEmulatedMouseButton > 0 ) {
getEventQueue ( ) - > mouseButtonRelease ( mx , my , lastEmulatedMouseButton ) ;
lastEmulatedMouseButton = 0 ;
}
else {
getEventQueue ( ) - > mouseButtonRelease ( mx , my , mouseButton ) ;
}
2007-01-09 18:06:20 +08:00
}
break ;
case kEventMouseDragged :
{
// get pressure from the pen, only when mouse/pen is dragged
TabletPointRec theTabletRecord ;
if ( noErr = = GetEventParameter ( theEvent , kEventParamTabletPointRec , typeTabletPointRec , NULL ,
sizeof ( TabletPointRec ) , NULL , ( void * ) & theTabletRecord ) ) {
getEventQueue ( ) - > penPressure ( theTabletRecord . pressure / 65535.0f ) ;
}
float mx = wheresMyMouse . h ;
float my = wheresMyMouse . v ;
transformMouseXY ( mx , my ) ;
getEventQueue ( ) - > mouseMotion ( mx , my ) ;
}
break ;
case kEventMouseMoved :
{
float mx = wheresMyMouse . h ;
float my = wheresMyMouse . v ;
transformMouseXY ( mx , my ) ;
getEventQueue ( ) - > mouseMotion ( mx , my ) ;
}
break ;
// mouse with scroll-wheels
case kEventMouseWheelMoved :
{
EventMouseWheelAxis axis ;
SInt32 delta ;
if ( noErr = = GetEventParameter ( theEvent , kEventParamMouseWheelAxis , typeMouseWheelAxis , NULL , sizeof ( axis ) , NULL , & axis ) ) {
if ( noErr = = GetEventParameter ( theEvent , kEventParamMouseWheelDelta , typeLongInteger , NULL , sizeof ( delta ) , NULL , & delta ) ) {
switch ( axis ) {
case kEventMouseWheelAxisX :
getEventQueue ( ) - > mouseScroll ( ( delta > 0 ) ? osgGA : : GUIEventAdapter : : SCROLL_RIGHT : osgGA : : GUIEventAdapter : : SCROLL_LEFT ) ;
break ;
case kEventMouseWheelAxisY :
getEventQueue ( ) - > mouseScroll ( ( delta < 0 ) ? osgGA : : GUIEventAdapter : : SCROLL_DOWN : osgGA : : GUIEventAdapter : : SCROLL_UP ) ;
break ;
}
}
}
}
break ;
// new trackpads and mighty mouse, (not officially documented, see http://developer.apple.com/qa/qa2005/qa1453.html )
case 11 :
{
enum
{
kEventParamMouseWheelSmoothVerticalDelta = ' saxy ' , // typeSInt32
2007-04-06 23:36:13 +08:00
kEventParamMouseWheelSmoothHorizontalDelta = ' saxx ' // typeSInt32
2007-01-09 18:06:20 +08:00
} ;
SInt32 scroll_delta_x = 0 ;
SInt32 scroll_delta_y = 0 ;
OSErr err = noErr ;
err = GetEventParameter ( theEvent , kEventParamMouseWheelSmoothVerticalDelta , typeLongInteger , NULL , sizeof ( scroll_delta_y ) , NULL , & scroll_delta_y ) ;
err = GetEventParameter ( theEvent , kEventParamMouseWheelSmoothHorizontalDelta , typeLongInteger , NULL , sizeof ( scroll_delta_x ) , NULL , & scroll_delta_x ) ;
if ( ( scroll_delta_x ! = 0 ) | | ( scroll_delta_y ! = 0 ) ) {
getEventQueue ( ) - > mouseScroll2D ( scroll_delta_x , scroll_delta_y ) ;
}
}
break ;
default :
2007-01-13 05:33:19 +08:00
return false ;
2007-01-09 18:06:20 +08:00
}
}
2007-01-13 05:33:19 +08:00
return true ;
2007-01-09 18:06:20 +08:00
}
2007-01-13 05:33:19 +08:00
bool GraphicsWindowCarbon : : handleKeyboardEvent ( EventRef theEvent )
2007-01-09 18:06:20 +08:00
{
2008-02-26 00:05:53 +08:00
handleModifierKeys ( theEvent ) ;
OSStatus status ;
2007-01-09 18:06:20 +08:00
UInt32 rawkey ;
GetEventParameter ( theEvent , kEventParamKeyCode , typeUInt32 , NULL , sizeof ( rawkey ) , NULL , & rawkey ) ;
2008-02-18 23:30:55 +08:00
// osg::notify(osg::INFO) << "key code: " << rawkey << " modifiers: " << modifierKeys << std::endl;
2007-01-09 18:06:20 +08:00
UInt32 dataSize ;
/* jbw check return status so that we don't allocate a huge array */
status = GetEventParameter ( theEvent , kEventParamKeyUnicodes , typeUnicodeText , NULL , 0 , & dataSize , NULL ) ;
2007-01-13 05:33:19 +08:00
if ( status ! = noErr ) return false ;
if ( dataSize < = 1 ) return false ;
2007-01-09 18:06:20 +08:00
UniChar * uniChars = new UniChar [ dataSize + 1 ] ;
GetEventParameter ( theEvent , kEventParamKeyUnicodes , typeUnicodeText , NULL , dataSize , NULL , ( void * ) uniChars ) ;
unsigned int keychar = remapOSXKey ( static_cast < unsigned long > ( uniChars [ 0 ] ) , rawkey ) ;
switch ( GetEventKind ( theEvent ) )
{
case kEventRawKeyDown :
case kEventRawKeyRepeat :
{
2007-07-05 18:51:47 +08:00
//getEventQueue()->getCurrentEventState()->setModKeyMask(modifierMask);
2008-02-18 23:30:55 +08:00
osg : : notify ( osg : : INFO ) < < " GraphicsWindowCarbon::keyPress " < < std : : endl ;
2007-04-25 17:32:12 +08:00
getEventQueue ( ) - > keyPress ( keychar ) ;
2007-01-09 18:06:20 +08:00
break ;
}
case kEventRawKeyUp :
{
2008-02-18 23:30:55 +08:00
osg : : notify ( osg : : INFO ) < < " GraphicsWindowCarbon::keyPress " < < std : : endl ;
2007-07-05 18:51:47 +08:00
//getEventQueue()->getCurrentEventState()->setModKeyMask(modifierMask);
2007-04-25 17:32:12 +08:00
getEventQueue ( ) - > keyRelease ( keychar ) ;
2007-01-09 18:06:20 +08:00
break ;
}
default :
break ;
}
delete [ ] uniChars ;
2007-01-13 05:33:19 +08:00
return true ;
2007-01-09 18:06:20 +08:00
}
2008-02-26 00:05:53 +08:00
void GraphicsWindowCarbon : : handleModifierKey ( UInt32 modifierKey , UInt32 modifierMask , osgGA : : GUIEventAdapter : : KeySymbol keySymbol ) {
if ( ( modifierKey & modifierMask ) & & ! ( _lastModifierKeys & modifierMask ) )
{
getEventQueue ( ) - > keyPress ( keySymbol ) ;
}
if ( ! ( modifierKey & modifierMask ) & & ( _lastModifierKeys & modifierMask ) )
{
getEventQueue ( ) - > keyRelease ( keySymbol ) ;
}
}
bool GraphicsWindowCarbon : : handleModifierKeys ( EventRef theEvent )
{
UInt32 modifierKeys ;
GetEventParameter ( theEvent , kEventParamKeyModifiers , typeUInt32 , NULL , sizeof ( modifierKeys ) , NULL , & modifierKeys ) ;
//std::cout << modifierKeys << std::endl;
if ( _lastModifierKeys = = modifierKeys )
return false ;
handleModifierKey ( modifierKeys , shiftKey , osgGA : : GUIEventAdapter : : KEY_Shift_L ) ;
handleModifierKey ( modifierKeys , controlKey , osgGA : : GUIEventAdapter : : KEY_Control_L ) ;
handleModifierKey ( modifierKeys , optionKey , osgGA : : GUIEventAdapter : : KEY_Alt_L ) ;
handleModifierKey ( modifierKeys , cmdKey , osgGA : : GUIEventAdapter : : KEY_Super_L ) ;
// Caps lock needs some special handling, i did not find a way to get informed when the caps-lock-key gets released
if ( ( modifierKeys & alphaLock ) & & ! ( _lastModifierKeys & alphaLock ) )
{
getEventQueue ( ) - > keyPress ( osgGA : : GUIEventAdapter : : KEY_Caps_Lock ) ;
getEventQueue ( ) - > keyRelease ( osgGA : : GUIEventAdapter : : KEY_Caps_Lock ) ;
}
if ( ! ( modifierKeys & alphaLock ) & & ( _lastModifierKeys & alphaLock ) )
{
getEventQueue ( ) - > keyPress ( osgGA : : GUIEventAdapter : : KEY_Caps_Lock ) ;
getEventQueue ( ) - > keyRelease ( osgGA : : GUIEventAdapter : : KEY_Caps_Lock ) ;
}
_lastModifierKeys = modifierKeys ;
return true ;
}
2007-01-09 18:06:20 +08:00
void GraphicsWindowCarbon : : checkEvents ( )
{
if ( ! _realized ) return ;
EventRef theEvent ;
EventTargetRef theTarget = GetEventDispatcherTarget ( ) ;
while ( ReceiveNextEvent ( 0 , NULL , 0 , true , & theEvent ) = = noErr )
{
switch ( GetEventClass ( theEvent ) )
{
2007-01-13 05:33:19 +08:00
case kEventClassMouse :
{
// handle the menubar
Point wheresMyMouse ;
GetEventParameter ( theEvent , kEventParamMouseLocation , typeQDPoint , NULL , sizeof ( wheresMyMouse ) , NULL , & wheresMyMouse ) ;
EventMouseButton mouseButton = 0 ;
GetEventParameter ( theEvent , kEventParamMouseButton , typeMouseButton , NULL , sizeof ( mouseButton ) , NULL , & mouseButton ) ;
WindowRef win ;
int fwres = FindWindow ( wheresMyMouse , & win ) ;
if ( ( fwres = = inMenuBar ) & & ( mouseButton > = 1 ) ) {
MenuSelect ( wheresMyMouse ) ;
HiliteMenu ( 0 ) ;
return ;
}
break ;
}
2007-01-09 18:06:20 +08:00
case kEventClassApplication :
switch ( GetEventKind ( theEvent ) ) {
case kEventAppQuit :
getEventQueue ( ) - > quitApplication ( ) ;
break ;
}
break ;
case kEventClassAppleEvent :
{
EventRecord eventRecord ;
ConvertEventRefToEventRecord ( theEvent , & eventRecord ) ;
AEProcessAppleEvent ( & eventRecord ) ;
return ;
}
break ;
}
SendEventToEventTarget ( theEvent , theTarget ) ;
ReleaseEvent ( theEvent ) ;
}
if ( _closeRequested )
2007-07-28 00:48:31 +08:00
getEventQueue ( ) - > closeWindow ( ) ;
2007-01-09 18:06:20 +08:00
if ( s_quit_requested ) {
getEventQueue ( ) - > quitApplication ( ) ;
s_quit_requested = false ;
}
}
2007-06-11 03:53:18 +08:00
bool GraphicsWindowCarbon : : setWindowRectangleImplementation ( int x , int y , int width , int height )
2007-04-13 22:23:10 +08:00
{
2007-05-20 21:42:41 +08:00
Rect bounds = { y , x , y + height , x + width } ;
SetWindowBounds ( getNativeWindowRef ( ) , kWindowContentRgn , & bounds ) ;
aglUpdateContext ( _context ) ;
MenubarController : : instance ( ) - > update ( ) ;
2007-06-11 03:53:18 +08:00
return true ;
2007-04-13 22:23:10 +08:00
}
2007-01-09 18:06:20 +08:00
void GraphicsWindowCarbon : : grabFocus ( )
{
SelectWindow ( _window ) ;
}
void GraphicsWindowCarbon : : grabFocusIfPointerInWindow ( )
{
// TODO: implement
2007-01-13 05:33:19 +08:00
osg : : notify ( osg : : ALWAYS ) < < " GraphicsWindowCarbon::grabFocusIfPointerInWindow " < < std : : endl ;
2007-01-09 18:06:20 +08:00
}
2007-12-17 18:24:20 +08:00
void GraphicsWindowCarbon : : useCursor ( bool cursorOn )
{
if ( _traits . valid ( ) )
_traits - > useCursor = cursorOn ;
OSXCarbonWindowingSystemInterface * wsi = dynamic_cast < OSXCarbonWindowingSystemInterface * > ( osg : : GraphicsContext : : getWindowingSystemInterface ( ) ) ;
if ( wsi = = NULL ) {
osg : : notify ( osg : : WARN ) < < " GraphicsWindowCarbon::useCursor :: could not get OSXCarbonWindowingSystemInterface " < < std : : endl ;
return ;
}
CGDirectDisplayID displayId = wsi - > getDisplayID ( ( * _traits ) ) ;
CGDisplayErr err = kCGErrorSuccess ;
switch ( cursorOn )
{
case true :
err = CGDisplayShowCursor ( displayId ) ;
break ;
case false :
err = CGDisplayHideCursor ( displayId ) ;
break ;
}
if ( err ! = kCGErrorSuccess ) {
osg : : notify ( osg : : WARN ) < < " GraphicsWindowCarbon::useCursor failed with " < < err < < std : : endl ;
}
}
2008-04-01 18:00:39 +08:00
// FIXME: need to implement all cursor types
// FIXME: I used deprecated functions, but don't know if there are any substitutable newer functions...
void GraphicsWindowCarbon : : setCursor ( MouseCursor mouseCursor )
{
UInt32 cursor ;
if ( _currentCursor = = mouseCursor )
return ;
switch ( mouseCursor )
{
case NoCursor :
HideCursor ( ) ;
_currentCursor = mouseCursor ;
return ;
case RightArrowCursor :
cursor = kThemeArrowCursor ;
break ;
case CrosshairCursor :
cursor = kThemeCrossCursor ;
break ;
case TextCursor :
cursor = kThemeIBeamCursor ;
break ;
case UpDownCursor :
cursor = kThemeResizeUpDownCursor ;
break ;
case LeftRightCursor :
cursor = kThemeResizeLeftRightCursor ;
break ;
default :
cursor = kThemeArrowCursor ;
osg : : notify ( osg : : WARN ) < < " GraphicsWindowCarbon::setCursor doesn't implement cursor: type = " < < mouseCursor < < std : : endl ;
}
_currentCursor = mouseCursor ;
SetThemeCursor ( cursor ) ;
ShowCursor ( ) ;
}
2007-12-17 18:24:20 +08:00
void GraphicsWindowCarbon : : setWindowName ( const std : : string & name )
{
_traits - > windowName = name ;
if ( ! _traits - > windowName . empty ( ) )
{
CFStringRef windowtitle = CFStringCreateWithBytes ( kCFAllocatorDefault , ( const UInt8 * ) ( _traits - > windowName . c_str ( ) ) , _traits - > windowName . length ( ) , kCFStringEncodingUTF8 , false ) ;
SetWindowTitleWithCFString ( _window , windowtitle ) ;
CFRelease ( windowtitle ) ;
}
}
2007-01-09 18:06:20 +08:00
2008-01-29 00:38:39 +08:00
2007-01-09 18:06:20 +08:00
void GraphicsWindowCarbon : : transformMouseXY ( float & x , float & y )
{
if ( getEventQueue ( ) - > getUseFixedMouseInputRange ( ) )
{
osgGA : : GUIEventAdapter * eventState = getEventQueue ( ) - > getCurrentEventState ( ) ;
x = eventState - > getXmin ( ) + ( eventState - > getXmax ( ) - eventState - > getXmin ( ) ) * x / float ( _traits - > width ) ;
y = eventState - > getYmin ( ) + ( eventState - > getYmax ( ) - eventState - > getYmin ( ) ) * y / float ( _traits - > height ) ;
}
}
struct RegisterWindowingSystemInterfaceProxy
{
RegisterWindowingSystemInterfaceProxy ( )
{
2007-01-13 05:33:19 +08:00
osg : : GraphicsContext : : setWindowingSystemInterface ( new osgViewer : : OSXCarbonWindowingSystemInterface ( ) ) ;
2007-01-09 18:06:20 +08:00
}
~ RegisterWindowingSystemInterfaceProxy ( )
{
2007-07-06 21:08:51 +08:00
if ( osg : : Referenced : : getDeleteHandler ( ) )
{
osg : : Referenced : : getDeleteHandler ( ) - > setNumFramesToRetainObjects ( 0 ) ;
osg : : Referenced : : getDeleteHandler ( ) - > flushAll ( ) ;
}
2007-01-09 18:06:20 +08:00
osg : : GraphicsContext : : setWindowingSystemInterface ( 0 ) ;
}
} ;
RegisterWindowingSystemInterfaceProxy createWindowingSystemInterfaceProxy ;
2007-06-11 03:53:18 +08:00
// declare C entry point for static compilation.
extern " C " void graphicswindow_Carbon ( void )
{
osg : : GraphicsContext : : setWindowingSystemInterface ( new osgViewer : : OSXCarbonWindowingSystemInterface ( ) ) ;
}
2007-01-09 18:06:20 +08:00
# endif