From Stephan Huber, "here are some small fixes/enahncements for the cocoa backend to allow
proper functioning when running the osgViewer run-loop in a secondary thread (e.g. when embedding GraphicsWindowCocoa-windows in a full blown cocoa application). OS X is picky when you want to change the user-interface from another thread than the main thread, not all UI stuff is thread-safe. So now window closes and showing / hiding the menu bar is done in the main thread via Cocoa's performSelectorOnMainThread-mechanism. These changes don't affect the normal osgViewer usage pattern."
This commit is contained in:
@@ -12,6 +12,39 @@
|
||||
#include "DarwinUtils.h"
|
||||
#include <Cocoa/Cocoa.h>
|
||||
|
||||
@interface MenubarToggler : NSObject {
|
||||
|
||||
}
|
||||
|
||||
-(void) show: (ID) data;
|
||||
-(void) hide: (ID) data;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MenubarToggler
|
||||
|
||||
|
||||
|
||||
-(void) hide:(ID) data
|
||||
{
|
||||
OSErr error = SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar);
|
||||
if (error) {
|
||||
osg::notify(osg::DEBUG_INFO) << "MenubarToggler::hide failed with " << error << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-(void) show:(ID) data
|
||||
{
|
||||
OSErr error = SetSystemUIMode(kUIModeNormal, 0);
|
||||
if (error) {
|
||||
osg::notify(osg::DEBUG_INFO) << "MenubarToggler::show failed with " << error << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
namespace osgDarwin {
|
||||
|
||||
|
||||
@@ -83,9 +116,9 @@ void MenubarController::detachWindow(osgViewer::GraphicsWindow* win)
|
||||
|
||||
// iterate through all open windows and check, if they intersect the area occupied by the menubar/dock, and if so, hide the menubar/dock
|
||||
|
||||
|
||||
void MenubarController::update()
|
||||
{
|
||||
OSErr error(noErr);
|
||||
unsigned int windowsCoveringMenubarArea = 0;
|
||||
unsigned int windowsIntersectingMainScreen = 0;
|
||||
for(WindowList::iterator i = _list.begin(); i != _list.end(); ) {
|
||||
@@ -115,16 +148,47 @@ void MenubarController::update()
|
||||
i= _list.erase(i);
|
||||
}
|
||||
|
||||
// see http://developer.apple.com/technotes/tn2002/tn2062.html for hiding the dock+menubar
|
||||
// if we use the cocoa implementation then we have a NSRunLoop in place, and so we can use the deferred menubar-toggling which is thread safe
|
||||
|
||||
#ifdef USE_DARWIN_COCOA_IMPLEMENTATION
|
||||
|
||||
// SetSystemUIMode is not threadsafe, you'll get crashes if you call this method from other threads
|
||||
// so use a small NSObject to switch the menubar on the main thread via performSelectorOnMainThread
|
||||
|
||||
if (windowsCoveringMenubarArea && _menubarShown)
|
||||
error = SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar);
|
||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
if (windowsCoveringMenubarArea && _menubarShown)
|
||||
{
|
||||
|
||||
//error = SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar);
|
||||
MenubarToggler* toggler = [[MenubarToggler alloc] init];
|
||||
[toggler performSelectorOnMainThread: @selector(hide:) withObject:NULL waitUntilDone: YES];
|
||||
[toggler autorelease];
|
||||
}
|
||||
if (!windowsCoveringMenubarArea && !_menubarShown)
|
||||
{
|
||||
//error = SetSystemUIMode(kUIModeNormal, 0);
|
||||
MenubarToggler* toggler = [[MenubarToggler alloc] init];
|
||||
[toggler performSelectorOnMainThread: @selector(show:) withObject:NULL waitUntilDone: YES];
|
||||
[toggler autorelease];
|
||||
}
|
||||
[pool release];
|
||||
|
||||
if (!windowsCoveringMenubarArea && !_menubarShown)
|
||||
error = SetSystemUIMode(kUIModeNormal, 0);
|
||||
_menubarShown = !windowsCoveringMenubarArea;
|
||||
#else
|
||||
|
||||
// osg::notify(osg::DEBUG_INFO) << "MenubarController:: " << windowsCoveringMenubarArea << " windows covering the menubar/dock area, " << windowsIntersectingMainScreen << " intersecting mainscreen" << std::endl;
|
||||
OSErr error;
|
||||
|
||||
// see http://developer.apple.com/technotes/tn2002/tn2062.html for hiding the dock+menubar
|
||||
if (windowsCoveringMenubarArea && _menubarShown)
|
||||
{
|
||||
error = SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = SetSystemUIMode(kUIModeNormal, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
_menubarShown = !windowsCoveringMenubarArea;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
|
||||
#include "DarwinUtils.h"
|
||||
|
||||
//#define DEBUG_OUT(s) std::cout << "GraphicsWindowCocoa :: " << s << std::endl;
|
||||
#define DEBUG_OUT(s) std::cout << "GraphicsWindowCocoa :: " << s << std::endl;
|
||||
|
||||
#define DEBUG_OUT(s) ;
|
||||
//#define DEBUG_OUT(s) ;
|
||||
|
||||
static bool s_quit_requested = false;
|
||||
|
||||
@@ -388,8 +388,8 @@ static NSRect convertToQuartzCoordinates(const NSRect& rect)
|
||||
|
||||
- (void) mouseMoved:(NSEvent*)theEvent
|
||||
{
|
||||
DEBUG_OUT("Mouse moved");
|
||||
NSPoint converted_point = [self getLocalPoint: theEvent];
|
||||
DEBUG_OUT("Mouse moved" << converted_point.x << "/" << converted_point.y);
|
||||
_win->getEventQueue()->mouseMotion(converted_point.x, converted_point.y);
|
||||
}
|
||||
|
||||
@@ -605,6 +605,8 @@ static NSRect convertToQuartzCoordinates(const NSRect& rect)
|
||||
{
|
||||
if (!_win) return;
|
||||
|
||||
DEBUG_OUT("middleMouseDown ");
|
||||
|
||||
NSPoint converted_point = [self getLocalPoint: theEvent];
|
||||
|
||||
if([theEvent clickCount] == 1)
|
||||
@@ -621,6 +623,8 @@ static NSRect convertToQuartzCoordinates(const NSRect& rect)
|
||||
{
|
||||
if (!_win) return;
|
||||
|
||||
DEBUG_OUT("extraMouseDown btn: " << button_number);
|
||||
|
||||
NSPoint converted_point = [self getLocalPoint: theEvent];
|
||||
if([theEvent clickCount] == 1)
|
||||
{
|
||||
@@ -1036,18 +1040,22 @@ void GraphicsWindowCocoa::closeImplementation()
|
||||
MenubarController* mbc = MenubarController::instance();
|
||||
if (mbc) mbc->detachWindow(this);
|
||||
|
||||
if (_window) {
|
||||
[_window close];
|
||||
[_window release];
|
||||
}
|
||||
|
||||
if (_view) {
|
||||
[_view setGraphicsWindowCocoa: NULL];
|
||||
}
|
||||
|
||||
if (_window) {
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
// we have to close + release the window in the main-thread
|
||||
|
||||
[_window performSelectorOnMainThread: @selector(close) withObject:NULL waitUntilDone: YES];
|
||||
[_window performSelectorOnMainThread: @selector(release) withObject:NULL waitUntilDone: YES];
|
||||
[pool release];
|
||||
}
|
||||
|
||||
_window = NULL;
|
||||
_view = NULL;
|
||||
|
||||
_view = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user