2015-04-05 05:36:53 +02:00
/ * RetroArch - A frontend for libretro .
* Copyright ( C ) 2013 -2014 - Jason Fetters
2017-01-22 13:40:32 +01:00
* Copyright ( C ) 2011 -2017 - Daniel De Matteis
2019-02-03 15:49:35 -08:00
*
2015-04-05 05:36:53 +02:00
* RetroArch is free software : you can redistribute it and / or modify it under the terms
* of the GNU General Public License as published by the Free Software Found -
* ation , either version 3 of the License , or ( at your option ) any later version .
*
* RetroArch is distributed in the hope that it will be useful , but WITHOUT ANY WARRANTY ;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE . See the GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License along with RetroArch .
* If not , see < http : // www . gnu . org / licenses / > .
* /
# import < AvailabilityMacros . h >
# include < sys / stat . h >
2015-04-20 12:52:16 +02:00
# include "cocoa_common.h"
2016-06-07 16:47:48 +02:00
# include "../ui_cocoa.h"
2016-09-08 11:59:44 +02:00
# include < retro_assert . h >
2016-06-08 07:41:59 +02:00
# include "../../../verbosity.h"
2015-04-05 05:36:53 +02:00
2019-02-09 21:10:28 +01:00
# include "../../../input/drivers/cocoa_input.h"
2019-06-17 11:18:27 +02:00
# include "../../../retroarch.h"
2015-12-05 17:15:32 +01:00
2019-01-26 13:18:32 -10:00
# ifdef HAVE_COCOATOUCH
# import "GCDWebUploader.h"
# import "WebServer.h"
2019-02-10 02:28:12 +01:00
2019-01-26 13:18:32 -10:00
# endif
2019-02-09 21:10:28 +01:00
# ifdef HAVE_METAL
@ implementation MetalView
- ( void ) keyDown : ( NSEvent * ) theEvent
{
}
/ * Stop the annoying sound when pressing a key . * /
- ( BOOL ) acceptsFirstResponder
{
return YES ;
}
- ( BOOL ) isFlipped
{
return YES ;
}
@ end
# endif
2015-04-20 20:39:39 +02:00
static CocoaView * g_instance ;
2015-04-05 05:36:53 +02:00
2015-04-12 16:50:39 +02:00
void * nsview_get _ptr ( void )
{
2019-02-09 21:10:28 +01:00
return ( BRIDGE void * ) g_instance ;
2018-05-13 09:50:47 -07:00
}
2015-04-05 05:36:53 +02:00
2015-04-12 16:50:39 +02:00
/ * forward declarations * /
2015-04-19 17:40:10 +02:00
void cocoagl_gfx _ctx _update ( void ) ;
2015-04-12 16:50:39 +02:00
void * glkitview_init ( void ) ;
2015-04-05 05:36:53 +02:00
2019-01-26 13:18:32 -10:00
# ifdef HAVE_COCOATOUCH
@ interface CocoaView ( ) < GCDWebUploaderDelegate > {
2019-02-03 15:49:35 -08:00
2019-01-26 13:18:32 -10:00
}
@ end
# endif
2015-04-20 20:39:39 +02:00
@ implementation CocoaView
2016-10-05 02:00:11 +02:00
2019-02-09 21:10:28 +01:00
# if defined ( HAVE_COCOA _METAL )
- ( BOOL ) layer : ( CALayer * ) layer shouldInheritContentsScale : ( CGFloat ) newScale fromWindow : ( NSWindow * ) window {
return YES ;
}
# endif
2016-10-05 02:00:11 +02:00
2019-02-09 21:10:28 +01:00
# if defined ( HAVE_COCOA ) || defined ( HAVE_COCOA _METAL )
2016-10-05 02:00:11 +02:00
- ( void ) scrollWheel : ( NSEvent * ) theEvent {
cocoa_input _data _t * apple = ( cocoa_input _data _t * ) input_driver _get _data ( ) ;
( void ) apple ;
}
# endif
2015-04-20 20:39:39 +02:00
+ ( CocoaView * ) get
2015-04-05 05:36:53 +02:00
{
if ( ! g_instance )
2015-04-20 20:39:39 +02:00
g_instance = [ CocoaView new ] ;
2019-02-03 15:49:35 -08:00
2015-04-05 05:36:53 +02:00
return g_instance ;
}
- ( id ) init
{
self = [ super init ] ;
2019-02-03 15:49:35 -08:00
2019-02-09 21:10:28 +01:00
# if defined ( HAVE_COCOA ) || defined ( HAVE_COCOA _METAL )
2015-04-05 05:36:53 +02:00
[ self setAutoresizingMask : NSViewWidthSizable | NSViewHeightSizable ] ;
2019-02-09 21:10:28 +01:00
# endif
# if defined ( HAVE_COCOA )
2018-11-04 09:29:40 -07:00
ui_window _cocoa _t cocoa_view ;
cocoa_view . data = ( CocoaView * ) self ;
2019-02-03 15:49:35 -08:00
2016-06-04 08:45:20 +02:00
[ self registerForDraggedTypes : [ NSArray arrayWithObjects : NSColorPboardType , NSFilenamesPboardType , nil ] ] ;
2019-02-09 21:10:28 +01:00
# elif defined ( HAVE_COCOA _METAL )
[ self registerForDraggedTypes : @ [ NSColorPboardType , NSFilenamesPboardType ] ] ;
2015-04-20 00:38:55 +02:00
# elif defined ( HAVE_COCOATOUCH )
2019-02-09 21:10:28 +01:00
self . view = ( BRIDGE GLKView * ) glkitview_init ( ) ;
2019-02-03 15:49:35 -08:00
# if TARGET_OS _IOS
2019-06-14 08:35:33 -10:00
UISwipeGestureRecognizer * swipe = [ [ UISwipeGestureRecognizer alloc ] initWithTarget : self action : @ selector ( showNativeMenu ) ] ;
swipe . numberOfTouchesRequired = 4 ;
swipe . direction = UISwipeGestureRecognizerDirectionDown ;
[ self . view addGestureRecognizer : swipe ] ;
2015-04-05 05:36:53 +02:00
# endif
2019-02-03 15:49:35 -08:00
# endif
2015-04-05 05:36:53 +02:00
return self ;
}
2019-02-09 21:10:28 +01:00
# if defined ( HAVE_COCOA ) || defined ( HAVE_COCOA _METAL )
2015-04-05 05:36:53 +02:00
- ( void ) setFrame : ( NSRect ) frameRect
{
[ super setFrame : frameRect ] ;
2018-11-04 09:29:40 -07:00
2015-04-19 17:40:10 +02:00
cocoagl_gfx _ctx _update ( ) ;
2015-04-05 05:36:53 +02:00
}
/ * Stop the annoying sound when pressing a key . * /
- ( BOOL ) acceptsFirstResponder
{
return YES ;
}
- ( BOOL ) isFlipped
{
return YES ;
}
- ( void ) keyDown : ( NSEvent * ) theEvent
{
}
2016-06-03 19:21:22 +02:00
- ( NSDragOperation ) draggingEntered : ( id < NSDraggingInfo > ) sender
{
NSDragOperation sourceDragMask = [ sender draggingSourceOperationMask ] ;
NSPasteboard * pboard = [ sender draggingPasteboard ] ;
2019-02-03 15:49:35 -08:00
2016-06-03 19:21:22 +02:00
if ( [ [ pboard types ] containsObject : NSFilenamesPboardType ] )
{
if ( sourceDragMask & NSDragOperationCopy )
return NSDragOperationCopy ;
}
2019-02-03 15:49:35 -08:00
2016-06-03 19:21:22 +02:00
return NSDragOperationNone ;
}
- ( BOOL ) performDragOperation : ( id < NSDraggingInfo > ) sender
{
NSPasteboard * pboard = [ sender draggingPasteboard ] ;
2019-02-03 15:49:35 -08:00
2016-06-03 19:21:22 +02:00
if ( [ [ pboard types ] containsObject : NSURLPboardType ] )
{
NSURL * fileURL = [ NSURL URLFromPasteboard : pboard ] ;
NSString * s = [ fileURL path ] ;
if ( s ! = nil )
{
RARCH_LOG ( "Drop name is: %s\n" , [ s UTF8String ] ) ;
}
}
return YES ;
}
- ( void ) draggingExited : ( id < NSDraggingInfo > ) sender
{
[ self setNeedsDisplay : YES ] ;
}
2019-01-26 13:18:32 -10:00
# elif TARGET_OS _IOS
2019-06-14 08:35:33 -10:00
- ( void ) showNativeMenu {
[ [ RetroArch_iOS get ] toggleUI ] ;
}
2018-11-27 09:29:30 -10:00
- ( UIRectEdge ) preferredScreenEdgesDeferringSystemGestures
{
return UIRectEdgeBottom ;
}
- ( BOOL ) prefersHomeIndicatorAutoHidden
{
return NO ;
}
- ( void ) viewWillTransitionToSize : ( CGSize ) size withTransitionCoordinator : ( id < UIViewControllerTransitionCoordinator > ) coordinator {
[ super viewWillTransitionToSize : size withTransitionCoordinator : coordinator ] ;
if ( @ available ( iOS 11 , * ) ) {
[ coordinator animateAlongsideTransition : ^ ( id < UIViewControllerTransitionCoordinatorContext > _Nonnull context ) {
[ self adjustViewFrameForSafeArea ] ;
} completion : ^ ( id < UIViewControllerTransitionCoordinatorContext > _Nonnull context ) {
} ] ;
}
}
- ( void ) adjustViewFrameForSafeArea {
// This is for adjusting the view frame to account for the notch in iPhone X phones
if ( @ available ( iOS 11 , * ) ) {
2019-02-09 21:10:28 +01:00
RAScreen * screen = ( BRIDGE RAScreen * ) get_chosen _screen ( ) ;
2018-11-27 09:29:30 -10:00
CGRect screenSize = [ screen bounds ] ;
UIEdgeInsets inset = [ [ UIApplication sharedApplication ] delegate ] . window . safeAreaInsets ;
UIInterfaceOrientation orientation = [ [ UIApplication sharedApplication ] statusBarOrientation ] ;
CGRect newFrame = screenSize ;
if ( orientation = = UIInterfaceOrientationPortrait ) {
newFrame = CGRectMake ( screenSize . origin . x , screenSize . origin . y + inset . top , screenSize . size . width , screenSize . size . height - inset . top ) ;
2019-05-19 21:11:30 +02:00
} else if ( orientation = = UIInterfaceOrientationLandscapeLeft ) {
newFrame = CGRectMake ( screenSize . origin . x + inset . right , screenSize . origin . y , screenSize . size . width - inset . right * 2 , screenSize . size . height ) ;
} else if ( orientation = = UIInterfaceOrientationLandscapeRight ) {
newFrame = CGRectMake ( screenSize . origin . x + inset . left , screenSize . origin . y , screenSize . size . width - inset . left * 2 , screenSize . size . height ) ;
2018-11-27 09:29:30 -10:00
}
self . view . frame = newFrame ;
}
}
2019-02-09 21:10:28 +01:00
2015-04-05 05:36:53 +02:00
- ( void ) viewWillLayoutSubviews
{
2015-11-05 22:11:46 +01:00
float width = 0.0 f , height = 0.0 f , tenpctw , tenpcth ;
2019-02-09 21:10:28 +01:00
RAScreen * screen = ( BRIDGE RAScreen * ) get_chosen _screen ( ) ;
2018-11-04 09:29:40 -07:00
UIInterfaceOrientation orientation = self . interfaceOrientation ;
2015-11-05 22:13:49 +01:00
CGRect screenSize = [ screen bounds ] ;
2015-11-05 22:11:46 +01:00
SEL selector = NSSelectorFromString ( BOXSTRING ( "coordinateSpace" ) ) ;
2019-02-03 15:49:35 -08:00
2015-11-05 22:11:46 +01:00
if ( [ screen respondsToSelector : selector ] )
{
screenSize = [ [ screen coordinateSpace ] bounds ] ;
width = CGRectGetWidth ( screenSize ) ;
height = CGRectGetHeight ( screenSize ) ;
}
else
{
width = ( ( int ) orientation < 3 ) ? CGRectGetWidth ( screenSize ) : CGRectGetHeight ( screenSize ) ;
height = ( ( int ) orientation < 3 ) ? CGRectGetHeight ( screenSize ) : CGRectGetWidth ( screenSize ) ;
}
2019-02-03 15:49:35 -08:00
2015-11-05 22:11:46 +01:00
tenpctw = width / 10.0 f ;
tenpcth = height / 10.0 f ;
2019-02-03 15:49:35 -08:00
2018-11-27 09:29:30 -10:00
[ self adjustViewFrameForSafeArea ] ;
2015-04-05 05:36:53 +02:00
}
/ * NOTE : This version runs on iOS6 + . * /
- ( NSUInteger ) supportedInterfaceOrientations
{
2016-05-02 14:54:08 +02:00
return ( NSUInteger ) apple_frontend _settings . orientation_flags ;
2015-04-05 05:36:53 +02:00
}
/ * NOTE : This version runs on iOS2 - iOS5 , but not iOS6 + . * /
- ( BOOL ) shouldAutorotateToInterfaceOrientation : ( UIInterfaceOrientation ) interfaceOrientation
{
switch ( interfaceOrientation )
{
case UIInterfaceOrientationPortrait :
return ( apple_frontend _settings . orientation_flags & UIInterfaceOrientationMaskPortrait ) ;
case UIInterfaceOrientationPortraitUpsideDown :
return ( apple_frontend _settings . orientation_flags & UIInterfaceOrientationMaskPortraitUpsideDown ) ;
case UIInterfaceOrientationLandscapeLeft :
return ( apple_frontend _settings . orientation_flags & UIInterfaceOrientationMaskLandscapeLeft ) ;
case UIInterfaceOrientationLandscapeRight :
return ( apple_frontend _settings . orientation_flags & UIInterfaceOrientationMaskLandscapeRight ) ;
default :
return ( apple_frontend _settings . orientation_flags & UIInterfaceOrientationMaskAll ) ;
}
2019-02-03 15:49:35 -08:00
2015-04-05 05:36:53 +02:00
return YES ;
}
# endif
2019-01-26 13:18:32 -10:00
# ifdef HAVE_COCOATOUCH
- ( void ) viewDidAppear : ( BOOL ) animated
{
# if TARGET_OS _IOS
if ( @ available ( iOS 11.0 , * ) ) {
[ self setNeedsUpdateOfHomeIndicatorAutoHidden ] ;
}
# elif TARGET_OS _TV
2019-02-03 15:49:35 -08:00
2019-01-26 13:18:32 -10:00
# endif
}
- ( void ) viewWillAppear : ( BOOL ) animated {
[ super viewWillAppear : animated ] ;
# if TARGET_OS _TV
[ [ WebServer sharedInstance ] startUploader ] ;
[ WebServer sharedInstance ] . webUploader . delegate = self ;
# endif
}
# pragma mark GCDWebServerDelegate
- ( void ) webServerDidCompleteBonjourRegistration : ( GCDWebServer * ) server {
NSMutableString * servers = [ [ NSMutableString alloc ] init ] ;
if ( server . serverURL ! = nil ) {
[ servers appendString : [ NSString stringWithFormat : @ "%@" , server . serverURL ] ] ;
}
if ( servers . length > 0 ) {
[ servers appendString : @ "\n\n" ] ;
}
if ( server . bonjourServerURL ! = nil ) {
[ servers appendString : [ NSString stringWithFormat : @ "%@" , server . bonjourServerURL ] ] ;
}
# if TARGET_OS _TV
2019-02-03 08:59:24 -10:00
UIAlertController * alert = [ UIAlertController alertControllerWithTitle : @ "Welcome to RetroArch" message : [ NSString stringWithFormat : @ "To transfer files from your computer, go to one of these addresses on your web browser:\n\n%@" , servers ] preferredStyle : UIAlertControllerStyleAlert ] ;
2019-01-26 13:18:32 -10:00
[ alert addAction : [ UIAlertAction actionWithTitle : @ "OK" style : UIAlertActionStyleDefault handler : ^ ( UIAlertAction * _Nonnull action ) {
} ] ] ;
[ self presentViewController : alert animated : YES completion : ^ {
} ] ;
# elif TARGET_OS _IOS
UIAlertController * alert = [ UIAlertController alertControllerWithTitle : @ "Web Server Started" message : [ NSString stringWithFormat : @ "To transfer ROMs from your computer, go to one of these addresses on your web browser:\n\n%@" , servers ] preferredStyle : UIAlertControllerStyleAlert ] ;
[ alert addAction : [ UIAlertAction actionWithTitle : @ "Stop Server" style : UIAlertActionStyleDefault handler : ^ ( UIAlertAction * _Nonnull action ) {
[ [ WebServer sharedInstance ] webUploader ] . delegate = nil ;
[ [ WebServer sharedInstance ] stopUploader ] ;
} ] ] ;
[ self presentViewController : alert animated : YES completion : ^ {
} ] ;
# endif
}
# endif // end HAVE_COCOATOUCH
2015-04-05 05:36:53 +02:00
@ end