Optimised OS X implementation regarding scaling factor

This also adds support for changing the screen profile or moving the window to another screen.
This commit is contained in:
Marco Antognini 2014-05-24 15:22:24 +02:00
parent a3ab6efa23
commit 7d4235a38f
6 changed files with 101 additions and 28 deletions

View File

@ -55,6 +55,7 @@ namespace sf {
BOOL m_mouseIsIn; ///< Mouse positional state BOOL m_mouseIsIn; ///< Mouse positional state
NSTrackingArea* m_trackingArea; ///< Mouse tracking area NSTrackingArea* m_trackingArea; ///< Mouse tracking area
BOOL m_fullscreen; ///< Indicate whether the window is fullscreen or not BOOL m_fullscreen; ///< Indicate whether the window is fullscreen or not
CGFloat m_scaleFactor; ///< Display scale factor (e.g. 1x for classic display, 2x for retina)
// Hidden text view used to convert key event to actual chars. // Hidden text view used to convert key event to actual chars.
// We use a silent responder to prevent sound alerts. // We use a silent responder to prevent sound alerts.
@ -106,6 +107,14 @@ namespace sf {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(void)disableKeyRepeat; -(void)disableKeyRepeat;
////////////////////////////////////////////////////////////
/// \brief Get the display scale factor
///
/// \return e.g. 1.0 for classic display, 2.0 for retina display
///
////////////////////////////////////////////////////////////
-(CGFloat)displayScaleFactor;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Compute the position of the cursor /// \brief Compute the position of the cursor
/// ///

View File

@ -55,6 +55,12 @@ BOOL isValidTextUnicode(NSEvent* event);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@interface SFOpenGLView () @interface SFOpenGLView ()
////////////////////////////////////////////////////////////
/// \brief Handle screen changed event
///
////////////////////////////////////////////////////////////
-(void)updateScaleFactor;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Handle view resized event /// \brief Handle view resized event
/// ///
@ -154,6 +160,7 @@ BOOL isValidTextUnicode(NSEvent* event);
[self addTrackingArea:m_trackingArea]; [self addTrackingArea:m_trackingArea];
m_fullscreen = isFullscreen; m_fullscreen = isFullscreen;
[self updateScaleFactor];
// Register for window focus events // Register for window focus events
[[NSNotificationCenter defaultCenter] addObserver:self [[NSNotificationCenter defaultCenter] addObserver:self
@ -169,6 +176,16 @@ BOOL isValidTextUnicode(NSEvent* event);
name:NSWindowWillCloseNotification name:NSWindowWillCloseNotification
object:[self window]]; object:[self window]];
// Register for changed screen and changed screen's profile events
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(updateScaleFactor)
name:NSWindowDidChangeScreenNotification
object:[self window]];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(updateScaleFactor)
name:NSWindowDidChangeScreenProfileNotification
object:[self window]];
// Create a hidden text view for parsing key down event properly // Create a hidden text view for parsing key down event properly
m_silentResponder = [[SFSilentResponder alloc] init]; m_silentResponder = [[SFSilentResponder alloc] init];
m_hiddenTextView = [[NSTextView alloc] initWithFrame:NSZeroRect]; m_hiddenTextView = [[NSTextView alloc] initWithFrame:NSZeroRect];
@ -234,6 +251,22 @@ BOOL isValidTextUnicode(NSEvent* event);
} }
////////////////////////////////////////////////////////
-(CGFloat)displayScaleFactor
{
return m_scaleFactor;
}
////////////////////////////////////////////////////////
-(void)updateScaleFactor
{
NSWindow* window = [self window];
NSScreen* screen = window ? [window screen] : [NSScreen mainScreen];
m_scaleFactor = [screen backingScaleFactor];
}
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)viewDidEndLiveResize -(void)viewDidEndLiveResize
{ {

View File

@ -89,6 +89,13 @@
} }
////////////////////////////////////////////////////////
-(CGFloat)displayScaleFactor
{
return [m_oglView displayScaleFactor];
}
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)setRequesterTo:(sf::priv::WindowImplCocoa*)requester -(void)setRequesterTo:(sf::priv::WindowImplCocoa*)requester
{ {

View File

@ -306,6 +306,13 @@
#pragma mark WindowImplDelegateProtocol's methods #pragma mark WindowImplDelegateProtocol's methods
////////////////////////////////////////////////////////
-(CGFloat)displayScaleFactor
{
return [m_oglView displayScaleFactor];
}
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
-(void)setRequesterTo:(sf::priv::WindowImplCocoa*)requester -(void)setRequesterTo:(sf::priv::WindowImplCocoa*)requester
{ {

View File

@ -43,6 +43,15 @@ namespace sf
namespace priv namespace priv
{ {
////////////////////////////////////////////////////////////
/// \brief Get the scale factor of the main screen
///
////////////////////////////////////////////////////////////
CGFloat getDefaultScaleFactor()
{
return [[NSScreen mainScreen] backingScaleFactor];
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Scale SFML coordinates to backing coordinates /// \brief Scale SFML coordinates to backing coordinates
/// ///
@ -50,27 +59,27 @@ namespace priv
/// has a retina display or not. /// has a retina display or not.
/// ///
/// \param in SFML coordinates to be converted /// \param in SFML coordinates to be converted
/// \param delegate a object implementing WindowImplDelegateProtocol, or nil for default scale
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
template <class T> template <class T>
void scaleIn(T& in) void scaleIn(T& in, id<WindowImplDelegateProtocol> delegate)
{ {
CGFloat scale = [[NSScreen mainScreen] backingScaleFactor]; in /= delegate ? [delegate displayScaleFactor] : getDefaultScaleFactor();
in /= scale;
} }
template <class T> template <class T>
void scaleInWidthHeight(T& in) void scaleInWidthHeight(T& in, id<WindowImplDelegateProtocol> delegate)
{ {
scaleIn(in.width); scaleIn(in.width, delegate);
scaleIn(in.height); scaleIn(in.height, delegate);
} }
template <class T> template <class T>
void scaleInXY(T& in) void scaleInXY(T& in, id<WindowImplDelegateProtocol> delegate)
{ {
scaleIn(in.x); scaleIn(in.x, delegate);
scaleIn(in.y); scaleIn(in.y, delegate);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -80,27 +89,27 @@ void scaleInXY(T& in)
/// has a retina display or not. /// has a retina display or not.
/// ///
/// \param out backing coordinates to be converted /// \param out backing coordinates to be converted
/// \param delegate a object implementing WindowImplDelegateProtocol, or nil for default scale
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
template <class T> template <class T>
void scaleOut(T& out) void scaleOut(T& out, id<WindowImplDelegateProtocol> delegate)
{ {
CGFloat scale = [[NSScreen mainScreen] backingScaleFactor]; out *= delegate ? [delegate displayScaleFactor] : getDefaultScaleFactor();
out *= scale;
} }
template <class T> template <class T>
void scaleOutWidthHeight(T& out) void scaleOutWidthHeight(T& out, id<WindowImplDelegateProtocol> delegate)
{ {
scaleOut(out.width); scaleOut(out.width, delegate);
scaleOut(out.height); scaleOut(out.height, delegate);
} }
template <class T> template <class T>
void scaleOutXY(T& out) void scaleOutXY(T& out, id<WindowImplDelegateProtocol> delegate)
{ {
scaleOut(out.x); scaleOut(out.x, delegate);
scaleOut(out.y); scaleOut(out.y, delegate);
} }
#pragma mark #pragma mark
@ -159,7 +168,7 @@ m_showCursor(true)
retainPool(); retainPool();
// Use backing size // Use backing size
scaleInWidthHeight(mode); scaleInWidthHeight(mode, nil);
m_delegate = [[SFWindowController alloc] initWithMode:mode andStyle:style]; m_delegate = [[SFWindowController alloc] initWithMode:mode andStyle:style];
[m_delegate changeTitle:sfStringToNSString(title)]; [m_delegate changeTitle:sfStringToNSString(title)];
@ -250,7 +259,7 @@ void WindowImplCocoa::windowResized(unsigned int width, unsigned int height)
event.type = Event::Resized; event.type = Event::Resized;
event.size.width = width; event.size.width = width;
event.size.height = height; event.size.height = height;
scaleOutWidthHeight(event.size); scaleOutWidthHeight(event.size, m_delegate);
pushEvent(event); pushEvent(event);
} }
@ -293,7 +302,7 @@ void WindowImplCocoa::mouseDownAt(Mouse::Button button, int x, int y)
event.mouseButton.button = button; event.mouseButton.button = button;
event.mouseButton.x = x; event.mouseButton.x = x;
event.mouseButton.y = y; event.mouseButton.y = y;
scaleOutXY(event.mouseButton); scaleOutXY(event.mouseButton, m_delegate);
pushEvent(event); pushEvent(event);
} }
@ -307,7 +316,7 @@ void WindowImplCocoa::mouseUpAt(Mouse::Button button, int x, int y)
event.mouseButton.button = button; event.mouseButton.button = button;
event.mouseButton.x = x; event.mouseButton.x = x;
event.mouseButton.y = y; event.mouseButton.y = y;
scaleOutXY(event.mouseButton); scaleOutXY(event.mouseButton, m_delegate);
pushEvent(event); pushEvent(event);
} }
@ -320,7 +329,7 @@ void WindowImplCocoa::mouseMovedAt(int x, int y)
event.type = Event::MouseMoved; event.type = Event::MouseMoved;
event.mouseMove.x = x; event.mouseMove.x = x;
event.mouseMove.y = y; event.mouseMove.y = y;
scaleOutXY(event.mouseMove); scaleOutXY(event.mouseMove, m_delegate);
pushEvent(event); pushEvent(event);
} }
@ -333,7 +342,7 @@ void WindowImplCocoa::mouseWheelScrolledAt(float delta, int x, int y)
event.mouseWheel.delta = delta; event.mouseWheel.delta = delta;
event.mouseWheel.x = x; event.mouseWheel.x = x;
event.mouseWheel.y = y; event.mouseWheel.y = y;
scaleOutXY(event.mouseWheel); scaleOutXY(event.mouseWheel, m_delegate);
pushEvent(event); pushEvent(event);
} }
@ -424,7 +433,7 @@ Vector2i WindowImplCocoa::getPosition() const
{ {
NSPoint pos = [m_delegate position]; NSPoint pos = [m_delegate position];
sf::Vector2i ret(pos.x, pos.y); sf::Vector2i ret(pos.x, pos.y);
scaleOutXY(ret); scaleOutXY(ret, m_delegate);
return ret; return ret;
} }
@ -433,7 +442,7 @@ Vector2i WindowImplCocoa::getPosition() const
void WindowImplCocoa::setPosition(const Vector2i& position) void WindowImplCocoa::setPosition(const Vector2i& position)
{ {
sf::Vector2i backingPosition = position; sf::Vector2i backingPosition = position;
scaleInXY(backingPosition); scaleInXY(backingPosition, m_delegate);
[m_delegate setWindowPositionToX:backingPosition.x Y:backingPosition.y]; [m_delegate setWindowPositionToX:backingPosition.x Y:backingPosition.y];
} }
@ -443,7 +452,7 @@ Vector2u WindowImplCocoa::getSize() const
{ {
NSSize size = [m_delegate size]; NSSize size = [m_delegate size];
Vector2u ret(size.width, size.height); Vector2u ret(size.width, size.height);
scaleOutXY(ret); scaleOutXY(ret, m_delegate);
return ret; return ret;
} }
@ -452,7 +461,7 @@ Vector2u WindowImplCocoa::getSize() const
void WindowImplCocoa::setSize(const Vector2u& size) void WindowImplCocoa::setSize(const Vector2u& size)
{ {
sf::Vector2u backingSize = size; sf::Vector2u backingSize = size;
scaleInXY(backingSize); scaleInXY(backingSize, m_delegate);
[m_delegate resizeTo:backingSize.x by:backingSize.y]; [m_delegate resizeTo:backingSize.x by:backingSize.y];
} }

View File

@ -66,6 +66,14 @@ namespace sf {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@protocol WindowImplDelegateProtocol @protocol WindowImplDelegateProtocol
////////////////////////////////////////////////////////////
/// \brief Get the display scale factor
///
/// \return e.g. 1.0 for classic display, 2.0 for retina display
///
////////////////////////////////////////////////////////////
-(CGFloat)displayScaleFactor;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Set the WindowImpl who requested this delegate /// \brief Set the WindowImpl who requested this delegate
/// ///