02120e188e
* osgDB::FileUtils uses now the Cocoa-API to determine the paths of the application-support-folder * DarwinUtils uses now modern functions of the quartz-api to get and set screen-resolutions. Removed some of the osg-deprecated stuff. "
632 lines
20 KiB
Plaintext
632 lines
20 KiB
Plaintext
/*
|
|
* DarwinUtils.cpp
|
|
* OpenSceneGraph
|
|
*
|
|
* Created by Stephan Huber on 27.06.08.
|
|
* Copyright 2008 Stephan Maximilian Huber, digital mind. All rights reserved.
|
|
*
|
|
*/
|
|
|
|
#include <osg/Referenced>
|
|
#include <osg/DeleteHandler>
|
|
#include "DarwinUtils.h"
|
|
#include <Cocoa/Cocoa.h>
|
|
#include <limits>
|
|
|
|
@interface MenubarToggler : NSObject {
|
|
|
|
osg::ref_ptr<osg::DisplaySettings> _displaySettings;
|
|
osg::DisplaySettings::OSXMenubarBehavior _menubarBehavior;
|
|
}
|
|
|
|
-(void) show;
|
|
-(void) hide;
|
|
-(void) setDisplaySettings: (osg::DisplaySettings*) display_settings;
|
|
|
|
@end
|
|
|
|
@implementation MenubarToggler
|
|
|
|
-(id) init
|
|
{
|
|
self = [super init];
|
|
_menubarBehavior = osg::DisplaySettings::MENUBAR_AUTO_HIDE;
|
|
_displaySettings = NULL;
|
|
return self;
|
|
}
|
|
|
|
-(void) setDisplaySettings: (osg::DisplaySettings*) display_settings
|
|
{
|
|
_displaySettings = display_settings;
|
|
}
|
|
|
|
-(void) hide
|
|
{
|
|
if(_displaySettings.valid()) _menubarBehavior = _displaySettings->getOSXMenubarBehavior();
|
|
|
|
if (_menubarBehavior == osg::DisplaySettings::MENUBAR_FORCE_SHOW)
|
|
return;
|
|
|
|
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
|
|
NSApplicationPresentationOptions options;
|
|
switch(_menubarBehavior) {
|
|
case osg::DisplaySettings::MENUBAR_AUTO_HIDE:
|
|
options = NSApplicationPresentationAutoHideMenuBar | NSApplicationPresentationAutoHideDock;
|
|
break;
|
|
|
|
case osg::DisplaySettings::MENUBAR_FORCE_HIDE:
|
|
options = NSApplicationPresentationHideMenuBar | NSApplicationPresentationHideDock;
|
|
break;
|
|
|
|
default:
|
|
options = NSApplicationPresentationDefault;
|
|
|
|
}
|
|
|
|
[[NSApplication sharedApplication] setPresentationOptions: options];
|
|
#else
|
|
SystemUIMode mode = kUIModeAllHidden;
|
|
SystemUIOptions options = 0;
|
|
switch(_menubarBehavior) {
|
|
case osg::DisplaySettings::MENUBAR_AUTO_HIDE:
|
|
options = kUIOptionAutoShowMenuBar;
|
|
break;
|
|
|
|
case osg::DisplaySettings::MENUBAR_FORCE_HIDE:
|
|
break;
|
|
|
|
default:
|
|
mode = kUIModeNormal;
|
|
|
|
}
|
|
|
|
OSErr error = SetSystemUIMode(mode, options);
|
|
if (error) {
|
|
OSG_DEBUG << "MenubarToggler::hide failed with " << error << std::endl;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
-(void) show
|
|
{
|
|
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
|
|
[[NSApplication sharedApplication] setPresentationOptions: NSApplicationPresentationDefault];
|
|
#else
|
|
OSErr error = SetSystemUIMode(kUIModeNormal, 0);
|
|
if (error) {
|
|
OSG_DEBUG << "MenubarToggler::show failed with " << error << std::endl;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
@end
|
|
|
|
namespace osgDarwin {
|
|
|
|
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
|
|
size_t displayBitsPerPixelForMode(CGDisplayModeRef mode)
|
|
{
|
|
CFStringRef pixEnc = CGDisplayModeCopyPixelEncoding(mode);
|
|
if (!pixEnc)
|
|
{
|
|
OSG_WARN << "CGDisplayModeCopyPixelEncoding returned NULL" << std::endl;
|
|
CGDisplayModeRelease(mode);
|
|
return 0;
|
|
}
|
|
|
|
size_t depth = 0;
|
|
if (CFStringCompare(pixEnc, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
|
|
{
|
|
depth = 32;
|
|
}
|
|
else if (CFStringCompare(pixEnc, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
|
|
{
|
|
depth = 16;
|
|
}
|
|
else if (CFStringCompare(pixEnc, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
|
|
{
|
|
depth = 8;
|
|
}
|
|
else
|
|
{
|
|
OSG_WARN << "Unable to match pixel encoding '" << CFStringGetCStringPtr(pixEnc, kCFStringEncodingUTF8) << "'" << std::endl;
|
|
}
|
|
CFRelease(pixEnc);
|
|
|
|
return depth;
|
|
}
|
|
|
|
#endif
|
|
|
|
size_t displayBitsPerPixel( CGDirectDisplayID displayId )
|
|
{
|
|
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
|
|
return CGDisplayBitsPerPixel(displayId);
|
|
#else
|
|
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayId);
|
|
if (!mode)
|
|
{
|
|
OSG_WARN << "CGDisplayCopyDisplayMode returned NULL" << std::endl;
|
|
return 0;
|
|
}
|
|
|
|
unsigned int depth = displayBitsPerPixelForMode(mode);
|
|
CGDisplayModeRelease(mode);
|
|
|
|
return depth;
|
|
#endif
|
|
}
|
|
|
|
|
|
static bool findBestDisplayModeFor(const CGDirectDisplayID& displayid, int desired_width, int desired_height, unsigned int desired_color_depth, double desired_refresh_rate) {
|
|
|
|
CFArrayRef availableModes = CGDisplayCopyAllDisplayModes(displayid, NULL);
|
|
unsigned int numberOfAvailableModes = CFArrayGetCount(availableModes);
|
|
|
|
CGDisplayModeRef best_match(NULL);
|
|
|
|
int best_dx = std::numeric_limits<int>::max();
|
|
int best_dy = std::numeric_limits<int>::max();
|
|
|
|
|
|
for (unsigned int i=0; i<numberOfAvailableModes; ++i)
|
|
{
|
|
CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(availableModes, i);
|
|
osg::GraphicsContext::ScreenSettings tmpSR;
|
|
|
|
int w = CGDisplayModeGetWidth(mode);
|
|
int h = CGDisplayModeGetHeight(mode);
|
|
unsigned int color_depth = displayBitsPerPixelForMode(mode);
|
|
|
|
double rate = CGDisplayModeGetRefreshRate(mode);
|
|
|
|
int dx(w - desired_width);
|
|
int dy(h - desired_height);
|
|
|
|
if ((dx > 0) && (dx <= best_dx) && (dy > 0) && (dy <= best_dy) && (color_depth >= desired_color_depth) && (rate >= desired_refresh_rate)) {
|
|
best_match = mode;
|
|
best_dx = dx;
|
|
best_dy = dy;
|
|
}
|
|
}
|
|
bool result = false;
|
|
if(best_match)
|
|
{
|
|
result = CGDisplaySetDisplayMode(displayid, best_match, NULL) != kCGErrorSuccess;
|
|
}
|
|
else if (desired_refresh_rate > 0)
|
|
{
|
|
// try again with a lower refresh-rate
|
|
result = findBestDisplayModeFor(displayid, desired_width, desired_height, desired_color_depth, 0);
|
|
}
|
|
else if (desired_color_depth > 0)
|
|
{
|
|
// try again with a lower color_depth
|
|
result = findBestDisplayModeFor(displayid, desired_width, desired_height, 0, 0);
|
|
}
|
|
|
|
CFRelease(availableModes);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline CGRect toCGRect(NSRect nsRect)
|
|
{
|
|
CGRect cgRect;
|
|
|
|
cgRect.origin.x = nsRect.origin.x;
|
|
cgRect.origin.y = nsRect.origin.y;
|
|
cgRect.size.width = nsRect.size.width;
|
|
cgRect.size.height = nsRect.size.height;
|
|
|
|
return cgRect;
|
|
}
|
|
|
|
|
|
MenubarController::MenubarController()
|
|
: osg::Referenced(),
|
|
_list(),
|
|
_menubarShown(true),
|
|
_mutex()
|
|
{
|
|
// the following code will query the system for the available rect on the main-display (typically the displaying showing the menubar + the dock
|
|
|
|
NSRect rect = [[[NSScreen screens] objectAtIndex: 0] visibleFrame];
|
|
_availRect = toCGRect(rect);
|
|
|
|
// now we need the rect of the main-display including the menubar and the dock
|
|
_mainScreenBounds = CGDisplayBounds( CGMainDisplayID() );
|
|
|
|
|
|
// NSRect 0/0 is bottom/left, _mainScreenBounds 0/0 is top/left
|
|
_availRect.origin.y = _mainScreenBounds.size.height - _availRect.size.height - _availRect.origin.y;
|
|
|
|
_toggler = [[MenubarToggler alloc] init];
|
|
update();
|
|
}
|
|
|
|
MenubarController::~MenubarController()
|
|
{
|
|
[_toggler release];
|
|
}
|
|
|
|
|
|
void MenubarController::setDisplaySettings(osg::DisplaySettings* display_settings)
|
|
{
|
|
[_toggler setDisplaySettings:display_settings];
|
|
update();
|
|
}
|
|
|
|
|
|
MenubarController* MenubarController::instance()
|
|
{
|
|
static osg::ref_ptr<MenubarController> s_menubar_controller = new MenubarController();
|
|
return s_menubar_controller.get();
|
|
}
|
|
|
|
|
|
void MenubarController::attachWindow(WindowAdapter* win)
|
|
{
|
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
|
_list.push_back(win);
|
|
update();
|
|
}
|
|
|
|
|
|
void MenubarController::detachWindow(osgViewer::GraphicsWindow* win)
|
|
{
|
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
|
for(WindowList::iterator i = _list.begin(); i != _list.end(); ) {
|
|
if ((*i)->getWindow() == win)
|
|
i = _list.erase(i);
|
|
else
|
|
++i;
|
|
}
|
|
update();
|
|
}
|
|
|
|
// iterate through all open windows and check, if they intersect the area occupied by the menubar/dock, and if so, hide the menubar/dock
|
|
|
|
|
|
void MenubarController::update()
|
|
{
|
|
unsigned int windowsCoveringMenubarArea = 0;
|
|
unsigned int windowsIntersectingMainScreen = 0;
|
|
for(WindowList::iterator i = _list.begin(); i != _list.end(); ) {
|
|
WindowAdapter* wi = (*i).get();
|
|
if (wi->valid()) {
|
|
CGRect windowBounds;
|
|
wi->getWindowBounds(windowBounds);
|
|
|
|
if (CGRectIntersectsRect(_mainScreenBounds, windowBounds))
|
|
{
|
|
++windowsIntersectingMainScreen;
|
|
// OSG_ALWAYS << "testing rect " << windowBounds.origin.x << "/" << windowBounds.origin.y << " " << windowBounds.size.width << "x" << windowBounds.size.height << std::endl;
|
|
// OSG_ALWAYS << "against " << _availRect.origin.x << "/" << _availRect.origin.y << " " << _availRect.size.width << "x" << _availRect.size.height << std::endl;
|
|
// the window intersects the main-screen, does it intersect with the menubar/dock?
|
|
if (((_availRect.origin.y > _mainScreenBounds.origin.y) && (_availRect.origin.y > windowBounds.origin.y)) ||
|
|
((_availRect.origin.x > _mainScreenBounds.origin.x) && (_availRect.origin.x > windowBounds.origin.x)) ||
|
|
((_availRect.size.width < _mainScreenBounds.size.width) && (_availRect.origin.x + _availRect.size.width < windowBounds.origin.x + windowBounds.size.width)) ||
|
|
((_availRect.size.height < _mainScreenBounds.size.height) && (_availRect.origin.y + _availRect.size.height < windowBounds.origin.y + windowBounds.size.height) ))
|
|
{
|
|
++windowsCoveringMenubarArea;
|
|
}
|
|
}
|
|
|
|
++i;
|
|
}
|
|
else
|
|
i = _list.erase(i);
|
|
}
|
|
|
|
// 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
|
|
|
|
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
|
if (windowsCoveringMenubarArea && _menubarShown)
|
|
{
|
|
|
|
//error = SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar);
|
|
[_toggler performSelectorOnMainThread: @selector(hide) withObject:NULL waitUntilDone: YES];
|
|
}
|
|
if (!windowsCoveringMenubarArea && !_menubarShown)
|
|
{
|
|
//error = SetSystemUIMode(kUIModeNormal, 0);
|
|
[_toggler performSelectorOnMainThread: @selector(show) withObject:NULL waitUntilDone: YES];
|
|
}
|
|
[pool release];
|
|
|
|
#else
|
|
|
|
OSErr error;
|
|
|
|
// see http://developer.apple.com/technotes/tn2002/tn2062.html for hiding the dock+menubar
|
|
if (windowsCoveringMenubarArea && _menubarShown)
|
|
{
|
|
error = SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar);
|
|
}
|
|
if (!windowsCoveringMenubarArea && !_menubarShown)
|
|
{
|
|
error = SetSystemUIMode(kUIModeNormal, 0);
|
|
}
|
|
#endif
|
|
|
|
_menubarShown = !windowsCoveringMenubarArea;
|
|
}
|
|
|
|
|
|
|
|
/** Helper method to get a double value out of a CFDictionary */
|
|
static double getDictDouble (CFDictionaryRef refDict, CFStringRef key)
|
|
{
|
|
double value;
|
|
CFNumberRef number_value = (CFNumberRef) CFDictionaryGetValue(refDict, key);
|
|
if (!number_value) // if can't get a number for the dictionary
|
|
return -1; // fail
|
|
if (!CFNumberGetValue(number_value, kCFNumberDoubleType, &value)) // or if cant convert it
|
|
return -1; // fail
|
|
return value; // otherwise return the long value
|
|
}
|
|
|
|
/** Helper method to get a long value out of a CFDictionary */
|
|
static long getDictLong(CFDictionaryRef refDict, CFStringRef key) // const void* key?
|
|
{
|
|
long value = 0;
|
|
CFNumberRef number_value = (CFNumberRef)CFDictionaryGetValue(refDict, key);
|
|
if (!number_value) // if can't get a number for the dictionary
|
|
return -1; // fail
|
|
if (!CFNumberGetValue(number_value, kCFNumberLongType, &value)) // or if cant convert it
|
|
return -1; // fail
|
|
return value;
|
|
}
|
|
|
|
|
|
|
|
/** ctor, get a list of all attached displays */
|
|
DarwinWindowingSystemInterface::DarwinWindowingSystemInterface() :
|
|
_initialized(false),
|
|
_displayCount(0),
|
|
_displayIds(NULL)
|
|
{
|
|
}
|
|
|
|
/** dtor */
|
|
DarwinWindowingSystemInterface::~DarwinWindowingSystemInterface()
|
|
{
|
|
if (osg::Referenced::getDeleteHandler())
|
|
{
|
|
osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0);
|
|
osg::Referenced::getDeleteHandler()->flushAll();
|
|
}
|
|
|
|
if (_displayIds) delete[] _displayIds;
|
|
_displayIds = NULL;
|
|
}
|
|
|
|
void DarwinWindowingSystemInterface::_init()
|
|
{
|
|
if (_initialized) return;
|
|
|
|
ProcessSerialNumber sn = { 0, kCurrentProcess };
|
|
TransformProcessType(&sn,kProcessTransformToForegroundApplication);
|
|
SetFrontProcess(&sn);
|
|
|
|
if( CGGetActiveDisplayList( 0, NULL, &_displayCount ) != CGDisplayNoErr )
|
|
{
|
|
OSG_WARN << "DarwinWindowingSystemInterface: could not get # of screens" << std::endl;
|
|
_displayCount = 0;
|
|
|
|
_initialized = true;
|
|
return;
|
|
}
|
|
|
|
_displayIds = new CGDirectDisplayID[_displayCount];
|
|
|
|
if( CGGetActiveDisplayList( _displayCount, _displayIds, &_displayCount ) != CGDisplayNoErr )
|
|
{
|
|
OSG_WARN << "DarwinWindowingSystemInterface: CGGetActiveDisplayList failed" << std::endl;
|
|
}
|
|
|
|
_initialized = true;
|
|
}
|
|
|
|
/** @return a CGDirectDisplayID for a ScreenIdentifier */
|
|
CGDirectDisplayID DarwinWindowingSystemInterface::getDisplayID(const osg::GraphicsContext::ScreenIdentifier& si)
|
|
{
|
|
_init();
|
|
|
|
if (_displayCount==0)
|
|
{
|
|
OSG_WARN << "DarwinWindowingSystemInterface::getDisplayID(..) no valid screens available returning 0 instead." << std::endl;
|
|
return 0;
|
|
}
|
|
|
|
if (si.screenNum < static_cast<int>(_displayCount))
|
|
{
|
|
return _displayIds[si.screenNum];
|
|
}
|
|
else
|
|
{
|
|
OSG_WARN << "DarwinWindowingSystemInterface::getDisplayID(..) invalid screen # " << si.screenNum << ", returning main-screen instead." << std::endl;
|
|
return _displayIds[0];
|
|
}
|
|
}
|
|
|
|
/** @return count of attached screens */
|
|
unsigned int DarwinWindowingSystemInterface::getNumScreens(const osg::GraphicsContext::ScreenIdentifier& si)
|
|
{
|
|
_init();
|
|
|
|
return _displayCount;
|
|
}
|
|
|
|
void DarwinWindowingSystemInterface::getScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution)
|
|
{
|
|
_init();
|
|
|
|
if (_displayCount==0)
|
|
{
|
|
resolution.width = 0;
|
|
resolution.height = 0;
|
|
resolution.colorDepth = 0;
|
|
resolution.refreshRate = 0;
|
|
return;
|
|
}
|
|
|
|
CGDirectDisplayID id = getDisplayID(si);
|
|
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
|
|
|
|
CGDisplayModeRef display_mode_ref = CGDisplayCopyDisplayMode(id);
|
|
resolution.width = CGDisplayModeGetWidth(display_mode_ref);
|
|
resolution.height = CGDisplayModeGetHeight(display_mode_ref);
|
|
resolution.colorDepth = displayBitsPerPixelForMode(display_mode_ref);
|
|
resolution.refreshRate = CGDisplayModeGetRefreshRate(display_mode_ref);
|
|
|
|
CGDisplayModeRelease(display_mode_ref);
|
|
|
|
#else
|
|
resolution.width = CGDisplayPixelsWide(id);
|
|
resolution.height = CGDisplayPixelsHigh(id);
|
|
resolution.colorDepth = displayBitsPerPixel(id);
|
|
|
|
resolution.refreshRate = getDictDouble (CGDisplayCurrentMode(id), kCGDisplayRefreshRate); // Not tested
|
|
#endif
|
|
if (resolution.refreshRate<0) resolution.refreshRate = 0;
|
|
}
|
|
|
|
|
|
void DarwinWindowingSystemInterface::enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, osg::GraphicsContext::ScreenSettingsList & resolutionList)
|
|
{
|
|
_init();
|
|
|
|
// Warning! This method has not been tested.
|
|
resolutionList.clear();
|
|
|
|
if (_displayCount==0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
CGDirectDisplayID displayid = getDisplayID(screenIdentifier);
|
|
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
|
|
|
|
CFArrayRef availableModes = CGDisplayCopyAllDisplayModes(displayid, NULL);
|
|
unsigned int numberOfAvailableModes = CFArrayGetCount(availableModes);
|
|
for (unsigned int i=0; i<numberOfAvailableModes; ++i)
|
|
{
|
|
CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(availableModes, i);
|
|
osg::GraphicsContext::ScreenSettings tmpSR;
|
|
|
|
tmpSR.width = CGDisplayModeGetWidth(mode);
|
|
tmpSR.height = CGDisplayModeGetHeight(mode);
|
|
tmpSR.colorDepth = displayBitsPerPixelForMode(mode);
|
|
tmpSR.refreshRate = CGDisplayModeGetRefreshRate(mode);
|
|
|
|
resolutionList.push_back(tmpSR);
|
|
}
|
|
|
|
CFRelease(availableModes);
|
|
|
|
#else
|
|
|
|
CFArrayRef availableModes = CGDisplayAvailableModes(displayid);
|
|
unsigned int numberOfAvailableModes = CFArrayGetCount(availableModes);
|
|
for (unsigned int i=0; i<numberOfAvailableModes; ++i) {
|
|
// look at each mode in the available list
|
|
CFDictionaryRef mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, i);
|
|
osg::GraphicsContext::ScreenSettings tmpSR;
|
|
|
|
long width = getDictLong(mode, kCGDisplayWidth);
|
|
tmpSR.width = width<=0 ? 0 : width;
|
|
long height = getDictLong(mode, kCGDisplayHeight);
|
|
tmpSR.height = height<=0 ? 0 : height;
|
|
long rate = getDictLong(mode, kCGDisplayRefreshRate);
|
|
tmpSR.refreshRate = rate<=0 ? 0 : rate;
|
|
long depth = getDictLong(mode, kCGDisplayBitsPerPixel);
|
|
tmpSR.colorDepth = depth<=0 ? 0 : depth;
|
|
|
|
resolutionList.push_back(tmpSR);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/** return the top left coord of a specific screen in global screen space */
|
|
void DarwinWindowingSystemInterface::getScreenTopLeft(const osg::GraphicsContext::ScreenIdentifier& si, int& x, int& y)
|
|
{
|
|
_init();
|
|
|
|
if (_displayCount==0)
|
|
{
|
|
x = 0;
|
|
y = 0;
|
|
return;
|
|
}
|
|
|
|
CGRect bounds = CGDisplayBounds( getDisplayID(si) );
|
|
x = static_cast<int>(bounds.origin.x);
|
|
y = static_cast<int>(bounds.origin.y);
|
|
|
|
// OSG_DEBUG << "topleft of screen " << si.screenNum <<" " << bounds.origin.x << "/" << bounds.origin.y << std::endl;
|
|
}
|
|
|
|
|
|
bool DarwinWindowingSystemInterface::setScreenSettings(const osg::GraphicsContext::ScreenIdentifier &si, const osg::GraphicsContext::ScreenSettings & settings)
|
|
{
|
|
CGDirectDisplayID displayid = getDisplayID(si);
|
|
|
|
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)
|
|
|
|
return findBestDisplayModeFor(displayid, settings.width, settings.height, settings.colorDepth, settings.refreshRate);
|
|
|
|
#else
|
|
// add next line and on following line replace hard coded depth and refresh rate
|
|
CGRefreshRate refresh = getDictDouble (CGDisplayCurrentMode(displayid), kCGDisplayRefreshRate);
|
|
CFDictionaryRef display_mode_values =
|
|
CGDisplayBestModeForParametersAndRefreshRate(
|
|
displayid,
|
|
settings.colorDepth,
|
|
settings.width, settings.height,
|
|
settings.refreshRate,
|
|
NULL);
|
|
|
|
|
|
return CGDisplaySwitchToMode(displayid, display_mode_values) != kCGErrorSuccess;
|
|
#endif
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned int DarwinWindowingSystemInterface::getScreenContaining(int x, int y, int w, int h)
|
|
{
|
|
_init();
|
|
|
|
if (_displayCount==0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
CGRect rect = CGRectMake(x,y,w,h);
|
|
for(unsigned int i = 0; i < _displayCount; ++i) {
|
|
CGRect bounds = CGDisplayBounds( getDisplayID(i) );
|
|
if (CGRectIntersectsRect(bounds, rect)) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
}
|