root/OpenSceneGraph/trunk/src/osgViewer/GraphicsWindowCarbon.cpp @ 9369

Revision 9369, 49.8 kB (checked in by robert, 6 years ago)

From Bob Kuehne, build fixes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
RevLine 
[5948]1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#ifdef __APPLE__
[5978]15#include <osg/observer_ptr>
[7079]16
[7039]17#include <osgViewer/api/Carbon/PixelBufferCarbon>
[6464]18#include <osgViewer/api/Carbon/GraphicsWindowCarbon>
[7079]19
20#include <osg/DeleteHandler>
21
[5948]22#include <Carbon/Carbon.h>
23#include <OpenGL/OpenGL.h>
[7866]24
25#include <iostream>
[8017]26
[5948]27using namespace osgViewer;
28
29
30// Carbon-Eventhandler to handle the click in the close-widget and the resize of windows
31
[5978]32static pascal OSStatus GraphicsWindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void* userData)
[5948]33{
34    WindowRef           window;
35    Rect                bounds;
36    OSStatus            result = eventNotHandledErr; /* report failure by default */
37   
[7866]38    osg::notify(osg::INFO) << "GraphicsWindowEventHandler" << std::endl;
[5948]39
40    GraphicsWindowCarbon* w = (GraphicsWindowCarbon*)userData;
41    if (!w)
42        return result;
43   
44    GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL,
45                         sizeof(window), NULL, &window);
[5978]46                         
47    switch(GetEventClass(event))
48    {
49        case kEventClassTablet:
50        case kEventClassMouse:
51            if (w->handleMouseEvent(event))
[5948]52                result = noErr;
[5978]53            break;
[7884]54               
[5978]55        case kEventClassKeyboard:
56            if (w->handleKeyboardEvent(event))
57                result = noErr;
58            break;
59           
60        case kEventClassWindow: {
61       
62            switch (GetEventKind(event))
63                {
64                    case kEventWindowBoundsChanging:
65                        // left the code for live-resizing, but it is not used, because of window-refreshing issues...
66                        GetEventParameter( event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &bounds );
67                       
68                        w->resized(bounds.left, bounds.top, bounds.right - bounds.left, bounds.bottom - bounds.top);
69                        w->getEventQueue()->windowResize(bounds.left, bounds.top, bounds.right - bounds.left, bounds.bottom - bounds.top, w->getEventQueue()->getTime());
70                        w->requestRedraw();
71                        result = noErr;
72                        break;
73                           
74                    case kEventWindowBoundsChanged:
75                        InvalWindowRect(window, GetWindowPortBounds(window, &bounds));
76                        GetWindowBounds(window, kWindowContentRgn, &bounds);
77                        w->resized(bounds.left, bounds.top, bounds.right - bounds.left, bounds.bottom - bounds.top);
78                        w->getEventQueue()->windowResize(bounds.left, bounds.top, bounds.right - bounds.left, bounds.bottom - bounds.top, w->getEventQueue()->getTime());
79                        result = noErr;
80                        break;
[5948]81                   
[7165]82                    case kEventWindowClose:
[5978]83                        w->requestClose();
[7165]84                        result = noErr;
[5978]85                        break;
86         
87                    default:
88                        break;
89                }
90            }
91        default:
[7884]92            //std::cout << "unknown: " << GetEventClass(event) << std::endl;
[5978]93            break;
94    }
[7165]95   
[7866]96    //if (result == eventNotHandledErr)
97    //    result = CallNextEventHandler (nextHandler, event);
[7165]98       
[5948]99    return result;
100}
101
[8017]102
[5948]103static bool s_quit_requested = false;
104
105// Application eventhandler -- listens for a quit-event
106static pascal OSStatus ApplicationEventHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
107{
108   
109    HICommand commandStruct;
110
111    OSErr  err = eventNotHandledErr;
112
113    GetEventParameter (inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &commandStruct);
114
115    switch(commandStruct.commandID) {
116        case kHICommandQuit:
117            s_quit_requested = true;
118            err = noErr;
119            break;
120                   
121    }
122   
123    return err;
124}
125
126// AppleEventHandler, listens to the Quit-AppleEvent
127static pascal OSErr QuitAppleEventHandler(const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon ) {
128    s_quit_requested = true;
129    return (noErr);
130}
131
132
133namespace osgViewer
134{
135
136// small helper class which maps the raw key codes to osgGA::GUIEventAdapter::Keys
137
138class OSXKeyboardMap {
139
140    public:
141        OSXKeyboardMap()
142        {
143            _keymap[53                ] =  osgGA::GUIEventAdapter::KEY_Escape;
144            _keymap[115                ] =  osgGA::GUIEventAdapter::KEY_Home;
145            _keymap[76                ] =  osgGA::GUIEventAdapter::KEY_KP_Enter;
146            _keymap[119                ] =  osgGA::GUIEventAdapter::KEY_End;
147            _keymap[36                ] =  osgGA::GUIEventAdapter::KEY_Return;
148            _keymap[116                ] =  osgGA::GUIEventAdapter::KEY_Page_Up;
149            _keymap[121                ] = osgGA::GUIEventAdapter::KEY_Page_Down;
150            _keymap[123                ] = osgGA::GUIEventAdapter::KEY_Left;
151            _keymap[124                ] = osgGA::GUIEventAdapter::KEY_Right;
152            _keymap[126                ] = osgGA::GUIEventAdapter::KEY_Up;
153            _keymap[125                ] = osgGA::GUIEventAdapter::KEY_Down;
154            _keymap[51                ] = osgGA::GUIEventAdapter::KEY_BackSpace;
155            _keymap[48                ] = osgGA::GUIEventAdapter::KEY_Tab;
156            _keymap[49                ] = osgGA::GUIEventAdapter::KEY_Space;
157            _keymap[117                ] = osgGA::GUIEventAdapter::KEY_Delete;
158           
159            _keymap[122                    ] = osgGA::GUIEventAdapter::KEY_F1;
160            _keymap[120                    ] = osgGA::GUIEventAdapter::KEY_F2;
161            _keymap[99                    ] = osgGA::GUIEventAdapter::KEY_F3;
162            _keymap[118                    ] = osgGA::GUIEventAdapter::KEY_F4;
163            _keymap[96                    ] = osgGA::GUIEventAdapter::KEY_F5;
164            _keymap[97                    ] = osgGA::GUIEventAdapter::KEY_F6;
165            _keymap[98                    ] = osgGA::GUIEventAdapter::KEY_F7;
166            _keymap[100                    ] = osgGA::GUIEventAdapter::KEY_F8;
167            _keymap[101                    ] = osgGA::GUIEventAdapter::KEY_F9;
168            _keymap[109                    ] = osgGA::GUIEventAdapter::KEY_F10;
169            _keymap[103                    ] = osgGA::GUIEventAdapter::KEY_F11;
170            _keymap[111                    ] = osgGA::GUIEventAdapter::KEY_F12;
171           
172            _keymap[75                    ] = osgGA::GUIEventAdapter::KEY_KP_Divide;
173            _keymap[67                    ] = osgGA::GUIEventAdapter::KEY_KP_Multiply;
174            _keymap[78                    ] = osgGA::GUIEventAdapter::KEY_KP_Subtract;
175            _keymap[69                    ] = osgGA::GUIEventAdapter::KEY_KP_Add;
176            _keymap[89                    ] = osgGA::GUIEventAdapter::KEY_KP_Home;
177            _keymap[91                    ] = osgGA::GUIEventAdapter::KEY_KP_Up;
178            _keymap[92                    ] = osgGA::GUIEventAdapter::KEY_KP_Page_Up;
179            _keymap[86                    ] = osgGA::GUIEventAdapter::KEY_KP_Left;
180            _keymap[87                    ] = osgGA::GUIEventAdapter::KEY_KP_Begin;
181            _keymap[88                    ] = osgGA::GUIEventAdapter::KEY_KP_Right;
182            _keymap[83                    ] = osgGA::GUIEventAdapter::KEY_KP_End;
183            _keymap[84                    ] = osgGA::GUIEventAdapter::KEY_KP_Down;
184            _keymap[85                    ] = osgGA::GUIEventAdapter::KEY_KP_Page_Down;
185            _keymap[82                    ] = osgGA::GUIEventAdapter::KEY_KP_Insert;
186            _keymap[65                    ] = osgGA::GUIEventAdapter::KEY_KP_Delete;
187
188        }
189       
190        ~OSXKeyboardMap() {
191        }
192       
193        unsigned int remapKey(unsigned int key, unsigned int rawkey)
194        {
195            KeyMap::iterator itr = _keymap.find(rawkey);
196            if (itr == _keymap.end()) return key;
197            else return itr->second;
198        }
199    private:
200        typedef std::map<unsigned int, osgGA::GUIEventAdapter::KeySymbol> KeyMap;
201        KeyMap _keymap;
202};
203
204/** remaps a native os x keycode to a GUIEventAdapter-keycode */
205static unsigned int remapOSXKey(unsigned int key, unsigned int rawkey)
206{
207    static OSXKeyboardMap s_OSXKeyboardMap;
208    return s_OSXKeyboardMap.remapKey(key,rawkey);
209}
210
211
212
213
[6106]214#pragma mark * * * MenubarController * * *
[5978]215
[6944]216/** the MenubarController class checks all open windows if they intersect with the menubar / dock and hide the menubar/dock if necessary */
[5978]217class MenubarController : public osg::Referenced
218{
219
220    public:
[6944]221        MenubarController() :
222            osg::Referenced(),
223            _list(),
[8017]224            _menubarShown(false),
225            _mutex()
[6944]226        {
[8017]227            // the following code will query the system for the available rect on the main-display (typically the displaying showing the menubar + the dock
[5978]228
229            GDHandle mainScreenDevice;
230           
231            DMGetGDeviceByDisplayID((DisplayIDType) CGMainDisplayID(), &mainScreenDevice, true);
232            GetAvailableWindowPositioningBounds (mainScreenDevice, &_availRect);
233           
234            // now we need the rect of the main-display including the menubar and the dock
235            _mainScreenBounds = CGDisplayBounds( CGMainDisplayID() );
236           
237            // hide the menubar initially
238            SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar);
239        }
240       
241        static MenubarController* instance();
242       
243        void attachWindow(GraphicsWindowCarbon* win);
244        void update();
245        void detachWindow(GraphicsWindowCarbon* win);
246       
247    private:
248        typedef std::list< osg::observer_ptr< GraphicsWindowCarbon > > WindowList;
[8017]249        WindowList            _list;
250        bool                _menubarShown;
251        Rect                _availRect;
252        CGRect                _mainScreenBounds;
253        OpenThreads::Mutex    _mutex;
[5978]254       
255};
256
257
258MenubarController* MenubarController::instance()
259{
260    static osg::ref_ptr<MenubarController> s_menubar_controller = new MenubarController();
261    return s_menubar_controller.get();
[5948]262}
263
[5978]264
265void MenubarController::attachWindow(GraphicsWindowCarbon* win)
266{
[8017]267    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
[5978]268    _list.push_back(win);
269    update();
270}
271
272
273void MenubarController::detachWindow(GraphicsWindowCarbon* win)
274{
[8017]275    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
[5978]276    for(WindowList::iterator i = _list.begin(); i != _list.end(); ) {
277        if ((*i).get() == win)
278            i = _list.erase(i);
279        else 
280            ++i;
281    }
282    update();
283}
284
285// iterate through all open windows and check, if they intersect the area occupied by the menubar/dock, and if so, hide the menubar/dock
286
287void MenubarController::update()
288{
289    OSErr error(noErr);
290    unsigned int windowsCoveringMenubarArea = 0;   
291    unsigned int windowsIntersectingMainScreen = 0;
292    for(WindowList::iterator i = _list.begin(); i != _list.end(); ) {
293        if ((*i).valid()) {
294            GraphicsWindowCarbon* w = (*i).get();
295            Rect windowBounds;
296            error = GetWindowBounds(w->getNativeWindowRef(), kWindowStructureRgn, &windowBounds);
297           
298            bool intersect = !( (_mainScreenBounds.origin.x > windowBounds.right) ||
299                                (_mainScreenBounds.origin.x + _mainScreenBounds.size.width < windowBounds.left) ||
300                                (_mainScreenBounds.origin.y > windowBounds.bottom) ||
301                                (_mainScreenBounds.origin.y + _mainScreenBounds.size.height < windowBounds.top));
302            if (intersect && !error)
303            {
304                ++windowsIntersectingMainScreen;
305               
306                // the window intersects the main-screen, does it intersect with the menubar/dock?
307                if (((_availRect.top > _mainScreenBounds.origin.y) && (_availRect.top > windowBounds.top)) ||
308                    ((_availRect.left > _mainScreenBounds.origin.x) && (_availRect.left > windowBounds.left)) ||
309                    ((_availRect.right < _mainScreenBounds.origin.x + _mainScreenBounds.size.width) && (_availRect.right < windowBounds.right)) ||
310                    ((_availRect.bottom < _mainScreenBounds.origin.y + _mainScreenBounds.size.height) && (_availRect.bottom < windowBounds.bottom) ))
311                {
312                    ++windowsCoveringMenubarArea;
313                }
314            }
315           
316            ++i;
317        }
318        else
319            i= _list.erase(i);
320    }
321   
322    // see http://developer.apple.com/technotes/tn2002/tn2062.html for hiding the dock+menubar
323       
324    if (windowsCoveringMenubarArea && _menubarShown)
325        error = SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar);
326   
327    if (!windowsCoveringMenubarArea && !_menubarShown)
328        error = SetSystemUIMode(kUIModeNormal, 0);
329        _menubarShown = !windowsCoveringMenubarArea;
330   
331    // osg::notify(osg::DEBUG_INFO) << "MenubarController:: " << windowsCoveringMenubarArea << " windows covering the menubar/dock area, " << windowsIntersectingMainScreen << " intersecting mainscreen" << std::endl;
332}
333
334
335#pragma mark * * * OSXWindowingSystemInterface * * *
336
337struct OSXCarbonWindowingSystemInterface : public osg::GraphicsContext::WindowingSystemInterface
338{
339   
340    /** ctor, get a list of all attached displays */
341    OSXCarbonWindowingSystemInterface() :
342        _displayCount(0),
343        _displayIds(NULL)
344    {
[6106]345        ProcessSerialNumber sn = { 0, kCurrentProcess };
346        TransformProcessType(&sn,kProcessTransformToForegroundApplication);
347        SetFrontProcess(&sn);
348       
[5978]349        if( CGGetActiveDisplayList( 0, NULL, &_displayCount ) != CGDisplayNoErr )
350            osg::notify(osg::WARN) << "OSXCarbonWindowingSystemInterface: could not get # of screens" << std::endl;
351           
352        _displayIds = new CGDirectDisplayID[_displayCount];
353        if( CGGetActiveDisplayList( _displayCount, _displayIds, &_displayCount ) != CGDisplayNoErr )
354            osg::notify(osg::WARN) << "OSXCarbonWindowingSystemInterface: CGGetActiveDisplayList failed" << std::endl;
355       
356        // register application event handler and AppleEventHandler to get quit-events:
357        static const EventTypeSpec menueventSpec = {kEventClassCommand, kEventCommandProcess};
358        OSErr status = InstallEventHandler(GetApplicationEventTarget(), NewEventHandlerUPP(ApplicationEventHandler), 1, &menueventSpec, 0, NULL);
359        status = AEInstallEventHandler( kCoreEventClass, kAEQuitApplication, NewAEEventHandlerUPP(QuitAppleEventHandler), 0, false);
360    }
361   
362    /** dtor */
[7074]363    ~OSXCarbonWindowingSystemInterface()
364    {
365        if (osg::Referenced::getDeleteHandler())
366        {
367            osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0);
368            osg::Referenced::getDeleteHandler()->flushAll();
369        }
370
371        if (_displayIds) delete[] _displayIds;
[5978]372        _displayIds = NULL;
373    }
374   
375    /** @return a CGDirectDisplayID for a ScreenIdentifier */
376    inline CGDirectDisplayID getDisplayID(const osg::GraphicsContext::ScreenIdentifier& si) {
[6907]377        if (si.screenNum < _displayCount)
378            return _displayIds[si.screenNum];
379        else {
380            osg::notify(osg::WARN) << "GraphicsWindowCarbon :: invalid screen # " << si.screenNum << ", returning main-screen instead" << std::endl;
381            return _displayIds[0];
382        }
[5978]383    }
384
385    /** @return count of attached screens */
386    virtual unsigned int getNumScreens(const osg::GraphicsContext::ScreenIdentifier& si)
387    {
388        return _displayCount;
389    }
390
391    /** returns the resolution of a specific display */
[9363]392    virtual void getScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution)
[5978]393    {
394        CGDirectDisplayID id = getDisplayID(si);
[9363]395        resolution.width = CGDisplayPixelsWide(id);
396        resolution.height = CGDisplayPixelsHigh(id);
397        resolution.colorDepth = CGDisplayBitsPerPixel(id);
[9369]398        resolution.refreshRate = getDictDouble (CGDisplayCurrentMode(id), kCGDisplayRefreshRate);        // Not tested
[9363]399        if (resolution.refreshRate<0) resolution.refreshRate = 0;
[5978]400    }
[9369]401
[5978]402    /** return the top left coord of a specific screen in global screen space */
403    void getScreenTopLeft(const osg::GraphicsContext::ScreenIdentifier& si, int& x, int& y) {
404        CGRect bounds = CGDisplayBounds( getDisplayID(si) );
[6831]405        x = static_cast<int>(bounds.origin.x);
406        y = static_cast<int>(bounds.origin.y);
[5978]407       
408        // osg::notify(osg::DEBUG_INFO) << "topleft of screen " << si.screenNum <<" " << bounds.origin.x << "/" << bounds.origin.y << std::endl;
409    }
[6706]410   
[9363]411    /** Helper method to get a double value out of a CFDictionary */
[6706]412    static double getDictDouble (CFDictionaryRef refDict, CFStringRef key)
413    {
[9363]414        double value;
415        CFNumberRef number_value = (CFNumberRef) CFDictionaryGetValue(refDict, key);
416        if (!number_value) // if can't get a number for the dictionary
417            return -1;  // fail
[9369]418        if (!CFNumberGetValue(number_value, kCFNumberDoubleType, &value)) // or if cant convert it
[6706]419            return -1; // fail
[9363]420        return value; // otherwise return the long value
[6706]421    }
422
[9363]423    /** Helper method to get a long value out of a CFDictionary */
424    static long getDictLong(CFDictionaryRef refDict, CFStringRef key)        // const void* key?
425    {
426        long value = 0;
427        CFNumberRef number_value = (CFNumberRef)CFDictionaryGetValue(refDict, key);
428        if (!number_value) // if can't get a number for the dictionary
429            return -1;  // fail
430        if (!CFNumberGetValue(number_value, kCFNumberLongType, &value)) // or if cant convert it
431            return -1; // fail
432        return value;
433    }
434
435    /** implementation of setScreenSettings */
436    virtual bool setScreenSettings(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, const osg::GraphicsContext::ScreenSettings & resolution)
[6706]437    {
438        CGDirectDisplayID displayID = getDisplayID(screenIdentifier);
[5978]439       
[9363]440        CGRefreshRate refresh = resolution.refreshRate>0 ? resolution.refreshRate : getDictDouble (CGDisplayCurrentMode(displayID), kCGDisplayRefreshRate); 
[9369]441        size_t depth = resolution.colorDepth>0 ? resolution.colorDepth : CGDisplayBitsPerPixel(displayID);
[6706]442        CFDictionaryRef display_mode_values =
443            CGDisplayBestModeForParametersAndRefreshRate(
444                            displayID,
[9363]445                            depth,
446                            resolution.width, resolution.height,
[6706]447                            refresh, 
448                            NULL);
449
[9363]450
[6706]451        CGDisplaySwitchToMode(displayID, display_mode_values);   
452        return true;
453    }
[9363]454
455    virtual void enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, osg::GraphicsContext::ScreenSettingsList & resolutionList) {
456        // Warning! This method has not been tested.
457        resolutionList.clear();
458
[6706]459        CGDirectDisplayID displayID = getDisplayID(screenIdentifier);
[9363]460        CFArrayRef availableModes = CGDisplayAvailableModes(displayID);
461        unsigned int numberOfAvailableModes = CFArrayGetCount(availableModes);
462        for (unsigned int i=0; i<numberOfAvailableModes; ++i) {
463            // look at each mode in the available list
464            CFDictionaryRef mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, i);
465            osg::GraphicsContext::ScreenSettings tmpSR;
[6706]466
[9363]467            long width = getDictLong(mode, kCGDisplayWidth);
468            tmpSR.width = width<=0 ? 0 : width;
469            long height = getDictLong(mode, kCGDisplayHeight);
470            tmpSR.height = height<=0 ? 0 : height;
471            long rate = getDictLong(mode, kCGDisplayRefreshRate);
472            tmpSR.refreshRate = rate<=0 ? 0 : rate;
473            long depth = getDictLong(mode, kCGDisplayBitsPerPixel);
474            tmpSR.colorDepth = depth<=0 ? 0 : depth;
475
476            resolutionList.push_back(tmpSR);
477        }
[6706]478    }
479
[5978]480    virtual osg::GraphicsContext* createGraphicsContext(osg::GraphicsContext::Traits* traits)
481    {
482        if (traits->pbuffer)
483        {
[7039]484            osg::ref_ptr<osgViewer::PixelBufferCarbon> pbuffer = new PixelBufferCarbon(traits);
[5978]485            if (pbuffer->valid()) return pbuffer.release();
486            else return 0;
487        }
488        else
489        {
490            osg::ref_ptr<osgViewer::GraphicsWindowCarbon> window = new GraphicsWindowCarbon(traits);
491            if (window->valid()) return window.release();
492            else return 0;
493        }
494    }
495   
496   
497   
498    private:
499        CGDisplayCount        _displayCount;
500        CGDirectDisplayID*    _displayIds;
501};
502
503}
504
505
506#pragma mark * * * GraphicsWindowCarbon * * *
507
508
[5948]509
[6706]510
[6404]511void GraphicsWindowCarbon::init()
[5948]512{
[7112]513    if (_initialized) return;
514
[8398]515    // getEventQueue()->setCurrentEventState(osgGA::GUIEventAdapter::getAccumulatedEventState().get());
[7884]516   
517    _lastModifierKeys = 0;
[6678]518    _windowTitleHeight = 0;
[5948]519    _closeRequested = false;
[6706]520    _ownsWindow = false;
[5948]521    _context = NULL;
522    _window = NULL;
[7039]523    _pixelFormat = PixelBufferCarbon::createPixelFormat(_traits.get());
[5948]524    if (!_pixelFormat)
525        osg::notify(osg::WARN) << "GraphicsWindowCarbon::init could not create a valid pixelformat" << std::endl;
526    _valid = (_pixelFormat != NULL);
527    _initialized = true;
528}
529
[6931]530bool GraphicsWindowCarbon::setWindowDecorationImplementation(bool flag)
[6706]531{
532    _useWindowDecoration = flag;
[6931]533
534    if (_realized)
535    {
[6706]536        OSErr err = noErr;
537        Rect bounds;
538        GetWindowBounds(getNativeWindowRef(), kWindowContentRgn, &bounds);
[5948]539
[6931]540        if (_useWindowDecoration)
541        {
[6706]542            err = ChangeWindowAttributes(getNativeWindowRef(),  kWindowStandardDocumentAttributes,  kWindowNoTitleBarAttribute | kWindowNoShadowAttribute);
543            SetWindowBounds(getNativeWindowRef(), kWindowContentRgn, &bounds);
[6931]544        }
545        else
546        {
[6706]547            err = ChangeWindowAttributes(getNativeWindowRef(), kWindowNoTitleBarAttribute | kWindowNoShadowAttribute, kWindowStandardDocumentAttributes);
[6944]548            SetWindowBounds(getNativeWindowRef(), kWindowContentRgn, &bounds);   
[6706]549        }
[5948]550
[6931]551        if (err != noErr)
552        {
[6706]553            osg::notify(osg::WARN) << "GraphicsWindowCarbon::setWindowDecoration failed with " << err << std::endl;
[6931]554            return false;
[6706]555        }
[6944]556       
557        // update titlebar-height
558        Rect titleRect;
559        GetWindowBounds(_window, kWindowTitleBarRgn, &titleRect);
560        _windowTitleHeight = abs(titleRect.bottom - titleRect.top);
561       
562        // 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.
563        // InvalWindowRect doesn't help here :-/
564       
565        aglSetDrawable(_context, 0);
566        aglSetDrawable(_context, GetWindowPort(_window));
567               
568        MenubarController::instance()->update();
[6706]569    }
[6931]570
571    return true;
[6706]572}
[5978]573
[6944]574
[6706]575WindowAttributes GraphicsWindowCarbon::computeWindowAttributes(bool useWindowDecoration, bool supportsResize) {
576    WindowAttributes attr;
[5978]577   
[6706]578    if (useWindowDecoration)
[5978]579    {
[6706]580        if (supportsResize)
[5948]581            attr = (kWindowStandardDocumentAttributes | kWindowStandardHandlerAttribute);
582        else
583            attr = (kWindowStandardDocumentAttributes | kWindowStandardHandlerAttribute) & ~kWindowResizableAttribute;
[5978]584    }
[6220]585    else 
586    {
587        attr = kWindowNoTitleBarAttribute | kWindowNoShadowAttribute | kWindowStandardHandlerAttribute;
[6706]588        if (supportsResize)
[5948]589            attr |= kWindowResizableAttribute;
590    }
[6706]591    return attr;
592}
[6220]593
[6706]594void GraphicsWindowCarbon::installEventHandler() {
595
[5948]596    // register window event handler to receive resize-events
[5978]597    EventTypeSpec   windEventList[] = {
598        { kEventClassWindow, kEventWindowBoundsChanged},
[7165]599        { kEventClassWindow, kEventWindowClose},
[5978]600       
601        {kEventClassMouse, kEventMouseDown},
602        {kEventClassMouse, kEventMouseUp},
603        {kEventClassMouse, kEventMouseMoved},
604        {kEventClassMouse, kEventMouseDragged},
605        {kEventClassMouse, kEventMouseWheelMoved},
[8192]606        {kEventClassMouse, 11 /* kEventMouseScroll */},
[5978]607
608        {kEventClassKeyboard, kEventRawKeyDown},
609        {kEventClassKeyboard, kEventRawKeyRepeat},
610        {kEventClassKeyboard, kEventRawKeyUp},
611        {kEventClassKeyboard, kEventRawKeyModifiersChanged},
612        {kEventClassKeyboard, kEventHotKeyPressed},
613        {kEventClassKeyboard, kEventHotKeyReleased},
614    };
[5948]615   
[5978]616    InstallWindowEventHandler(_window, NewEventHandlerUPP(GraphicsWindowEventHandler),  GetEventTypeCount(windEventList), windEventList, this, NULL);
[7866]617 }
[6706]618
619
620bool GraphicsWindowCarbon::realizeImplementation()
621{
[5978]622   
[6706]623    if (!_initialized) init();
624    if (!_initialized) return false;
625    if (!_traits) return false;
626   
[7866]627    osg::notify(osg::INFO) << "GraphicsWindowCarbon:: realizeIMplementation" << std::endl;
628   
[6706]629    setWindowDecoration(_traits->windowDecoration);
[7709]630    useCursor(_traits->useCursor);
[7841]631
[6706]632    // move the window to the right screen
633    OSXCarbonWindowingSystemInterface* wsi = dynamic_cast<OSXCarbonWindowingSystemInterface*>(osg::GraphicsContext::getWindowingSystemInterface());
634    int screenLeft(0), screenTop(0);
635    if (wsi) {
636       
637        wsi->getScreenTopLeft((*_traits), screenLeft, screenTop);
638        _traits->y += screenTop;
639        _traits->x += screenLeft;
640    }
641   
[8017]642    WindowData *windowData = ( _traits.get() && _traits->inheritedWindowData.get() ) ? static_cast<osgViewer::GraphicsWindowCarbon::WindowData*>(_traits->inheritedWindowData.get()) : 0;
[7866]643     
[6706]644    _ownsWindow = (windowData) ? (windowData->getNativeWindowRef() == NULL) : true;
645   
646    if (_ownsWindow) {
647       
648        // create the window
649        Rect bounds = {_traits->y, _traits->x, _traits->y + _traits->height, _traits->x + _traits->width};
650        OSStatus err = 0;
651        WindowAttributes attr = computeWindowAttributes(_useWindowDecoration, _traits->supportsResize);
652       
653        err = CreateNewWindow(kDocumentWindowClass, attr, &bounds, &_window);
654
655        if (err) {
656            osg::notify(osg::WARN) << "GraphicsWindowCarbon::realizeImplementation() failed creating a window: " << err << std::endl;
657            return false;
658        } else {
659            osg::notify(osg::INFO) << "GraphicsWindowCarbon::realizeImplementation() - window created with bounds(" << bounds.top << ", " << bounds.left << ", " << bounds.bottom << ", " << bounds.right << ")" << std::endl;
660        }
661    }
662    else {
[7866]663         _window = windowData->getNativeWindowRef();
[6706]664    }
665   
666    Rect titleRect;
667    GetWindowBounds(_window, kWindowTitleBarRgn, &titleRect);
[6934]668    _windowTitleHeight = abs(titleRect.bottom - titleRect.top);
[6706]669   
670    if ((_ownsWindow) || (windowData && windowData->installEventHandler()))
671        installEventHandler();
672   
[5948]673    // set the window title
[7709]674    setWindowName(_traits->windowName);
[5948]675   
676    // create the context
[7039]677    AGLContext sharedContextCarbon = NULL;
678   
679    GraphicsWindowCarbon* graphicsWindowCarbon = dynamic_cast<GraphicsWindowCarbon*>(_traits->sharedContext);
680    if (graphicsWindowCarbon)
[6204]681    {
[7039]682        sharedContextCarbon = graphicsWindowCarbon->getAGLContext();
[6204]683    }
684    else
685    {
[7039]686        PixelBufferCarbon* pixelbuffer = dynamic_cast<PixelBufferCarbon*>(_traits->sharedContext);
687        if (pixelbuffer) {
688            sharedContextCarbon = pixelbuffer->getAGLContext();
689        }
[6204]690    }
[7039]691    _context = aglCreateContext (_pixelFormat, sharedContextCarbon);
[6204]692
693
[5948]694    if (!_context) {
695        osg::notify(osg::WARN) << "GraphicsWindowCarbon::realizeImplementation failed creating a context: " << aglGetError() << std::endl;
696        return false;
697    }
[7866]698
699     
700    if ( windowData && windowData->getAGLDrawable() ) {
[8017]701        aglSetDrawable(_context, (AGLDrawable)*(windowData->getAGLDrawable()) );
702               
[7866]703    } else {
[8017]704        aglSetDrawable(_context, GetWindowPort(_window));
705        ShowWindow(_window);
[7866]706        MenubarController::instance()->attachWindow(this);
707    }
708   
[5948]709    makeCurrent();
710
[6220]711    if ((_traits->useMultiThreadedOpenGLEngine) && (OpenThreads::GetNumberOfProcessors() > 1)) {
[6106]712        // enable Multi-threaded OpenGL Execution:
713        CGLError cgerr = kCGLNoError;
714        CGLContextObj ctx = CGLGetCurrentContext();
[5948]715
[6826]716#if 0
[6106]717        cgerr =  CGLEnable( ctx, kCGLCEMPEngine);
[6826]718#else
719        // the above use of kCGLCEMPEngine is not backwards compatible
720        // so we'll use the raw value of it to keep things compiling on older
721        // versions of OSX.
722        cgerr =  CGLEnable( ctx, static_cast <CGLContextEnable>(313) );
723#endif   
[6106]724        if (cgerr != kCGLNoError )
725        {
726            osg::notify(osg::INFO) << "GraphicsWindowCarbon:: Multi-threaded OpenGL Execution not available" << std::endl;
727        }
[6220]728    }
[5948]729   
[8017]730    InitCursor();
731   
[5948]732    //enable vsync
733    if (_traits->vsync) {
734        GLint swap = 1;
735        aglSetInteger (_context, AGL_SWAP_INTERVAL, &swap);
736    }
737
738    _realized = true;
739    return _realized;
740}
741
742
743
744bool GraphicsWindowCarbon::makeCurrentImplementation()
745{
746       
747    return (aglSetCurrentContext(_context) == GL_TRUE);
748}
749
750bool GraphicsWindowCarbon::releaseContextImplementation()
751{
752    if (!_realized)
753    {
754        osg::notify(osg::NOTICE)<<"Warning: GraphicsWindow not realized, cannot do makeCurrent."<<std::endl;
755        return false;
756    }
757
758    // osg::notify(osg::NOTICE)<<"makeCurrentImplementation "<<this<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
759    // osg::notify(osg::NOTICE)<<"   glXMakeCurrent ("<<_display<<","<<_window<<","<<_glxContext<<std::endl;
760    return (aglSetCurrentContext(NULL) == GL_TRUE);
761}
762
763
764
765void GraphicsWindowCarbon::closeImplementation()
766{
[7165]767    // osg::notify(osg::INFO) << "GraphicsWindowCarbon::closeImplementation" << std::endl;
[5948]768    _valid = false;
769    _realized = false;
770   
[8017]771    // there's a possibility that the MenubarController is destructed already, so prevent a crash:
772    MenubarController* mbc = MenubarController::instance();
773    if (mbc) mbc->detachWindow(this);
[5978]774   
[5948]775    if (_pixelFormat)
776    {
777        aglDestroyPixelFormat(_pixelFormat);
778        _pixelFormat = NULL;
779    }
780   
781    if (_context)
782    {
783        aglSetDrawable(_context, NULL);
784        aglSetCurrentContext(NULL);
785        aglDestroyContext(_context);
786        _context = NULL;
787    }
788   
[6706]789    if (_ownsWindow && _window) DisposeWindow(_window);
[5948]790    _window = NULL;
791}
792
793
794
795void GraphicsWindowCarbon::swapBuffersImplementation()
796{
797    aglSwapBuffers(_context);
798}
799
800
801
802void GraphicsWindowCarbon::resizedImplementation(int x, int y, int width, int height)
803{
[5978]804    GraphicsContext::resizedImplementation(x, y, width, height);
805
[5948]806    aglUpdateContext(_context);
[5978]807    MenubarController::instance()->update();
[5948]808}
809
810
811
[5978]812bool GraphicsWindowCarbon::handleMouseEvent(EventRef theEvent)
[5948]813{
814
[5978]815    static unsigned int lastEmulatedMouseButton = 0;
[5948]816    // mouse down event   
817    Point wheresMyMouse;
[5978]818    GetEventParameter (theEvent, kEventParamWindowMouseLocation, typeQDPoint, NULL, sizeof(wheresMyMouse), NULL, &wheresMyMouse);
[5948]819   
[6678]820    wheresMyMouse.v -= _windowTitleHeight;
821    if (_useWindowDecoration && (wheresMyMouse.v < 0))
822        return false;
823   
[5978]824    Point wheresMyMouseGlobal;
825    GetEventParameter (theEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(wheresMyMouse), NULL, &wheresMyMouseGlobal);
826   
[5948]827    EventMouseButton mouseButton = 0;
828    GetEventParameter (theEvent, kEventParamMouseButton, typeMouseButton, NULL, sizeof(mouseButton), NULL, &mouseButton);
[5978]829   
830    UInt32 modifierKeys;
831    GetEventParameter (theEvent,kEventParamKeyModifiers,typeUInt32, NULL,sizeof(modifierKeys), NULL,&modifierKeys);
832   
833   
[5948]834    WindowRef win;
[5978]835    int fwres = FindWindow(wheresMyMouseGlobal, &win);
[8017]836    // return false when Window is inactive; For enabling click-to-active on window by delegating event to default handler
837    if (((fwres != inContent) && (fwres > 0) && (mouseButton >= 1)) || !IsWindowActive(win))
[5948]838    {
[5978]839        return false;
[5948]840    }
841    else
842    {
[7841]843        UInt32 clickCount;
844        GetEventParameter(theEvent, kEventParamClickCount, typeUInt32, NULL, sizeof(clickCount), NULL, &clickCount);
[5948]845        // swap right and middle buttons so that middle button is 2, right button is 3.
846        if (mouseButton==3) mouseButton = 2;
847        else if (mouseButton==2) mouseButton = 3;
848       
849        // check tablet pointer device and map it to a musebutton
850        TabletProximityRec    theTabletRecord;    // The Tablet Proximity Record
851        // Extract the Tablet Proximity reccord from the event.
852        if(noErr == GetEventParameter(theEvent, kEventParamTabletProximityRec,
853                                      typeTabletProximityRec, NULL,
854                                      sizeof(TabletProximityRec),
855                                      NULL, (void *)&theTabletRecord))
856        {           
857            osgGA::GUIEventAdapter::TabletPointerType pointerType;
858            switch(theTabletRecord.pointerType)
859            {
860                case 1: // pen
861                    pointerType = osgGA::GUIEventAdapter::PEN;
862                    break;
863                   
864                case 2: // puck
865                    pointerType = osgGA::GUIEventAdapter::PUCK;
866                    break;
867                   
868                case 3: //eraser
869                    pointerType = osgGA::GUIEventAdapter::ERASER;
870                    break;
871
872                default:
873                   pointerType = osgGA::GUIEventAdapter::UNKNOWN;
874                   break;
875            }
876           
877            getEventQueue()->penProximity(pointerType, (theTabletRecord.enterProximity != 0));
878        }
879
[8085]880        // get tilt and rotation from the pen
881        TabletPointRec theTabletPointRecord;
882        if(noErr == GetEventParameter(theEvent,  kEventParamTabletPointRec, typeTabletPointRec, NULL,
883                sizeof(TabletPointRec), NULL, (void *)&theTabletPointRecord))
884        {
885            int penRotation = (int)theTabletPointRecord.rotation * 9 / 575; //to get angle between 0 to 360 grad
886            penRotation = -(((penRotation + 180) % 360) - 180) ;          //for same range on all plattforms we need -180 to 180
887            getEventQueue()->penOrientation (
888                    theTabletPointRecord.tiltX * 60 / 32767.0f,  //multiply with 60 to get angle between -60 to 60 grad
889                    -theTabletPointRecord.tiltY * 60 / 32767.0f,  //multiply with 60 to get angle between -60 to 60 grad
890                    penRotation
891            );
892        }
893           
[5948]894        switch(GetEventKind(theEvent))
895        {
896            case kEventMouseDown:
897                {
898                    float mx =wheresMyMouse.h;
899                    float my =wheresMyMouse.v;
900                    transformMouseXY(mx, my);
[5978]901                   
902                    lastEmulatedMouseButton = 0;
903                   
904                    if (mouseButton == 1)
905                    {
906                        if( modifierKeys & cmdKey )
907                        {
908                            mouseButton = lastEmulatedMouseButton = 3;
909                        }
910                        else if( modifierKeys & optionKey )
911                        {
912                            mouseButton = lastEmulatedMouseButton = 2;
913                        }
914                    }
915                   
[7841]916                    if (clickCount > 1)
917                        getEventQueue()->mouseDoubleButtonPress(mx,my, mouseButton);
918                    else
919                        getEventQueue()->mouseButtonPress(mx, my, mouseButton);
[5948]920                }
921                break;
922            case kEventMouseUp:
923                {
924                    float mx =wheresMyMouse.h;
925                    float my =wheresMyMouse.v;
926                    transformMouseXY(mx, my);
[5978]927                    if (lastEmulatedMouseButton > 0) {
928                        getEventQueue()->mouseButtonRelease(mx, my, lastEmulatedMouseButton);
929                        lastEmulatedMouseButton = 0;
930                    }
931                    else {
932                        getEventQueue()->mouseButtonRelease(mx, my, mouseButton);
933                    }
[5948]934                }
935                break;
936               
937            case kEventMouseDragged:
938                {
939                    // get pressure from the pen, only when mouse/pen is dragged
940                    TabletPointRec    theTabletRecord;
941                    if(noErr == GetEventParameter(theEvent,  kEventParamTabletPointRec, typeTabletPointRec, NULL,
942                                    sizeof(TabletPointRec), NULL, (void *)&theTabletRecord)) {
943                   
944                        getEventQueue()->penPressure(theTabletRecord.pressure / 65535.0f);
945           
946                    }
947                   
948                    float mx =wheresMyMouse.h;
949                    float my =wheresMyMouse.v;
950                    transformMouseXY(mx, my);
951                    getEventQueue()->mouseMotion(mx, my);
952                }
953                break;
954               
955            case kEventMouseMoved:
956                {
957                    float mx = wheresMyMouse.h;
958                    float my = wheresMyMouse.v;
959                    transformMouseXY(mx, my);
960                    getEventQueue()->mouseMotion(mx, my);
961                }
962                break;
963               
964            // mouse with scroll-wheels
965            case kEventMouseWheelMoved:
966                {
967                    EventMouseWheelAxis axis;
968                    SInt32 delta;
969                    if (noErr == GetEventParameter( theEvent, kEventParamMouseWheelAxis, typeMouseWheelAxis, NULL, sizeof(axis), NULL, &axis )) {
970                        if (noErr == GetEventParameter( theEvent, kEventParamMouseWheelDelta, typeLongInteger, NULL, sizeof(delta), NULL, &delta )) {
971                            switch (axis) {
972                                case kEventMouseWheelAxisX:
973                                    getEventQueue()->mouseScroll( (delta > 0) ? osgGA::GUIEventAdapter::SCROLL_RIGHT : osgGA::GUIEventAdapter::SCROLL_LEFT);
974                                    break;
975                                case kEventMouseWheelAxisY:
976                                    getEventQueue()->mouseScroll( (delta < 0) ? osgGA::GUIEventAdapter::SCROLL_DOWN : osgGA::GUIEventAdapter::SCROLL_UP);
977                                    break;
978                            }
979                        }
980                    }
981                }
982                break;
983           
984            // new trackpads and mighty mouse, (not officially documented, see http://developer.apple.com/qa/qa2005/qa1453.html )
985            case 11:
986                {
987                    enum
988                        {
989                        kEventParamMouseWheelSmoothVerticalDelta       = 'saxy', // typeSInt32
[6461]990                        kEventParamMouseWheelSmoothHorizontalDelta     = 'saxx' // typeSInt32
[5948]991                        };
992                   
993                    SInt32 scroll_delta_x = 0;
994                    SInt32 scroll_delta_y = 0;
995                    OSErr err = noErr;
996                    err = GetEventParameter( theEvent, kEventParamMouseWheelSmoothVerticalDelta, typeLongInteger, NULL, sizeof(scroll_delta_y), NULL, &scroll_delta_y );
997                    err = GetEventParameter( theEvent, kEventParamMouseWheelSmoothHorizontalDelta, typeLongInteger, NULL, sizeof(scroll_delta_x), NULL, &scroll_delta_x );
998                   
999                    if ((scroll_delta_x != 0) || (scroll_delta_y != 0)) {
1000                        getEventQueue()->mouseScroll2D( scroll_delta_x, scroll_delta_y);
1001                    }
1002                }
1003                break;
1004           
1005            default:
[5978]1006                return false;
[5948]1007        }
1008    }
[5978]1009   
1010    return true;
[5948]1011}
1012
1013
1014
[5978]1015bool GraphicsWindowCarbon::handleKeyboardEvent(EventRef theEvent)
[5948]1016{
[7884]1017    handleModifierKeys(theEvent);
1018       
1019    OSStatus status;
[5948]1020   
1021    UInt32 rawkey;
1022    GetEventParameter (theEvent,kEventParamKeyCode,typeUInt32, NULL,sizeof(rawkey), NULL,&rawkey);
1023   
[7866]1024    // osg::notify(osg::INFO) << "key code: " << rawkey << " modifiers: " << modifierKeys << std::endl;
[5948]1025           
1026    UInt32 dataSize;
1027    /* jbw check return status so that we don't allocate a huge array */
1028    status = GetEventParameter( theEvent, kEventParamKeyUnicodes, typeUnicodeText, NULL, 0, &dataSize, NULL );
[5978]1029    if (status != noErr) return false;
1030    if (dataSize<=1) return false;
[5948]1031   
1032    UniChar* uniChars = new UniChar[dataSize+1];
1033    GetEventParameter( theEvent, kEventParamKeyUnicodes, typeUnicodeText, NULL, dataSize, NULL, (void*)uniChars );
1034   
1035    unsigned int keychar = remapOSXKey(static_cast<unsigned long>(uniChars[0]), rawkey);
1036   
1037    switch(GetEventKind(theEvent))
1038    {
1039        case kEventRawKeyDown:
1040        case kEventRawKeyRepeat:
1041        {
[7066]1042            //getEventQueue()->getCurrentEventState()->setModKeyMask(modifierMask);
[7866]1043            osg::notify(osg::INFO) << "GraphicsWindowCarbon::keyPress" << std::endl;
[5948]1044            getEventQueue()->keyPress(keychar);
1045            break;
1046        }
1047       
1048        case kEventRawKeyUp:
1049        {                 
[7866]1050            osg::notify(osg::INFO) << "GraphicsWindowCarbon::keyPress" << std::endl;
[7066]1051            //getEventQueue()->getCurrentEventState()->setModKeyMask(modifierMask);
[5948]1052            getEventQueue()->keyRelease(keychar);
1053            break;
1054        }
1055       
1056        default:
1057             break;
1058   
1059    }
1060
1061    delete[] uniChars;
1062
[5978]1063    return true;
[5948]1064}
1065
[7884]1066void GraphicsWindowCarbon::handleModifierKey(UInt32 modifierKey, UInt32 modifierMask, osgGA::GUIEventAdapter::KeySymbol keySymbol) {
[5948]1067
[7884]1068    if ((modifierKey & modifierMask) && !(_lastModifierKeys & modifierMask))
1069    {
1070        getEventQueue()->keyPress(keySymbol);
1071    }
1072   
1073    if (!(modifierKey & modifierMask) && (_lastModifierKeys & modifierMask))
1074    {
1075        getEventQueue()->keyRelease(keySymbol);
1076    }
1077}
[5948]1078
[7884]1079bool GraphicsWindowCarbon::handleModifierKeys(EventRef theEvent)
1080{
1081    UInt32 modifierKeys;
1082    GetEventParameter (theEvent,kEventParamKeyModifiers,typeUInt32, NULL,sizeof(modifierKeys), NULL,&modifierKeys);
1083
1084    //std::cout << modifierKeys << std::endl;
1085    if (_lastModifierKeys == modifierKeys)
1086        return false;
1087       
1088    handleModifierKey(modifierKeys, shiftKey, osgGA::GUIEventAdapter::KEY_Shift_L);
1089    handleModifierKey(modifierKeys, controlKey, osgGA::GUIEventAdapter::KEY_Control_L);
1090    handleModifierKey(modifierKeys, optionKey, osgGA::GUIEventAdapter::KEY_Alt_L);
1091    handleModifierKey(modifierKeys, cmdKey, osgGA::GUIEventAdapter::KEY_Super_L);
1092   
1093    // Caps lock needs some special handling, i did not find a way to get informed when the caps-lock-key gets released   
1094    if ((modifierKeys & alphaLock) && !(_lastModifierKeys & alphaLock))
1095    {
1096        getEventQueue()->keyPress(osgGA::GUIEventAdapter::KEY_Caps_Lock);
1097        getEventQueue()->keyRelease(osgGA::GUIEventAdapter::KEY_Caps_Lock);
1098    }
1099   
1100    if (!(modifierKeys & alphaLock) && (_lastModifierKeys & alphaLock))
1101    {
1102        getEventQueue()->keyPress(osgGA::GUIEventAdapter::KEY_Caps_Lock);
1103        getEventQueue()->keyRelease(osgGA::GUIEventAdapter::KEY_Caps_Lock);
1104    }
1105   
1106    _lastModifierKeys = modifierKeys;
1107    return true;
1108}
1109
1110
1111
[5948]1112void GraphicsWindowCarbon::checkEvents()
1113{
1114    if (!_realized) return;
1115   
1116    EventRef theEvent;
1117    EventTargetRef theTarget = GetEventDispatcherTarget();
1118    while (ReceiveNextEvent(0, NULL, 0,true, &theEvent)== noErr)
1119    {
1120        switch(GetEventClass(theEvent))
1121        {
[5978]1122            case kEventClassMouse:
1123                    {
1124                    // handle the menubar
1125                    Point wheresMyMouse;
1126                    GetEventParameter (theEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(wheresMyMouse), NULL, &wheresMyMouse);
1127                   
1128                    EventMouseButton mouseButton = 0;
1129                    GetEventParameter (theEvent, kEventParamMouseButton, typeMouseButton, NULL, sizeof(mouseButton), NULL, &mouseButton);
1130                   
1131                    WindowRef win;
1132                    int fwres = FindWindow(wheresMyMouse, &win);
1133
1134                    if ((fwres == inMenuBar) && (mouseButton >= 1)) {
1135                        MenuSelect(wheresMyMouse);
1136                        HiliteMenu(0);
1137                        return;
1138                    }
1139                    break;
1140                }
1141
[5948]1142            case kEventClassApplication:
1143                switch (GetEventKind(theEvent)) {
1144                    case kEventAppQuit:
1145                        getEventQueue()->quitApplication();
1146                        break;
1147                }
1148                break;
1149           
1150            case kEventClassAppleEvent:
1151                {
1152                    EventRecord eventRecord;
1153                    ConvertEventRefToEventRecord(theEvent, &eventRecord);
1154                    AEProcessAppleEvent(&eventRecord);
1155                    return;
1156                }
1157                break;
1158
1159        }
1160        SendEventToEventTarget (theEvent, theTarget);
1161        ReleaseEvent(theEvent);       
1162    } 
1163    if (_closeRequested)
[7165]1164        getEventQueue()->closeWindow();
[5948]1165       
1166    if (s_quit_requested) {
1167        getEventQueue()->quitApplication();
1168        s_quit_requested = false;
1169    }
1170           
1171}
1172
1173
[6931]1174bool GraphicsWindowCarbon::setWindowRectangleImplementation(int x, int y, int width, int height)
[6495]1175{
[6706]1176    Rect bounds = {y, x, y + height, x + width};
1177    SetWindowBounds(getNativeWindowRef(), kWindowContentRgn, &bounds);
1178    aglUpdateContext(_context);
1179    MenubarController::instance()->update();
[6931]1180    return true;
[6495]1181}
[5948]1182
1183void GraphicsWindowCarbon::grabFocus()
1184{
1185    SelectWindow(_window);
1186}
1187
1188
1189
1190void GraphicsWindowCarbon::grabFocusIfPointerInWindow()
1191{
1192   // TODO: implement
[5978]1193   osg::notify(osg::ALWAYS) << "GraphicsWindowCarbon::grabFocusIfPointerInWindow" << std::endl;
[5948]1194}
1195
1196
[7709]1197void GraphicsWindowCarbon::useCursor(bool cursorOn)
1198{
[5948]1199
[7709]1200    if (_traits.valid())
1201        _traits->useCursor = cursorOn;
1202    OSXCarbonWindowingSystemInterface* wsi = dynamic_cast<OSXCarbonWindowingSystemInterface*>(osg::GraphicsContext::getWindowingSystemInterface());
1203    if (wsi == NULL) {
1204        osg::notify(osg::WARN) << "GraphicsWindowCarbon::useCursor :: could not get OSXCarbonWindowingSystemInterface" << std::endl;
1205        return;
1206    }
1207   
1208    CGDirectDisplayID displayId = wsi->getDisplayID((*_traits));
1209    CGDisplayErr err = kCGErrorSuccess;
1210    switch (cursorOn)
1211    {
1212        case true:
1213            err = CGDisplayShowCursor(displayId);
1214            break;
1215        case false:
1216            err = CGDisplayHideCursor(displayId);
1217            break;
1218    }
1219    if (err != kCGErrorSuccess) {
1220        osg::notify(osg::WARN) << "GraphicsWindowCarbon::useCursor failed with " << err << std::endl;
1221    }
1222}
1223
[8017]1224// FIXME: need to implement all cursor types
1225// FIXME: I used deprecated functions, but don't know if there are any substitutable newer functions...
1226void GraphicsWindowCarbon::setCursor(MouseCursor mouseCursor)
1227{
1228    UInt32 cursor;
1229    if (_currentCursor == mouseCursor)
1230      return;
1231    switch (mouseCursor)
1232    {
1233        case NoCursor:
1234          HideCursor();
1235          _currentCursor = mouseCursor;
1236          return;
1237        case RightArrowCursor:
1238            cursor = kThemeArrowCursor;
1239            break;
1240        case CrosshairCursor:
1241            cursor = kThemeCrossCursor;
1242            break;
1243        case TextCursor:
1244            cursor = kThemeIBeamCursor;
1245            break;
1246        case UpDownCursor:
1247            cursor = kThemeResizeUpDownCursor;
1248            break;
1249        case LeftRightCursor:
1250            cursor = kThemeResizeLeftRightCursor;
1251            break;
1252        default:
1253            cursor = kThemeArrowCursor;
1254            osg::notify(osg::WARN) << "GraphicsWindowCarbon::setCursor doesn't implement cursor: type = " << mouseCursor << std::endl;
1255    }
1256   
1257    _currentCursor = mouseCursor;
1258    SetThemeCursor(cursor);
1259    ShowCursor();
1260}
[7709]1261
1262
1263void GraphicsWindowCarbon::setWindowName (const std::string& name)
1264{
1265    _traits->windowName = name;
1266    if (!_traits->windowName.empty())
1267    {
1268        CFStringRef windowtitle = CFStringCreateWithBytes( kCFAllocatorDefault, (const UInt8*)(_traits->windowName.c_str()), _traits->windowName.length(),kCFStringEncodingUTF8, false );
1269        SetWindowTitleWithCFString( _window, windowtitle );
1270        CFRelease(windowtitle);
1271    }
1272}
1273
[9120]1274void GraphicsWindowCarbon::requestWarpPointer(float x,float y)
1275{
[7709]1276
[9120]1277    OSXCarbonWindowingSystemInterface* wsi = dynamic_cast<OSXCarbonWindowingSystemInterface*>(osg::GraphicsContext::getWindowingSystemInterface());
1278    if (wsi == NULL) {
1279        osg::notify(osg::WARN) << "GraphicsWindowCarbon::useCursor :: could not get OSXCarbonWindowingSystemInterface" << std::endl;
1280        return;
1281    }
[7841]1282
[9120]1283    CGDirectDisplayID displayId = wsi->getDisplayID((*_traits));
1284
1285    CGPoint point;
[9357]1286    point.x = x + _traits->x;
1287    point.y = y + _traits->y;
[9120]1288    CGDisplayMoveCursorToPoint(displayId, point);
1289
1290    getEventQueue()->mouseWarped(x,y);
1291}
1292
1293
[5948]1294void GraphicsWindowCarbon::transformMouseXY(float& x, float& y)
1295{
1296    if (getEventQueue()->getUseFixedMouseInputRange())
1297    {
1298        osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState();
1299        x = eventState->getXmin() + (eventState->getXmax()-eventState->getXmin())*x/float(_traits->width);
1300        y = eventState->getYmin() + (eventState->getYmax()-eventState->getYmin())*y/float(_traits->height);
1301    }
1302}
1303
1304
1305
1306
1307
1308
1309struct RegisterWindowingSystemInterfaceProxy
1310{
1311    RegisterWindowingSystemInterfaceProxy()
1312    {
[5978]1313        osg::GraphicsContext::setWindowingSystemInterface(new osgViewer::OSXCarbonWindowingSystemInterface());
[5948]1314    }
1315
1316    ~RegisterWindowingSystemInterfaceProxy()
1317    {
[7074]1318        if (osg::Referenced::getDeleteHandler())
1319        {
1320            osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0);
1321            osg::Referenced::getDeleteHandler()->flushAll();
1322        }
1323
[5948]1324        osg::GraphicsContext::setWindowingSystemInterface(0);
1325    }
1326};
1327
1328RegisterWindowingSystemInterfaceProxy createWindowingSystemInterfaceProxy;
1329
[6931]1330// declare C entry point for static compilation.
1331extern "C" void graphicswindow_Carbon(void)
1332{
1333    osg::GraphicsContext::setWindowingSystemInterface(new osgViewer::OSXCarbonWindowingSystemInterface());
1334}
1335
[5948]1336#endif
Note: See TracBrowser for help on using the browser.