mirror of
https://github.com/SFML/SFML.git
synced 2024-12-01 15:51:04 +08:00
fixes for ios window size including device-orientation-changes and retina support
This commit is contained in:
parent
2cab5789af
commit
cac4d58b3d
@ -58,8 +58,6 @@
|
|||||||
#define GLEXT_GL_FRAMEBUFFER GL_FRAMEBUFFER_OES
|
#define GLEXT_GL_FRAMEBUFFER GL_FRAMEBUFFER_OES
|
||||||
#define GLEXT_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_OES
|
#define GLEXT_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_OES
|
||||||
#define GLEXT_GL_RENDERBUFFER GL_RENDERBUFFER_OES
|
#define GLEXT_GL_RENDERBUFFER GL_RENDERBUFFER_OES
|
||||||
#define GLEXT_GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES
|
|
||||||
#define GLEXT_GL_STENCIL_ATTACHMENT GL_STENCIL_ATTACHMENT_OES
|
|
||||||
#define GLEXT_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_OES
|
#define GLEXT_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_OES
|
||||||
#define GLEXT_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_OES
|
#define GLEXT_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_OES
|
||||||
#define GLEXT_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_OES
|
#define GLEXT_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_OES
|
||||||
|
@ -100,11 +100,34 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
- (void)notifyCharacter:(sf::Uint32)character;
|
- (void)notifyCharacter:(sf::Uint32)character;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Tells if the dimensions of the current window must be flipped when switching to a given orientation
|
||||||
|
///
|
||||||
|
/// \param orientation the device has changed to
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
- (bool)needsToFlipFrameForOrientation:(UIDeviceOrientation)orientation;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Tells if app and view support a requested device orientation or not
|
||||||
|
///
|
||||||
|
/// \param orientation the device has changed to
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
- (bool)supportsOrientation:(UIDeviceOrientation)orientation;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Initializes the factor which is required to convert from points to pixels and back
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
- (void)initBackingScale;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@property (nonatomic) sf::priv::WindowImplUIKit* sfWindow; ///< Main window of the application
|
@property (nonatomic) sf::priv::WindowImplUIKit* sfWindow; ///< Main window of the application
|
||||||
@property (readonly, nonatomic) CMMotionManager* motionManager; ///< Instance of the motion manager
|
@property (readonly, nonatomic) CMMotionManager* motionManager; ///< Instance of the motion manager
|
||||||
|
@property (nonatomic) CGFloat backingScaleFactor;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@ namespace
|
|||||||
@implementation SFAppDelegate
|
@implementation SFAppDelegate
|
||||||
|
|
||||||
@synthesize sfWindow;
|
@synthesize sfWindow;
|
||||||
|
@synthesize backingScaleFactor;
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -73,6 +74,8 @@ namespace
|
|||||||
// Save the delegate instance
|
// Save the delegate instance
|
||||||
delegateInstance = self;
|
delegateInstance = self;
|
||||||
|
|
||||||
|
[self initBackingScale];
|
||||||
|
|
||||||
// Instantiate the motion manager
|
// Instantiate the motion manager
|
||||||
self.motionManager = [[CMMotionManager alloc] init];
|
self.motionManager = [[CMMotionManager alloc] init];
|
||||||
|
|
||||||
@ -90,6 +93,14 @@ namespace
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)initBackingScale
|
||||||
|
{
|
||||||
|
id data = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSHighResolutionCapable"];
|
||||||
|
if(data && [data boolValue])
|
||||||
|
backingScaleFactor = [[UIScreen mainScreen] scale];
|
||||||
|
else
|
||||||
|
backingScaleFactor = 1;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
- (void)applicationWillResignActive:(UIApplication *)application
|
- (void)applicationWillResignActive:(UIApplication *)application
|
||||||
@ -151,6 +162,38 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (bool)supportsOrientation:(UIDeviceOrientation)orientation
|
||||||
|
{
|
||||||
|
if (!self.sfWindow)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
UIViewController* rootViewController = [((__bridge UIWindow*)(self.sfWindow->getSystemHandle())) rootViewController];
|
||||||
|
if (!rootViewController || ![rootViewController shouldAutorotate])
|
||||||
|
return false;
|
||||||
|
|
||||||
|
NSArray *supportedOrientations = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UISupportedInterfaceOrientations"];
|
||||||
|
if (!supportedOrientations)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int appFlags = 0;
|
||||||
|
if ([supportedOrientations containsObject:@"UIInterfaceOrientationPortrait"])
|
||||||
|
appFlags += UIInterfaceOrientationMaskPortrait;
|
||||||
|
if ([supportedOrientations containsObject:@"UIInterfaceOrientationPortraitUpsideDown"])
|
||||||
|
appFlags += UIInterfaceOrientationMaskPortraitUpsideDown;
|
||||||
|
if ([supportedOrientations containsObject:@"UIInterfaceOrientationLandscapeLeft"])
|
||||||
|
appFlags += UIInterfaceOrientationMaskLandscapeLeft;
|
||||||
|
if ([supportedOrientations containsObject:@"UIInterfaceOrientationLandscapeRight"])
|
||||||
|
appFlags += UIInterfaceOrientationMaskLandscapeRight;
|
||||||
|
|
||||||
|
return (1 << orientation) & [rootViewController supportedInterfaceOrientations] & appFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (bool)needsToFlipFrameForOrientation:(UIDeviceOrientation)orientation
|
||||||
|
{
|
||||||
|
sf::Vector2u size = self.sfWindow->getSize();
|
||||||
|
return ((!UIDeviceOrientationIsLandscape(orientation) && size.x > size.y)
|
||||||
|
|| (UIDeviceOrientationIsLandscape(orientation) && size.y > size.x));
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
- (void)deviceOrientationDidChange:(NSNotification *)notification
|
- (void)deviceOrientationDidChange:(NSNotification *)notification
|
||||||
@ -159,23 +202,20 @@ namespace
|
|||||||
{
|
{
|
||||||
// Get the new orientation
|
// Get the new orientation
|
||||||
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
|
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
|
||||||
|
|
||||||
// Filter interesting orientations
|
// Filter interesting orientations
|
||||||
if ((orientation == UIDeviceOrientationLandscapeLeft) ||
|
if (UIDeviceOrientationIsValidInterfaceOrientation(orientation))
|
||||||
(orientation == UIDeviceOrientationLandscapeRight) ||
|
|
||||||
(orientation == UIDeviceOrientationPortrait) ||
|
|
||||||
(orientation == UIDeviceOrientationPortraitUpsideDown))
|
|
||||||
{
|
{
|
||||||
// Get the new size
|
// Get the new size
|
||||||
sf::Vector2u size = self.sfWindow->getSize();
|
sf::Vector2u size = self.sfWindow->getSize();
|
||||||
if (UIDeviceOrientationIsLandscape(orientation))
|
// Check if the app can switch to this orientation and if so if the window's size must be adjusted
|
||||||
|
if ([self supportsOrientation:orientation] && [self needsToFlipFrameForOrientation:orientation])
|
||||||
std::swap(size.x, size.y);
|
std::swap(size.x, size.y);
|
||||||
|
|
||||||
// Send a Resized event to the current window
|
// Send a Resized event to the current window
|
||||||
sf::Event event;
|
sf::Event event;
|
||||||
event.type = sf::Event::Resized;
|
event.type = sf::Event::Resized;
|
||||||
event.size.width = size.x;
|
event.size.width = size.x * backingScaleFactor;
|
||||||
event.size.height = size.y;
|
event.size.height = size.y * backingScaleFactor;
|
||||||
sfWindow->forwardEvent(event);
|
sfWindow->forwardEvent(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,8 +253,8 @@ namespace
|
|||||||
sf::Event event;
|
sf::Event event;
|
||||||
event.type = sf::Event::TouchBegan;
|
event.type = sf::Event::TouchBegan;
|
||||||
event.touch.finger = index;
|
event.touch.finger = index;
|
||||||
event.touch.x = position.x;
|
event.touch.x = position.x * backingScaleFactor;
|
||||||
event.touch.y = position.y;
|
event.touch.y = position.y * backingScaleFactor;
|
||||||
sfWindow->forwardEvent(event);
|
sfWindow->forwardEvent(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -234,8 +274,8 @@ namespace
|
|||||||
sf::Event event;
|
sf::Event event;
|
||||||
event.type = sf::Event::TouchMoved;
|
event.type = sf::Event::TouchMoved;
|
||||||
event.touch.finger = index;
|
event.touch.finger = index;
|
||||||
event.touch.x = position.x;
|
event.touch.x = position.x * backingScaleFactor;
|
||||||
event.touch.y = position.y;
|
event.touch.y = position.y * backingScaleFactor;
|
||||||
sfWindow->forwardEvent(event);
|
sfWindow->forwardEvent(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -254,8 +294,8 @@ namespace
|
|||||||
sf::Event event;
|
sf::Event event;
|
||||||
event.type = sf::Event::TouchEnded;
|
event.type = sf::Event::TouchEnded;
|
||||||
event.touch.finger = index;
|
event.touch.finger = index;
|
||||||
event.touch.x = position.x;
|
event.touch.x = position.x * backingScaleFactor;
|
||||||
event.touch.y = position.y;
|
event.touch.y = position.y * backingScaleFactor;
|
||||||
sfWindow->forwardEvent(event);
|
sfWindow->forwardEvent(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
/// \return Id of the view
|
/// \return Id of the view
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
-(id)initWithFrame:(CGRect)frame;
|
- (id)initWithFrame:(CGRect)frame andContentScaleFactor:(CGFloat)factor;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
|
@ -31,7 +31,6 @@
|
|||||||
#include <QuartzCore/CAEAGLLayer.h>
|
#include <QuartzCore/CAEAGLLayer.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
|
||||||
@interface SFView()
|
@interface SFView()
|
||||||
|
|
||||||
@property (nonatomic) NSMutableArray* touches;
|
@property (nonatomic) NSMutableArray* touches;
|
||||||
@ -175,11 +174,13 @@
|
|||||||
return [CAEAGLLayer class];
|
return [CAEAGLLayer class];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
-(id)initWithFrame:(CGRect)frame
|
- (id)initWithFrame:(CGRect)frame andContentScaleFactor:(CGFloat)factor
|
||||||
{
|
{
|
||||||
self = [super initWithFrame:frame];
|
self = [super initWithFrame:frame];
|
||||||
|
|
||||||
|
self.contentScaleFactor = factor;
|
||||||
|
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
self.context = NULL;
|
self.context = NULL;
|
||||||
|
@ -36,8 +36,6 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
|
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
|
||||||
{
|
{
|
||||||
(void)interfaceOrientation;
|
|
||||||
|
|
||||||
return self.orientationCanChange;
|
return self.orientationCanChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,9 +26,9 @@
|
|||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Window/VideoModeImpl.hpp>
|
#include <SFML/Window/VideoModeImpl.hpp>
|
||||||
|
#include <SFML/Window/iOS/SFAppDelegate.hpp>
|
||||||
#include <UIKit/UIKit.h>
|
#include <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
namespace priv
|
namespace priv
|
||||||
@ -50,7 +50,8 @@ std::vector<VideoMode> VideoModeImpl::getFullscreenModes()
|
|||||||
VideoMode VideoModeImpl::getDesktopMode()
|
VideoMode VideoModeImpl::getDesktopMode()
|
||||||
{
|
{
|
||||||
CGRect bounds = [[UIScreen mainScreen] bounds];
|
CGRect bounds = [[UIScreen mainScreen] bounds];
|
||||||
return VideoMode(bounds.size.width, bounds.size.height);
|
float backingScale = [SFAppDelegate getInstance].backingScaleFactor;
|
||||||
|
return VideoMode(bounds.size.width * backingScale, bounds.size.height * backingScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
@ -215,6 +215,7 @@ private:
|
|||||||
SFView* m_view; ///< OpenGL view of the window
|
SFView* m_view; ///< OpenGL view of the window
|
||||||
SFViewController* m_viewController; ///< Controller attached to the view
|
SFViewController* m_viewController; ///< Controller attached to the view
|
||||||
bool m_hasFocus; ///< Current focus state of the window
|
bool m_hasFocus; ///< Current focus state of the window
|
||||||
|
float m_backingScale; ///< Converts from points to pixels and vice versa
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
@ -33,7 +33,6 @@
|
|||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
#include <UIKit/UIKit.h>
|
#include <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
namespace priv
|
namespace priv
|
||||||
@ -51,6 +50,8 @@ WindowImplUIKit::WindowImplUIKit(VideoMode mode,
|
|||||||
unsigned long style,
|
unsigned long style,
|
||||||
const ContextSettings& /*settings*/)
|
const ContextSettings& /*settings*/)
|
||||||
{
|
{
|
||||||
|
m_backingScale = [SFAppDelegate getInstance].backingScaleFactor;
|
||||||
|
|
||||||
// Apply the fullscreen flag
|
// Apply the fullscreen flag
|
||||||
[UIApplication sharedApplication].statusBarHidden = !(style & Style::Titlebar) || (style & Style::Fullscreen);
|
[UIApplication sharedApplication].statusBarHidden = !(style & Style::Titlebar) || (style & Style::Fullscreen);
|
||||||
|
|
||||||
@ -68,8 +69,15 @@ WindowImplUIKit::WindowImplUIKit(VideoMode mode,
|
|||||||
// Assign it to the application delegate
|
// Assign it to the application delegate
|
||||||
[SFAppDelegate getInstance].sfWindow = this;
|
[SFAppDelegate getInstance].sfWindow = this;
|
||||||
|
|
||||||
|
CGRect viewRect = frame;
|
||||||
|
// if UI-orientation doesn't match window-layout, swap the view size and notify the window about it
|
||||||
|
// iOS 7 and 8 do different stuff here. In iOS 7 frame.x<frame.y always! In iOS 8 it correctly depends on orientation
|
||||||
|
if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1)
|
||||||
|
if ((mode.width > mode.height) != (frame.size.width > frame.size.height))
|
||||||
|
std::swap(viewRect.size.width, viewRect.size.height);
|
||||||
|
|
||||||
// Create the view
|
// Create the view
|
||||||
m_view = [[SFView alloc] initWithFrame:frame];
|
m_view = [[SFView alloc] initWithFrame:viewRect andContentScaleFactor:m_backingScale];
|
||||||
[m_view resignFirstResponder];
|
[m_view resignFirstResponder];
|
||||||
|
|
||||||
// Create the view controller
|
// Create the view controller
|
||||||
@ -107,7 +115,8 @@ WindowHandle WindowImplUIKit::getSystemHandle() const
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Vector2i WindowImplUIKit::getPosition() const
|
Vector2i WindowImplUIKit::getPosition() const
|
||||||
{
|
{
|
||||||
return Vector2i(m_window.frame.origin.x, m_window.frame.origin.y);
|
CGPoint origin = m_window.frame.origin;
|
||||||
|
return Vector2i(origin.x * m_backingScale, origin.y * m_backingScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -120,7 +129,12 @@ void WindowImplUIKit::setPosition(const Vector2i& position)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Vector2u WindowImplUIKit::getSize() const
|
Vector2u WindowImplUIKit::getSize() const
|
||||||
{
|
{
|
||||||
return Vector2u(m_window.frame.size.width, m_window.frame.size.height);
|
auto physicalFrame = m_window.frame;
|
||||||
|
// iOS 7 and 8 do different stuff here. In iOS 7 frame.x<frame.y always! In iOS 8 it correctly depends on orientation
|
||||||
|
if ((NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1)
|
||||||
|
&& UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]))
|
||||||
|
std::swap(physicalFrame.size.width, physicalFrame.size.height);
|
||||||
|
return Vector2u(physicalFrame.size.width * m_backingScale, physicalFrame.size.height * m_backingScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -129,6 +143,10 @@ void WindowImplUIKit::setSize(const Vector2u& size)
|
|||||||
{
|
{
|
||||||
// @todo ...
|
// @todo ...
|
||||||
|
|
||||||
|
// if these sizes are required one day, don't forget to scale them!
|
||||||
|
// size.x /= m_backingScale;
|
||||||
|
// size.y /= m_backingScale;
|
||||||
|
|
||||||
// Set the orientation according to the requested size
|
// Set the orientation according to the requested size
|
||||||
if (size.x > size.y)
|
if (size.x > size.y)
|
||||||
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeLeft];
|
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeLeft];
|
||||||
|
Loading…
Reference in New Issue
Block a user