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.

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