The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

754 lines
28KB

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