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

Revision 11263, 39.5 kB (checked in by robert, 5 years ago)

From Ulrich Hertlein, changed init() call to _init().

  • 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
[9894]14#if defined (__APPLE__) && (!__LP64__)
15
[5978]16#include <osg/observer_ptr>
[7079]17
[7039]18#include <osgViewer/api/Carbon/PixelBufferCarbon>
[6464]19#include <osgViewer/api/Carbon/GraphicsWindowCarbon>
[7079]20
21#include <osg/DeleteHandler>
22
[5948]23#include <Carbon/Carbon.h>
24#include <OpenGL/OpenGL.h>
[7866]25
26#include <iostream>
[8017]27
[9894]28#include "DarwinUtils.h"
29
[5948]30using namespace osgViewer;
[9894]31using namespace osgDarwin;
[5948]32
33
34// Carbon-Eventhandler to handle the click in the close-widget and the resize of windows
35
[5978]36static pascal OSStatus GraphicsWindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void* userData)
[5948]37{
38    WindowRef           window;
39    Rect                bounds;
40    OSStatus            result = eventNotHandledErr; /* report failure by default */
41   
[11046]42    OSG_NOTIFY(osg::INFO) << "GraphicsWindowEventHandler" << std::endl;
[5948]43
44    GraphicsWindowCarbon* w = (GraphicsWindowCarbon*)userData;
45    if (!w)
46        return result;
47   
48    GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL,
49                         sizeof(window), NULL, &window);
[5978]50                         
51    switch(GetEventClass(event))
52    {
53        case kEventClassTablet:
54        case kEventClassMouse:
55            if (w->handleMouseEvent(event))
[5948]56                result = noErr;
[5978]57            break;
[7884]58               
[5978]59        case kEventClassKeyboard:
60            if (w->handleKeyboardEvent(event))
61                result = noErr;
62            break;
63           
64        case kEventClassWindow: {
65       
66            switch (GetEventKind(event))
67                {
68                    case kEventWindowBoundsChanging:
69                        // left the code for live-resizing, but it is not used, because of window-refreshing issues...
70                        GetEventParameter( event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &bounds );
71                       
[9894]72                        w->adaptResize(bounds.left, bounds.top, bounds.right - bounds.left, bounds.bottom - bounds.top);
[5978]73                        w->requestRedraw();
74                        result = noErr;
75                        break;
76                           
77                    case kEventWindowBoundsChanged:
78                        InvalWindowRect(window, GetWindowPortBounds(window, &bounds));
79                        GetWindowBounds(window, kWindowContentRgn, &bounds);
[9894]80                        w->adaptResize(bounds.left, bounds.top, bounds.right - bounds.left, bounds.bottom - bounds.top);
[5978]81                        result = noErr;
82                        break;
[5948]83                   
[7165]84                    case kEventWindowClose:
[5978]85                        w->requestClose();
[7165]86                        result = noErr;
[5978]87                        break;
88         
89                    default:
90                        break;
91                }
92            }
93        default:
[7884]94            //std::cout << "unknown: " << GetEventClass(event) << std::endl;
[5978]95            break;
96    }
[7165]97   
[7866]98    //if (result == eventNotHandledErr)
99    //    result = CallNextEventHandler (nextHandler, event);
[7165]100       
[5948]101    return result;
102}
103
[8017]104
[5948]105static bool s_quit_requested = false;
106
107// Application eventhandler -- listens for a quit-event
108static pascal OSStatus ApplicationEventHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
109{
110   
111    HICommand commandStruct;
112
113    OSErr  err = eventNotHandledErr;
114
115    GetEventParameter (inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &commandStruct);
116
117    switch(commandStruct.commandID) {
118        case kHICommandQuit:
119            s_quit_requested = true;
120            err = noErr;
121            break;
122                   
123    }
124   
125    return err;
126}
127
128// AppleEventHandler, listens to the Quit-AppleEvent
129static pascal OSErr QuitAppleEventHandler(const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon ) {
130    s_quit_requested = true;
131    return (noErr);
132}
133
134
135namespace osgViewer
136{
137
138// small helper class which maps the raw key codes to osgGA::GUIEventAdapter::Keys
139
[9894]140class CarbonKeyboardMap {
[5948]141
142    public:
[9894]143        CarbonKeyboardMap()
[5948]144        {
145            _keymap[53                ] =  osgGA::GUIEventAdapter::KEY_Escape;
146            _keymap[115                ] =  osgGA::GUIEventAdapter::KEY_Home;
147            _keymap[76                ] =  osgGA::GUIEventAdapter::KEY_KP_Enter;
148            _keymap[119                ] =  osgGA::GUIEventAdapter::KEY_End;
149            _keymap[36                ] =  osgGA::GUIEventAdapter::KEY_Return;
150            _keymap[116                ] =  osgGA::GUIEventAdapter::KEY_Page_Up;
151            _keymap[121                ] = osgGA::GUIEventAdapter::KEY_Page_Down;
152            _keymap[123                ] = osgGA::GUIEventAdapter::KEY_Left;
153            _keymap[124                ] = osgGA::GUIEventAdapter::KEY_Right;
154            _keymap[126                ] = osgGA::GUIEventAdapter::KEY_Up;
155            _keymap[125                ] = osgGA::GUIEventAdapter::KEY_Down;
156            _keymap[51                ] = osgGA::GUIEventAdapter::KEY_BackSpace;
157            _keymap[48                ] = osgGA::GUIEventAdapter::KEY_Tab;
158            _keymap[49                ] = osgGA::GUIEventAdapter::KEY_Space;
159            _keymap[117                ] = osgGA::GUIEventAdapter::KEY_Delete;
160           
161            _keymap[122                    ] = osgGA::GUIEventAdapter::KEY_F1;
162            _keymap[120                    ] = osgGA::GUIEventAdapter::KEY_F2;
163            _keymap[99                    ] = osgGA::GUIEventAdapter::KEY_F3;
164            _keymap[118                    ] = osgGA::GUIEventAdapter::KEY_F4;
165            _keymap[96                    ] = osgGA::GUIEventAdapter::KEY_F5;
166            _keymap[97                    ] = osgGA::GUIEventAdapter::KEY_F6;
167            _keymap[98                    ] = osgGA::GUIEventAdapter::KEY_F7;
168            _keymap[100                    ] = osgGA::GUIEventAdapter::KEY_F8;
169            _keymap[101                    ] = osgGA::GUIEventAdapter::KEY_F9;
170            _keymap[109                    ] = osgGA::GUIEventAdapter::KEY_F10;
171            _keymap[103                    ] = osgGA::GUIEventAdapter::KEY_F11;
172            _keymap[111                    ] = osgGA::GUIEventAdapter::KEY_F12;
173           
174            _keymap[75                    ] = osgGA::GUIEventAdapter::KEY_KP_Divide;
175            _keymap[67                    ] = osgGA::GUIEventAdapter::KEY_KP_Multiply;
176            _keymap[78                    ] = osgGA::GUIEventAdapter::KEY_KP_Subtract;
177            _keymap[69                    ] = osgGA::GUIEventAdapter::KEY_KP_Add;
178            _keymap[89                    ] = osgGA::GUIEventAdapter::KEY_KP_Home;
179            _keymap[91                    ] = osgGA::GUIEventAdapter::KEY_KP_Up;
180            _keymap[92                    ] = osgGA::GUIEventAdapter::KEY_KP_Page_Up;
181            _keymap[86                    ] = osgGA::GUIEventAdapter::KEY_KP_Left;
182            _keymap[87                    ] = osgGA::GUIEventAdapter::KEY_KP_Begin;
183            _keymap[88                    ] = osgGA::GUIEventAdapter::KEY_KP_Right;
184            _keymap[83                    ] = osgGA::GUIEventAdapter::KEY_KP_End;
185            _keymap[84                    ] = osgGA::GUIEventAdapter::KEY_KP_Down;
186            _keymap[85                    ] = osgGA::GUIEventAdapter::KEY_KP_Page_Down;
187            _keymap[82                    ] = osgGA::GUIEventAdapter::KEY_KP_Insert;
188            _keymap[65                    ] = osgGA::GUIEventAdapter::KEY_KP_Delete;
189
190        }
191       
[9894]192        ~CarbonKeyboardMap() {
[5948]193        }
194       
195        unsigned int remapKey(unsigned int key, unsigned int rawkey)
196        {
197            KeyMap::iterator itr = _keymap.find(rawkey);
198            if (itr == _keymap.end()) return key;
199            else return itr->second;
200        }
201    private:
202        typedef std::map<unsigned int, osgGA::GUIEventAdapter::KeySymbol> KeyMap;
203        KeyMap _keymap;
204};
205
206/** remaps a native os x keycode to a GUIEventAdapter-keycode */
[9894]207static unsigned int remapCarbonKey(unsigned int key, unsigned int rawkey)
[5948]208{
[9894]209    static CarbonKeyboardMap s_CarbonKeyboardMap;
210    return s_CarbonKeyboardMap.remapKey(key,rawkey);
[5948]211}
212
213
[9894]214class CarbonWindowAdapter : public MenubarController::WindowAdapter {
215public:
216    CarbonWindowAdapter(GraphicsWindowCarbon* win) : MenubarController::WindowAdapter(), _win(win) {}
217    virtual bool valid() {return (_win.valid() && _win->valid()); }
218    virtual void getWindowBounds(CGRect& rect)
[5978]219    {
[9894]220        Rect windowBounds;
221        OSErr error = GetWindowBounds(_win->getNativeWindowRef(), kWindowStructureRgn, &windowBounds);
222        rect.origin.x = windowBounds.left;
223        rect.origin.y = windowBounds.top;
224        rect.size.width = windowBounds.right - windowBounds.left;
225        rect.size.height = windowBounds.bottom - windowBounds.top;
[5978]226    }
227       
[9894]228    osgViewer::GraphicsWindow* getWindow()  { return _win.get(); }
229private:
230    osg::observer_ptr<GraphicsWindowCarbon> _win;
[5978]231};
232
233
234
[6404]235void GraphicsWindowCarbon::init()
[5948]236{
[7112]237    if (_initialized) return;
238
[8398]239    // getEventQueue()->setCurrentEventState(osgGA::GUIEventAdapter::getAccumulatedEventState().get());
[7884]240   
241    _lastModifierKeys = 0;
[6678]242    _windowTitleHeight = 0;
[5948]243    _closeRequested = false;
[6706]244    _ownsWindow = false;
[5948]245    _context = NULL;
246    _window = NULL;
[7039]247    _pixelFormat = PixelBufferCarbon::createPixelFormat(_traits.get());
[5948]248    if (!_pixelFormat)
[11043]249    {
[11046]250        OSG_NOTIFY(osg::WARN) << "GraphicsWindowCarbon::init could not create a valid pixelformat" << std::endl;
[11043]251    }
[5948]252    _valid = (_pixelFormat != NULL);
253    _initialized = true;
254}
255
[6931]256bool GraphicsWindowCarbon::setWindowDecorationImplementation(bool flag)
[6706]257{
258    _useWindowDecoration = flag;
[6931]259
260    if (_realized)
261    {
[6706]262        OSErr err = noErr;
263        Rect bounds;
264        GetWindowBounds(getNativeWindowRef(), kWindowContentRgn, &bounds);
[5948]265
[6931]266        if (_useWindowDecoration)
267        {
[6706]268            err = ChangeWindowAttributes(getNativeWindowRef(),  kWindowStandardDocumentAttributes,  kWindowNoTitleBarAttribute | kWindowNoShadowAttribute);
269            SetWindowBounds(getNativeWindowRef(), kWindowContentRgn, &bounds);
[6931]270        }
271        else
272        {
[6706]273            err = ChangeWindowAttributes(getNativeWindowRef(), kWindowNoTitleBarAttribute | kWindowNoShadowAttribute, kWindowStandardDocumentAttributes);
[6944]274            SetWindowBounds(getNativeWindowRef(), kWindowContentRgn, &bounds);   
[6706]275        }
[5948]276
[6931]277        if (err != noErr)
278        {
[11046]279            OSG_NOTIFY(osg::WARN) << "GraphicsWindowCarbon::setWindowDecoration failed with " << err << std::endl;
[6931]280            return false;
[6706]281        }
[6944]282       
283        // update titlebar-height
284        Rect titleRect;
285        GetWindowBounds(_window, kWindowTitleBarRgn, &titleRect);
286        _windowTitleHeight = abs(titleRect.bottom - titleRect.top);
287       
288        // 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.
289        // InvalWindowRect doesn't help here :-/
290       
291        aglSetDrawable(_context, 0);
292        aglSetDrawable(_context, GetWindowPort(_window));
293               
294        MenubarController::instance()->update();
[6706]295    }
[6931]296
297    return true;
[6706]298}
[5978]299
[6944]300
[6706]301WindowAttributes GraphicsWindowCarbon::computeWindowAttributes(bool useWindowDecoration, bool supportsResize) {
302    WindowAttributes attr;
[5978]303   
[6706]304    if (useWindowDecoration)
[5978]305    {
[6706]306        if (supportsResize)
[5948]307            attr = (kWindowStandardDocumentAttributes | kWindowStandardHandlerAttribute);
308        else
309            attr = (kWindowStandardDocumentAttributes | kWindowStandardHandlerAttribute) & ~kWindowResizableAttribute;
[5978]310    }
[6220]311    else 
312    {
313        attr = kWindowNoTitleBarAttribute | kWindowNoShadowAttribute | kWindowStandardHandlerAttribute;
[6706]314        if (supportsResize)
[5948]315            attr |= kWindowResizableAttribute;
316    }
[6706]317    return attr;
318}
[6220]319
[6706]320void GraphicsWindowCarbon::installEventHandler() {
321
[5948]322    // register window event handler to receive resize-events
[5978]323    EventTypeSpec   windEventList[] = {
324        { kEventClassWindow, kEventWindowBoundsChanged},
[7165]325        { kEventClassWindow, kEventWindowClose},
[5978]326       
327        {kEventClassMouse, kEventMouseDown},
328        {kEventClassMouse, kEventMouseUp},
329        {kEventClassMouse, kEventMouseMoved},
330        {kEventClassMouse, kEventMouseDragged},
331        {kEventClassMouse, kEventMouseWheelMoved},
[8192]332        {kEventClassMouse, 11 /* kEventMouseScroll */},
[5978]333
334        {kEventClassKeyboard, kEventRawKeyDown},
335        {kEventClassKeyboard, kEventRawKeyRepeat},
336        {kEventClassKeyboard, kEventRawKeyUp},
337        {kEventClassKeyboard, kEventRawKeyModifiersChanged},
338        {kEventClassKeyboard, kEventHotKeyPressed},
339        {kEventClassKeyboard, kEventHotKeyReleased},
340    };
[5948]341   
[5978]342    InstallWindowEventHandler(_window, NewEventHandlerUPP(GraphicsWindowEventHandler),  GetEventTypeCount(windEventList), windEventList, this, NULL);
[7866]343 }
[6706]344
345
346bool GraphicsWindowCarbon::realizeImplementation()
347{
[5978]348   
[6706]349    if (!_initialized) init();
350    if (!_initialized) return false;
351    if (!_traits) return false;
352   
[11046]353    OSG_NOTIFY(osg::INFO) << "GraphicsWindowCarbon:: realizeIMplementation" << std::endl;
[7866]354   
[6706]355    setWindowDecoration(_traits->windowDecoration);
[7709]356    useCursor(_traits->useCursor);
[7841]357
[6706]358    // move the window to the right screen
[9894]359    DarwinWindowingSystemInterface* wsi = dynamic_cast<DarwinWindowingSystemInterface*>(osg::GraphicsContext::getWindowingSystemInterface());
[6706]360    int screenLeft(0), screenTop(0);
[9894]361    if (wsi)
362    {
[6706]363        wsi->getScreenTopLeft((*_traits), screenLeft, screenTop);
364    }
365   
[8017]366    WindowData *windowData = ( _traits.get() && _traits->inheritedWindowData.get() ) ? static_cast<osgViewer::GraphicsWindowCarbon::WindowData*>(_traits->inheritedWindowData.get()) : 0;
[7866]367     
[6706]368    _ownsWindow = (windowData) ? (windowData->getNativeWindowRef() == NULL) : true;
369   
370    if (_ownsWindow) {
371       
372        // create the window
[9894]373        Rect bounds = {_traits->y + screenTop, _traits->x + screenLeft, _traits->y + _traits->height + screenTop, _traits->x + _traits->width + screenLeft};
[6706]374        OSStatus err = 0;
375        WindowAttributes attr = computeWindowAttributes(_useWindowDecoration, _traits->supportsResize);
376       
377        err = CreateNewWindow(kDocumentWindowClass, attr, &bounds, &_window);
378
379        if (err) {
[11046]380            OSG_NOTIFY(osg::WARN) << "GraphicsWindowCarbon::realizeImplementation() failed creating a window: " << err << std::endl;
[6706]381            return false;
382        } else {
[11046]383            OSG_NOTIFY(osg::INFO) << "GraphicsWindowCarbon::realizeImplementation() - window created with bounds(" << bounds.top << ", " << bounds.left << ", " << bounds.bottom << ", " << bounds.right << ")" << std::endl;
[6706]384        }
385    }
386    else {
[7866]387         _window = windowData->getNativeWindowRef();
[6706]388    }
389   
390    Rect titleRect;
391    GetWindowBounds(_window, kWindowTitleBarRgn, &titleRect);
[6934]392    _windowTitleHeight = abs(titleRect.bottom - titleRect.top);
[6706]393   
394    if ((_ownsWindow) || (windowData && windowData->installEventHandler()))
395        installEventHandler();
396   
[5948]397    // set the window title
[7709]398    setWindowName(_traits->windowName);
[5948]399   
400    // create the context
[7039]401    AGLContext sharedContextCarbon = NULL;
402   
[10813]403    GraphicsHandleCarbon* graphicsHandleCarbon = dynamic_cast<GraphicsHandleCarbon*>(_traits->sharedContext);
404    if (graphicsHandleCarbon)
[6204]405    {
[10813]406        sharedContextCarbon = graphicsHandleCarbon->getAGLContext();
[6204]407    }
[10813]408
[7039]409    _context = aglCreateContext (_pixelFormat, sharedContextCarbon);
[6204]410
411
[5948]412    if (!_context) {
[11046]413        OSG_NOTIFY(osg::WARN) << "GraphicsWindowCarbon::realizeImplementation failed creating a context: " << aglGetError() << std::endl;
[5948]414        return false;
415    }
[7866]416
417     
418    if ( windowData && windowData->getAGLDrawable() ) {
[8017]419        aglSetDrawable(_context, (AGLDrawable)*(windowData->getAGLDrawable()) );
420               
[7866]421    } else {
[8017]422        aglSetDrawable(_context, GetWindowPort(_window));
423        ShowWindow(_window);
[9894]424        MenubarController::instance()->attachWindow( new CarbonWindowAdapter(this) );
[7866]425    }
426   
[5948]427    makeCurrent();
428
[6220]429    if ((_traits->useMultiThreadedOpenGLEngine) && (OpenThreads::GetNumberOfProcessors() > 1)) {
[6106]430        // enable Multi-threaded OpenGL Execution:
431        CGLError cgerr = kCGLNoError;
432        CGLContextObj ctx = CGLGetCurrentContext();
[5948]433
[6826]434#if 0
[6106]435        cgerr =  CGLEnable( ctx, kCGLCEMPEngine);
[6826]436#else
437        // the above use of kCGLCEMPEngine is not backwards compatible
438        // so we'll use the raw value of it to keep things compiling on older
439        // versions of OSX.
440        cgerr =  CGLEnable( ctx, static_cast <CGLContextEnable>(313) );
441#endif   
[6106]442        if (cgerr != kCGLNoError )
443        {
[11046]444            OSG_NOTIFY(osg::INFO) << "GraphicsWindowCarbon:: Multi-threaded OpenGL Execution not available" << std::endl;
[6106]445        }
[6220]446    }
[5948]447   
[8017]448    InitCursor();
449   
[5948]450    //enable vsync
451    if (_traits->vsync) {
452        GLint swap = 1;
453        aglSetInteger (_context, AGL_SWAP_INTERVAL, &swap);
454    }
455
456    _realized = true;
457    return _realized;
458}
459
460
461
462bool GraphicsWindowCarbon::makeCurrentImplementation()
463{
464       
465    return (aglSetCurrentContext(_context) == GL_TRUE);
466}
467
468bool GraphicsWindowCarbon::releaseContextImplementation()
469{
470    if (!_realized)
471    {
[11046]472        OSG_NOTIFY(osg::NOTICE)<<"Warning: GraphicsWindow not realized, cannot do makeCurrent."<<std::endl;
[5948]473        return false;
474    }
475
[11046]476    // OSG_NOTIFY(osg::NOTICE)<<"makeCurrentImplementation "<<this<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
477    // OSG_NOTIFY(osg::NOTICE)<<"   glXMakeCurrent ("<<_display<<","<<_window<<","<<_glxContext<<std::endl;
[5948]478    return (aglSetCurrentContext(NULL) == GL_TRUE);
479}
480
481
482
483void GraphicsWindowCarbon::closeImplementation()
484{
[11046]485    // OSG_NOTIFY(osg::INFO) << "GraphicsWindowCarbon::closeImplementation" << std::endl;
[5948]486    _valid = false;
487    _realized = false;
488   
[8017]489    // there's a possibility that the MenubarController is destructed already, so prevent a crash:
490    MenubarController* mbc = MenubarController::instance();
491    if (mbc) mbc->detachWindow(this);
[5978]492   
[5948]493    if (_pixelFormat)
494    {
495        aglDestroyPixelFormat(_pixelFormat);
496        _pixelFormat = NULL;
497    }
498   
499    if (_context)
500    {
501        aglSetDrawable(_context, NULL);
502        aglSetCurrentContext(NULL);
503        aglDestroyContext(_context);
504        _context = NULL;
505    }
506   
[6706]507    if (_ownsWindow && _window) DisposeWindow(_window);
[5948]508    _window = NULL;
509}
510
511
512
513void GraphicsWindowCarbon::swapBuffersImplementation()
514{
515    aglSwapBuffers(_context);
516}
517
518
519
520void GraphicsWindowCarbon::resizedImplementation(int x, int y, int width, int height)
521{
[5978]522    GraphicsContext::resizedImplementation(x, y, width, height);
523
[5948]524    aglUpdateContext(_context);
[5978]525    MenubarController::instance()->update();
[9894]526   
527    getEventQueue()->windowResize(x,y,width, height, getEventQueue()->getTime());
[5948]528}
529
530
531
[5978]532bool GraphicsWindowCarbon::handleMouseEvent(EventRef theEvent)
[5948]533{
534
[5978]535    static unsigned int lastEmulatedMouseButton = 0;
[5948]536    // mouse down event   
537    Point wheresMyMouse;
[5978]538    GetEventParameter (theEvent, kEventParamWindowMouseLocation, typeQDPoint, NULL, sizeof(wheresMyMouse), NULL, &wheresMyMouse);
[5948]539   
[6678]540    wheresMyMouse.v -= _windowTitleHeight;
541    if (_useWindowDecoration && (wheresMyMouse.v < 0))
542        return false;
543   
[5978]544    Point wheresMyMouseGlobal;
545    GetEventParameter (theEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(wheresMyMouse), NULL, &wheresMyMouseGlobal);
546   
[5948]547    EventMouseButton mouseButton = 0;
548    GetEventParameter (theEvent, kEventParamMouseButton, typeMouseButton, NULL, sizeof(mouseButton), NULL, &mouseButton);
[5978]549   
550    UInt32 modifierKeys;
551    GetEventParameter (theEvent,kEventParamKeyModifiers,typeUInt32, NULL,sizeof(modifierKeys), NULL,&modifierKeys);
552   
553   
[5948]554    WindowRef win;
[5978]555    int fwres = FindWindow(wheresMyMouseGlobal, &win);
[8017]556    // return false when Window is inactive; For enabling click-to-active on window by delegating event to default handler
557    if (((fwres != inContent) && (fwres > 0) && (mouseButton >= 1)) || !IsWindowActive(win))
[5948]558    {
[5978]559        return false;
[5948]560    }
561    else
562    {
[7841]563        UInt32 clickCount;
564        GetEventParameter(theEvent, kEventParamClickCount, typeUInt32, NULL, sizeof(clickCount), NULL, &clickCount);
[5948]565        // swap right and middle buttons so that middle button is 2, right button is 3.
566        if (mouseButton==3) mouseButton = 2;
567        else if (mouseButton==2) mouseButton = 3;
568       
569        // check tablet pointer device and map it to a musebutton
570        TabletProximityRec    theTabletRecord;    // The Tablet Proximity Record
571        // Extract the Tablet Proximity reccord from the event.
572        if(noErr == GetEventParameter(theEvent, kEventParamTabletProximityRec,
573                                      typeTabletProximityRec, NULL,
574                                      sizeof(TabletProximityRec),
575                                      NULL, (void *)&theTabletRecord))
576        {           
577            osgGA::GUIEventAdapter::TabletPointerType pointerType;
578            switch(theTabletRecord.pointerType)
579            {
580                case 1: // pen
581                    pointerType = osgGA::GUIEventAdapter::PEN;
582                    break;
583                   
584                case 2: // puck
585                    pointerType = osgGA::GUIEventAdapter::PUCK;
586                    break;
587                   
588                case 3: //eraser
589                    pointerType = osgGA::GUIEventAdapter::ERASER;
590                    break;
591
592                default:
593                   pointerType = osgGA::GUIEventAdapter::UNKNOWN;
594                   break;
595            }
596           
597            getEventQueue()->penProximity(pointerType, (theTabletRecord.enterProximity != 0));
598        }
599
[8085]600        // get tilt and rotation from the pen
601        TabletPointRec theTabletPointRecord;
602        if(noErr == GetEventParameter(theEvent,  kEventParamTabletPointRec, typeTabletPointRec, NULL,
603                sizeof(TabletPointRec), NULL, (void *)&theTabletPointRecord))
604        {
605            int penRotation = (int)theTabletPointRecord.rotation * 9 / 575; //to get angle between 0 to 360 grad
606            penRotation = -(((penRotation + 180) % 360) - 180) ;          //for same range on all plattforms we need -180 to 180
607            getEventQueue()->penOrientation (
608                    theTabletPointRecord.tiltX * 60 / 32767.0f,  //multiply with 60 to get angle between -60 to 60 grad
609                    -theTabletPointRecord.tiltY * 60 / 32767.0f,  //multiply with 60 to get angle between -60 to 60 grad
610                    penRotation
611            );
612        }
613           
[5948]614        switch(GetEventKind(theEvent))
615        {
616            case kEventMouseDown:
617                {
618                    float mx =wheresMyMouse.h;
619                    float my =wheresMyMouse.v;
620                    transformMouseXY(mx, my);
[5978]621                   
622                    lastEmulatedMouseButton = 0;
623                   
624                    if (mouseButton == 1)
625                    {
626                        if( modifierKeys & cmdKey )
627                        {
628                            mouseButton = lastEmulatedMouseButton = 3;
629                        }
630                        else if( modifierKeys & optionKey )
631                        {
632                            mouseButton = lastEmulatedMouseButton = 2;
633                        }
634                    }
635                   
[7841]636                    if (clickCount > 1)
637                        getEventQueue()->mouseDoubleButtonPress(mx,my, mouseButton);
638                    else
639                        getEventQueue()->mouseButtonPress(mx, my, mouseButton);
[5948]640                }
641                break;
642            case kEventMouseUp:
643                {
644                    float mx =wheresMyMouse.h;
645                    float my =wheresMyMouse.v;
646                    transformMouseXY(mx, my);
[5978]647                    if (lastEmulatedMouseButton > 0) {
648                        getEventQueue()->mouseButtonRelease(mx, my, lastEmulatedMouseButton);
649                        lastEmulatedMouseButton = 0;
650                    }
651                    else {
652                        getEventQueue()->mouseButtonRelease(mx, my, mouseButton);
653                    }
[5948]654                }
655                break;
656               
657            case kEventMouseDragged:
658                {
659                    // get pressure from the pen, only when mouse/pen is dragged
660                    TabletPointRec    theTabletRecord;
661                    if(noErr == GetEventParameter(theEvent,  kEventParamTabletPointRec, typeTabletPointRec, NULL,
662                                    sizeof(TabletPointRec), NULL, (void *)&theTabletRecord)) {
663                   
664                        getEventQueue()->penPressure(theTabletRecord.pressure / 65535.0f);
665           
666                    }
667                   
668                    float mx =wheresMyMouse.h;
669                    float my =wheresMyMouse.v;
670                    transformMouseXY(mx, my);
671                    getEventQueue()->mouseMotion(mx, my);
672                }
673                break;
674               
675            case kEventMouseMoved:
676                {
677                    float mx = wheresMyMouse.h;
678                    float my = wheresMyMouse.v;
679                    transformMouseXY(mx, my);
680                    getEventQueue()->mouseMotion(mx, my);
681                }
682                break;
683               
684            // mouse with scroll-wheels
685            case kEventMouseWheelMoved:
686                {
687                    EventMouseWheelAxis axis;
688                    SInt32 delta;
689                    if (noErr == GetEventParameter( theEvent, kEventParamMouseWheelAxis, typeMouseWheelAxis, NULL, sizeof(axis), NULL, &axis )) {
690                        if (noErr == GetEventParameter( theEvent, kEventParamMouseWheelDelta, typeLongInteger, NULL, sizeof(delta), NULL, &delta )) {
691                            switch (axis) {
692                                case kEventMouseWheelAxisX:
693                                    getEventQueue()->mouseScroll( (delta > 0) ? osgGA::GUIEventAdapter::SCROLL_RIGHT : osgGA::GUIEventAdapter::SCROLL_LEFT);
694                                    break;
695                                case kEventMouseWheelAxisY:
696                                    getEventQueue()->mouseScroll( (delta < 0) ? osgGA::GUIEventAdapter::SCROLL_DOWN : osgGA::GUIEventAdapter::SCROLL_UP);
697                                    break;
698                            }
699                        }
700                    }
701                }
702                break;
703           
704            // new trackpads and mighty mouse, (not officially documented, see http://developer.apple.com/qa/qa2005/qa1453.html )
705            case 11:
706                {
707                    enum
708                        {
709                        kEventParamMouseWheelSmoothVerticalDelta       = 'saxy', // typeSInt32
[6461]710                        kEventParamMouseWheelSmoothHorizontalDelta     = 'saxx' // typeSInt32
[5948]711                        };
712                   
713                    SInt32 scroll_delta_x = 0;
714                    SInt32 scroll_delta_y = 0;
715                    OSErr err = noErr;
716                    err = GetEventParameter( theEvent, kEventParamMouseWheelSmoothVerticalDelta, typeLongInteger, NULL, sizeof(scroll_delta_y), NULL, &scroll_delta_y );
717                    err = GetEventParameter( theEvent, kEventParamMouseWheelSmoothHorizontalDelta, typeLongInteger, NULL, sizeof(scroll_delta_x), NULL, &scroll_delta_x );
718                   
719                    if ((scroll_delta_x != 0) || (scroll_delta_y != 0)) {
720                        getEventQueue()->mouseScroll2D( scroll_delta_x, scroll_delta_y);
721                    }
722                }
723                break;
724           
725            default:
[5978]726                return false;
[5948]727        }
728    }
[5978]729   
730    return true;
[5948]731}
732
733
734
[5978]735bool GraphicsWindowCarbon::handleKeyboardEvent(EventRef theEvent)
[5948]736{
[7884]737    handleModifierKeys(theEvent);
738       
739    OSStatus status;
[5948]740   
741    UInt32 rawkey;
742    GetEventParameter (theEvent,kEventParamKeyCode,typeUInt32, NULL,sizeof(rawkey), NULL,&rawkey);
743   
[11046]744    // OSG_NOTIFY(osg::INFO) << "key code: " << rawkey << " modifiers: " << modifierKeys << std::endl;
[5948]745           
746    UInt32 dataSize;
747    /* jbw check return status so that we don't allocate a huge array */
748    status = GetEventParameter( theEvent, kEventParamKeyUnicodes, typeUnicodeText, NULL, 0, &dataSize, NULL );
[5978]749    if (status != noErr) return false;
750    if (dataSize<=1) return false;
[5948]751   
752    UniChar* uniChars = new UniChar[dataSize+1];
753    GetEventParameter( theEvent, kEventParamKeyUnicodes, typeUnicodeText, NULL, dataSize, NULL, (void*)uniChars );
754   
[9894]755    unsigned int keychar = remapCarbonKey(static_cast<unsigned long>(uniChars[0]), rawkey);
[5948]756   
757    switch(GetEventKind(theEvent))
758    {
759        case kEventRawKeyDown:
760        case kEventRawKeyRepeat:
761        {
[7066]762            //getEventQueue()->getCurrentEventState()->setModKeyMask(modifierMask);
[11046]763            OSG_NOTIFY(osg::INFO) << "GraphicsWindowCarbon::keyPress" << std::endl;
[5948]764            getEventQueue()->keyPress(keychar);
765            break;
766        }
767       
768        case kEventRawKeyUp:
769        {                 
[11046]770            OSG_NOTIFY(osg::INFO) << "GraphicsWindowCarbon::keyPress" << std::endl;
[7066]771            //getEventQueue()->getCurrentEventState()->setModKeyMask(modifierMask);
[5948]772            getEventQueue()->keyRelease(keychar);
773            break;
774        }
775       
776        default:
777             break;
778   
779    }
780
781    delete[] uniChars;
782
[5978]783    return true;
[5948]784}
785
[7884]786void GraphicsWindowCarbon::handleModifierKey(UInt32 modifierKey, UInt32 modifierMask, osgGA::GUIEventAdapter::KeySymbol keySymbol) {
[5948]787
[7884]788    if ((modifierKey & modifierMask) && !(_lastModifierKeys & modifierMask))
789    {
790        getEventQueue()->keyPress(keySymbol);
791    }
792   
793    if (!(modifierKey & modifierMask) && (_lastModifierKeys & modifierMask))
794    {
795        getEventQueue()->keyRelease(keySymbol);
796    }
797}
[5948]798
[7884]799bool GraphicsWindowCarbon::handleModifierKeys(EventRef theEvent)
800{
801    UInt32 modifierKeys;
802    GetEventParameter (theEvent,kEventParamKeyModifiers,typeUInt32, NULL,sizeof(modifierKeys), NULL,&modifierKeys);
803
804    //std::cout << modifierKeys << std::endl;
805    if (_lastModifierKeys == modifierKeys)
806        return false;
807       
808    handleModifierKey(modifierKeys, shiftKey, osgGA::GUIEventAdapter::KEY_Shift_L);
809    handleModifierKey(modifierKeys, controlKey, osgGA::GUIEventAdapter::KEY_Control_L);
810    handleModifierKey(modifierKeys, optionKey, osgGA::GUIEventAdapter::KEY_Alt_L);
811    handleModifierKey(modifierKeys, cmdKey, osgGA::GUIEventAdapter::KEY_Super_L);
812   
813    // Caps lock needs some special handling, i did not find a way to get informed when the caps-lock-key gets released   
814    if ((modifierKeys & alphaLock) && !(_lastModifierKeys & alphaLock))
815    {
816        getEventQueue()->keyPress(osgGA::GUIEventAdapter::KEY_Caps_Lock);
817        getEventQueue()->keyRelease(osgGA::GUIEventAdapter::KEY_Caps_Lock);
818    }
819   
820    if (!(modifierKeys & alphaLock) && (_lastModifierKeys & alphaLock))
821    {
822        getEventQueue()->keyPress(osgGA::GUIEventAdapter::KEY_Caps_Lock);
823        getEventQueue()->keyRelease(osgGA::GUIEventAdapter::KEY_Caps_Lock);
824    }
825   
826    _lastModifierKeys = modifierKeys;
827    return true;
828}
829
830
831
[5948]832void GraphicsWindowCarbon::checkEvents()
833{
834    if (!_realized) return;
835   
836    EventRef theEvent;
837    EventTargetRef theTarget = GetEventDispatcherTarget();
838    while (ReceiveNextEvent(0, NULL, 0,true, &theEvent)== noErr)
839    {
840        switch(GetEventClass(theEvent))
841        {
[5978]842            case kEventClassMouse:
843                    {
844                    // handle the menubar
845                    Point wheresMyMouse;
846                    GetEventParameter (theEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(wheresMyMouse), NULL, &wheresMyMouse);
847                   
848                    EventMouseButton mouseButton = 0;
849                    GetEventParameter (theEvent, kEventParamMouseButton, typeMouseButton, NULL, sizeof(mouseButton), NULL, &mouseButton);
850                   
851                    WindowRef win;
852                    int fwres = FindWindow(wheresMyMouse, &win);
853
854                    if ((fwres == inMenuBar) && (mouseButton >= 1)) {
855                        MenuSelect(wheresMyMouse);
856                        HiliteMenu(0);
857                        return;
858                    }
859                    break;
860                }
861
[5948]862            case kEventClassApplication:
863                switch (GetEventKind(theEvent)) {
864                    case kEventAppQuit:
865                        getEventQueue()->quitApplication();
866                        break;
867                }
868                break;
869           
870            case kEventClassAppleEvent:
871                {
872                    EventRecord eventRecord;
873                    ConvertEventRefToEventRecord(theEvent, &eventRecord);
874                    AEProcessAppleEvent(&eventRecord);
875                    return;
876                }
877                break;
878
879        }
880        SendEventToEventTarget (theEvent, theTarget);
881        ReleaseEvent(theEvent);       
882    } 
883    if (_closeRequested)
[7165]884        getEventQueue()->closeWindow();
[5948]885       
886    if (s_quit_requested) {
887        getEventQueue()->quitApplication();
888        s_quit_requested = false;
889    }
890           
891}
892
893
[6931]894bool GraphicsWindowCarbon::setWindowRectangleImplementation(int x, int y, int width, int height)
[6495]895{
[9894]896    int screenLeft(0), screenTop(0);
897    DarwinWindowingSystemInterface* wsi = dynamic_cast<DarwinWindowingSystemInterface*>(osg::GraphicsContext::getWindowingSystemInterface());
898   if (wsi)
899    {
900        wsi->getScreenTopLeft((*_traits), screenLeft, screenTop);
901    }
902   
903    Rect bounds = {y + screenTop, x + screenLeft, y + height + screenTop, x + width + screenLeft};
[6706]904    SetWindowBounds(getNativeWindowRef(), kWindowContentRgn, &bounds);
905    aglUpdateContext(_context);
906    MenubarController::instance()->update();
[6931]907    return true;
[6495]908}
[5948]909
[9894]910
911
912void GraphicsWindowCarbon::adaptResize(int x, int y, int w, int h)
913{
914    DarwinWindowingSystemInterface* wsi = dynamic_cast<DarwinWindowingSystemInterface*>(osg::GraphicsContext::getWindowingSystemInterface());
915    int screenLeft(0), screenTop(0);
916    if (wsi) {
917       
918        // get the screen containing the window
919        unsigned int screenNdx = wsi->getScreenContaining(x,y,w,h);
920       
921        // update traits
922        _traits->screenNum = screenNdx;
923       
924        // get top left of screen
925        wsi->getScreenTopLeft((*_traits), screenLeft, screenTop);
926    }
927   
928    resized(x-screenLeft,y-screenTop,w,h);
929}
930
931
932
[5948]933void GraphicsWindowCarbon::grabFocus()
934{
935    SelectWindow(_window);
936}
937
938
939
940void GraphicsWindowCarbon::grabFocusIfPointerInWindow()
941{
942   // TODO: implement
[11046]943   OSG_NOTIFY(osg::ALWAYS) << "GraphicsWindowCarbon::grabFocusIfPointerInWindow" << std::endl;
[5948]944}
945
946
[7709]947void GraphicsWindowCarbon::useCursor(bool cursorOn)
948{
[5948]949
[7709]950    if (_traits.valid())
951        _traits->useCursor = cursorOn;
[9894]952    DarwinWindowingSystemInterface* wsi = dynamic_cast<DarwinWindowingSystemInterface*>(osg::GraphicsContext::getWindowingSystemInterface());
[7709]953    if (wsi == NULL) {
[11046]954        OSG_NOTIFY(osg::WARN) << "GraphicsWindowCarbon::useCursor :: could not get OSXCarbonWindowingSystemInterface" << std::endl;
[7709]955        return;
956    }
957   
958    CGDirectDisplayID displayId = wsi->getDisplayID((*_traits));
959    CGDisplayErr err = kCGErrorSuccess;
960    switch (cursorOn)
961    {
962        case true:
963            err = CGDisplayShowCursor(displayId);
964            break;
965        case false:
966            err = CGDisplayHideCursor(displayId);
967            break;
968    }
969    if (err != kCGErrorSuccess) {
[11046]970        OSG_NOTIFY(osg::WARN) << "GraphicsWindowCarbon::useCursor failed with " << err << std::endl;
[7709]971    }
972}
973
[8017]974// FIXME: need to implement all cursor types
975// FIXME: I used deprecated functions, but don't know if there are any substitutable newer functions...
976void GraphicsWindowCarbon::setCursor(MouseCursor mouseCursor)
977{
978    UInt32 cursor;
979    if (_currentCursor == mouseCursor)
980      return;
981    switch (mouseCursor)
982    {
983        case NoCursor:
984          HideCursor();
985          _currentCursor = mouseCursor;
986          return;
987        case RightArrowCursor:
988            cursor = kThemeArrowCursor;
989            break;
990        case CrosshairCursor:
991            cursor = kThemeCrossCursor;
992            break;
993        case TextCursor:
994            cursor = kThemeIBeamCursor;
995            break;
996        case UpDownCursor:
997            cursor = kThemeResizeUpDownCursor;
998            break;
999        case LeftRightCursor:
1000            cursor = kThemeResizeLeftRightCursor;
1001            break;
1002        default:
1003            cursor = kThemeArrowCursor;
[11046]1004            OSG_NOTIFY(osg::WARN) << "GraphicsWindowCarbon::setCursor doesn't implement cursor: type = " << mouseCursor << std::endl;
[8017]1005    }
1006   
1007    _currentCursor = mouseCursor;
1008    SetThemeCursor(cursor);
1009    ShowCursor();
1010}
[7709]1011
1012
1013void GraphicsWindowCarbon::setWindowName (const std::string& name)
1014{
1015    _traits->windowName = name;
1016    if (!_traits->windowName.empty())
1017    {
1018        CFStringRef windowtitle = CFStringCreateWithBytes( kCFAllocatorDefault, (const UInt8*)(_traits->windowName.c_str()), _traits->windowName.length(),kCFStringEncodingUTF8, false );
1019        SetWindowTitleWithCFString( _window, windowtitle );
1020        CFRelease(windowtitle);
1021    }
1022}
1023
[9120]1024void GraphicsWindowCarbon::requestWarpPointer(float x,float y)
1025{
[7709]1026
[9894]1027    DarwinWindowingSystemInterface* wsi = dynamic_cast<DarwinWindowingSystemInterface*>(osg::GraphicsContext::getWindowingSystemInterface());
[9120]1028    if (wsi == NULL) {
[11046]1029        OSG_NOTIFY(osg::WARN) << "GraphicsWindowCarbon::useCursor :: could not get OSXCarbonWindowingSystemInterface" << std::endl;
[9120]1030        return;
1031    }
[7841]1032
[9120]1033    CGDirectDisplayID displayId = wsi->getDisplayID((*_traits));
1034
1035    CGPoint point;
[9357]1036    point.x = x + _traits->x;
1037    point.y = y + _traits->y;
[9120]1038    CGDisplayMoveCursorToPoint(displayId, point);
1039
1040    getEventQueue()->mouseWarped(x,y);
1041}
1042
1043
[5948]1044void GraphicsWindowCarbon::transformMouseXY(float& x, float& y)
1045{
1046    if (getEventQueue()->getUseFixedMouseInputRange())
1047    {
1048        osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState();
1049        x = eventState->getXmin() + (eventState->getXmax()-eventState->getXmin())*x/float(_traits->width);
1050        y = eventState->getYmin() + (eventState->getYmax()-eventState->getYmin())*y/float(_traits->height);
1051    }
1052}
1053
[9894]1054class CarbonWindowingSystemInterface : public  DarwinWindowingSystemInterface {
1055public:
[11207]1056    CarbonWindowingSystemInterface() : DarwinWindowingSystemInterface()
[5948]1057    {
[11207]1058    }
1059
1060    virtual osg::GraphicsContext* createGraphicsContext(osg::GraphicsContext::Traits* traits)
1061    {
1062        _init();
1063
1064        return createGraphicsContextImplementation<PixelBufferCarbon, GraphicsWindowCarbon>(traits);
1065    }
1066
1067    virtual void _init()
1068    {
1069        if (_initialized) return;
1070
[11263]1071        DarwinWindowingSystemInterface::_init();
[11207]1072
[9894]1073        // register application event handler and AppleEventHandler to get quit-events:
1074        static const EventTypeSpec menueventSpec = {kEventClassCommand, kEventCommandProcess};
1075        OSErr status = InstallEventHandler(GetApplicationEventTarget(), NewEventHandlerUPP(ApplicationEventHandler), 1, &menueventSpec, 0, NULL);
1076        status = AEInstallEventHandler( kCoreEventClass, kAEQuitApplication, NewAEEventHandlerUPP(QuitAppleEventHandler), 0, false);
[5948]1077    }
[11207]1078
[5948]1079};
1080
1081
[9894]1082}
1083
1084#ifdef USE_DARWIN_CARBON_IMPLEMENTATION
1085RegisterWindowingSystemInterfaceProxy<CarbonWindowingSystemInterface> createWindowingSystemInterfaceProxy;
1086#endif
1087
1088
[6931]1089// declare C entry point for static compilation.
1090extern "C" void graphicswindow_Carbon(void)
1091{
[9894]1092    osg::GraphicsContext::setWindowingSystemInterface(new osgViewer::CarbonWindowingSystemInterface());
[6931]1093}
1094
[5948]1095#endif
Note: See TracBrowser for help on using the browser.