root/OpenSceneGraph/trunk/src/osgViewer/GraphicsWindowCocoa.mm @ 9879

Revision 9879, 41.9 kB (checked in by robert, 5 years ago)

From Stephan Huber, support for Cocoa windowing under OSX.

  • Property svn:executable set to *
RevLine 
[9879]1/*
2 *  GraphicsWindowCocoa.cpp
3 *  OpenSceneGraph
4 *
5 *  Created by Stephan Huber on 27.06.08.
6 *  Copyright 2008 Stephan Maximilian Huber, digital mind. All rights reserved.
7 *
8 *  Some code borrowed from the implementation of CocoaViewer,
9 *  Created by Eric Wing on 11/12/06. and ported by Martin Lavery 7/06/07
10 */
11
12#include <iostream>
13#include <osgViewer/api/Cocoa/PixelBufferCocoa>
14#include <osgViewer/api/Cocoa/GraphicsWindowCocoa>
15
16#include <Cocoa/Cocoa.h>
17
18#include "DarwinUtils.h"
19
20
21static bool s_quit_requested = false;
22
23
24// ----------------------------------------------------------------------------------------------------------
25// small helper class remapping key-codes
26// ----------------------------------------------------------------------------------------------------------
27// small helper class which maps the raw key codes to osgGA::GUIEventAdapter::Keys
28
29class CocoaKeyboardMap {
30
31    public:
32        CocoaKeyboardMap()
33        {
34            _keymap[27]     = osgGA::GUIEventAdapter::KEY_Escape;
35            _keymap[13]     = osgGA::GUIEventAdapter::KEY_KP_Enter;
36            _keymap[3]      = osgGA::GUIEventAdapter::KEY_Return;
37            _keymap[9]      = osgGA::GUIEventAdapter::KEY_Tab;
38            _keymap[32]     = osgGA::GUIEventAdapter::KEY_Space;
39            _keymap[127]    = osgGA::GUIEventAdapter::KEY_BackSpace;
40           
41           
42            _keymap[NSHomeFunctionKey]          = osgGA::GUIEventAdapter::KEY_Home;
43            _keymap[NSEndFunctionKey]           = osgGA::GUIEventAdapter::KEY_End;
44            _keymap[NSPageUpFunctionKey]        = osgGA::GUIEventAdapter::KEY_Page_Up;
45            _keymap[NSPageDownFunctionKey]      = osgGA::GUIEventAdapter::KEY_Page_Down;
46            _keymap[NSLeftArrowFunctionKey]     = osgGA::GUIEventAdapter::KEY_Left;
47            _keymap[NSRightArrowFunctionKey]    = osgGA::GUIEventAdapter::KEY_Right;
48            _keymap[NSUpArrowFunctionKey]       = osgGA::GUIEventAdapter::KEY_Up;
49            _keymap[NSDownArrowFunctionKey]     = osgGA::GUIEventAdapter::KEY_Down;
50           
51            _keymap[NSDeleteFunctionKey]        = osgGA::GUIEventAdapter::KEY_Delete;
52           
53            _keymap[NSF1FunctionKey]  = osgGA::GUIEventAdapter::KEY_F1;
54            _keymap[NSF2FunctionKey]  = osgGA::GUIEventAdapter::KEY_F2;
55            _keymap[NSF3FunctionKey]  = osgGA::GUIEventAdapter::KEY_F3;
56            _keymap[NSF4FunctionKey]  = osgGA::GUIEventAdapter::KEY_F4;
57            _keymap[NSF5FunctionKey]  = osgGA::GUIEventAdapter::KEY_F5;
58            _keymap[NSF6FunctionKey]  = osgGA::GUIEventAdapter::KEY_F6;
59            _keymap[NSF7FunctionKey]  = osgGA::GUIEventAdapter::KEY_F7;
60            _keymap[NSF8FunctionKey]  = osgGA::GUIEventAdapter::KEY_F8;
61            _keymap[NSF9FunctionKey]  = osgGA::GUIEventAdapter::KEY_F9;
62           
63            _keymap[NSF10FunctionKey]  = osgGA::GUIEventAdapter::KEY_F10;
64            _keymap[NSF11FunctionKey]  = osgGA::GUIEventAdapter::KEY_F11;
65            _keymap[NSF12FunctionKey]  = osgGA::GUIEventAdapter::KEY_F12;
66            _keymap[NSF13FunctionKey]  = osgGA::GUIEventAdapter::KEY_F13;
67            _keymap[NSF14FunctionKey]  = osgGA::GUIEventAdapter::KEY_F14;
68            _keymap[NSF15FunctionKey]  = osgGA::GUIEventAdapter::KEY_F15;
69            _keymap[NSF16FunctionKey]  = osgGA::GUIEventAdapter::KEY_F16;
70            _keymap[NSF17FunctionKey]  = osgGA::GUIEventAdapter::KEY_F17;
71            _keymap[NSF18FunctionKey]  = osgGA::GUIEventAdapter::KEY_F18;
72            _keymap[NSF19FunctionKey]  = osgGA::GUIEventAdapter::KEY_F19;
73           
74            _keymap[NSF20FunctionKey]  = osgGA::GUIEventAdapter::KEY_F20;
75            _keymap[NSF21FunctionKey]  = osgGA::GUIEventAdapter::KEY_F21;
76            _keymap[NSF22FunctionKey]  = osgGA::GUIEventAdapter::KEY_F22;
77            _keymap[NSF23FunctionKey]  = osgGA::GUIEventAdapter::KEY_F23;
78            _keymap[NSF24FunctionKey]  = osgGA::GUIEventAdapter::KEY_F24;
79            _keymap[NSF25FunctionKey]  = osgGA::GUIEventAdapter::KEY_F25;
80            _keymap[NSF26FunctionKey]  = osgGA::GUIEventAdapter::KEY_F26;
81            _keymap[NSF27FunctionKey]  = osgGA::GUIEventAdapter::KEY_F27;
82            _keymap[NSF28FunctionKey]  = osgGA::GUIEventAdapter::KEY_F28;
83            _keymap[NSF29FunctionKey]  = osgGA::GUIEventAdapter::KEY_F29;
84           
85            _keymap[NSF30FunctionKey]  = osgGA::GUIEventAdapter::KEY_F30;
86            _keymap[NSF31FunctionKey]  = osgGA::GUIEventAdapter::KEY_F31;
87            _keymap[NSF32FunctionKey]  = osgGA::GUIEventAdapter::KEY_F32;
88            _keymap[NSF33FunctionKey]  = osgGA::GUIEventAdapter::KEY_F33;
89            _keymap[NSF34FunctionKey]  = osgGA::GUIEventAdapter::KEY_F34;
90            _keymap[NSF35FunctionKey]  = osgGA::GUIEventAdapter::KEY_F35;
91                       
92           
93            _keypadmap['='] = osgGA::GUIEventAdapter::KEY_KP_Equal;
94            _keypadmap['*'] = osgGA::GUIEventAdapter::KEY_KP_Multiply;
95            _keypadmap['+'] = osgGA::GUIEventAdapter::KEY_KP_Add;
96            _keypadmap['-'] = osgGA::GUIEventAdapter::KEY_KP_Subtract;
97            _keypadmap['.'] = osgGA::GUIEventAdapter::KEY_KP_Decimal;
98            _keypadmap['/'] = osgGA::GUIEventAdapter::KEY_KP_Divide;
99           
100            _keypadmap['0'] = osgGA::GUIEventAdapter::KEY_KP_0;
101            _keypadmap['1'] = osgGA::GUIEventAdapter::KEY_KP_1;
102            _keypadmap['2'] = osgGA::GUIEventAdapter::KEY_KP_2;
103            _keypadmap['3'] = osgGA::GUIEventAdapter::KEY_KP_3;
104            _keypadmap['4'] = osgGA::GUIEventAdapter::KEY_KP_4;
105            _keypadmap['5'] = osgGA::GUIEventAdapter::KEY_KP_5;
106            _keypadmap['6'] = osgGA::GUIEventAdapter::KEY_KP_6;
107            _keypadmap['7'] = osgGA::GUIEventAdapter::KEY_KP_7;
108            _keypadmap['8'] = osgGA::GUIEventAdapter::KEY_KP_8;
109            _keypadmap['9'] = osgGA::GUIEventAdapter::KEY_KP_9;
110        }
111       
112        ~CocoaKeyboardMap() {
113        }
114       
115        unsigned int remapKey(unsigned int key, bool pressedOnKeypad = false)
116        {
117            if (pressedOnKeypad) {
118                 KeyMap::iterator itr = _keypadmap.find(key);
119                if (itr == _keypadmap.end()) return key;
120                else return itr->second;
121            }
122           
123            KeyMap::iterator itr = _keymap.find(key);
124            if (itr == _keymap.end()) return key;
125            else return itr->second;
126        }
127    private:
128        typedef std::map<unsigned int, osgGA::GUIEventAdapter::KeySymbol> KeyMap;
129        KeyMap _keymap, _keypadmap;
130};
131
132
133// ----------------------------------------------------------------------------------------------------------
134// remapCocoaKey
135// ----------------------------------------------------------------------------------------------------------
136static unsigned int remapCocoaKey(unsigned int key, bool pressedOnKeypad = false)
137{
138    static CocoaKeyboardMap s_CocoaKeyboardMap;
139    return s_CocoaKeyboardMap.remapKey(key, pressedOnKeypad);
140}
141
142
143std::ostream& operator<<(std::ostream& os, const NSRect& rect)
144{
145        os << rect.origin.x << "/" << rect.origin.y << " " << rect.size.width << "x" << rect.size.height;
146        return os;
147}
148
149// ----------------------------------------------------------------------------------------------------------
150// Cocoa uses a coordinate system where its origin is in the bottom left corner,
151// osg and quartz uses top left for the origin
152//
153// these 2 methods convets rects between the different coordinate systems
154// ----------------------------------------------------------------------------------------------------------
155
156static NSRect convertFromQuartzCoordinates(const NSRect& rect) 
157{
158    NSRect frame = [[[NSScreen screens] objectAtIndex: 0] frame];
159    float y = frame.size.height - rect.origin.y - rect.size.height;
160        NSRect converted = NSMakeRect(rect.origin.x, y, rect.size.width, rect.size.height);
161       
162        // std::cout << "converting from Quartz " << rect << " to " << converted << " using screen rect " << frame << std::endl;
163       
164    return converted;
165}
166
167static NSRect convertToQuartzCoordinates(const NSRect& rect)
168{
169    NSRect frame = [[[NSScreen screens] objectAtIndex: 0] frame];
170   
171    float y = frame.size.height - (rect.origin.y + rect.size.height);
172        NSRect converted = NSMakeRect(rect.origin.x, y, rect.size.width, rect.size.height);
173       
174        // std::cout << "converting To Quartz   " << rect << " to " << converted << " using screen rect " << frame << std::endl;
175       
176    return converted;
177}
178
179#pragma mark CocoaAppDelegate
180
181// ----------------------------------------------------------------------------------------------------------
182// the app-delegate, handling quit-requests
183// ----------------------------------------------------------------------------------------------------------
184
185@interface CocoaAppDelegate : NSObject 
186{
187}
188
189- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
190@end
191
192@implementation CocoaAppDelegate
193- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
194{
195    s_quit_requested = true;
196    // std::cout << "quit requested " << std::endl;
197    return NSTerminateNow;
198}
199
200@end
201
202#pragma mark GraphicsWindowCocoaWindow
203
204// ----------------------------------------------------------------------------------------------------------
205// GraphicsWindowCocoaWindow, implements canBecomeKeyWindow + canBecomeMainWindow
206// ----------------------------------------------------------------------------------------------------------
207
208@interface GraphicsWindowCocoaWindow : NSWindow
209{
210}
211
212- (BOOL) canBecomeKeyWindow;
213- (BOOL) canBecomeMainWindow;
214
215@end
216
217@implementation GraphicsWindowCocoaWindow
218
219
220- (BOOL) canBecomeKeyWindow
221{
222    return YES;
223}
224
225- (BOOL) canBecomeMainWindow
226{
227    return YES;
228}
229
230@end
231
232#pragma mark GraphicsWindowCocoaGLView
233
234
235// ----------------------------------------------------------------------------------------------------------
236// GraphicsWindowCocoaGLView
237// custom NSOpenGLView-class handling mouse- and keyboard-events, forwarding them to the EventQueue
238// some code borrowed from the example osgCocoaViewer from E.Wing
239// ----------------------------------------------------------------------------------------------------------
240
241@interface GraphicsWindowCocoaGLView : NSOpenGLView
242{
243    @private
244        osgViewer::GraphicsWindowCocoa* _win;
245        BOOL _isUsingCtrlClick, _isUsingOptionClick;
246        unsigned int _cachedModifierFlags;
247                BOOL _handleTabletEvents;
248       
249}
250- (void)setGraphicsWindowCocoa: (osgViewer::GraphicsWindowCocoa*) win;
251
252- (void)keyDown:(NSEvent *)theEvent;
253- (void)keyUp:(NSEvent *)theEvent;
254- (void)flagsChanged:(NSEvent *)theEvent;
255- (void) mouseMoved:(NSEvent*)theEvent;
256- (void) mouseDown:(NSEvent*)theEvent;
257- (void) mouseDragged:(NSEvent*)theEvent;
258- (void) mouseUp:(NSEvent*)theEvent;
259- (void) rightMouseDown:(NSEvent*)theEvent;
260- (void) rightMouseDragged:(NSEvent*)theEvent;
261- (void) rightMouseUp:(NSEvent*)theEvent;
262- (void) otherMouseDown:(NSEvent*)theEvent;
263- (void) otherMouseDragged:(NSEvent*)theEvent;
264- (void) otherMouseUp:(NSEvent*)theEvent;
265
266- (NSPoint) getLocalPoint: (NSEvent*)theEvent;
267- (void) handleModifiers: (NSEvent*)theEvent;
268- (void) setIsUsingCtrlClick:(BOOL)is_using_ctrl_click;
269- (BOOL) isUsingCtrlClick;
270- (void) setIsUsingOptionClick:(BOOL)is_using_option_click;
271- (BOOL) isUsingOptionClick;
272
273- (void) doLeftMouseButtonDown:(NSEvent*)theEvent;
274- (void) doLeftMouseButtonUp:(NSEvent*)theEvent;
275- (void) doRightMouseButtonDown:(NSEvent*)theEvent;
276- (void) doRightMouseButtonUp:(NSEvent*)theEvent;
277- (void) doMiddleMouseButtonDown:(NSEvent*)theEvent;
278- (void) doExtraMouseButtonDown:(NSEvent*)theEvent buttonNumber:(int)button_number;
279- (void) doMiddleMouseButtonUp:(NSEvent*)theEvent;
280- (void) doExtraMouseButtonUp:(NSEvent*)theEvent buttonNumber:(int)button_number;
281- (void) scrollWheel:(NSEvent*)theEvent;
282
283- (void)tabletPoint:(NSEvent *)theEvent;
284- (void)tabletProximity:(NSEvent *)theEvent;
285- (void)handleTabletEvents:(NSEvent*)theEvent;
286
287- (BOOL)acceptsFirstResponder;
288- (BOOL)becomeFirstResponder;
289- (BOOL)resignFirstResponder;
290
291@end
292
293@implementation GraphicsWindowCocoaGLView 
294
295
296-(void) setGraphicsWindowCocoa: (osgViewer::GraphicsWindowCocoa*) win
297{
298    _win = win;
299}
300
301- (BOOL)acceptsFirstResponder
302{
303  return YES;
304}
305
306- (BOOL)becomeFirstResponder
307{
308  return YES;
309}
310
311- (BOOL)resignFirstResponder
312{
313  return YES;
314}
315
316
317- (NSPoint) getLocalPoint: (NSEvent*)theEvent
318{
319    return  [self convertPoint:[theEvent locationInWindow] fromView:nil];
320}
321
322
323- (void) handleModifiers: (NSEvent*)theEvent
324{
325    unsigned int flags = [theEvent modifierFlags];
326   
327    if (flags == _cachedModifierFlags)
328        return;
329   
330    const unsigned int masks[] = {
331        NSShiftKeyMask,
332        NSControlKeyMask,
333        NSAlternateKeyMask,
334        NSCommandKeyMask,
335        NSAlphaShiftKeyMask
336    };
337   
338    const unsigned int keys[] = {
339        osgGA::GUIEventAdapter::KEY_Shift_L,
340        osgGA::GUIEventAdapter::KEY_Control_L,
341        osgGA::GUIEventAdapter::KEY_Alt_L,
342        osgGA::GUIEventAdapter::KEY_Super_L,
343        osgGA::GUIEventAdapter::KEY_Caps_Lock
344    };
345   
346    for(unsigned int i = 0; i < 5; ++i) {
347       
348        if ((flags & masks[i]) && !(_cachedModifierFlags & masks[i]))
349        {
350            _win->getEventQueue()->keyPress(keys[i]);
351        }
352       
353        if (!(flags & masks[i]) && (_cachedModifierFlags & masks[i]))
354        {
355            _win->getEventQueue()->keyRelease(keys[i]);
356        }
357    }
358   
359    _cachedModifierFlags = flags;
360   
361}
362
363- (void)flagsChanged:(NSEvent *)theEvent {
364        [self handleModifiers: theEvent];
365}
366
367- (void) mouseMoved:(NSEvent*)theEvent 
368{
369    NSPoint converted_point = [self getLocalPoint: theEvent];
370    _win->getEventQueue()->mouseMotion(converted_point.x, converted_point.y);
371}
372
373
374
375- (void) mouseDown:(NSEvent*)theEvent
376{
377    // Because many Mac users have only a 1-button mouse, we should provide ways
378    // to access the button 2 and 3 actions of osgViewer.
379    // I will use the Ctrl modifer to represent right-clicking
380    // and Option modifier to represent middle clicking.
381    if([theEvent modifierFlags] & NSControlKeyMask)
382    {
383        [self setIsUsingCtrlClick:YES];
384        [self doRightMouseButtonDown:theEvent];
385    }
386    else if([theEvent modifierFlags] & NSAlternateKeyMask)
387    {
388        [self setIsUsingOptionClick:YES];
389        [self doMiddleMouseButtonDown:theEvent];
390    }
391    else
392    {
393        [self doLeftMouseButtonDown:theEvent];
394    }
395       
396        if ([theEvent subtype] == NSTabletPointEventSubtype) {
397                _handleTabletEvents = true;
398                [self handleTabletEvents:theEvent];
399        }
400}
401
402
403- (void) mouseDragged:(NSEvent*)theEvent
404{
405    NSPoint converted_point = [self getLocalPoint: theEvent];   
406    _win->getEventQueue()->mouseMotion(converted_point.x, converted_point.y);
407       
408        if (_handleTabletEvents)
409                [self handleTabletEvents:theEvent];
410}
411
412
413- (void) mouseUp:(NSEvent*)theEvent
414{
415    // Because many Mac users have only a 1-button mouse, we should provide ways
416    // to access the button 2 and 3 actions of osgViewer.
417    // I will use the Ctrl modifer to represent right-clicking
418    // and Option modifier to represent middle clicking.
419    if([self isUsingCtrlClick] == YES)
420    {
421        [self setIsUsingCtrlClick:NO];
422        [self doRightMouseButtonUp:theEvent];
423    }
424    else if([self isUsingOptionClick] == YES)
425    {
426        [self setIsUsingOptionClick:NO];
427        [self doMiddleMouseButtonUp:theEvent];
428    }
429    else
430    {
431        [self doLeftMouseButtonUp:theEvent];
432    }
433        _handleTabletEvents = false;
434}
435
436- (void) rightMouseDown:(NSEvent*)theEvent
437{
438    [self doRightMouseButtonDown:theEvent];
439}
440
441- (void) rightMouseDragged:(NSEvent*)theEvent
442{
443   
444    NSPoint converted_point = [self getLocalPoint: theEvent];
445    _win->getEventQueue()->mouseMotion(converted_point.x, converted_point.y);
446}
447
448- (void) rightMouseUp:(NSEvent*)theEvent
449{
450    [self doRightMouseButtonUp:theEvent];
451        _handleTabletEvents = false;
452}
453
454// "otherMouse" seems to capture middle button and any other buttons beyond (4th, etc).
455- (void) otherMouseDown:(NSEvent*)theEvent
456{
457    // Button 0 is left
458    // Button 1 is right
459    // Button 2 is middle
460    // Button 3 keeps going
461    // osgViewer expects 1 for left, 3 for right, 2 for middle
462    // osgViewer has a reversed number mapping for right and middle compared to Cocoa
463    if([theEvent buttonNumber] == 2)
464    {
465        [self doMiddleMouseButtonDown:theEvent];
466    }
467    else // buttonNumber should be 3,4,5,etc; must map to 4,5,6,etc in osgViewer
468    {
469        [self doExtraMouseButtonDown:theEvent buttonNumber:[theEvent buttonNumber]];
470    }
471}
472
473- (void) otherMouseDragged:(NSEvent*)theEvent
474{
475    NSPoint converted_point = [self getLocalPoint: theEvent];   
476    _win->getEventQueue()->mouseMotion(converted_point.x, converted_point.y);
477   
478}
479
480// "otherMouse" seems to capture middle button and any other buttons beyond (4th, etc).
481- (void) otherMouseUp:(NSEvent*)theEvent
482{
483   
484    // Button 0 is left
485    // Button 1 is right
486    // Button 2 is middle
487    // Button 3 keeps going
488    // osgViewer expects 1 for left, 3 for right, 2 for middle
489    // osgViewer has a reversed number mapping for right and middle compared to Cocoa
490    if([theEvent buttonNumber] == 2)
491    {
492        [self doMiddleMouseButtonUp:theEvent];
493    }
494    else // buttonNumber should be 3,4,5,etc; must map to 4,5,6,etc in osgViewer
495    {
496        // I don't think osgViewer does anything for these additional buttons,
497        // but just in case, pass them along. But as a Cocoa programmer, you might
498        // think about things you can do natively here instead of passing the buck.
499        [self doExtraMouseButtonUp:theEvent buttonNumber:[theEvent buttonNumber]];
500    }
501}
502
503- (void) setIsUsingCtrlClick:(BOOL)is_using_ctrl_click
504{
505    _isUsingCtrlClick = is_using_ctrl_click;
506}
507
508- (BOOL) isUsingCtrlClick
509{
510    return _isUsingCtrlClick;
511}
512
513- (void) setIsUsingOptionClick:(BOOL)is_using_option_click
514{
515    _isUsingOptionClick = is_using_option_click;
516}
517
518- (BOOL) isUsingOptionClick
519{
520    return _isUsingOptionClick;
521}
522
523
524- (void) doLeftMouseButtonDown:(NSEvent*)theEvent
525{
526    NSPoint converted_point = [self getLocalPoint: theEvent];
527   
528    if([theEvent clickCount] == 1)
529    {
530        _win->getEventQueue()->mouseButtonPress(converted_point.x, converted_point.y, 1);
531    }
532    else
533    {
534        _win->getEventQueue()->mouseDoubleButtonPress(converted_point.x, converted_point.y, 1);
535    }
536}
537
538- (void) doLeftMouseButtonUp:(NSEvent*)theEvent
539{
540    NSPoint converted_point = [self getLocalPoint: theEvent];
541   
542    _win->getEventQueue()->mouseButtonRelease(converted_point.x, converted_point.y, 1);
543
544}
545
546- (void) doRightMouseButtonDown:(NSEvent*)theEvent
547{
548    NSPoint converted_point = [self getLocalPoint: theEvent];
549    if([theEvent clickCount] == 1)
550    {
551        _win->getEventQueue()->mouseButtonPress(converted_point.x, converted_point.y, 3);
552    }
553    else
554    {
555        _win->getEventQueue()->mouseDoubleButtonPress(converted_point.x, converted_point.y, 3);
556    }
557
558}
559
560
561- (void) doRightMouseButtonUp:(NSEvent*)theEvent
562{
563    NSPoint converted_point = [self getLocalPoint: theEvent];   
564    _win->getEventQueue()->mouseButtonRelease(converted_point.x, converted_point.y, 3);
565}
566
567- (void) doMiddleMouseButtonDown:(NSEvent*)theEvent
568{
569    NSPoint converted_point = [self getLocalPoint: theEvent];
570   
571    if([theEvent clickCount] == 1)
572    {
573        _win->getEventQueue()->mouseButtonPress(converted_point.x, converted_point.y, 2);
574    }
575    else
576    {
577        _win->getEventQueue()->mouseDoubleButtonPress(converted_point.x, converted_point.y, 2);
578    }
579}
580
581- (void) doExtraMouseButtonDown:(NSEvent*)theEvent buttonNumber:(int)button_number
582{
583    NSPoint converted_point = [self getLocalPoint: theEvent];
584    if([theEvent clickCount] == 1)
585    {
586        _win->getEventQueue()->mouseButtonPress(converted_point.x, converted_point.y, button_number+1);
587    }
588    else
589    {
590        _win->getEventQueue()->mouseDoubleButtonPress(converted_point.x, converted_point.y, button_number+1);
591    }
592}
593
594
595- (void) doMiddleMouseButtonUp:(NSEvent*)theEvent
596{
597    NSPoint converted_point = [self getLocalPoint: theEvent];
598    _win->getEventQueue()->mouseButtonRelease(converted_point.x, converted_point.y, 2);
599
600}
601
602- (void) doExtraMouseButtonUp:(NSEvent*)theEvent buttonNumber:(int)button_number
603{
604    NSPoint converted_point = [self getLocalPoint: theEvent];
605    _win->getEventQueue()->mouseButtonRelease(converted_point.x, converted_point.y, button_number+1);
606}
607
608
609
610- (void) scrollWheel:(NSEvent*)theEvent
611{
612    // Unfortunately, it turns out mouseScroll2D doesn't actually do anything.
613    // The camera manipulators don't seem to implement any code that utilize the scroll values.
614    // This this call does nothing.
615    _win->getEventQueue()->mouseScroll2D([theEvent deltaX], [theEvent deltaY]);
616}
617
618
619
620- (void)keyDown:(NSEvent *)theEvent 
621{
622    NSString* chars = [theEvent charactersIgnoringModifiers];
623    unsigned int keyCode = remapCocoaKey([chars characterAtIndex:0], ([theEvent modifierFlags] & NSFunctionKeyMask) );
624    // std::cout << "key dn: " <<[chars characterAtIndex:0] << "=" << keyCode << std::endl;   
625    _win->getEventQueue()->keyPress( remapCocoaKey(keyCode), [theEvent timestamp]);
626}
627
628
629- (void)keyUp:(NSEvent *)theEvent 
630{   
631    NSString* chars = [theEvent charactersIgnoringModifiers];
632    unsigned int keyCode = remapCocoaKey([chars characterAtIndex:0], ([theEvent modifierFlags] & NSFunctionKeyMask));
633    // std::cout << "key up: " <<[chars characterAtIndex:0] << "=" << keyCode << std::endl;   
634    _win->getEventQueue()->keyRelease( remapCocoaKey(keyCode), [theEvent timestamp]);
635}
636
637
638- (void)tabletPoint:(NSEvent *)theEvent
639{
640        //_handleTabletEvents = YES;
641        //[self handleTabletEvents:theEvent];
642}
643
644-(void)handleTabletEvents:(NSEvent *)theEvent
645{
646        float pressure = [theEvent pressure];
647        _win->getEventQueue()->penPressure(pressure);
648        NSPoint tilt = [theEvent tilt];
649       
650        _win->getEventQueue()->penOrientation (tilt.x, tilt.y, [theEvent rotation]);
651}
652
653
654- (void)tabletProximity:(NSEvent *)theEvent
655{
656        osgGA::GUIEventAdapter::TabletPointerType pt(osgGA::GUIEventAdapter::UNKNOWN);
657        switch ([theEvent pointingDeviceType]) {
658                case NSPenPointingDevice:
659                        pt = osgGA::GUIEventAdapter::PEN;
660                        break;
661                case NSCursorPointingDevice:
662                        pt = osgGA::GUIEventAdapter::PUCK;
663                        break;
664                case NSEraserPointingDevice:
665                        pt = osgGA::GUIEventAdapter::ERASER;
666                        break;
667                default:
668                        break;
669        }
670        _win->getEventQueue()->penProximity(pt, [theEvent isEnteringProximity]);
671}
672
673
674@end
675
676
677#pragma mark GraphicsWindowCocoaDelegate
678
679
680// ----------------------------------------------------------------------------------------------------------
681// the window-delegate, handles moving/resizing of the window etc.
682// ----------------------------------------------------------------------------------------------------------
683
684@interface GraphicsWindowCocoaDelegate : NSObject
685{
686    @private
687        osgViewer::GraphicsWindowCocoa* _win;
688        BOOL                            _inDidMove;
689}
690
691- (id)initWith: (osgViewer::GraphicsWindowCocoa*) win;
692- (void)windowDidMove:(NSNotification *)notification;
693- (void)windowDidResize:(NSNotification *)notification;
694- (BOOL)windowShouldClose:(id)window;
695- (void)updateWindowBounds;
696
697@end
698
699
700@implementation GraphicsWindowCocoaDelegate
701
702- (id)initWith: (osgViewer::GraphicsWindowCocoa*) win
703{
704    _inDidMove = false;
705    _win = win;
706    return [super init];
707}
708
709
710- (void)windowDidMove:(NSNotification *)notification
711{
712    [self updateWindowBounds];
713}
714
715- (void)windowDidResize:(NSNotification *)notification
716{
717    [self updateWindowBounds];
718}
719
720-(void)updateWindowBounds
721{
722    if (_inDidMove) return;
723    _inDidMove = true;
724   
725    GraphicsWindowCocoaWindow* nswin = _win->getWindow();
726    NSRect bounds = [nswin contentRectForFrameRect: [nswin frame] ];
727   
728    // convert to quartz-coordinate-system
729    bounds = convertToQuartzCoordinates(bounds);
730   
731    // std::cout << "windowdidmove: " << bounds.origin.x << " " << bounds.origin.y << " " << bounds.size.width << " " << bounds.size.height << std::endl;
732   
733    _win->adaptResize(bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height);
734    //_win->getEventQueue()->windowResize(bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height, _win->getEventQueue()->getTime());
735    _win->requestRedraw();
736    _inDidMove = false;
737}
738
739- (BOOL)windowShouldClose:(id)window 
740{
741    return _win->requestClose();
742}
743
744@end
745
746
747#pragma mark CocoaWindowAdapter
748
749
750
751using namespace osgDarwin;
752namespace osgViewer {
753
754
755// ----------------------------------------------------------------------------------------------------------
756// small adapter class to handle the dock/menubar
757// ----------------------------------------------------------------------------------------------------------
758
759class CocoaWindowAdapter : public MenubarController::WindowAdapter {
760public:
761    CocoaWindowAdapter(GraphicsWindowCocoa* win) : MenubarController::WindowAdapter(), _win(win) {}
762   
763    virtual bool valid() { return (_win.valid() && _win->valid()); }
764       
765    virtual void getWindowBounds(CGRect& rect)
766    {
767        NSRect nsrect = [_win->getWindow() frame];
768        nsrect = convertToQuartzCoordinates(nsrect);
769       
770        rect.origin.x = nsrect.origin.x;
771        rect.origin.y = nsrect.origin.y;
772        rect.size.width = nsrect.size.width;
773        rect.size.height = nsrect.size.height;
774    }
775       
776    virtual osgViewer::GraphicsWindow* getWindow() {return _win.get(); }
777private:
778    osg::observer_ptr<GraphicsWindowCocoa> _win;
779};
780
781#pragma mark GraphicsWindowCocoa
782
783
784
785// ----------------------------------------------------------------------------------------------------------
786// init
787// ----------------------------------------------------------------------------------------------------------
788
789void GraphicsWindowCocoa::init()
790{
791    if (_initialized) return;
792
793    _closeRequested = false;
794    _ownsWindow = false;
795    _context = NULL;
796    _window = NULL;
797    _valid = _initialized = true;
798}
799
800
801// ----------------------------------------------------------------------------------------------------------
802// setupNSWindow
803// sets up the NSWindow, adds delegates, etc
804// ----------------------------------------------------------------------------------------------------------
805
806void GraphicsWindowCocoa::setupNSWindow(NSWindow* win)
807{
808
809    [win setReleasedWhenClosed:NO];
810        [win setDisplaysWhenScreenProfileChanges:YES]; 
811    GraphicsWindowCocoaDelegate* delegate = [[GraphicsWindowCocoaDelegate alloc] initWith: this];
812    [win setDelegate: delegate ];
813    //[delegate autorelease];
814           
815    [win makeKeyAndOrderFront:nil];
816    [win setAcceptsMouseMovedEvents: YES];
817
818}
819
820
821// ----------------------------------------------------------------------------------------------------------
822// realizeImplementation, creates the window + context
823// ----------------------------------------------------------------------------------------------------------
824
825bool GraphicsWindowCocoa::realizeImplementation()
826{
827    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
828   
829    unsigned int style(NSBorderlessWindowMask);
830   
831    if (_traits->windowDecoration) {
832        style = NSClosableWindowMask | NSMiniaturizableWindowMask | NSTitledWindowMask;
833       
834        // supportsResize works only with windows with titlebar
835        if (_traits->supportsResize)
836            style |= NSResizableWindowMask;
837    }
838       
839    DarwinWindowingSystemInterface* wsi = dynamic_cast<DarwinWindowingSystemInterface*>(osg::GraphicsContext::getWindowingSystemInterface());
840    int screenLeft(0), screenTop(0);
841    if (wsi) {
842        wsi->getScreenTopLeft((*_traits), screenLeft, screenTop);
843    }
844   
845        NSRect rect = NSMakeRect(_traits->x + screenLeft, _traits->y + screenTop, _traits->width, _traits->height);
846   
847        _window = [[GraphicsWindowCocoaWindow alloc] initWithContentRect: rect styleMask: style backing: NSBackingStoreBuffered defer: NO];
848       
849    if (!_window) {
850        osg::notify(osg::WARN) << "GraphicsWindowCocoa::realizeImplementation :: could not create window" << std::endl;
851        return false;
852    }
853   
854    rect = convertFromQuartzCoordinates(rect);
855    [_window setFrameOrigin: rect.origin];
856         
857        NSOpenGLPixelFormatAttribute attr[32];
858    int i = 0;
859   
860    attr[i++] = NSOpenGLPFADepthSize;
861    attr[i++] = static_cast<NSOpenGLPixelFormatAttribute>(_traits->depth);
862
863    if (_traits->doubleBuffer) {
864        attr[i++] = NSOpenGLPFADoubleBuffer;
865    }
866   
867    if (_traits->alpha) {
868        attr[i++] = NSOpenGLPFAAlphaSize;
869        attr[i++] = static_cast<NSOpenGLPixelFormatAttribute>(_traits->alpha);
870    }
871
872    if (_traits->stencil) {
873        attr[i++] = NSOpenGLPFAStencilSize;
874        attr[i++] = static_cast<NSOpenGLPixelFormatAttribute>(_traits->stencil);
875    }
876 
877
878    if (_traits->sampleBuffers) {
879        attr[i++] = NSOpenGLPFASampleBuffers;
880        attr[i++] = static_cast<NSOpenGLPixelFormatAttribute>(_traits->sampleBuffers);
881        attr[i++] = NSOpenGLPFASamples;
882        attr[i++] = static_cast<NSOpenGLPixelFormatAttribute>(_traits->samples);
883    }
884
885   
886    attr[i++] = NSOpenGLPFAAccelerated;
887    attr[i] = static_cast<NSOpenGLPixelFormatAttribute>(0);
888   
889    // create the context
890    NSOpenGLContext* sharedContext = NULL;
891   
892    GraphicsWindowCocoa* graphicsWindowCocoa = dynamic_cast<GraphicsWindowCocoa*>(_traits->sharedContext);
893    if (graphicsWindowCocoa)
894    {
895        sharedContext = graphicsWindowCocoa->getContext();
896    }
897    else
898    {
899        PixelBufferCocoa* pixelbuffer = dynamic_cast<PixelBufferCocoa*>(_traits->sharedContext);
900        if (pixelbuffer) {
901            sharedContext = pixelbuffer->getContext();
902        }
903    }
904       
905        NSOpenGLPixelFormat* pixelformat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr ];
906    _context = [[NSOpenGLContext alloc] initWithFormat: pixelformat shareContext: sharedContext];
907   
908    if (!_context) {
909        osg::notify(osg::WARN) << "GraphicsWindowCocoa::realizeImplementation :: could not create context" << std::endl;
910        return false;
911    }
912        GraphicsWindowCocoaGLView* theView = [[ GraphicsWindowCocoaGLView alloc ] initWithFrame:[ _window frame ] ];
913    [theView setAutoresizingMask:  (NSViewWidthSizable | NSViewHeightSizable) ];
914    [theView setGraphicsWindowCocoa: this];
915    [theView setOpenGLContext:_context];
916        [_window setContentView: theView];
917       
918    setupNSWindow(_window);
919   
920    [theView release];
921    [pool release];
922       
923    MenubarController::instance()->attachWindow( new CocoaWindowAdapter(this) );
924   
925    useCursor(_traits->useCursor);
926    setWindowName(_traits->windowName);
927    setVSync(_traits->vsync);
928   
929    MenubarController::instance()->update();
930   
931    // Cocoa's origin is bottom/left:
932    getEventQueue()->getCurrentEventState()->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
933   
934    _valid = _initialized = _realized = true;
935    return _valid;
936}
937
938
939
940
941// ----------------------------------------------------------------------------------------------------------
942// closeImplementation
943// ----------------------------------------------------------------------------------------------------------
944void GraphicsWindowCocoa::closeImplementation()
945{
946    _valid = false;
947    _realized = false;
948   
949    // there's a possibility that the MenubarController is destructed already, so prevent a crash:
950    MenubarController* mbc = MenubarController::instance();
951    if (mbc) mbc->detachWindow(this);
952   
953        [_window close];
954    [_window release];
955}
956
957
958// ----------------------------------------------------------------------------------------------------------
959// makeCurrentImplementation
960// ----------------------------------------------------------------------------------------------------------
961
962bool GraphicsWindowCocoa:: makeCurrentImplementation()
963{
964        [_context makeCurrentContext];
965        return true;
966}
967
968
969// ----------------------------------------------------------------------------------------------------------
970// releaseContextImplementation
971// ----------------------------------------------------------------------------------------------------------
972
973bool GraphicsWindowCocoa::releaseContextImplementation()
974{
975        [NSOpenGLContext clearCurrentContext];
976        return true;
977}
978
979
980// ----------------------------------------------------------------------------------------------------------
981// swapBuffersImplementation
982// ----------------------------------------------------------------------------------------------------------
983
984void GraphicsWindowCocoa::swapBuffersImplementation()
985{
986        [_context flushBuffer];
987}
988
989
990// ----------------------------------------------------------------------------------------------------------
991// checkEvents
992// process all pending events
993// ----------------------------------------------------------------------------------------------------------
994void GraphicsWindowCocoa::checkEvents()
995{
996        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
997   
998    while(1)
999    {
1000        /*  NOTE: It may be better to use something like
1001            NSEventTrackingRunLoopMode since we don't necessarily want all
1002            timers/sources/observers to run, only those which would
1003            run while tracking events.  However, it should be noted that
1004            NSEventTrackingRunLoopMode is in the common set of modes
1005            so it may not effectively make much of a difference.
1006         */
1007        NSEvent *event = [ [NSApplication sharedApplication]
1008                nextEventMatchingMask:NSAnyEventMask
1009                untilDate:[NSDate distantPast]
1010                inMode:NSDefaultRunLoopMode
1011                dequeue: YES];
1012        if(!event)
1013            break;
1014        [[NSApplication sharedApplication] sendEvent: event];
1015    }   
1016   
1017    if (_closeRequested)
1018        getEventQueue()->closeWindow();
1019       
1020    if (s_quit_requested) {
1021        getEventQueue()->quitApplication();
1022        s_quit_requested = false;
1023    }
1024       
1025        [pool release];
1026}
1027
1028
1029
1030// ----------------------------------------------------------------------------------------------------------
1031// setWindowDecorationImplementation
1032//
1033// unfortunately there's no way to change the decoration of a window, so we create an new one
1034// and swap the content
1035// ----------------------------------------------------------------------------------------------------------
1036
1037bool GraphicsWindowCocoa::setWindowDecorationImplementation(bool flag)
1038{
1039    if (!_realized) return false;
1040       
1041    unsigned int style(NSBorderlessWindowMask);
1042   
1043    if (flag) {
1044        style = NSClosableWindowMask | NSMiniaturizableWindowMask | NSTitledWindowMask;
1045       
1046        // supportsResize works only with windows with titlebar
1047        if (_traits->supportsResize)
1048            style |= NSResizableWindowMask;
1049    }
1050        NSRect rect = [_window contentRectForFrameRect: [_window frame] ];
1051        GraphicsWindowCocoaWindow* new_win = [[GraphicsWindowCocoaWindow alloc] initWithContentRect: rect styleMask: style backing: NSBackingStoreBuffered defer: NO];
1052   
1053    if (new_win) {
1054        [new_win setContentView: [_window contentView]];
1055        setupNSWindow(new_win);
1056        [new_win setTitle: [_window title]];
1057        [_window close];
1058        [_window release];
1059
1060        _window = new_win;
1061        [_window makeKeyAndOrderFront: nil];
1062    }
1063   
1064        return true;
1065}
1066
1067
1068// ----------------------------------------------------------------------------------------------------------
1069// grabFocus
1070// ----------------------------------------------------------------------------------------------------------
1071void GraphicsWindowCocoa::grabFocus()
1072{
1073        [_window makeKeyAndOrderFront: nil];
1074}
1075
1076
1077// ----------------------------------------------------------------------------------------------------------
1078// grabFocusIfPointerInWindow
1079// ----------------------------------------------------------------------------------------------------------
1080void GraphicsWindowCocoa::grabFocusIfPointerInWindow()
1081{
1082        osg::notify(osg::INFO) << "GraphicsWindowCocoa :: grabFocusIfPointerInWindow not implemented yet " << std::endl;
1083}
1084
1085
1086// ----------------------------------------------------------------------------------------------------------
1087// resizedImplementation
1088// ----------------------------------------------------------------------------------------------------------
1089
1090void GraphicsWindowCocoa::resizedImplementation(int x, int y, int width, int height)
1091{
1092        std::cout << "resized implementation" << x << " " << y << " " << width << " " << height << std::endl;
1093        GraphicsContext::resizedImplementation(x, y, width, height);
1094   
1095    [_context update];
1096    MenubarController::instance()->update();
1097        getEventQueue()->windowResize(x,y,width, height, getEventQueue()->getTime());
1098}
1099
1100
1101
1102
1103// ----------------------------------------------------------------------------------------------------------
1104// setWindowRectangleImplementation
1105// ----------------------------------------------------------------------------------------------------------
1106bool GraphicsWindowCocoa::setWindowRectangleImplementation(int x, int y, int width, int height)
1107{
1108        DarwinWindowingSystemInterface* wsi = dynamic_cast<DarwinWindowingSystemInterface*>(osg::GraphicsContext::getWindowingSystemInterface());
1109    int screenLeft(0), screenTop(0);
1110    if (wsi) {
1111        wsi->getScreenTopLeft((*_traits), screenLeft, screenTop);
1112    }
1113
1114
1115    NSRect rect = NSMakeRect(x+screenLeft,y+screenTop,width, height);
1116    rect = convertFromQuartzCoordinates(rect);
1117   
1118    [_window setFrame: [NSWindow frameRectForContentRect: rect styleMask: [_window styleMask]] display: YES];
1119    [_context update];
1120    MenubarController::instance()->update();
1121   
1122    return true;
1123}
1124
1125
1126// ----------------------------------------------------------------------------------------------------------
1127//
1128// ----------------------------------------------------------------------------------------------------------
1129
1130void GraphicsWindowCocoa::adaptResize(int x, int y, int w, int h)
1131{
1132
1133        DarwinWindowingSystemInterface* wsi = dynamic_cast<DarwinWindowingSystemInterface*>(osg::GraphicsContext::getWindowingSystemInterface());
1134    int screenLeft(0), screenTop(0);
1135    if (wsi) {
1136               
1137                // get the screen containing the window
1138                unsigned int screenNdx = wsi->getScreenContaining(x,y,w,h);
1139               
1140                // update traits
1141                _traits->screenNum = screenNdx;
1142               
1143                // get top left of screen
1144        wsi->getScreenTopLeft((*_traits), screenLeft, screenTop);
1145    }
1146       
1147        resized(x-screenLeft,y-screenTop,w,h);
1148}
1149
1150
1151// ----------------------------------------------------------------------------------------------------------
1152// setWindowName
1153// ----------------------------------------------------------------------------------------------------------
1154
1155void GraphicsWindowCocoa::setWindowName (const std::string & name)
1156{
1157        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1158   
1159    NSString* title = [NSString stringWithCString: name.c_str() encoding: NSUTF8StringEncoding];
1160        [_window setTitle: title];
1161        [title release];
1162    [pool release];
1163}
1164
1165
1166// ----------------------------------------------------------------------------------------------------------
1167// useCursor
1168// ----------------------------------------------------------------------------------------------------------
1169
1170void GraphicsWindowCocoa::useCursor(bool cursorOn)
1171{
1172        if (_traits.valid())
1173        _traits->useCursor = cursorOn;
1174    DarwinWindowingSystemInterface* wsi = dynamic_cast<DarwinWindowingSystemInterface*>(osg::GraphicsContext::getWindowingSystemInterface());
1175    if (wsi == NULL) {
1176        osg::notify(osg::WARN) << "GraphicsWindowCarbon::useCursor :: could not get OSXCarbonWindowingSystemInterface" << std::endl;
1177        return;
1178    }
1179   
1180    CGDirectDisplayID displayId = wsi->getDisplayID((*_traits));
1181    CGDisplayErr err = kCGErrorSuccess;
1182    switch (cursorOn)
1183    {
1184        case true:
1185            err = CGDisplayShowCursor(displayId);
1186            break;
1187        case false:
1188            err = CGDisplayHideCursor(displayId);
1189            break;
1190    }
1191    if (err != kCGErrorSuccess) {
1192        osg::notify(osg::WARN) << "GraphicsWindowCocoa::useCursor failed with " << err << std::endl;
1193    }
1194}
1195
1196
1197// ----------------------------------------------------------------------------------------------------------
1198// setCursor
1199// ----------------------------------------------------------------------------------------------------------
1200
1201void GraphicsWindowCocoa::setCursor(MouseCursor mouseCursor)
1202{
1203        switch (mouseCursor)
1204    {
1205
1206        case NoCursor:
1207            [NSCursor hide];
1208            break;
1209   
1210        case LeftArrowCursor:
1211            [[NSCursor arrowCursor] set];
1212            break;
1213       
1214        case TextCursor:
1215            [[NSCursor IBeamCursor] set];
1216            break;
1217           
1218        case CrosshairCursor:
1219            [[NSCursor crosshairCursor] set];
1220            break;
1221       
1222        default:
1223            osg::notify(osg::INFO) << "GraphicsWindowCocoa::setCursor :: unsupported MouseCursor: " << mouseCursor << std::endl;   
1224    }
1225}
1226
1227
1228// ----------------------------------------------------------------------------------------------------------
1229// setVSync
1230// ----------------------------------------------------------------------------------------------------------
1231
1232void GraphicsWindowCocoa::setVSync(bool f)
1233{
1234    GLint VBL(f?1:0);
1235        [_context setValues:&VBL forParameter:NSOpenGLCPSwapInterval];
1236}
1237
1238
1239// ----------------------------------------------------------------------------------------------------------
1240// d'tor
1241// ----------------------------------------------------------------------------------------------------------
1242
1243GraphicsWindowCocoa::~GraphicsWindowCocoa()
1244{
1245}
1246
1247
1248
1249#pragma mark CocoaWindowingSystemInterface
1250
1251// ----------------------------------------------------------------------------------------------------------
1252// CocoaWindowingSystemInterface
1253// ----------------------------------------------------------------------------------------------------------
1254
1255struct CocoaWindowingSystemInterface : public DarwinWindowingSystemInterface {
1256       
1257        CocoaWindowingSystemInterface()
1258        :       DarwinWindowingSystemInterface()
1259        {
1260                localPool = [[NSAutoreleasePool alloc] init];
1261        [[NSApplication sharedApplication] setDelegate: [[CocoaAppDelegate alloc] init] ];
1262        }
1263       
1264        virtual osg::GraphicsContext* createGraphicsContext(osg::GraphicsContext::Traits* traits)
1265        {
1266                return createGraphicsContextImplementation<PixelBufferCocoa, GraphicsWindowCocoa>(traits);
1267        }
1268       
1269        virtual ~CocoaWindowingSystemInterface()
1270        {
1271                [localPool release];
1272        }
1273       
1274        NSAutoreleasePool *localPool;
1275
1276};
1277
1278
1279}
1280
1281#ifdef USE_DARWIN_COCOA_IMPLEMENTATION
1282RegisterWindowingSystemInterfaceProxy<osgViewer::CocoaWindowingSystemInterface> createWindowingSystemInterfaceProxy;
1283#endif
1284
1285// declare C entry point for static compilation.
1286extern "C" void graphicswindow_Cocoa(void)
1287{
1288    osg::GraphicsContext::setWindowingSystemInterface(new osgViewer::CocoaWindowingSystemInterface());
1289}
Note: See TracBrowser for help on using the browser.