Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

juce_ios_Windowing.mm 28KB

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