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
NSTrackingArea* m_trackingArea; ///< Mouse tracking area
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.
// We use a silent responder to prevent sound alerts.
@ -106,6 +107,14 @@ namespace sf {
////////////////////////////////////////////////////////////
-(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
///

View File

@ -55,6 +55,12 @@ BOOL isValidTextUnicode(NSEvent* event);
////////////////////////////////////////////////////////////
@interface SFOpenGLView ()
////////////////////////////////////////////////////////////
/// \brief Handle screen changed event
///
////////////////////////////////////////////////////////////
-(void)updateScaleFactor;
////////////////////////////////////////////////////////////
/// \brief Handle view resized event
///
@ -154,6 +160,7 @@ BOOL isValidTextUnicode(NSEvent* event);
[self addTrackingArea:m_trackingArea];
m_fullscreen = isFullscreen;
[self updateScaleFactor];
// Register for window focus events
[[NSNotificationCenter defaultCenter] addObserver:self
@ -169,6 +176,16 @@ BOOL isValidTextUnicode(NSEvent* event);
name:NSWindowWillCloseNotification
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
m_silentResponder = [[SFSilentResponder alloc] init];
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
{

View File

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

View File

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

View File

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

View File

@ -66,6 +66,14 @@ namespace sf {
////////////////////////////////////////////////////////////
@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
///