From b8a76a0ce0ee04514fef6f3e0d67f83e0c642633 Mon Sep 17 00:00:00 2001 From: Paul MARTZ Date: Mon, 22 Mar 2010 15:09:17 +0000 Subject: [PATCH] 2.8 branch. 2nd attempt: The main point of this commit is to eliminate static initializers for OS X. Merges: 9894, 11207, 11263, and 11273. --- src/osgViewer/DarwinUtils.h | 11 +- src/osgViewer/DarwinUtils.mm | 168 +++++++--- src/osgViewer/GraphicsWindowCarbon.cpp | 431 ++++++------------------- src/osgViewer/GraphicsWindowCocoa.mm | 17 +- 4 files changed, 237 insertions(+), 390 deletions(-) diff --git a/src/osgViewer/DarwinUtils.h b/src/osgViewer/DarwinUtils.h index bed2ffa4d..34a3c6f0f 100755 --- a/src/osgViewer/DarwinUtils.h +++ b/src/osgViewer/DarwinUtils.h @@ -90,7 +90,9 @@ struct DarwinWindowingSystemInterface : public osg::GraphicsContext::WindowingSy unsigned int getScreenContaining(int x, int y, int w, int h); protected: - + + virtual void _init(); + /** implementation of setScreenResolution */ bool setScreenResolutionImpl(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, unsigned int width, unsigned int height) ; @@ -114,9 +116,10 @@ struct DarwinWindowingSystemInterface : public osg::GraphicsContext::WindowingSy else return 0; } } - - - private: + + protected: + + bool _initialized; CGDisplayCount _displayCount; CGDirectDisplayID* _displayIds; diff --git a/src/osgViewer/DarwinUtils.mm b/src/osgViewer/DarwinUtils.mm index fa909d09e..1bcacfd39 100755 --- a/src/osgViewer/DarwinUtils.mm +++ b/src/osgViewer/DarwinUtils.mm @@ -221,21 +221,11 @@ static long getDictLong(CFDictionaryRef refDict, CFStringRef key) // cons /** ctor, get a list of all attached displays */ DarwinWindowingSystemInterface::DarwinWindowingSystemInterface() : + _initialized(false), _displayCount(0), _displayIds(NULL) { - ProcessSerialNumber sn = { 0, kCurrentProcess }; - TransformProcessType(&sn,kProcessTransformToForegroundApplication); - SetFrontProcess(&sn); - - if( CGGetActiveDisplayList( 0, NULL, &_displayCount ) != CGDisplayNoErr ) - osg::notify(osg::WARN) << "DarwinWindowingSystemInterface: could not get # of screens" << std::endl; - - _displayIds = new CGDirectDisplayID[_displayCount]; - if( CGGetActiveDisplayList( _displayCount, _displayIds, &_displayCount ) != CGDisplayNoErr ) - osg::notify(osg::WARN) << "DarwinWindowingSystemInterface: CGGetActiveDisplayList failed" << std::endl; - - } +} /** dtor */ DarwinWindowingSystemInterface::~DarwinWindowingSystemInterface() @@ -250,12 +240,51 @@ DarwinWindowingSystemInterface::~DarwinWindowingSystemInterface() _displayIds = NULL; } +void DarwinWindowingSystemInterface::_init() +{ + if (_initialized) return; + + ProcessSerialNumber sn = { 0, kCurrentProcess }; + TransformProcessType(&sn,kProcessTransformToForegroundApplication); + SetFrontProcess(&sn); + + if( CGGetActiveDisplayList( 0, NULL, &_displayCount ) != CGDisplayNoErr ) + { + osg::notify(osg::WARN) << "DarwinWindowingSystemInterface: could not get # of screens" << std::endl; + _displayCount = 0; + + _initialized = true; + return; + } + + _displayIds = new CGDirectDisplayID[_displayCount]; + + if( CGGetActiveDisplayList( _displayCount, _displayIds, &_displayCount ) != CGDisplayNoErr ) + { + osg::notify(osg::WARN) << "DarwinWindowingSystemInterface: CGGetActiveDisplayList failed" << std::endl; + } + + _initialized = true; +} + /** @return a CGDirectDisplayID for a ScreenIdentifier */ -CGDirectDisplayID DarwinWindowingSystemInterface::getDisplayID(const osg::GraphicsContext::ScreenIdentifier& si) { +CGDirectDisplayID DarwinWindowingSystemInterface::getDisplayID(const osg::GraphicsContext::ScreenIdentifier& si) +{ + _init(); + + if (_displayCount==0) + { + osg::notify(osg::WARN) << "DarwinWindowingSystemInterface::getDisplayID(..) no valid screens available returning 0 instead." << std::endl; + return 0; + } + if (si.screenNum < static_cast(_displayCount)) + { return _displayIds[si.screenNum]; - else { - osg::notify(osg::WARN) << "GraphicsWindowCarbon :: invalid screen # " << si.screenNum << ", returning main-screen instead" << std::endl; + } + else + { + osg::notify(osg::WARN) << "DarwinWindowingSystemInterface::getDisplayID(..) invalid screen # " << si.screenNum << ", returning main-screen instead." << std::endl; return _displayIds[0]; } } @@ -263,11 +292,24 @@ CGDirectDisplayID DarwinWindowingSystemInterface::getDisplayID(const osg::Graphi /** @return count of attached screens */ unsigned int DarwinWindowingSystemInterface::getNumScreens(const osg::GraphicsContext::ScreenIdentifier& si) { + _init(); + return _displayCount; } void DarwinWindowingSystemInterface::getScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution) { + _init(); + + if (_displayCount==0) + { + resolution.width = 0; + resolution.height = 0; + resolution.colorDepth = 0; + resolution.refreshRate = 0; + return; + } + CGDirectDisplayID id = getDisplayID(si); resolution.width = CGDisplayPixelsWide(id); resolution.height = CGDisplayPixelsHigh(id); @@ -277,33 +319,51 @@ void DarwinWindowingSystemInterface::getScreenSettings(const osg::GraphicsContex } -void DarwinWindowingSystemInterface::enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, osg::GraphicsContext::ScreenSettingsList & resolutionList) { - // Warning! This method has not been tested. - resolutionList.clear(); +void DarwinWindowingSystemInterface::enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, osg::GraphicsContext::ScreenSettingsList & resolutionList) +{ + _init(); - CGDirectDisplayID displayid = getDisplayID(screenIdentifier); - CFArrayRef availableModes = CGDisplayAvailableModes(displayid); - unsigned int numberOfAvailableModes = CFArrayGetCount(availableModes); - for (unsigned int i=0; i(bounds.origin.x); y = static_cast(bounds.origin.y); @@ -316,8 +376,10 @@ bool DarwinWindowingSystemInterface::setScreenSettings(const osg::GraphicsContex { bool result = setScreenResolutionImpl(si, settings.width, settings.height); if (result) + { setScreenRefreshRateImpl(si, settings.refreshRate); - + } + return result; } @@ -326,6 +388,13 @@ bool DarwinWindowingSystemInterface::setScreenSettings(const osg::GraphicsContex /** implementation of setScreenResolution */ bool DarwinWindowingSystemInterface::setScreenResolutionImpl(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, unsigned int width, unsigned int height) { + _init(); + + if (_displayCount==0) + { + return false; + } + CGDirectDisplayID displayid = getDisplayID(screenIdentifier); // add next line and on following line replace hard coded depth and refresh rate @@ -344,8 +413,15 @@ bool DarwinWindowingSystemInterface::setScreenResolutionImpl(const osg::Graphics } /** implementation of setScreenRefreshRate */ -bool DarwinWindowingSystemInterface::setScreenRefreshRateImpl(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, double refreshRate) { - +bool DarwinWindowingSystemInterface::setScreenRefreshRateImpl(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, double refreshRate) +{ + _init(); + + if (_displayCount==0) + { + return false; + } + boolean_t success(false); unsigned width, height; getScreenResolution(screenIdentifier, width, height); @@ -371,6 +447,13 @@ bool DarwinWindowingSystemInterface::setScreenRefreshRateImpl(const osg::Graphic unsigned int DarwinWindowingSystemInterface::getScreenContaining(int x, int y, int w, int h) { + _init(); + + if (_displayCount==0) + { + return 0; + } + CGRect rect = CGRectMake(x,y,w,h); for(unsigned int i = 0; i < _displayCount; ++i) { CGRect bounds = CGDisplayBounds( getDisplayID(i) ); @@ -382,9 +465,4 @@ unsigned int DarwinWindowingSystemInterface::getScreenContaining(int x, int y, i return 0; } - - - - - } diff --git a/src/osgViewer/GraphicsWindowCarbon.cpp b/src/osgViewer/GraphicsWindowCarbon.cpp index fd93fa1ca..5e321a1ae 100644 --- a/src/osgViewer/GraphicsWindowCarbon.cpp +++ b/src/osgViewer/GraphicsWindowCarbon.cpp @@ -11,7 +11,8 @@ * OpenSceneGraph Public License for more details. */ -#ifdef __APPLE__ +#if defined (__APPLE__) && (!__LP64__) + #include #include @@ -24,7 +25,10 @@ #include +#include "DarwinUtils.h" + using namespace osgViewer; +using namespace osgDarwin; // Carbon-Eventhandler to handle the click in the close-widget and the resize of windows @@ -65,8 +69,7 @@ static pascal OSStatus GraphicsWindowEventHandler(EventHandlerCallRef nextHandle // 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->adaptResize(bounds.left, bounds.top, bounds.right - bounds.left, bounds.bottom - bounds.top); w->requestRedraw(); result = noErr; break; @@ -74,8 +77,7 @@ static pascal OSStatus GraphicsWindowEventHandler(EventHandlerCallRef nextHandle 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()); + w->adaptResize(bounds.left, bounds.top, bounds.right - bounds.left, bounds.bottom - bounds.top); result = noErr; break; @@ -135,10 +137,10 @@ namespace osgViewer // small helper class which maps the raw key codes to osgGA::GUIEventAdapter::Keys -class OSXKeyboardMap { +class CarbonKeyboardMap { public: - OSXKeyboardMap() + CarbonKeyboardMap() { _keymap[53 ] = osgGA::GUIEventAdapter::KEY_Escape; _keymap[115 ] = osgGA::GUIEventAdapter::KEY_Home; @@ -187,7 +189,7 @@ class OSXKeyboardMap { } - ~OSXKeyboardMap() { + ~CarbonKeyboardMap() { } unsigned int remapKey(unsigned int key, unsigned int rawkey) @@ -202,311 +204,33 @@ class OSXKeyboardMap { }; /** remaps a native os x keycode to a GUIEventAdapter-keycode */ -static unsigned int remapOSXKey(unsigned int key, unsigned int rawkey) +static unsigned int remapCarbonKey(unsigned int key, unsigned int rawkey) { - static OSXKeyboardMap s_OSXKeyboardMap; - return s_OSXKeyboardMap.remapKey(key,rawkey); + static CarbonKeyboardMap s_CarbonKeyboardMap; + return s_CarbonKeyboardMap.remapKey(key,rawkey); } - - -#pragma mark * * * MenubarController * * * - -/** the MenubarController class checks all open windows if they intersect with the menubar / dock and hide the menubar/dock if necessary */ -class MenubarController : public osg::Referenced -{ - - public: - MenubarController() : - osg::Referenced(), - _list(), - _menubarShown(false), - _mutex() - { - // the following code will query the system for the available rect on the main-display (typically the displaying showing the menubar + the dock - - 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; - WindowList _list; - bool _menubarShown; - Rect _availRect; - CGRect _mainScreenBounds; - OpenThreads::Mutex _mutex; +class CarbonWindowAdapter : public MenubarController::WindowAdapter { +public: + CarbonWindowAdapter(GraphicsWindowCarbon* win) : MenubarController::WindowAdapter(), _win(win) {} + virtual bool valid() {return (_win.valid() && _win->valid()); } + virtual void getWindowBounds(CGRect& rect) + { + Rect windowBounds; + OSErr error = GetWindowBounds(_win->getNativeWindowRef(), kWindowStructureRgn, &windowBounds); + rect.origin.x = windowBounds.left; + rect.origin.y = windowBounds.top; + rect.size.width = windowBounds.right - windowBounds.left; + rect.size.height = windowBounds.bottom - windowBounds.top; + } + osgViewer::GraphicsWindow* getWindow() { return _win.get(); } +private: + osg::observer_ptr _win; }; -MenubarController* MenubarController::instance() -{ - static osg::ref_ptr s_menubar_controller = new MenubarController(); - return s_menubar_controller.get(); -} - - -void MenubarController::attachWindow(GraphicsWindowCarbon* win) -{ - OpenThreads::ScopedLock lock(_mutex); - _list.push_back(win); - update(); -} - - -void MenubarController::detachWindow(GraphicsWindowCarbon* win) -{ - OpenThreads::ScopedLock lock(_mutex); - 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) - { - ProcessSerialNumber sn = { 0, kCurrentProcess }; - TransformProcessType(&sn,kProcessTransformToForegroundApplication); - SetFrontProcess(&sn); - - 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 */ - ~OSXCarbonWindowingSystemInterface() - { - if (osg::Referenced::getDeleteHandler()) - { - osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0); - osg::Referenced::getDeleteHandler()->flushAll(); - } - - if (_displayIds) delete[] _displayIds; - _displayIds = NULL; - } - - /** @return a CGDirectDisplayID for a ScreenIdentifier */ - inline CGDirectDisplayID getDisplayID(const osg::GraphicsContext::ScreenIdentifier& si) { - 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]; - } - } - - /** @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 getScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution) - { - CGDirectDisplayID id = getDisplayID(si); - resolution.width = CGDisplayPixelsWide(id); - resolution.height = CGDisplayPixelsHigh(id); - resolution.colorDepth = CGDisplayBitsPerPixel(id); - resolution.refreshRate = getDictDouble (CGDisplayCurrentMode(id), kCGDisplayRefreshRate); // Not tested - if (resolution.refreshRate<0) resolution.refreshRate = 0; - } - - /** 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) ); - x = static_cast(bounds.origin.x); - y = static_cast(bounds.origin.y); - - // osg::notify(osg::DEBUG_INFO) << "topleft of screen " << si.screenNum <<" " << bounds.origin.x << "/" << bounds.origin.y << std::endl; - } - - /** Helper method to get a double value out of a CFDictionary */ - static double getDictDouble (CFDictionaryRef refDict, CFStringRef key) - { - 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, &value)) // or if cant convert it - return -1; // fail - return value; // otherwise return the long value - } - - /** Helper method to get a long value out of a CFDictionary */ - static long getDictLong(CFDictionaryRef refDict, CFStringRef key) // const void* key? - { - long value = 0; - 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, kCFNumberLongType, &value)) // or if cant convert it - return -1; // fail - return value; - } - - /** implementation of setScreenSettings */ - virtual bool setScreenSettings(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, const osg::GraphicsContext::ScreenSettings & resolution) - { - CGDirectDisplayID displayID = getDisplayID(screenIdentifier); - - CGRefreshRate refresh = resolution.refreshRate>0 ? resolution.refreshRate : getDictDouble (CGDisplayCurrentMode(displayID), kCGDisplayRefreshRate); - size_t depth = resolution.colorDepth>0 ? resolution.colorDepth : CGDisplayBitsPerPixel(displayID); - CFDictionaryRef display_mode_values = - CGDisplayBestModeForParametersAndRefreshRate( - displayID, - depth, - resolution.width, resolution.height, - refresh, - NULL); - - - CGDisplaySwitchToMode(displayID, display_mode_values); - return true; - } - - virtual void enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, osg::GraphicsContext::ScreenSettingsList & resolutionList) { - // Warning! This method has not been tested. - resolutionList.clear(); - - CGDirectDisplayID displayID = getDisplayID(screenIdentifier); - CFArrayRef availableModes = CGDisplayAvailableModes(displayID); - unsigned int numberOfAvailableModes = CFArrayGetCount(availableModes); - for (unsigned int i=0; ipbuffer) - { - osg::ref_ptr pbuffer = new PixelBufferCarbon(traits); - if (pbuffer->valid()) return pbuffer.release(); - else return 0; - } - else - { - osg::ref_ptr window = new GraphicsWindowCarbon(traits); - if (window->valid()) return window.release(); - else return 0; - } - } - - - - private: - CGDisplayCount _displayCount; - CGDirectDisplayID* _displayIds; -}; - -} - - -#pragma mark * * * GraphicsWindowCarbon * * * - - - void GraphicsWindowCarbon::init() { @@ -630,13 +354,11 @@ bool GraphicsWindowCarbon::realizeImplementation() useCursor(_traits->useCursor); // move the window to the right screen - OSXCarbonWindowingSystemInterface* wsi = dynamic_cast(osg::GraphicsContext::getWindowingSystemInterface()); + DarwinWindowingSystemInterface* wsi = dynamic_cast(osg::GraphicsContext::getWindowingSystemInterface()); int screenLeft(0), screenTop(0); - if (wsi) { - + if (wsi) + { wsi->getScreenTopLeft((*_traits), screenLeft, screenTop); - _traits->y += screenTop; - _traits->x += screenLeft; } WindowData *windowData = ( _traits.get() && _traits->inheritedWindowData.get() ) ? static_cast(_traits->inheritedWindowData.get()) : 0; @@ -646,7 +368,7 @@ bool GraphicsWindowCarbon::realizeImplementation() if (_ownsWindow) { // create the window - Rect bounds = {_traits->y, _traits->x, _traits->y + _traits->height, _traits->x + _traits->width}; + Rect bounds = {_traits->y + screenTop, _traits->x + screenLeft, _traits->y + _traits->height + screenTop, _traits->x + _traits->width + screenLeft}; OSStatus err = 0; WindowAttributes attr = computeWindowAttributes(_useWindowDecoration, _traits->supportsResize); @@ -703,7 +425,7 @@ bool GraphicsWindowCarbon::realizeImplementation() } else { aglSetDrawable(_context, GetWindowPort(_window)); ShowWindow(_window); - MenubarController::instance()->attachWindow(this); + MenubarController::instance()->attachWindow( new CarbonWindowAdapter(this) ); } makeCurrent(); @@ -805,6 +527,8 @@ void GraphicsWindowCarbon::resizedImplementation(int x, int y, int width, int he aglUpdateContext(_context); MenubarController::instance()->update(); + + getEventQueue()->windowResize(x,y,width, height, getEventQueue()->getTime()); } @@ -1032,7 +756,7 @@ bool GraphicsWindowCarbon::handleKeyboardEvent(EventRef theEvent) UniChar* uniChars = new UniChar[dataSize+1]; GetEventParameter( theEvent, kEventParamKeyUnicodes, typeUnicodeText, NULL, dataSize, NULL, (void*)uniChars ); - unsigned int keychar = remapOSXKey(static_cast(uniChars[0]), rawkey); + unsigned int keychar = remapCarbonKey(static_cast(uniChars[0]), rawkey); switch(GetEventKind(theEvent)) { @@ -1173,13 +897,43 @@ void GraphicsWindowCarbon::checkEvents() bool GraphicsWindowCarbon::setWindowRectangleImplementation(int x, int y, int width, int height) { - Rect bounds = {y, x, y + height, x + width}; + int screenLeft(0), screenTop(0); + DarwinWindowingSystemInterface* wsi = dynamic_cast(osg::GraphicsContext::getWindowingSystemInterface()); + if (wsi) + { + wsi->getScreenTopLeft((*_traits), screenLeft, screenTop); + } + + Rect bounds = {y + screenTop, x + screenLeft, y + height + screenTop, x + width + screenLeft}; SetWindowBounds(getNativeWindowRef(), kWindowContentRgn, &bounds); aglUpdateContext(_context); MenubarController::instance()->update(); return true; } + + +void GraphicsWindowCarbon::adaptResize(int x, int y, int w, int h) +{ + DarwinWindowingSystemInterface* wsi = dynamic_cast(osg::GraphicsContext::getWindowingSystemInterface()); + int screenLeft(0), screenTop(0); + if (wsi) { + + // get the screen containing the window + unsigned int screenNdx = wsi->getScreenContaining(x,y,w,h); + + // update traits + _traits->screenNum = screenNdx; + + // get top left of screen + wsi->getScreenTopLeft((*_traits), screenLeft, screenTop); + } + + resized(x-screenLeft,y-screenTop,w,h); +} + + + void GraphicsWindowCarbon::grabFocus() { SelectWindow(_window); @@ -1199,7 +953,7 @@ void GraphicsWindowCarbon::useCursor(bool cursorOn) if (_traits.valid()) _traits->useCursor = cursorOn; - OSXCarbonWindowingSystemInterface* wsi = dynamic_cast(osg::GraphicsContext::getWindowingSystemInterface()); + DarwinWindowingSystemInterface* wsi = dynamic_cast(osg::GraphicsContext::getWindowingSystemInterface()); if (wsi == NULL) { osg::notify(osg::WARN) << "GraphicsWindowCarbon::useCursor :: could not get OSXCarbonWindowingSystemInterface" << std::endl; return; @@ -1274,7 +1028,7 @@ void GraphicsWindowCarbon::setWindowName (const std::string& name) void GraphicsWindowCarbon::requestWarpPointer(float x,float y) { - OSXCarbonWindowingSystemInterface* wsi = dynamic_cast(osg::GraphicsContext::getWindowingSystemInterface()); + DarwinWindowingSystemInterface* wsi = dynamic_cast(osg::GraphicsContext::getWindowingSystemInterface()); if (wsi == NULL) { osg::notify(osg::WARN) << "GraphicsWindowCarbon::useCursor :: could not get OSXCarbonWindowingSystemInterface" << std::endl; return; @@ -1301,36 +1055,45 @@ void GraphicsWindowCarbon::transformMouseXY(float& x, float& y) } } - - - - - -struct RegisterWindowingSystemInterfaceProxy -{ - RegisterWindowingSystemInterfaceProxy() +class CarbonWindowingSystemInterface : public DarwinWindowingSystemInterface { +public: + CarbonWindowingSystemInterface() : DarwinWindowingSystemInterface() { - osg::GraphicsContext::setWindowingSystemInterface(new osgViewer::OSXCarbonWindowingSystemInterface()); } - ~RegisterWindowingSystemInterfaceProxy() + virtual osg::GraphicsContext* createGraphicsContext(osg::GraphicsContext::Traits* traits) { - if (osg::Referenced::getDeleteHandler()) - { - osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0); - osg::Referenced::getDeleteHandler()->flushAll(); - } + _init(); - osg::GraphicsContext::setWindowingSystemInterface(0); + return createGraphicsContextImplementation(traits); } + + virtual void _init() + { + if (_initialized) return; + + DarwinWindowingSystemInterface::_init(); + + // 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); + } + }; -RegisterWindowingSystemInterfaceProxy createWindowingSystemInterfaceProxy; + +} + +#ifdef USE_DARWIN_CARBON_IMPLEMENTATION +RegisterWindowingSystemInterfaceProxy createWindowingSystemInterfaceProxy; +#endif + // declare C entry point for static compilation. extern "C" void graphicswindow_Carbon(void) { - osg::GraphicsContext::setWindowingSystemInterface(new osgViewer::OSXCarbonWindowingSystemInterface()); + osg::GraphicsContext::setWindowingSystemInterface(new osgViewer::CarbonWindowingSystemInterface()); } #endif diff --git a/src/osgViewer/GraphicsWindowCocoa.mm b/src/osgViewer/GraphicsWindowCocoa.mm index f645a87ea..3c0da1234 100755 --- a/src/osgViewer/GraphicsWindowCocoa.mm +++ b/src/osgViewer/GraphicsWindowCocoa.mm @@ -1378,16 +1378,17 @@ GraphicsWindowCocoa::~GraphicsWindowCocoa() // CocoaWindowingSystemInterface // ---------------------------------------------------------------------------------------------------------- -struct CocoaWindowingSystemInterface : public DarwinWindowingSystemInterface { - - CocoaWindowingSystemInterface() - : DarwinWindowingSystemInterface() - - { +struct CocoaWindowingSystemInterface : public DarwinWindowingSystemInterface +{ + + CocoaWindowingSystemInterface() : DarwinWindowingSystemInterface() + { } - + void initAsStandaloneApplication() { + _init(); + static bool s_inited = false; if (s_inited) return; s_inited = true; @@ -1417,6 +1418,8 @@ struct CocoaWindowingSystemInterface : public DarwinWindowingSystemInterface { virtual osg::GraphicsContext* createGraphicsContext(osg::GraphicsContext::Traits* traits) { + _init(); + if (!traits->pbuffer) { GraphicsWindowCocoa::WindowData* windowData = traits->inheritedWindowData ? dynamic_cast(traits->inheritedWindowData.get()) : NULL;