juce_ios_Windowing.mm 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. namespace juce
  20. {
  21. extern bool isIOSAppActive;
  22. struct AppInactivityCallback // NB: careful, this declaration is duplicated in other modules
  23. {
  24. virtual ~AppInactivityCallback() {}
  25. virtual void appBecomingInactive() = 0;
  26. };
  27. // This is an internal list of callbacks (but currently used between modules)
  28. Array<AppInactivityCallback*> appBecomingInactiveCallbacks;
  29. }
  30. #if JUCE_PUSH_NOTIFICATIONS && defined (__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
  31. @interface JuceAppStartupDelegate : NSObject <UIApplicationDelegate, UNUserNotificationCenterDelegate>
  32. #else
  33. @interface JuceAppStartupDelegate : NSObject <UIApplicationDelegate>
  34. #endif
  35. {
  36. UIBackgroundTaskIdentifier appSuspendTask;
  37. }
  38. @property (strong, nonatomic) UIWindow *window;
  39. - (id) init;
  40. - (void) dealloc;
  41. - (void) applicationDidFinishLaunching: (UIApplication*) application;
  42. - (void) applicationWillTerminate: (UIApplication*) application;
  43. - (void) applicationDidEnterBackground: (UIApplication*) application;
  44. - (void) applicationWillEnterForeground: (UIApplication*) application;
  45. - (void) applicationDidBecomeActive: (UIApplication*) application;
  46. - (void) applicationWillResignActive: (UIApplication*) application;
  47. - (void) application: (UIApplication*) application handleEventsForBackgroundURLSession: (NSString*) identifier
  48. completionHandler: (void (^)(void)) completionHandler;
  49. - (void) applicationDidReceiveMemoryWarning: (UIApplication *) application;
  50. #if JUCE_PUSH_NOTIFICATIONS
  51. - (void) application: (UIApplication*) application didRegisterUserNotificationSettings: (UIUserNotificationSettings*) notificationSettings;
  52. - (void) application: (UIApplication*) application didRegisterForRemoteNotificationsWithDeviceToken: (NSData*) deviceToken;
  53. - (void) application: (UIApplication*) application didFailToRegisterForRemoteNotificationsWithError: (NSError*) error;
  54. - (void) application: (UIApplication*) application didReceiveRemoteNotification: (NSDictionary*) userInfo;
  55. - (void) application: (UIApplication*) application didReceiveRemoteNotification: (NSDictionary*) userInfo
  56. fetchCompletionHandler: (void (^)(UIBackgroundFetchResult result)) completionHandler;
  57. - (void) application: (UIApplication*) application handleActionWithIdentifier: (NSString*) identifier
  58. forRemoteNotification: (NSDictionary*) userInfo withResponseInfo: (NSDictionary*) responseInfo
  59. completionHandler: (void(^)()) completionHandler;
  60. - (void) application: (UIApplication*) application didReceiveLocalNotification: (UILocalNotification*) notification;
  61. - (void) application: (UIApplication*) application handleActionWithIdentifier: (NSString*) identifier
  62. forLocalNotification: (UILocalNotification*) notification completionHandler: (void(^)()) completionHandler;
  63. - (void) application: (UIApplication*) application handleActionWithIdentifier: (NSString*) identifier
  64. forLocalNotification: (UILocalNotification*) notification withResponseInfo: (NSDictionary*) responseInfo
  65. completionHandler: (void(^)()) completionHandler;
  66. #if defined (__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
  67. - (void) userNotificationCenter: (UNUserNotificationCenter*) center willPresentNotification: (UNNotification*) notification
  68. withCompletionHandler: (void (^)(UNNotificationPresentationOptions options)) completionHandler;
  69. - (void) userNotificationCenter: (UNUserNotificationCenter*) center didReceiveNotificationResponse: (UNNotificationResponse*) response
  70. withCompletionHandler: (void(^)())completionHandler;
  71. #endif
  72. #endif
  73. @end
  74. @implementation JuceAppStartupDelegate
  75. NSObject* _pushNotificationsDelegate;
  76. - (id) init
  77. {
  78. self = [super init];
  79. appSuspendTask = UIBackgroundTaskInvalid;
  80. #if JUCE_PUSH_NOTIFICATIONS && defined (__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
  81. [UNUserNotificationCenter currentNotificationCenter].delegate = self;
  82. #endif
  83. return self;
  84. }
  85. - (void) dealloc
  86. {
  87. [super dealloc];
  88. }
  89. - (void) applicationDidFinishLaunching: (UIApplication*) application
  90. {
  91. ignoreUnused (application);
  92. initialiseJuce_GUI();
  93. if (auto* app = JUCEApplicationBase::createInstance())
  94. {
  95. if (! app->initialiseApp())
  96. exit (app->shutdownApp());
  97. }
  98. else
  99. {
  100. jassertfalse; // you must supply an application object for an iOS app!
  101. }
  102. }
  103. - (void) applicationWillTerminate: (UIApplication*) application
  104. {
  105. ignoreUnused (application);
  106. JUCEApplicationBase::appWillTerminateByForce();
  107. }
  108. - (void) applicationDidEnterBackground: (UIApplication*) application
  109. {
  110. if (auto* app = JUCEApplicationBase::getInstance())
  111. {
  112. #if JUCE_EXECUTE_APP_SUSPEND_ON_BACKGROUND_TASK
  113. appSuspendTask = [application beginBackgroundTaskWithName:@"JUCE Suspend Task" expirationHandler:^{
  114. if (appSuspendTask != UIBackgroundTaskInvalid)
  115. {
  116. [application endBackgroundTask:appSuspendTask];
  117. appSuspendTask = UIBackgroundTaskInvalid;
  118. }
  119. }];
  120. MessageManager::callAsync ([app] { app->suspended(); });
  121. #else
  122. ignoreUnused (application);
  123. app->suspended();
  124. #endif
  125. }
  126. }
  127. - (void) applicationWillEnterForeground: (UIApplication*) application
  128. {
  129. ignoreUnused (application);
  130. if (auto* app = JUCEApplicationBase::getInstance())
  131. app->resumed();
  132. }
  133. - (void) applicationDidBecomeActive: (UIApplication*) application
  134. {
  135. application.applicationIconBadgeNumber = 0;
  136. isIOSAppActive = true;
  137. }
  138. - (void) applicationWillResignActive: (UIApplication*) application
  139. {
  140. ignoreUnused (application);
  141. isIOSAppActive = false;
  142. for (int i = appBecomingInactiveCallbacks.size(); --i >= 0;)
  143. appBecomingInactiveCallbacks.getReference(i)->appBecomingInactive();
  144. }
  145. - (void) application: (UIApplication*) application handleEventsForBackgroundURLSession: (NSString*)identifier
  146. completionHandler: (void (^)(void))completionHandler
  147. {
  148. ignoreUnused (application);
  149. URL::DownloadTask::juce_iosURLSessionNotify (nsStringToJuce (identifier));
  150. completionHandler();
  151. }
  152. - (void) applicationDidReceiveMemoryWarning: (UIApplication*) application
  153. {
  154. ignoreUnused (application);
  155. if (auto* app = JUCEApplicationBase::getInstance())
  156. app->memoryWarningReceived();
  157. }
  158. - (void) setPushNotificationsDelegateToUse: (NSObject*) delegate
  159. {
  160. _pushNotificationsDelegate = delegate;
  161. }
  162. #if JUCE_PUSH_NOTIFICATIONS
  163. - (void) application: (UIApplication*) application didRegisterUserNotificationSettings: (UIUserNotificationSettings*) notificationSettings
  164. {
  165. ignoreUnused (application);
  166. SEL selector = NSSelectorFromString (@"application:didRegisterUserNotificationSettings:");
  167. if (_pushNotificationsDelegate != nil && [_pushNotificationsDelegate respondsToSelector: selector])
  168. {
  169. NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: [_pushNotificationsDelegate methodSignatureForSelector: selector]];
  170. [invocation setSelector: selector];
  171. [invocation setTarget: _pushNotificationsDelegate];
  172. [invocation setArgument: &application atIndex:2];
  173. [invocation setArgument: &notificationSettings atIndex:3];
  174. [invocation invoke];
  175. }
  176. }
  177. - (void) application: (UIApplication*) application didRegisterForRemoteNotificationsWithDeviceToken: (NSData*) deviceToken
  178. {
  179. ignoreUnused (application);
  180. SEL selector = NSSelectorFromString (@"application:didRegisterForRemoteNotificationsWithDeviceToken:");
  181. if (_pushNotificationsDelegate != nil && [_pushNotificationsDelegate respondsToSelector: selector])
  182. {
  183. NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: [_pushNotificationsDelegate methodSignatureForSelector: selector]];
  184. [invocation setSelector: selector];
  185. [invocation setTarget: _pushNotificationsDelegate];
  186. [invocation setArgument: &application atIndex:2];
  187. [invocation setArgument: &deviceToken atIndex:3];
  188. [invocation invoke];
  189. }
  190. }
  191. - (void) application: (UIApplication*) application didFailToRegisterForRemoteNotificationsWithError: (NSError*) error
  192. {
  193. ignoreUnused (application);
  194. SEL selector = NSSelectorFromString (@"application:didFailToRegisterForRemoteNotificationsWithError:");
  195. if (_pushNotificationsDelegate != nil && [_pushNotificationsDelegate respondsToSelector: selector])
  196. {
  197. NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: [_pushNotificationsDelegate methodSignatureForSelector: selector]];
  198. [invocation setSelector: selector];
  199. [invocation setTarget: _pushNotificationsDelegate];
  200. [invocation setArgument: &application atIndex:2];
  201. [invocation setArgument: &error atIndex:3];
  202. [invocation invoke];
  203. }
  204. }
  205. - (void) application: (UIApplication*) application didReceiveRemoteNotification: (NSDictionary*) userInfo
  206. {
  207. ignoreUnused (application);
  208. SEL selector = NSSelectorFromString (@"application:didReceiveRemoteNotification:");
  209. if (_pushNotificationsDelegate != nil && [_pushNotificationsDelegate respondsToSelector: selector])
  210. {
  211. NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: [_pushNotificationsDelegate methodSignatureForSelector: selector]];
  212. [invocation setSelector: selector];
  213. [invocation setTarget: _pushNotificationsDelegate];
  214. [invocation setArgument: &application atIndex:2];
  215. [invocation setArgument: &userInfo atIndex:3];
  216. [invocation invoke];
  217. }
  218. }
  219. - (void) application: (UIApplication*) application didReceiveRemoteNotification: (NSDictionary*) userInfo
  220. fetchCompletionHandler: (void (^)(UIBackgroundFetchResult result)) completionHandler
  221. {
  222. ignoreUnused (application);
  223. SEL selector = NSSelectorFromString (@"application:didReceiveRemoteNotification:fetchCompletionHandler:");
  224. if (_pushNotificationsDelegate != nil && [_pushNotificationsDelegate respondsToSelector: selector])
  225. {
  226. NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: [_pushNotificationsDelegate methodSignatureForSelector: selector]];
  227. [invocation setSelector: selector];
  228. [invocation setTarget: _pushNotificationsDelegate];
  229. [invocation setArgument: &application atIndex:2];
  230. [invocation setArgument: &userInfo atIndex:3];
  231. [invocation setArgument: &completionHandler atIndex:4];
  232. [invocation invoke];
  233. }
  234. }
  235. - (void) application: (UIApplication*) application handleActionWithIdentifier: (NSString*) identifier
  236. forRemoteNotification: (NSDictionary*) userInfo withResponseInfo: (NSDictionary*) responseInfo
  237. completionHandler: (void(^)()) completionHandler
  238. {
  239. ignoreUnused (application);
  240. SEL selector = NSSelectorFromString (@"application:handleActionWithIdentifier:forRemoteNotification:withResponseInfo:completionHandler:");
  241. if (_pushNotificationsDelegate != nil && [_pushNotificationsDelegate respondsToSelector: selector])
  242. {
  243. NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: [_pushNotificationsDelegate methodSignatureForSelector: selector]];
  244. [invocation setSelector: selector];
  245. [invocation setTarget: _pushNotificationsDelegate];
  246. [invocation setArgument: &application atIndex:2];
  247. [invocation setArgument: &identifier atIndex:3];
  248. [invocation setArgument: &userInfo atIndex:4];
  249. [invocation setArgument: &responseInfo atIndex:5];
  250. [invocation setArgument: &completionHandler atIndex:6];
  251. [invocation invoke];
  252. }
  253. }
  254. - (void) application: (UIApplication*) application didReceiveLocalNotification: (UILocalNotification*) notification
  255. {
  256. ignoreUnused (application);
  257. SEL selector = NSSelectorFromString (@"application:didReceiveLocalNotification:");
  258. if (_pushNotificationsDelegate != nil && [_pushNotificationsDelegate respondsToSelector: selector])
  259. {
  260. NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: [_pushNotificationsDelegate methodSignatureForSelector: selector]];
  261. [invocation setSelector: selector];
  262. [invocation setTarget: _pushNotificationsDelegate];
  263. [invocation setArgument: &application atIndex:2];
  264. [invocation setArgument: &notification atIndex:3];
  265. [invocation invoke];
  266. }
  267. }
  268. - (void) application: (UIApplication*) application handleActionWithIdentifier: (NSString*) identifier
  269. forLocalNotification: (UILocalNotification*) notification completionHandler: (void(^)()) completionHandler
  270. {
  271. ignoreUnused (application);
  272. SEL selector = NSSelectorFromString (@"application:handleActionWithIdentifier:forLocalNotification:completionHandler:");
  273. if (_pushNotificationsDelegate != nil && [_pushNotificationsDelegate respondsToSelector: selector])
  274. {
  275. NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: [_pushNotificationsDelegate methodSignatureForSelector: selector]];
  276. [invocation setSelector: selector];
  277. [invocation setTarget: _pushNotificationsDelegate];
  278. [invocation setArgument: &application atIndex:2];
  279. [invocation setArgument: &identifier atIndex:3];
  280. [invocation setArgument: &notification atIndex:4];
  281. [invocation setArgument: &completionHandler atIndex:5];
  282. [invocation invoke];
  283. }
  284. }
  285. - (void) application: (UIApplication*) application handleActionWithIdentifier: (NSString*) identifier
  286. forLocalNotification: (UILocalNotification*) notification withResponseInfo: (NSDictionary*) responseInfo
  287. completionHandler: (void(^)()) completionHandler
  288. {
  289. ignoreUnused (application);
  290. SEL selector = NSSelectorFromString (@"application:handleActionWithIdentifier:forLocalNotification:withResponseInfo:completionHandler:");
  291. if (_pushNotificationsDelegate != nil && [_pushNotificationsDelegate respondsToSelector: selector])
  292. {
  293. NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: [_pushNotificationsDelegate methodSignatureForSelector: selector]];
  294. [invocation setSelector: selector];
  295. [invocation setTarget: _pushNotificationsDelegate];
  296. [invocation setArgument: &application atIndex:2];
  297. [invocation setArgument: &identifier atIndex:3];
  298. [invocation setArgument: &notification atIndex:4];
  299. [invocation setArgument: &responseInfo atIndex:5];
  300. [invocation setArgument: &completionHandler atIndex:6];
  301. [invocation invoke];
  302. }
  303. }
  304. #if defined (__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
  305. - (void) userNotificationCenter: (UNUserNotificationCenter*) center willPresentNotification: (UNNotification*) notification
  306. withCompletionHandler: (void (^)(UNNotificationPresentationOptions options)) completionHandler
  307. {
  308. ignoreUnused (center);
  309. SEL selector = NSSelectorFromString (@"userNotificationCenter:willPresentNotification:withCompletionHandler:");
  310. if (_pushNotificationsDelegate != nil && [_pushNotificationsDelegate respondsToSelector: selector])
  311. {
  312. NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: [_pushNotificationsDelegate methodSignatureForSelector: selector]];
  313. [invocation setSelector: selector];
  314. [invocation setTarget: _pushNotificationsDelegate];
  315. [invocation setArgument: &center atIndex:2];
  316. [invocation setArgument: &notification atIndex:3];
  317. [invocation setArgument: &completionHandler atIndex:4];
  318. [invocation invoke];
  319. }
  320. }
  321. - (void) userNotificationCenter: (UNUserNotificationCenter*) center didReceiveNotificationResponse: (UNNotificationResponse*) response
  322. withCompletionHandler: (void(^)()) completionHandler
  323. {
  324. ignoreUnused (center);
  325. SEL selector = NSSelectorFromString (@"userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:");
  326. if (_pushNotificationsDelegate != nil && [_pushNotificationsDelegate respondsToSelector: selector])
  327. {
  328. NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: [_pushNotificationsDelegate methodSignatureForSelector: selector]];
  329. [invocation setSelector: selector];
  330. [invocation setTarget: _pushNotificationsDelegate];
  331. [invocation setArgument: &center atIndex:2];
  332. [invocation setArgument: &response atIndex:3];
  333. [invocation setArgument: &completionHandler atIndex:4];
  334. [invocation invoke];
  335. }
  336. }
  337. #endif
  338. #endif
  339. @end
  340. namespace juce
  341. {
  342. int juce_iOSMain (int argc, const char* argv[], void* customDelegatePtr);
  343. int juce_iOSMain (int argc, const char* argv[], void* customDelegatePtr)
  344. {
  345. Class delegateClass = (customDelegatePtr != nullptr ? reinterpret_cast<Class> (customDelegatePtr) : [JuceAppStartupDelegate class]);
  346. return UIApplicationMain (argc, const_cast<char**> (argv), nil, NSStringFromClass (delegateClass));
  347. }
  348. //==============================================================================
  349. void LookAndFeel::playAlertSound()
  350. {
  351. // TODO
  352. }
  353. //==============================================================================
  354. class iOSMessageBox;
  355. #if defined (__IPHONE_8_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0
  356. #define JUCE_USE_NEW_IOS_ALERTWINDOW 1
  357. #endif
  358. #if ! JUCE_USE_NEW_IOS_ALERTWINDOW
  359. } // (juce namespace)
  360. @interface JuceAlertBoxDelegate : NSObject <UIAlertViewDelegate>
  361. {
  362. @public
  363. iOSMessageBox* owner;
  364. }
  365. - (void) alertView: (UIAlertView*) alertView clickedButtonAtIndex: (NSInteger) buttonIndex;
  366. @end
  367. namespace juce
  368. {
  369. #endif
  370. class iOSMessageBox
  371. {
  372. public:
  373. iOSMessageBox (const String& title, const String& message,
  374. NSString* button1, NSString* button2, NSString* button3,
  375. ModalComponentManager::Callback* cb, const bool async)
  376. : result (0), resultReceived (false), callback (cb), isAsync (async)
  377. {
  378. #if JUCE_USE_NEW_IOS_ALERTWINDOW
  379. if (currentlyFocusedPeer != nullptr)
  380. {
  381. UIAlertController* alert = [UIAlertController alertControllerWithTitle: juceStringToNS (title)
  382. message: juceStringToNS (message)
  383. preferredStyle: UIAlertControllerStyleAlert];
  384. addButton (alert, button1, 0);
  385. addButton (alert, button2, 1);
  386. addButton (alert, button3, 2);
  387. [currentlyFocusedPeer->controller presentViewController: alert
  388. animated: YES
  389. completion: nil];
  390. }
  391. else
  392. {
  393. // Since iOS8, alert windows need to be associated with a window, so you need to
  394. // have at least one window on screen when you use this
  395. jassertfalse;
  396. }
  397. #else
  398. delegate = [[JuceAlertBoxDelegate alloc] init];
  399. delegate->owner = this;
  400. alert = [[UIAlertView alloc] initWithTitle: juceStringToNS (title)
  401. message: juceStringToNS (message)
  402. delegate: delegate
  403. cancelButtonTitle: button1
  404. otherButtonTitles: button2, button3, nil];
  405. [alert retain];
  406. [alert show];
  407. #endif
  408. }
  409. ~iOSMessageBox()
  410. {
  411. #if ! JUCE_USE_NEW_IOS_ALERTWINDOW
  412. [alert release];
  413. [delegate release];
  414. #endif
  415. }
  416. int getResult()
  417. {
  418. jassert (callback == nullptr);
  419. JUCE_AUTORELEASEPOOL
  420. {
  421. #if JUCE_USE_NEW_IOS_ALERTWINDOW
  422. while (! resultReceived)
  423. #else
  424. while (! (alert.hidden || resultReceived))
  425. #endif
  426. [[NSRunLoop mainRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]];
  427. }
  428. return result;
  429. }
  430. void buttonClicked (const int buttonIndex) noexcept
  431. {
  432. result = buttonIndex;
  433. resultReceived = true;
  434. if (callback != nullptr)
  435. callback->modalStateFinished (result);
  436. if (isAsync)
  437. delete this;
  438. }
  439. private:
  440. int result;
  441. bool resultReceived;
  442. std::unique_ptr<ModalComponentManager::Callback> callback;
  443. const bool isAsync;
  444. #if JUCE_USE_NEW_IOS_ALERTWINDOW
  445. void addButton (UIAlertController* alert, NSString* text, int index)
  446. {
  447. if (text != nil)
  448. [alert addAction: [UIAlertAction actionWithTitle: text
  449. style: UIAlertActionStyleDefault
  450. handler: ^(UIAlertAction*) { this->buttonClicked (index); }]];
  451. }
  452. #else
  453. UIAlertView* alert;
  454. JuceAlertBoxDelegate* delegate;
  455. #endif
  456. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (iOSMessageBox)
  457. };
  458. #if ! JUCE_USE_NEW_IOS_ALERTWINDOW
  459. } // (juce namespace)
  460. @implementation JuceAlertBoxDelegate
  461. - (void) alertView: (UIAlertView*) alertView clickedButtonAtIndex: (NSInteger) buttonIndex
  462. {
  463. owner->buttonClicked ((int) buttonIndex);
  464. alertView.hidden = true;
  465. }
  466. @end
  467. namespace juce
  468. {
  469. #endif
  470. //==============================================================================
  471. #if JUCE_MODAL_LOOPS_PERMITTED
  472. void JUCE_CALLTYPE NativeMessageBox::showMessageBox (AlertWindow::AlertIconType /*iconType*/,
  473. const String& title, const String& message,
  474. Component* /*associatedComponent*/)
  475. {
  476. JUCE_AUTORELEASEPOOL
  477. {
  478. iOSMessageBox mb (title, message, @"OK", nil, nil, nullptr, false);
  479. ignoreUnused (mb.getResult());
  480. }
  481. }
  482. #endif
  483. void JUCE_CALLTYPE NativeMessageBox::showMessageBoxAsync (AlertWindow::AlertIconType /*iconType*/,
  484. const String& title, const String& message,
  485. Component* /*associatedComponent*/,
  486. ModalComponentManager::Callback* callback)
  487. {
  488. new iOSMessageBox (title, message, @"OK", nil, nil, callback, true);
  489. }
  490. bool JUCE_CALLTYPE NativeMessageBox::showOkCancelBox (AlertWindow::AlertIconType /*iconType*/,
  491. const String& title, const String& message,
  492. Component* /*associatedComponent*/,
  493. ModalComponentManager::Callback* callback)
  494. {
  495. std::unique_ptr<iOSMessageBox> mb (new iOSMessageBox (title, message, @"Cancel", @"OK",
  496. nil, callback, callback != nullptr));
  497. if (callback == nullptr)
  498. return mb->getResult() == 1;
  499. mb.release();
  500. return false;
  501. }
  502. int JUCE_CALLTYPE NativeMessageBox::showYesNoCancelBox (AlertWindow::AlertIconType /*iconType*/,
  503. const String& title, const String& message,
  504. Component* /*associatedComponent*/,
  505. ModalComponentManager::Callback* callback)
  506. {
  507. std::unique_ptr<iOSMessageBox> mb (new iOSMessageBox (title, message, @"Cancel", @"Yes", @"No", callback, callback != nullptr));
  508. if (callback == nullptr)
  509. return mb->getResult();
  510. mb.release();
  511. return 0;
  512. }
  513. int JUCE_CALLTYPE NativeMessageBox::showYesNoBox (AlertWindow::AlertIconType /*iconType*/,
  514. const String& title, const String& message,
  515. Component* /*associatedComponent*/,
  516. ModalComponentManager::Callback* callback)
  517. {
  518. std::unique_ptr<iOSMessageBox> mb (new iOSMessageBox (title, message, @"No", @"Yes", nil, callback, callback != nullptr));
  519. if (callback == nullptr)
  520. return mb->getResult();
  521. mb.release();
  522. return 0;
  523. }
  524. //==============================================================================
  525. bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray&, bool, Component*, std::function<void()>)
  526. {
  527. jassertfalse; // no such thing on iOS!
  528. return false;
  529. }
  530. bool DragAndDropContainer::performExternalDragDropOfText (const String&, Component*, std::function<void()>)
  531. {
  532. jassertfalse; // no such thing on iOS!
  533. return false;
  534. }
  535. //==============================================================================
  536. void Desktop::setScreenSaverEnabled (const bool isEnabled)
  537. {
  538. if (! SystemStats::isRunningInAppExtensionSandbox())
  539. [[UIApplication sharedApplication] setIdleTimerDisabled: ! isEnabled];
  540. }
  541. bool Desktop::isScreenSaverEnabled()
  542. {
  543. if (SystemStats::isRunningInAppExtensionSandbox())
  544. return true;
  545. return ! [[UIApplication sharedApplication] isIdleTimerDisabled];
  546. }
  547. //==============================================================================
  548. bool juce_areThereAnyAlwaysOnTopWindows()
  549. {
  550. return false;
  551. }
  552. //==============================================================================
  553. Image juce_createIconForFile (const File&)
  554. {
  555. return Image();
  556. }
  557. //==============================================================================
  558. void SystemClipboard::copyTextToClipboard (const String& text)
  559. {
  560. [[UIPasteboard generalPasteboard] setValue: juceStringToNS (text)
  561. forPasteboardType: @"public.text"];
  562. }
  563. String SystemClipboard::getTextFromClipboard()
  564. {
  565. return nsStringToJuce ([[UIPasteboard generalPasteboard] valueForPasteboardType: @"public.text"]);
  566. }
  567. //==============================================================================
  568. bool MouseInputSource::SourceList::addSource()
  569. {
  570. addSource (sources.size(), MouseInputSource::InputSourceType::touch);
  571. return true;
  572. }
  573. bool MouseInputSource::SourceList::canUseTouch()
  574. {
  575. return true;
  576. }
  577. bool Desktop::canUseSemiTransparentWindows() noexcept
  578. {
  579. return true;
  580. }
  581. Point<float> MouseInputSource::getCurrentRawMousePosition()
  582. {
  583. return juce_lastMousePos;
  584. }
  585. void MouseInputSource::setRawMousePosition (Point<float>)
  586. {
  587. }
  588. double Desktop::getDefaultMasterScale()
  589. {
  590. return 1.0;
  591. }
  592. Desktop::DisplayOrientation Desktop::getCurrentOrientation() const
  593. {
  594. UIInterfaceOrientation orientation = SystemStats::isRunningInAppExtensionSandbox() ? UIInterfaceOrientationPortrait
  595. : [[UIApplication sharedApplication] statusBarOrientation];
  596. return Orientations::convertToJuce (orientation);
  597. }
  598. void Displays::findDisplays (float masterScale)
  599. {
  600. JUCE_AUTORELEASEPOOL
  601. {
  602. UIScreen* s = [UIScreen mainScreen];
  603. Display d;
  604. d.userArea = d.totalArea = UIViewComponentPeer::realScreenPosToRotated (convertToRectInt ([s bounds])) / masterScale;
  605. d.isMain = true;
  606. d.scale = masterScale;
  607. if ([s respondsToSelector: @selector (scale)])
  608. d.scale *= s.scale;
  609. d.dpi = 160 * d.scale;
  610. displays.add (d);
  611. }
  612. }
  613. } // namespace juce