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.

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