mirror of
https://github.com/SFML/SFML.git
synced 2024-11-28 22:31:09 +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_BINDING GL_FRAMEBUFFER_BINDING_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_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_OES
|
||||
#define GLEXT_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_OES
|
||||
|
@ -100,11 +100,34 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
- (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
|
||||
////////////////////////////////////////////////////////////
|
||||
@property (nonatomic) sf::priv::WindowImplUIKit* sfWindow; ///< Main window of the application
|
||||
@property (readonly, nonatomic) CMMotionManager* motionManager; ///< Instance of the motion manager
|
||||
@property (nonatomic) CGFloat backingScaleFactor;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -50,17 +50,18 @@ namespace
|
||||
@implementation SFAppDelegate
|
||||
|
||||
@synthesize sfWindow;
|
||||
@synthesize backingScaleFactor;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
+(SFAppDelegate*)getInstance
|
||||
+ (SFAppDelegate*)getInstance
|
||||
{
|
||||
return delegateInstance;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
-(void)runUserMain
|
||||
- (void)runUserMain
|
||||
{
|
||||
// Arguments intentionally dropped, see comments in main in sfml-main
|
||||
sfmlMain(0, NULL);
|
||||
@ -73,6 +74,8 @@ namespace
|
||||
// Save the delegate instance
|
||||
delegateInstance = self;
|
||||
|
||||
[self initBackingScale];
|
||||
|
||||
// Instantiate the motion manager
|
||||
self.motionManager = [[CMMotionManager alloc] init];
|
||||
|
||||
@ -90,6 +93,14 @@ namespace
|
||||
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
|
||||
@ -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
|
||||
@ -159,23 +202,20 @@ namespace
|
||||
{
|
||||
// Get the new orientation
|
||||
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
|
||||
|
||||
// Filter interesting orientations
|
||||
if ((orientation == UIDeviceOrientationLandscapeLeft) ||
|
||||
(orientation == UIDeviceOrientationLandscapeRight) ||
|
||||
(orientation == UIDeviceOrientationPortrait) ||
|
||||
(orientation == UIDeviceOrientationPortraitUpsideDown))
|
||||
if (UIDeviceOrientationIsValidInterfaceOrientation(orientation))
|
||||
{
|
||||
// Get the new size
|
||||
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);
|
||||
|
||||
// Send a Resized event to the current window
|
||||
sf::Event event;
|
||||
event.type = sf::Event::Resized;
|
||||
event.size.width = size.x;
|
||||
event.size.height = size.y;
|
||||
event.size.width = size.x * backingScaleFactor;
|
||||
event.size.height = size.y * backingScaleFactor;
|
||||
sfWindow->forwardEvent(event);
|
||||
}
|
||||
}
|
||||
@ -213,8 +253,8 @@ namespace
|
||||
sf::Event event;
|
||||
event.type = sf::Event::TouchBegan;
|
||||
event.touch.finger = index;
|
||||
event.touch.x = position.x;
|
||||
event.touch.y = position.y;
|
||||
event.touch.x = position.x * backingScaleFactor;
|
||||
event.touch.y = position.y * backingScaleFactor;
|
||||
sfWindow->forwardEvent(event);
|
||||
}
|
||||
}
|
||||
@ -234,8 +274,8 @@ namespace
|
||||
sf::Event event;
|
||||
event.type = sf::Event::TouchMoved;
|
||||
event.touch.finger = index;
|
||||
event.touch.x = position.x;
|
||||
event.touch.y = position.y;
|
||||
event.touch.x = position.x * backingScaleFactor;
|
||||
event.touch.y = position.y * backingScaleFactor;
|
||||
sfWindow->forwardEvent(event);
|
||||
}
|
||||
}
|
||||
@ -254,8 +294,8 @@ namespace
|
||||
sf::Event event;
|
||||
event.type = sf::Event::TouchEnded;
|
||||
event.touch.finger = index;
|
||||
event.touch.x = position.x;
|
||||
event.touch.y = position.y;
|
||||
event.touch.x = position.x * backingScaleFactor;
|
||||
event.touch.y = position.y * backingScaleFactor;
|
||||
sfWindow->forwardEvent(event);
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@
|
||||
/// \return Id of the view
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
-(id)initWithFrame:(CGRect)frame;
|
||||
- (id)initWithFrame:(CGRect)frame andContentScaleFactor:(CGFloat)factor;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include <QuartzCore/CAEAGLLayer.h>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
@interface SFView()
|
||||
|
||||
@property (nonatomic) NSMutableArray* touches;
|
||||
@ -170,16 +169,18 @@
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
+(Class)layerClass
|
||||
+ (Class)layerClass
|
||||
{
|
||||
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)
|
||||
{
|
||||
self.context = NULL;
|
||||
|
@ -36,8 +36,6 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
|
||||
{
|
||||
(void)interfaceOrientation;
|
||||
|
||||
return self.orientationCanChange;
|
||||
}
|
||||
|
||||
|
@ -26,9 +26,9 @@
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Window/VideoModeImpl.hpp>
|
||||
#include <SFML/Window/iOS/SFAppDelegate.hpp>
|
||||
#include <UIKit/UIKit.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
@ -50,7 +50,8 @@ std::vector<VideoMode> VideoModeImpl::getFullscreenModes()
|
||||
VideoMode VideoModeImpl::getDesktopMode()
|
||||
{
|
||||
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
|
||||
|
@ -215,6 +215,7 @@ private:
|
||||
SFView* m_view; ///< OpenGL view of the window
|
||||
SFViewController* m_viewController; ///< Controller attached to the view
|
||||
bool m_hasFocus; ///< Current focus state of the window
|
||||
float m_backingScale; ///< Converts from points to pixels and vice versa
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <UIKit/UIKit.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
@ -51,6 +50,8 @@ WindowImplUIKit::WindowImplUIKit(VideoMode mode,
|
||||
unsigned long style,
|
||||
const ContextSettings& /*settings*/)
|
||||
{
|
||||
m_backingScale = [SFAppDelegate getInstance].backingScaleFactor;
|
||||
|
||||
// Apply the fullscreen flag
|
||||
[UIApplication sharedApplication].statusBarHidden = !(style & Style::Titlebar) || (style & Style::Fullscreen);
|
||||
|
||||
@ -68,8 +69,15 @@ WindowImplUIKit::WindowImplUIKit(VideoMode mode,
|
||||
// Assign it to the application delegate
|
||||
[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
|
||||
m_view = [[SFView alloc] initWithFrame:frame];
|
||||
m_view = [[SFView alloc] initWithFrame:viewRect andContentScaleFactor:m_backingScale];
|
||||
[m_view resignFirstResponder];
|
||||
|
||||
// Create the view controller
|
||||
@ -107,7 +115,8 @@ WindowHandle WindowImplUIKit::getSystemHandle() 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
|
||||
{
|
||||
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 ...
|
||||
|
||||
// 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
|
||||
if (size.x > size.y)
|
||||
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeLeft];
|
||||
|
Loading…
Reference in New Issue
Block a user