juce_ios_Windowing.mm 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. extern bool isIOSAppActive;
  18. } // (juce namespace)
  19. @interface JuceAppStartupDelegate : NSObject <UIApplicationDelegate>
  20. {
  21. }
  22. - (void) applicationDidFinishLaunching: (UIApplication*) application;
  23. - (void) applicationWillTerminate: (UIApplication*) application;
  24. - (void) applicationDidEnterBackground: (UIApplication*) application;
  25. - (void) applicationWillEnterForeground: (UIApplication*) application;
  26. - (void) applicationDidBecomeActive: (UIApplication*) application;
  27. - (void) applicationWillResignActive: (UIApplication*) application;
  28. @end
  29. @implementation JuceAppStartupDelegate
  30. - (void) applicationDidFinishLaunching: (UIApplication*) application
  31. {
  32. (void) application;
  33. initialiseJuce_GUI();
  34. JUCEApplicationBase* app = JUCEApplicationBase::createInstance();
  35. if (! app->initialiseApp())
  36. exit (0);
  37. }
  38. - (void) applicationWillTerminate: (UIApplication*) application
  39. {
  40. (void) application;
  41. JUCEApplicationBase::appWillTerminateByForce();
  42. }
  43. - (void) applicationDidEnterBackground: (UIApplication*) application
  44. {
  45. (void) application;
  46. if (JUCEApplicationBase* const app = JUCEApplicationBase::getInstance())
  47. app->suspended();
  48. }
  49. - (void) applicationWillEnterForeground: (UIApplication*) application
  50. {
  51. (void) application;
  52. if (JUCEApplicationBase* const app = JUCEApplicationBase::getInstance())
  53. app->resumed();
  54. }
  55. - (void) applicationDidBecomeActive: (UIApplication*) application
  56. {
  57. (void) application;
  58. isIOSAppActive = true;
  59. }
  60. - (void) applicationWillResignActive: (UIApplication*) application
  61. {
  62. (void) application;
  63. isIOSAppActive = false;
  64. }
  65. @end
  66. namespace juce
  67. {
  68. int juce_iOSMain (int argc, const char* argv[]);
  69. int juce_iOSMain (int argc, const char* argv[])
  70. {
  71. return UIApplicationMain (argc, const_cast<char**> (argv), nil, @"JuceAppStartupDelegate");
  72. }
  73. //==============================================================================
  74. void LookAndFeel::playAlertSound()
  75. {
  76. //xxx
  77. //AudioServicesPlaySystemSound ();
  78. }
  79. //==============================================================================
  80. class iOSMessageBox;
  81. } // (juce namespace)
  82. @interface JuceAlertBoxDelegate : NSObject <UIAlertViewDelegate>
  83. {
  84. @public
  85. iOSMessageBox* owner;
  86. }
  87. - (void) alertView: (UIAlertView*) alertView clickedButtonAtIndex: (NSInteger) buttonIndex;
  88. @end
  89. namespace juce
  90. {
  91. class iOSMessageBox
  92. {
  93. public:
  94. iOSMessageBox (const String& title, const String& message,
  95. NSString* button1, NSString* button2, NSString* button3,
  96. ModalComponentManager::Callback* cb, const bool async)
  97. : result (0), resultReceived (false), delegate (nil), alert (nil),
  98. callback (cb), isYesNo (button3 != nil), isAsync (async)
  99. {
  100. delegate = [[JuceAlertBoxDelegate alloc] init];
  101. delegate->owner = this;
  102. alert = [[UIAlertView alloc] initWithTitle: juceStringToNS (title)
  103. message: juceStringToNS (message)
  104. delegate: delegate
  105. cancelButtonTitle: button1
  106. otherButtonTitles: button2, button3, nil];
  107. [alert retain];
  108. [alert show];
  109. }
  110. ~iOSMessageBox()
  111. {
  112. [alert release];
  113. [delegate release];
  114. }
  115. int getResult()
  116. {
  117. jassert (callback == nullptr);
  118. JUCE_AUTORELEASEPOOL
  119. {
  120. while (! (alert.hidden || resultReceived))
  121. [[NSRunLoop mainRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]];
  122. }
  123. return result;
  124. }
  125. void buttonClicked (const int buttonIndex) noexcept
  126. {
  127. result = buttonIndex;
  128. resultReceived = true;
  129. if (callback != nullptr)
  130. callback->modalStateFinished (result);
  131. if (isAsync)
  132. delete this;
  133. }
  134. private:
  135. int result;
  136. bool resultReceived;
  137. JuceAlertBoxDelegate* delegate;
  138. UIAlertView* alert;
  139. ScopedPointer<ModalComponentManager::Callback> callback;
  140. const bool isYesNo, isAsync;
  141. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (iOSMessageBox)
  142. };
  143. } // (juce namespace)
  144. @implementation JuceAlertBoxDelegate
  145. - (void) alertView: (UIAlertView*) alertView clickedButtonAtIndex: (NSInteger) buttonIndex
  146. {
  147. owner->buttonClicked ((int) buttonIndex);
  148. alertView.hidden = true;
  149. }
  150. @end
  151. namespace juce
  152. {
  153. //==============================================================================
  154. #if JUCE_MODAL_LOOPS_PERMITTED
  155. void JUCE_CALLTYPE NativeMessageBox::showMessageBox (AlertWindow::AlertIconType /*iconType*/,
  156. const String& title, const String& message,
  157. Component* /*associatedComponent*/)
  158. {
  159. JUCE_AUTORELEASEPOOL
  160. {
  161. iOSMessageBox mb (title, message, @"OK", nil, nil, nullptr, false);
  162. (void) mb.getResult();
  163. }
  164. }
  165. #endif
  166. void JUCE_CALLTYPE NativeMessageBox::showMessageBoxAsync (AlertWindow::AlertIconType /*iconType*/,
  167. const String& title, const String& message,
  168. Component* /*associatedComponent*/,
  169. ModalComponentManager::Callback* callback)
  170. {
  171. new iOSMessageBox (title, message, @"OK", nil, nil, callback, true);
  172. }
  173. bool JUCE_CALLTYPE NativeMessageBox::showOkCancelBox (AlertWindow::AlertIconType /*iconType*/,
  174. const String& title, const String& message,
  175. Component* /*associatedComponent*/,
  176. ModalComponentManager::Callback* callback)
  177. {
  178. ScopedPointer<iOSMessageBox> mb (new iOSMessageBox (title, message, @"Cancel", @"OK",
  179. nil, callback, callback != nullptr));
  180. if (callback == nullptr)
  181. return mb->getResult() == 1;
  182. mb.release();
  183. return false;
  184. }
  185. int JUCE_CALLTYPE NativeMessageBox::showYesNoCancelBox (AlertWindow::AlertIconType /*iconType*/,
  186. const String& title, const String& message,
  187. Component* /*associatedComponent*/,
  188. ModalComponentManager::Callback* callback)
  189. {
  190. ScopedPointer<iOSMessageBox> mb (new iOSMessageBox (title, message, @"Cancel", @"Yes", @"No", callback, callback != nullptr));
  191. if (callback == nullptr)
  192. return mb->getResult();
  193. mb.release();
  194. return 0;
  195. }
  196. //==============================================================================
  197. bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray&, bool)
  198. {
  199. jassertfalse; // no such thing on iOS!
  200. return false;
  201. }
  202. bool DragAndDropContainer::performExternalDragDropOfText (const String&)
  203. {
  204. jassertfalse; // no such thing on iOS!
  205. return false;
  206. }
  207. //==============================================================================
  208. void Desktop::setScreenSaverEnabled (const bool isEnabled)
  209. {
  210. [[UIApplication sharedApplication] setIdleTimerDisabled: ! isEnabled];
  211. }
  212. bool Desktop::isScreenSaverEnabled()
  213. {
  214. return ! [[UIApplication sharedApplication] isIdleTimerDisabled];
  215. }
  216. //==============================================================================
  217. bool juce_areThereAnyAlwaysOnTopWindows()
  218. {
  219. return false;
  220. }
  221. //==============================================================================
  222. Image juce_createIconForFile (const File&)
  223. {
  224. return Image::null;
  225. }
  226. //==============================================================================
  227. void SystemClipboard::copyTextToClipboard (const String& text)
  228. {
  229. [[UIPasteboard generalPasteboard] setValue: juceStringToNS (text)
  230. forPasteboardType: @"public.text"];
  231. }
  232. String SystemClipboard::getTextFromClipboard()
  233. {
  234. NSString* text = [[UIPasteboard generalPasteboard] valueForPasteboardType: @"public.text"];
  235. return text == nil ? String::empty
  236. : nsStringToJuce (text);
  237. }
  238. //==============================================================================
  239. bool MouseInputSource::SourceList::addSource()
  240. {
  241. addSource (sources.size(), false);
  242. return true;
  243. }
  244. bool Desktop::canUseSemiTransparentWindows() noexcept
  245. {
  246. return true;
  247. }
  248. Point<float> MouseInputSource::getCurrentRawMousePosition()
  249. {
  250. return juce_lastMousePos;
  251. }
  252. void MouseInputSource::setRawMousePosition (Point<float>)
  253. {
  254. }
  255. double Desktop::getDefaultMasterScale()
  256. {
  257. return 1.0;
  258. }
  259. Desktop::DisplayOrientation Desktop::getCurrentOrientation() const
  260. {
  261. return Orientations::convertToJuce ([[UIApplication sharedApplication] statusBarOrientation]);
  262. }
  263. void Desktop::Displays::findDisplays (float masterScale)
  264. {
  265. JUCE_AUTORELEASEPOOL
  266. {
  267. UIScreen* s = [UIScreen mainScreen];
  268. Display d;
  269. d.userArea = UIViewComponentPeer::realScreenPosToRotated (convertToRectInt ([s applicationFrame])) / masterScale;
  270. d.totalArea = UIViewComponentPeer::realScreenPosToRotated (convertToRectInt ([s bounds])) / masterScale;
  271. d.isMain = true;
  272. d.scale = masterScale;
  273. if ([s respondsToSelector: @selector (scale)])
  274. d.scale *= s.scale;
  275. d.dpi = 160 * d.scale;
  276. displays.add (d);
  277. }
  278. }