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.

1583 lines
47KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-7 by Raw Material Software ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the
  7. GNU General Public License, as published by the Free Software Foundation;
  8. either version 2 of the License, or (at your option) any later version.
  9. JUCE is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with JUCE; if not, visit www.gnu.org/licenses or write to the
  15. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  16. Boston, MA 02111-1307 USA
  17. ------------------------------------------------------------------------------
  18. If you'd like to release a closed-source product which uses JUCE, commercial
  19. licenses are also available: visit www.rawmaterialsoftware.com/juce for
  20. more information.
  21. ==============================================================================
  22. */
  23. // (This file gets included by juce_mac_NativeCode.mm, rather than being
  24. // compiled on its own).
  25. #ifdef JUCE_INCLUDED_FILE
  26. class NSViewComponentPeer;
  27. //==============================================================================
  28. END_JUCE_NAMESPACE
  29. #define JuceNSView MakeObjCClassName(JuceNSView)
  30. @interface JuceNSView : NSView
  31. {
  32. @public
  33. NSViewComponentPeer* owner;
  34. NSNotificationCenter* notificationCenter;
  35. }
  36. - (JuceNSView*) initWithOwner: (NSViewComponentPeer*) owner withFrame: (NSRect) frame;
  37. - (void) dealloc;
  38. - (BOOL) isOpaque;
  39. - (void) drawRect: (NSRect) r;
  40. - (void) mouseDown: (NSEvent*) ev;
  41. - (void) asyncMouseDown: (NSEvent*) ev;
  42. - (void) mouseUp: (NSEvent*) ev;
  43. - (void) asyncMouseUp: (NSEvent*) ev;
  44. - (void) mouseDragged: (NSEvent*) ev;
  45. - (void) mouseMoved: (NSEvent*) ev;
  46. - (void) mouseEntered: (NSEvent*) ev;
  47. - (void) mouseExited: (NSEvent*) ev;
  48. - (void) rightMouseDown: (NSEvent*) ev;
  49. - (void) rightMouseDragged: (NSEvent*) ev;
  50. - (void) rightMouseUp: (NSEvent*) ev;
  51. - (void) otherMouseDown: (NSEvent*) ev;
  52. - (void) otherMouseDragged: (NSEvent*) ev;
  53. - (void) otherMouseUp: (NSEvent*) ev;
  54. - (void) scrollWheel: (NSEvent*) ev;
  55. - (BOOL) acceptsFirstMouse: (NSEvent*) ev;
  56. - (void) frameChanged: (NSNotification*) n;
  57. - (void) keyDown: (NSEvent*) ev;
  58. - (void) keyUp: (NSEvent*) ev;
  59. - (void) flagsChanged: (NSEvent*) ev;
  60. #if MACOS_10_4_OR_EARLIER
  61. - (BOOL) performKeyEquivalent: (NSEvent*) ev;
  62. #endif
  63. - (BOOL) becomeFirstResponder;
  64. - (BOOL) resignFirstResponder;
  65. - (BOOL) acceptsFirstResponder;
  66. - (NSArray*) getSupportedDragTypes;
  67. - (BOOL) sendDragCallback: (int) type sender: (id <NSDraggingInfo>) sender;
  68. - (NSDragOperation) draggingEntered: (id <NSDraggingInfo>) sender;
  69. - (NSDragOperation) draggingUpdated: (id <NSDraggingInfo>) sender;
  70. - (void) draggingEnded: (id <NSDraggingInfo>) sender;
  71. - (void) draggingExited: (id <NSDraggingInfo>) sender;
  72. - (BOOL) prepareForDragOperation: (id <NSDraggingInfo>) sender;
  73. - (BOOL) performDragOperation: (id <NSDraggingInfo>) sender;
  74. - (void) concludeDragOperation: (id <NSDraggingInfo>) sender;
  75. @end
  76. //==============================================================================
  77. #define JuceNSWindow MakeObjCClassName(JuceNSWindow)
  78. @interface JuceNSWindow : NSWindow
  79. {
  80. @private
  81. NSViewComponentPeer* owner;
  82. bool isZooming;
  83. }
  84. - (void) setOwner: (NSViewComponentPeer*) owner;
  85. - (BOOL) canBecomeKeyWindow;
  86. - (void) becomeKeyWindow;
  87. - (BOOL) windowShouldClose: (id) window;
  88. - (NSRect) constrainFrameRect: (NSRect) frameRect toScreen: (NSScreen*) screen;
  89. - (NSSize) windowWillResize: (NSWindow*) window toSize: (NSSize) proposedFrameSize;
  90. - (void) zoom: (id) sender;
  91. @end
  92. BEGIN_JUCE_NAMESPACE
  93. //==============================================================================
  94. class NSViewComponentPeer : public ComponentPeer
  95. {
  96. public:
  97. NSViewComponentPeer (Component* const component,
  98. const int windowStyleFlags,
  99. NSView* viewToAttachTo);
  100. ~NSViewComponentPeer();
  101. //==============================================================================
  102. void* getNativeHandle() const;
  103. void setVisible (bool shouldBeVisible);
  104. void setTitle (const String& title);
  105. void setPosition (int x, int y);
  106. void setSize (int w, int h);
  107. void setBounds (int x, int y, int w, int h, const bool isNowFullScreen);
  108. void getBounds (int& x, int& y, int& w, int& h, const bool global) const;
  109. void getBounds (int& x, int& y, int& w, int& h) const;
  110. int getScreenX() const;
  111. int getScreenY() const;
  112. void relativePositionToGlobal (int& x, int& y);
  113. void globalPositionToRelative (int& x, int& y);
  114. void setMinimised (bool shouldBeMinimised);
  115. bool isMinimised() const;
  116. void setFullScreen (bool shouldBeFullScreen);
  117. bool isFullScreen() const;
  118. bool contains (int x, int y, bool trueIfInAChildWindow) const;
  119. const BorderSize getFrameSize() const;
  120. bool setAlwaysOnTop (bool alwaysOnTop);
  121. void toFront (bool makeActiveWindow);
  122. void toBehind (ComponentPeer* other);
  123. void setIcon (const Image& newIcon);
  124. /* When you use multiple DLLs which share similarly-named obj-c classes - like
  125. for example having more than one juce plugin loaded into a host, then when a
  126. method is called, the actual code that runs might actually be in a different module
  127. than the one you expect... So any calls to library functions or statics that are
  128. made inside obj-c methods will probably end up getting executed in a different DLL's
  129. memory space. Not a great thing to happen - this obviously leads to bizarre crashes.
  130. To work around this insanity, I'm only allowing obj-c methods to make calls to
  131. virtual methods of an object that's known to live inside the right module's space.
  132. */
  133. virtual void redirectMouseDown (NSEvent* ev);
  134. virtual void redirectMouseUp (NSEvent* ev);
  135. virtual void redirectMouseDrag (NSEvent* ev);
  136. virtual void redirectMouseMove (NSEvent* ev);
  137. virtual void redirectMouseEnter (NSEvent* ev);
  138. virtual void redirectMouseExit (NSEvent* ev);
  139. virtual void redirectMouseWheel (NSEvent* ev);
  140. bool handleKeyEvent (NSEvent* ev, bool isKeyDown);
  141. virtual bool redirectKeyDown (NSEvent* ev);
  142. virtual bool redirectKeyUp (NSEvent* ev);
  143. virtual void redirectModKeyChange (NSEvent* ev);
  144. #if MACOS_10_4_OR_EARLIER
  145. virtual bool redirectPerformKeyEquivalent (NSEvent* ev);
  146. #endif
  147. virtual BOOL sendDragCallback (int type, id <NSDraggingInfo> sender);
  148. virtual bool isOpaque();
  149. virtual void drawRect (NSRect r);
  150. virtual bool canBecomeKeyWindow();
  151. virtual bool windowShouldClose();
  152. virtual void redirectMovedOrResized();
  153. virtual NSRect constrainRect (NSRect r);
  154. static void showArrowCursorIfNeeded();
  155. //==============================================================================
  156. virtual void viewFocusGain();
  157. virtual void viewFocusLoss();
  158. bool isFocused() const;
  159. void grabFocus();
  160. void textInputRequired (int x, int y);
  161. //==============================================================================
  162. void repaint (int x, int y, int w, int h);
  163. void performAnyPendingRepaintsNow();
  164. //==============================================================================
  165. juce_UseDebuggingNewOperator
  166. NSWindow* window;
  167. JuceNSView* view;
  168. bool isSharedWindow, fullScreen;
  169. };
  170. //==============================================================================
  171. END_JUCE_NAMESPACE
  172. @implementation JuceNSView
  173. - (JuceNSView*) initWithOwner: (NSViewComponentPeer*) owner_
  174. withFrame: (NSRect) frame
  175. {
  176. [super initWithFrame: frame];
  177. owner = owner_;
  178. notificationCenter = [NSNotificationCenter defaultCenter];
  179. [notificationCenter addObserver: self
  180. selector: @selector (frameChanged:)
  181. name: NSViewFrameDidChangeNotification
  182. object: self];
  183. if (! owner_->isSharedWindow)
  184. {
  185. [notificationCenter addObserver: self
  186. selector: @selector (frameChanged:)
  187. name: NSWindowDidMoveNotification
  188. object: owner_->window];
  189. }
  190. [self registerForDraggedTypes: [self getSupportedDragTypes]];
  191. return self;
  192. }
  193. - (void) dealloc
  194. {
  195. [notificationCenter removeObserver: self];
  196. [super dealloc];
  197. }
  198. //==============================================================================
  199. - (void) drawRect: (NSRect) r
  200. {
  201. if (owner != 0)
  202. owner->drawRect (r);
  203. }
  204. - (BOOL) isOpaque
  205. {
  206. return owner == 0 || owner->isOpaque();
  207. }
  208. //==============================================================================
  209. - (void) mouseDown: (NSEvent*) ev
  210. {
  211. // In some host situations, the host will stop modal loops from working
  212. // correctly if they're called from a mouse event, so we'll trigger
  213. // the event asynchronously..
  214. if (JUCEApplication::getInstance() == 0)
  215. [self performSelectorOnMainThread: @selector (asyncMouseDown:)
  216. withObject: ev
  217. waitUntilDone: NO];
  218. else
  219. [self asyncMouseDown: ev];
  220. }
  221. - (void) asyncMouseDown: (NSEvent*) ev
  222. {
  223. if (owner != 0)
  224. owner->redirectMouseDown (ev);
  225. }
  226. - (void) mouseUp: (NSEvent*) ev
  227. {
  228. // In some host situations, the host will stop modal loops from working
  229. // correctly if they're called from a mouse event, so we'll trigger
  230. // the event asynchronously..
  231. if (JUCEApplication::getInstance() == 0)
  232. [self performSelectorOnMainThread: @selector (asyncMouseUp:)
  233. withObject: ev
  234. waitUntilDone: NO];
  235. else
  236. [self asyncMouseUp: ev];
  237. }
  238. - (void) asyncMouseUp: (NSEvent*) ev
  239. {
  240. if (owner != 0)
  241. owner->redirectMouseUp (ev);
  242. }
  243. - (void) mouseDragged: (NSEvent*) ev
  244. {
  245. if (owner != 0)
  246. owner->redirectMouseDrag (ev);
  247. }
  248. - (void) mouseMoved: (NSEvent*) ev
  249. {
  250. if (owner != 0)
  251. owner->redirectMouseMove (ev);
  252. }
  253. - (void) mouseEntered: (NSEvent*) ev
  254. {
  255. if (owner != 0)
  256. owner->redirectMouseEnter (ev);
  257. }
  258. - (void) mouseExited: (NSEvent*) ev
  259. {
  260. if (owner != 0)
  261. owner->redirectMouseExit (ev);
  262. }
  263. - (void) rightMouseDown: (NSEvent*) ev
  264. {
  265. [self mouseDown: ev];
  266. }
  267. - (void) rightMouseDragged: (NSEvent*) ev
  268. {
  269. [self mouseDragged: ev];
  270. }
  271. - (void) rightMouseUp: (NSEvent*) ev
  272. {
  273. [self mouseUp: ev];
  274. }
  275. - (void) otherMouseDown: (NSEvent*) ev
  276. {
  277. [self mouseDown: ev];
  278. }
  279. - (void) otherMouseDragged: (NSEvent*) ev
  280. {
  281. [self mouseDragged: ev];
  282. }
  283. - (void) otherMouseUp: (NSEvent*) ev
  284. {
  285. [self mouseUp: ev];
  286. }
  287. - (void) scrollWheel: (NSEvent*) ev
  288. {
  289. if (owner != 0)
  290. owner->redirectMouseWheel (ev);
  291. }
  292. - (BOOL) acceptsFirstMouse: (NSEvent*) ev
  293. {
  294. return YES;
  295. }
  296. - (void) frameChanged: (NSNotification*) n
  297. {
  298. if (owner != 0)
  299. owner->redirectMovedOrResized();
  300. }
  301. //==============================================================================
  302. - (void) keyDown: (NSEvent*) ev
  303. {
  304. if (owner == 0 || ! owner->redirectKeyDown (ev))
  305. [super keyDown: ev];
  306. }
  307. - (void) keyUp: (NSEvent*) ev
  308. {
  309. if (owner == 0 || ! owner->redirectKeyUp (ev))
  310. [super keyUp: ev];
  311. }
  312. - (void) flagsChanged: (NSEvent*) ev
  313. {
  314. if (owner != 0)
  315. owner->redirectModKeyChange (ev);
  316. }
  317. #if MACOS_10_4_OR_EARLIER
  318. - (BOOL) performKeyEquivalent: (NSEvent*) ev
  319. {
  320. if (owner != 0 && owner->redirectPerformKeyEquivalent (ev))
  321. return true;
  322. return [super performKeyEquivalent: ev];
  323. }
  324. #endif
  325. - (BOOL) becomeFirstResponder
  326. {
  327. if (owner != 0)
  328. owner->viewFocusGain();
  329. return true;
  330. }
  331. - (BOOL) resignFirstResponder
  332. {
  333. if (owner != 0)
  334. owner->viewFocusLoss();
  335. return true;
  336. }
  337. - (BOOL) acceptsFirstResponder
  338. {
  339. return owner != 0 && owner->canBecomeKeyWindow();
  340. }
  341. //==============================================================================
  342. - (NSArray*) getSupportedDragTypes
  343. {
  344. return [NSArray arrayWithObjects: NSFilenamesPboardType, /*NSFilesPromisePboardType, NSStringPboardType,*/ nil];
  345. }
  346. - (BOOL) sendDragCallback: (int) type sender: (id <NSDraggingInfo>) sender
  347. {
  348. return owner != 0 && owner->sendDragCallback (type, sender);
  349. }
  350. - (NSDragOperation) draggingEntered: (id <NSDraggingInfo>) sender
  351. {
  352. if ([self sendDragCallback: 0 sender: sender])
  353. return NSDragOperationCopy | NSDragOperationMove | NSDragOperationGeneric;
  354. else
  355. return NSDragOperationNone;
  356. }
  357. - (NSDragOperation) draggingUpdated: (id <NSDraggingInfo>) sender
  358. {
  359. if ([self sendDragCallback: 0 sender: sender])
  360. return NSDragOperationCopy | NSDragOperationMove | NSDragOperationGeneric;
  361. else
  362. return NSDragOperationNone;
  363. }
  364. - (void) draggingEnded: (id <NSDraggingInfo>) sender
  365. {
  366. [self sendDragCallback: 1 sender: sender];
  367. }
  368. - (void) draggingExited: (id <NSDraggingInfo>) sender
  369. {
  370. [self sendDragCallback: 1 sender: sender];
  371. }
  372. - (BOOL) prepareForDragOperation: (id <NSDraggingInfo>) sender
  373. {
  374. return YES;
  375. }
  376. - (BOOL) performDragOperation: (id <NSDraggingInfo>) sender
  377. {
  378. return [self sendDragCallback: 2 sender: sender];
  379. }
  380. - (void) concludeDragOperation: (id <NSDraggingInfo>) sender
  381. {
  382. }
  383. @end
  384. //==============================================================================
  385. @implementation JuceNSWindow
  386. - (void) setOwner: (NSViewComponentPeer*) owner_
  387. {
  388. owner = owner_;
  389. isZooming = false;
  390. }
  391. - (BOOL) canBecomeKeyWindow
  392. {
  393. return owner != 0 && owner->canBecomeKeyWindow();
  394. }
  395. - (void) becomeKeyWindow
  396. {
  397. [super becomeKeyWindow];
  398. if (owner != 0)
  399. owner->grabFocus();
  400. }
  401. - (BOOL) windowShouldClose: (id) window
  402. {
  403. return owner == 0 || owner->windowShouldClose();
  404. }
  405. - (NSRect) constrainFrameRect: (NSRect) frameRect toScreen: (NSScreen*) screen
  406. {
  407. if (owner != 0)
  408. frameRect = owner->constrainRect (frameRect);
  409. return frameRect;
  410. }
  411. - (NSSize) windowWillResize: (NSWindow*) window toSize: (NSSize) proposedFrameSize
  412. {
  413. if (isZooming)
  414. return proposedFrameSize;
  415. NSRect frameRect = [self frame];
  416. frameRect.origin.y -= proposedFrameSize.height - frameRect.size.height;
  417. frameRect.size = proposedFrameSize;
  418. if (owner != 0)
  419. frameRect = owner->constrainRect (frameRect);
  420. return frameRect.size;
  421. }
  422. - (void) zoom: (id) sender
  423. {
  424. isZooming = true;
  425. [super zoom: sender];
  426. isZooming = false;
  427. }
  428. - (void) windowWillMove: (NSNotification*) notification
  429. {
  430. if (juce::Component::getCurrentlyModalComponent() != 0
  431. && owner->getComponent()->isCurrentlyBlockedByAnotherModalComponent()
  432. && (owner->getStyleFlags() & juce::ComponentPeer::windowHasTitleBar) != 0)
  433. juce::Component::getCurrentlyModalComponent()->inputAttemptWhenModal();
  434. }
  435. @end
  436. //==============================================================================
  437. //==============================================================================
  438. BEGIN_JUCE_NAMESPACE
  439. //==============================================================================
  440. class JuceNSImage
  441. {
  442. public:
  443. JuceNSImage (const int width, const int height, const bool hasAlpha)
  444. : juceImage (hasAlpha ? Image::ARGB : Image::RGB,
  445. width, height, hasAlpha)
  446. {
  447. lineStride = 0;
  448. pixelStride = 0;
  449. imageData = juceImage.lockPixelDataReadWrite (0, 0, width, height,
  450. lineStride, pixelStride);
  451. imageRep = [[NSBitmapImageRep alloc]
  452. initWithBitmapDataPlanes: &imageData
  453. pixelsWide: width
  454. pixelsHigh: height
  455. bitsPerSample: 8
  456. samplesPerPixel: pixelStride
  457. hasAlpha: hasAlpha
  458. isPlanar: NO
  459. colorSpaceName: NSCalibratedRGBColorSpace
  460. bitmapFormat: /*NSAlphaFirstBitmapFormat*/ (NSBitmapFormat) 0
  461. bytesPerRow: lineStride
  462. bitsPerPixel: 8 * pixelStride ];
  463. juceImage.releasePixelDataReadWrite (imageData);
  464. }
  465. ~JuceNSImage()
  466. {
  467. [imageRep release];
  468. }
  469. Image& getJuceImage() throw() { return juceImage; }
  470. void draw (const float x, const float y,
  471. const RectangleList& clip,
  472. const int originX, const int originY) const
  473. {
  474. // Our data is BGRA and the damned image rep only takes RGBA, so
  475. // we need to byte-swap the active areas if there's an alpha channel...
  476. if (juceImage.hasAlphaChannel())
  477. {
  478. RectangleList::Iterator iter (clip);
  479. while (iter.next())
  480. {
  481. const Rectangle* const r = iter.getRectangle();
  482. swapRGBOrder (r->getX() + originX,
  483. r->getY() + originY,
  484. r->getWidth(),
  485. r->getHeight());
  486. }
  487. }
  488. NSPoint p;
  489. p.x = x;
  490. p.y = y;
  491. [imageRep drawAtPoint: p];
  492. }
  493. void drawNSImage (NSImage* imageToDraw)
  494. {
  495. const ScopedAutoReleasePool pool;
  496. [NSGraphicsContext setCurrentContext:
  497. [NSGraphicsContext graphicsContextWithBitmapImageRep: imageRep]];
  498. [imageToDraw drawAtPoint: NSZeroPoint
  499. fromRect: NSMakeRect (0, 0, [imageToDraw size].width, [imageToDraw size].height)
  500. operation: NSCompositeSourceOver
  501. fraction: 1.0f];
  502. [[NSGraphicsContext currentContext] flushGraphics];
  503. if (juceImage.hasAlphaChannel())
  504. swapRGBOrder (0, 0, juceImage.getWidth(), juceImage.getHeight());
  505. }
  506. private:
  507. Image juceImage;
  508. NSBitmapImageRep* imageRep;
  509. uint8* imageData;
  510. int pixelStride, lineStride;
  511. void swapRGBOrder (const int x, const int y, const int w, int h) const
  512. {
  513. #if JUCE_BIG_ENDIAN
  514. jassert (pixelStride == 4);
  515. #endif
  516. jassert (Rectangle (0, 0, juceImage.getWidth(), juceImage.getHeight())
  517. .contains (Rectangle (x, y, w, h)));
  518. uint8* start = imageData + x * pixelStride + y * lineStride;
  519. while (--h >= 0)
  520. {
  521. uint8* p = start;
  522. start += lineStride;
  523. for (int i = w; --i >= 0;)
  524. {
  525. #if JUCE_BIG_ENDIAN
  526. const uint8 oldp3 = p[3];
  527. const uint8 oldp1 = p[1];
  528. p[3] = p[0];
  529. p[0] = oldp1;
  530. p[1] = p[2];
  531. p[2] = oldp3;
  532. #else
  533. const uint8 oldp0 = p[0];
  534. p[0] = p[2];
  535. p[2] = oldp0;
  536. #endif
  537. p += pixelStride;
  538. }
  539. }
  540. }
  541. };
  542. //==============================================================================
  543. static ComponentPeer* currentlyFocusedPeer = 0;
  544. static VoidArray keysCurrentlyDown;
  545. bool KeyPress::isKeyCurrentlyDown (const int keyCode) throw()
  546. {
  547. if (keysCurrentlyDown.contains ((void*) keyCode))
  548. return true;
  549. if (keyCode >= 'A' && keyCode <= 'Z'
  550. && keysCurrentlyDown.contains ((void*) (int) CharacterFunctions::toLowerCase ((tchar) keyCode)))
  551. return true;
  552. if (keyCode >= 'a' && keyCode <= 'z'
  553. && keysCurrentlyDown.contains ((void*) (int) CharacterFunctions::toUpperCase ((tchar) keyCode)))
  554. return true;
  555. return false;
  556. }
  557. static int getKeyCodeFromEvent (NSEvent* ev)
  558. {
  559. const String unmodified (nsStringToJuce ([ev charactersIgnoringModifiers]));
  560. int keyCode = unmodified[0];
  561. if (keyCode == 0x19) // (backwards-tab)
  562. keyCode = '\t';
  563. else if (keyCode == 0x03) // (enter)
  564. keyCode = '\r';
  565. return keyCode;
  566. }
  567. static int currentModifiers = 0;
  568. static void updateModifiers (NSEvent* e)
  569. {
  570. int m = currentModifiers & ~(ModifierKeys::shiftModifier | ModifierKeys::ctrlModifier
  571. | ModifierKeys::altModifier | ModifierKeys::commandModifier);
  572. if (([e modifierFlags] & NSShiftKeyMask) != 0)
  573. m |= ModifierKeys::shiftModifier;
  574. if (([e modifierFlags] & NSControlKeyMask) != 0)
  575. m |= ModifierKeys::ctrlModifier;
  576. if (([e modifierFlags] & NSAlternateKeyMask) != 0)
  577. m |= ModifierKeys::altModifier;
  578. if (([e modifierFlags] & NSCommandKeyMask) != 0)
  579. m |= ModifierKeys::commandModifier;
  580. currentModifiers = m;
  581. }
  582. static void updateKeysDown (NSEvent* ev, bool isKeyDown)
  583. {
  584. updateModifiers (ev);
  585. int keyCode = getKeyCodeFromEvent (ev);
  586. if (keyCode != 0)
  587. {
  588. if (isKeyDown)
  589. keysCurrentlyDown.addIfNotAlreadyThere ((void*) keyCode);
  590. else
  591. keysCurrentlyDown.removeValue ((void*) keyCode);
  592. }
  593. }
  594. const ModifierKeys ModifierKeys::getCurrentModifiersRealtime() throw()
  595. {
  596. return ModifierKeys (currentModifiers);
  597. }
  598. void ModifierKeys::updateCurrentModifiers() throw()
  599. {
  600. currentModifierFlags = currentModifiers;
  601. }
  602. static int64 getMouseTime (NSEvent* e) { return (int64) [e timestamp] * 1000.0; }
  603. static void getMousePos (NSEvent* e, NSView* view, int& x, int& y)
  604. {
  605. NSPoint p = [view convertPoint: [e locationInWindow] fromView: nil];
  606. x = roundFloatToInt (p.x);
  607. y = roundFloatToInt ([view frame].size.height - p.y);
  608. }
  609. static int getModifierForButtonNumber (const int num) throw()
  610. {
  611. return num == 0 ? ModifierKeys::leftButtonModifier
  612. : (num == 1 ? ModifierKeys::rightButtonModifier
  613. : (num == 2 ? ModifierKeys::middleButtonModifier : 0));
  614. }
  615. //==============================================================================
  616. NSViewComponentPeer::NSViewComponentPeer (Component* const component,
  617. const int windowStyleFlags,
  618. NSView* viewToAttachTo)
  619. : ComponentPeer (component, windowStyleFlags),
  620. window (0),
  621. view (0)
  622. {
  623. NSRect r;
  624. r.origin.x = 0;
  625. r.origin.y = 0;
  626. r.size.width = (float) component->getWidth();
  627. r.size.height = (float) component->getHeight();
  628. view = [[JuceNSView alloc] initWithOwner: this withFrame: r];
  629. [view setPostsFrameChangedNotifications: YES];
  630. if (viewToAttachTo != 0)
  631. {
  632. window = [viewToAttachTo window];
  633. [viewToAttachTo addSubview: view];
  634. isSharedWindow = true;
  635. setVisible (component->isVisible());
  636. }
  637. else
  638. {
  639. isSharedWindow = false;
  640. r.origin.x = (float) component->getX();
  641. r.origin.y = (float) component->getY();
  642. r.origin.y = [[[NSScreen screens] objectAtIndex: 0] frame].size.height - (r.origin.y + r.size.height);
  643. unsigned int style = 0;
  644. if ((windowStyleFlags & windowHasTitleBar) == 0)
  645. style = NSBorderlessWindowMask;
  646. else
  647. style = NSTitledWindowMask;
  648. if ((windowStyleFlags & windowHasMinimiseButton) != 0)
  649. style |= NSMiniaturizableWindowMask;
  650. if ((windowStyleFlags & windowHasCloseButton) != 0)
  651. style |= NSClosableWindowMask;
  652. if ((windowStyleFlags & windowIsResizable) != 0)
  653. style |= NSResizableWindowMask;
  654. window = [[JuceNSWindow alloc] initWithContentRect: r
  655. styleMask: style
  656. backing: NSBackingStoreBuffered
  657. defer: YES ];
  658. [((JuceNSWindow*) window) setOwner: this];
  659. [window orderOut: nil];
  660. [window setDelegate: window];
  661. [window setOpaque: component->isOpaque()];
  662. [window setHasShadow: ((windowStyleFlags & windowHasDropShadow) != 0)];
  663. if (component->isAlwaysOnTop())
  664. [window setLevel: NSFloatingWindowLevel];
  665. [window setContentView: view];
  666. [window setAutodisplay: YES];
  667. [window setAcceptsMouseMovedEvents: YES];
  668. [window setReleasedWhenClosed: YES];
  669. [window setExcludedFromWindowsMenu: (windowStyleFlags & windowIsTemporary) != 0];
  670. [window setIgnoresMouseEvents: (windowStyleFlags & windowIgnoresMouseClicks) != 0];
  671. }
  672. setTitle (component->getName());
  673. }
  674. NSViewComponentPeer::~NSViewComponentPeer()
  675. {
  676. view->owner = 0;
  677. [view removeFromSuperview];
  678. [view release];
  679. if (! isSharedWindow)
  680. {
  681. [((JuceNSWindow*) window) setOwner: 0];
  682. [window close];
  683. }
  684. }
  685. //==============================================================================
  686. void* NSViewComponentPeer::getNativeHandle() const
  687. {
  688. return view;
  689. }
  690. void NSViewComponentPeer::setVisible (bool shouldBeVisible)
  691. {
  692. if (isSharedWindow)
  693. {
  694. [view setHidden: ! shouldBeVisible];
  695. }
  696. else
  697. {
  698. if (shouldBeVisible)
  699. [window orderFront: nil];
  700. else
  701. [window orderOut: nil];
  702. }
  703. }
  704. void NSViewComponentPeer::setTitle (const String& title)
  705. {
  706. const ScopedAutoReleasePool pool;
  707. if (! isSharedWindow)
  708. [window setTitle: juceStringToNS (title)];
  709. }
  710. void NSViewComponentPeer::setPosition (int x, int y)
  711. {
  712. setBounds (x, y, component->getWidth(), component->getHeight(), false);
  713. }
  714. void NSViewComponentPeer::setSize (int w, int h)
  715. {
  716. setBounds (component->getX(), component->getY(), w, h, false);
  717. }
  718. void NSViewComponentPeer::setBounds (int x, int y, int w, int h, const bool isNowFullScreen)
  719. {
  720. fullScreen = isNowFullScreen;
  721. w = jmax (0, w);
  722. h = jmax (0, h);
  723. NSRect r;
  724. r.origin.x = (float) x;
  725. r.origin.y = (float) y;
  726. r.size.width = (float) w;
  727. r.size.height = (float) h;
  728. if (isSharedWindow)
  729. {
  730. r.origin.y = [[view superview] frame].size.height - (r.origin.y + r.size.height);
  731. if ([view frame].size.width != r.size.width
  732. || [view frame].size.height != r.size.height)
  733. [view setNeedsDisplay: true];
  734. [view setFrame: r];
  735. }
  736. else
  737. {
  738. r.origin.y = [[[NSScreen screens] objectAtIndex: 0] frame].size.height - (r.origin.y + r.size.height);
  739. [window setFrame: [window frameRectForContentRect: r]
  740. display: true];
  741. }
  742. }
  743. void NSViewComponentPeer::getBounds (int& x, int& y, int& w, int& h, const bool global) const
  744. {
  745. NSRect r = [view frame];
  746. if (global && [view window] != 0)
  747. {
  748. r = [view convertRect: r toView: nil];
  749. NSRect wr = [[view window] frame];
  750. r.origin.x += wr.origin.x;
  751. r.origin.y += wr.origin.y;
  752. y = (int) ([[[NSScreen screens] objectAtIndex:0] frame].size.height - r.origin.y - r.size.height);
  753. }
  754. else
  755. {
  756. y = (int) ([[view superview] frame].size.height - r.origin.y - r.size.height);
  757. }
  758. x = (int) r.origin.x;
  759. w = (int) r.size.width;
  760. h = (int) r.size.height;
  761. }
  762. void NSViewComponentPeer::getBounds (int& x, int& y, int& w, int& h) const
  763. {
  764. getBounds (x, y, w, h, ! isSharedWindow);
  765. }
  766. int NSViewComponentPeer::getScreenX() const
  767. {
  768. int x, y, w, h;
  769. getBounds (x, y, w, h, true);
  770. return x;
  771. }
  772. int NSViewComponentPeer::getScreenY() const
  773. {
  774. int x, y, w, h;
  775. getBounds (x, y, w, h, true);
  776. return y;
  777. }
  778. void NSViewComponentPeer::relativePositionToGlobal (int& x, int& y)
  779. {
  780. int wx, wy, ww, wh;
  781. getBounds (wx, wy, ww, wh, true);
  782. x += wx;
  783. y += wy;
  784. }
  785. void NSViewComponentPeer::globalPositionToRelative (int& x, int& y)
  786. {
  787. int wx, wy, ww, wh;
  788. getBounds (wx, wy, ww, wh, true);
  789. x -= wx;
  790. y -= wy;
  791. }
  792. NSRect NSViewComponentPeer::constrainRect (NSRect r)
  793. {
  794. if (constrainer != 0)
  795. {
  796. NSRect current = [window frame];
  797. current.origin.y = [[[NSScreen screens] objectAtIndex: 0] frame].size.height - current.origin.y - current.size.height;
  798. r.origin.y = [[[NSScreen screens] objectAtIndex: 0] frame].size.height - r.origin.y - r.size.height;
  799. int x = (int) r.origin.x;
  800. int y = (int) r.origin.y;
  801. int w = (int) r.size.width;
  802. int h = (int) r.size.height;
  803. Rectangle original ((int) current.origin.x, (int) current.origin.y,
  804. (int) current.size.width, (int) current.size.height);
  805. constrainer->checkBounds (x, y, w, h,
  806. original,
  807. Desktop::getInstance().getAllMonitorDisplayAreas().getBounds(),
  808. y != original.getY() && y + h == original.getBottom(),
  809. x != original.getX() && x + w == original.getRight(),
  810. y == original.getY() && y + h != original.getBottom(),
  811. x == original.getX() && x + w != original.getRight());
  812. r.origin.x = x;
  813. r.origin.y = [[[NSScreen screens] objectAtIndex: 0] frame].size.height - r.size.height - y;
  814. r.size.width = w;
  815. r.size.height = h;
  816. }
  817. return r;
  818. }
  819. void NSViewComponentPeer::setMinimised (bool shouldBeMinimised)
  820. {
  821. if (! isSharedWindow)
  822. {
  823. if (shouldBeMinimised)
  824. [window miniaturize: nil];
  825. else
  826. [window deminiaturize: nil];
  827. }
  828. }
  829. bool NSViewComponentPeer::isMinimised() const
  830. {
  831. return window != 0 && [window isMiniaturized];
  832. }
  833. void NSViewComponentPeer::setFullScreen (bool shouldBeFullScreen)
  834. {
  835. if (! isSharedWindow)
  836. {
  837. Rectangle r (lastNonFullscreenBounds);
  838. setMinimised (false);
  839. if (fullScreen != shouldBeFullScreen)
  840. {
  841. if (shouldBeFullScreen)
  842. r = Desktop::getInstance().getMainMonitorArea();
  843. // (can't call the component's setBounds method because that'll reset our fullscreen flag)
  844. if (r != getComponent()->getBounds() && ! r.isEmpty())
  845. setBounds (r.getX(), r.getY(), r.getWidth(), r.getHeight(), shouldBeFullScreen);
  846. }
  847. }
  848. }
  849. bool NSViewComponentPeer::isFullScreen() const
  850. {
  851. return fullScreen;
  852. }
  853. bool NSViewComponentPeer::contains (int x, int y, bool trueIfInAChildWindow) const
  854. {
  855. if (((unsigned int) x) >= (unsigned int) component->getWidth()
  856. || ((unsigned int) y) >= (unsigned int) component->getHeight())
  857. return false;
  858. NSPoint p;
  859. p.x = (float) x;
  860. p.y = (float) y;
  861. NSView* v = [view hitTest: p];
  862. if (trueIfInAChildWindow)
  863. return v != nil;
  864. return v == view;
  865. }
  866. const BorderSize NSViewComponentPeer::getFrameSize() const
  867. {
  868. BorderSize b;
  869. if (! isSharedWindow)
  870. {
  871. NSRect v = [view convertRect: [view frame] toView: nil];
  872. NSRect w = [window frame];
  873. b.setTop ((int) (w.size.height - (v.origin.y + v.size.height)));
  874. b.setBottom ((int) v.origin.y);
  875. b.setLeft ((int) v.origin.x);
  876. b.setRight ((int) (w.size.width - (v.origin.x + v.size.width)));
  877. }
  878. return b;
  879. }
  880. bool NSViewComponentPeer::setAlwaysOnTop (bool alwaysOnTop)
  881. {
  882. if (! isSharedWindow)
  883. {
  884. [window setLevel: alwaysOnTop ? NSFloatingWindowLevel
  885. : NSNormalWindowLevel];
  886. }
  887. return true;
  888. }
  889. void NSViewComponentPeer::toFront (bool makeActiveWindow)
  890. {
  891. if (isSharedWindow)
  892. {
  893. [[view superview] addSubview: view
  894. positioned: NSWindowAbove
  895. relativeTo: nil];
  896. }
  897. if (window != 0 && component->isVisible())
  898. {
  899. if (makeActiveWindow)
  900. [window makeKeyAndOrderFront: nil];
  901. else
  902. [window orderFront: nil];
  903. }
  904. }
  905. void NSViewComponentPeer::toBehind (ComponentPeer* other)
  906. {
  907. NSViewComponentPeer* o = (NSViewComponentPeer*) other;
  908. if (isSharedWindow)
  909. {
  910. [[view superview] addSubview: view
  911. positioned: NSWindowBelow
  912. relativeTo: o->view];
  913. }
  914. else
  915. {
  916. [window orderWindow: NSWindowBelow
  917. relativeTo: o->window != 0 ? [o->window windowNumber]
  918. : nil ];
  919. }
  920. }
  921. void NSViewComponentPeer::setIcon (const Image& /*newIcon*/)
  922. {
  923. // to do..
  924. }
  925. //==============================================================================
  926. void NSViewComponentPeer::viewFocusGain()
  927. {
  928. if (currentlyFocusedPeer != this)
  929. {
  930. if (ComponentPeer::isValidPeer (currentlyFocusedPeer))
  931. currentlyFocusedPeer->handleFocusLoss();
  932. currentlyFocusedPeer = this;
  933. handleFocusGain();
  934. }
  935. }
  936. void NSViewComponentPeer::viewFocusLoss()
  937. {
  938. if (currentlyFocusedPeer == this)
  939. {
  940. currentlyFocusedPeer = 0;
  941. handleFocusLoss();
  942. }
  943. }
  944. void juce_HandleProcessFocusChange()
  945. {
  946. keysCurrentlyDown.clear();
  947. if (NSViewComponentPeer::isValidPeer (currentlyFocusedPeer))
  948. {
  949. if (Process::isForegroundProcess())
  950. {
  951. currentlyFocusedPeer->handleFocusGain();
  952. ComponentPeer::bringModalComponentToFront();
  953. }
  954. else
  955. {
  956. currentlyFocusedPeer->handleFocusLoss();
  957. // turn kiosk mode off if we lose focus..
  958. Desktop::getInstance().setKioskModeComponent (0);
  959. }
  960. }
  961. }
  962. bool NSViewComponentPeer::isFocused() const
  963. {
  964. return isSharedWindow ? this == currentlyFocusedPeer
  965. : (window != 0 && [window isKeyWindow]);
  966. }
  967. void NSViewComponentPeer::grabFocus()
  968. {
  969. if (window != 0)
  970. {
  971. [window makeKeyWindow];
  972. [window makeFirstResponder: view];
  973. viewFocusGain();
  974. }
  975. }
  976. void NSViewComponentPeer::textInputRequired (int /*x*/, int /*y*/)
  977. {
  978. }
  979. bool NSViewComponentPeer::handleKeyEvent (NSEvent* ev, bool isKeyDown)
  980. {
  981. String unicode (nsStringToJuce ([ev characters]));
  982. String unmodified (nsStringToJuce ([ev charactersIgnoringModifiers]));
  983. int keyCode = getKeyCodeFromEvent (ev);
  984. //DBG ("unicode: " + unicode + " " + String::toHexString ((int) unicode[0]));
  985. //DBG ("unmodified: " + unmodified + " " + String::toHexString ((int) unmodified[0]));
  986. if (unicode.isNotEmpty() || keyCode != 0)
  987. {
  988. if (isKeyDown)
  989. {
  990. bool used = false;
  991. while (unicode.length() > 0)
  992. {
  993. juce_wchar textCharacter = unicode[0];
  994. unicode = unicode.substring (1);
  995. if (([ev modifierFlags] & NSCommandKeyMask) != 0)
  996. textCharacter = 0;
  997. used = handleKeyUpOrDown() || used;
  998. used = handleKeyPress (keyCode, textCharacter) || used;
  999. }
  1000. return used;
  1001. }
  1002. else
  1003. {
  1004. if (handleKeyUpOrDown())
  1005. return true;
  1006. }
  1007. }
  1008. return false;
  1009. }
  1010. bool NSViewComponentPeer::redirectKeyDown (NSEvent* ev)
  1011. {
  1012. updateKeysDown (ev, true);
  1013. bool used = handleKeyEvent (ev, true);
  1014. if (([ev modifierFlags] & NSCommandKeyMask) != 0)
  1015. {
  1016. // for command keys, the key-up event is thrown away, so simulate one..
  1017. updateKeysDown (ev, false);
  1018. used = (isValidPeer (this) && handleKeyEvent (ev, false)) || used;
  1019. }
  1020. // (If we're running modally, don't allow unused keystrokes to be passed
  1021. // along to other blocked views..)
  1022. if (Component::getCurrentlyModalComponent() != 0)
  1023. used = true;
  1024. return used;
  1025. }
  1026. bool NSViewComponentPeer::redirectKeyUp (NSEvent* ev)
  1027. {
  1028. updateKeysDown (ev, false);
  1029. return handleKeyEvent (ev, false)
  1030. || Component::getCurrentlyModalComponent() != 0;
  1031. }
  1032. void NSViewComponentPeer::redirectModKeyChange (NSEvent* ev)
  1033. {
  1034. updateModifiers (ev);
  1035. handleModifierKeysChange();
  1036. }
  1037. #if MACOS_10_4_OR_EARLIER
  1038. bool NSViewComponentPeer::redirectPerformKeyEquivalent (NSEvent* ev)
  1039. {
  1040. if ([ev type] == NSKeyDown)
  1041. return redirectKeyDown (ev);
  1042. else if ([ev type] == NSKeyUp)
  1043. return redirectKeyUp (ev);
  1044. return false;
  1045. }
  1046. #endif
  1047. //==============================================================================
  1048. void NSViewComponentPeer::redirectMouseDown (NSEvent* ev)
  1049. {
  1050. updateModifiers (ev);
  1051. currentModifiers |= getModifierForButtonNumber ([ev buttonNumber]);
  1052. int x, y;
  1053. getMousePos (ev, view, x, y);
  1054. handleMouseDown (x, y, getMouseTime (ev));
  1055. }
  1056. void NSViewComponentPeer::redirectMouseUp (NSEvent* ev)
  1057. {
  1058. const int oldMods = currentModifiers;
  1059. updateModifiers (ev);
  1060. currentModifiers &= ~getModifierForButtonNumber ([ev buttonNumber]);
  1061. int x, y;
  1062. getMousePos (ev, view, x, y);
  1063. handleMouseUp (oldMods, x, y, getMouseTime (ev));
  1064. showArrowCursorIfNeeded();
  1065. }
  1066. void NSViewComponentPeer::redirectMouseDrag (NSEvent* ev)
  1067. {
  1068. updateModifiers (ev);
  1069. currentModifiers |= getModifierForButtonNumber ([ev buttonNumber]);
  1070. int x, y;
  1071. getMousePos (ev, view, x, y);
  1072. handleMouseDrag (x, y, getMouseTime (ev));
  1073. }
  1074. void NSViewComponentPeer::redirectMouseMove (NSEvent* ev)
  1075. {
  1076. updateModifiers (ev);
  1077. int x, y;
  1078. getMousePos (ev, view, x, y);
  1079. handleMouseMove (x, y, getMouseTime (ev));
  1080. showArrowCursorIfNeeded();
  1081. }
  1082. void NSViewComponentPeer::redirectMouseEnter (NSEvent* ev)
  1083. {
  1084. updateModifiers (ev);
  1085. int x, y;
  1086. getMousePos (ev, view, x, y);
  1087. handleMouseEnter (x, y, getMouseTime (ev));
  1088. }
  1089. void NSViewComponentPeer::redirectMouseExit (NSEvent* ev)
  1090. {
  1091. updateModifiers (ev);
  1092. int x, y;
  1093. getMousePos (ev, view, x, y);
  1094. handleMouseExit (x, y, getMouseTime (ev));
  1095. }
  1096. void NSViewComponentPeer::redirectMouseWheel (NSEvent* ev)
  1097. {
  1098. updateModifiers (ev);
  1099. handleMouseWheel (roundFloatToInt ([ev deltaX] * 10.0f),
  1100. roundFloatToInt ([ev deltaY] * 10.0f),
  1101. getMouseTime (ev));
  1102. }
  1103. void NSViewComponentPeer::showArrowCursorIfNeeded()
  1104. {
  1105. if (Component::getComponentUnderMouse() == 0)
  1106. {
  1107. int mx, my;
  1108. Desktop::getInstance().getMousePosition (mx, my);
  1109. if (Desktop::getInstance().findComponentAt (mx, my) == 0)
  1110. [[NSCursor arrowCursor] set];
  1111. }
  1112. }
  1113. //==============================================================================
  1114. BOOL NSViewComponentPeer::sendDragCallback (int type, id <NSDraggingInfo> sender)
  1115. {
  1116. NSString* bestType
  1117. = [[sender draggingPasteboard] availableTypeFromArray: [view getSupportedDragTypes]];
  1118. if (bestType == nil)
  1119. return false;
  1120. NSPoint p = [view convertPoint: [sender draggingLocation] fromView: nil];
  1121. int x = (int) p.x;
  1122. int y = (int) ([view frame].size.height - p.y);
  1123. StringArray files;
  1124. id list = [[sender draggingPasteboard] propertyListForType: bestType];
  1125. if (list == nil)
  1126. return false;
  1127. if ([list isKindOfClass: [NSArray class]])
  1128. {
  1129. NSArray* items = (NSArray*) list;
  1130. for (unsigned int i = 0; i < [items count]; ++i)
  1131. files.add (nsStringToJuce ((NSString*) [items objectAtIndex: i]));
  1132. }
  1133. if (files.size() == 0)
  1134. return false;
  1135. if (type == 0)
  1136. handleFileDragMove (files, x, y);
  1137. else if (type == 1)
  1138. handleFileDragExit (files);
  1139. else if (type == 2)
  1140. handleFileDragDrop (files, x, y);
  1141. return true;
  1142. }
  1143. bool NSViewComponentPeer::isOpaque()
  1144. {
  1145. if (! getComponent()->isValidComponent())
  1146. return true;
  1147. return getComponent()->isOpaque();
  1148. }
  1149. void NSViewComponentPeer::drawRect (NSRect r)
  1150. {
  1151. if (r.size.width < 1.0f || r.size.height < 1.0f)
  1152. return;
  1153. const float y = [view frame].size.height - (r.origin.y + r.size.height);
  1154. JuceNSImage temp ((int) (r.size.width + 0.5f),
  1155. (int) (r.size.height + 0.5f),
  1156. ! getComponent()->isOpaque());
  1157. LowLevelGraphicsSoftwareRenderer context (temp.getJuceImage());
  1158. const int originX = -roundFloatToInt (r.origin.x);
  1159. const int originY = -roundFloatToInt (y);
  1160. context.setOrigin (originX, originY);
  1161. const NSRect* rects = 0;
  1162. NSInteger numRects = 0;
  1163. [view getRectsBeingDrawn: &rects count: &numRects];
  1164. RectangleList clip;
  1165. for (int i = 0; i < numRects; ++i)
  1166. {
  1167. clip.addWithoutMerging (Rectangle (roundFloatToInt (rects[i].origin.x),
  1168. roundFloatToInt ([view frame].size.height - (rects[i].origin.y + rects[i].size.height)),
  1169. roundFloatToInt (rects[i].size.width),
  1170. roundFloatToInt (rects[i].size.height)));
  1171. }
  1172. if (context.reduceClipRegion (clip))
  1173. {
  1174. handlePaint (context);
  1175. temp.draw (r.origin.x, r.origin.y, clip, originX, originY);
  1176. }
  1177. }
  1178. bool NSViewComponentPeer::canBecomeKeyWindow()
  1179. {
  1180. // If running as a plugin, let the component decide whether it's going to allow the window to get focused.
  1181. return JUCEApplication::getInstance() != 0
  1182. || (isValidPeer (this) && getComponent()->getWantsKeyboardFocus());
  1183. }
  1184. bool NSViewComponentPeer::windowShouldClose()
  1185. {
  1186. if (! isValidPeer (this))
  1187. return YES;
  1188. handleUserClosingWindow();
  1189. return NO;
  1190. }
  1191. void NSViewComponentPeer::redirectMovedOrResized()
  1192. {
  1193. handleMovedOrResized();
  1194. }
  1195. //==============================================================================
  1196. void juce_setKioskComponent (Component* kioskModeComponent, bool enableOrDisable, bool allowMenusAndBars)
  1197. {
  1198. // Very annoyingly, this function has to use the old SetSystemUIMode function,
  1199. // which is in Carbon.framework. But, because there's no Cocoa equivalent, it
  1200. // is apparently still available in 64-bit apps..
  1201. if (enableOrDisable)
  1202. {
  1203. SetSystemUIMode (kUIModeAllSuppressed, allowMenusAndBars ? kUIOptionAutoShowMenuBar : 0);
  1204. kioskModeComponent->setBounds (Desktop::getInstance().getMainMonitorArea (false));
  1205. }
  1206. else
  1207. {
  1208. SetSystemUIMode (kUIModeNormal, 0);
  1209. }
  1210. }
  1211. //==============================================================================
  1212. void NSViewComponentPeer::repaint (int x, int y, int w, int h)
  1213. {
  1214. [view setNeedsDisplayInRect:
  1215. NSMakeRect ((float) x, (float) ([view frame].size.height - (y + h)),
  1216. (float) w, (float) h)];
  1217. }
  1218. void NSViewComponentPeer::performAnyPendingRepaintsNow()
  1219. {
  1220. [view displayIfNeeded];
  1221. }
  1222. ComponentPeer* Component::createNewPeer (int styleFlags, void* windowToAttachTo)
  1223. {
  1224. return new NSViewComponentPeer (this, styleFlags, (NSView*) windowToAttachTo);
  1225. }
  1226. //==============================================================================
  1227. static Image* NSImageToJuceImage (NSImage* image)
  1228. {
  1229. JuceNSImage juceIm ((int) [image size].width,
  1230. (int) [image size].height,
  1231. true);
  1232. juceIm.drawNSImage (image);
  1233. return juceIm.getJuceImage().createCopy();
  1234. }
  1235. Image* juce_createIconForFile (const File& file)
  1236. {
  1237. const ScopedAutoReleasePool pool;
  1238. NSImage* im = [[NSWorkspace sharedWorkspace] iconForFile: juceStringToNS (file.getFullPathName())];
  1239. return NSImageToJuceImage (im);
  1240. }
  1241. //==============================================================================
  1242. const int KeyPress::spaceKey = ' ';
  1243. const int KeyPress::returnKey = 0x0d;
  1244. const int KeyPress::escapeKey = 0x1b;
  1245. const int KeyPress::backspaceKey = 0x7f;
  1246. const int KeyPress::leftKey = NSLeftArrowFunctionKey;
  1247. const int KeyPress::rightKey = NSRightArrowFunctionKey;
  1248. const int KeyPress::upKey = NSUpArrowFunctionKey;
  1249. const int KeyPress::downKey = NSDownArrowFunctionKey;
  1250. const int KeyPress::pageUpKey = NSPageUpFunctionKey;
  1251. const int KeyPress::pageDownKey = NSPageDownFunctionKey;
  1252. const int KeyPress::endKey = NSEndFunctionKey;
  1253. const int KeyPress::homeKey = NSHomeFunctionKey;
  1254. const int KeyPress::deleteKey = NSDeleteFunctionKey;
  1255. const int KeyPress::insertKey = -1;
  1256. const int KeyPress::tabKey = 9;
  1257. const int KeyPress::F1Key = NSF1FunctionKey;
  1258. const int KeyPress::F2Key = NSF2FunctionKey;
  1259. const int KeyPress::F3Key = NSF3FunctionKey;
  1260. const int KeyPress::F4Key = NSF4FunctionKey;
  1261. const int KeyPress::F5Key = NSF5FunctionKey;
  1262. const int KeyPress::F6Key = NSF6FunctionKey;
  1263. const int KeyPress::F7Key = NSF7FunctionKey;
  1264. const int KeyPress::F8Key = NSF8FunctionKey;
  1265. const int KeyPress::F9Key = NSF9FunctionKey;
  1266. const int KeyPress::F10Key = NSF10FunctionKey;
  1267. const int KeyPress::F11Key = NSF1FunctionKey;
  1268. const int KeyPress::F12Key = NSF12FunctionKey;
  1269. const int KeyPress::F13Key = NSF13FunctionKey;
  1270. const int KeyPress::F14Key = NSF14FunctionKey;
  1271. const int KeyPress::F15Key = NSF15FunctionKey;
  1272. const int KeyPress::F16Key = NSF16FunctionKey;
  1273. const int KeyPress::numberPad0 = 0x30020;
  1274. const int KeyPress::numberPad1 = 0x30021;
  1275. const int KeyPress::numberPad2 = 0x30022;
  1276. const int KeyPress::numberPad3 = 0x30023;
  1277. const int KeyPress::numberPad4 = 0x30024;
  1278. const int KeyPress::numberPad5 = 0x30025;
  1279. const int KeyPress::numberPad6 = 0x30026;
  1280. const int KeyPress::numberPad7 = 0x30027;
  1281. const int KeyPress::numberPad8 = 0x30028;
  1282. const int KeyPress::numberPad9 = 0x30029;
  1283. const int KeyPress::numberPadAdd = 0x3002a;
  1284. const int KeyPress::numberPadSubtract = 0x3002b;
  1285. const int KeyPress::numberPadMultiply = 0x3002c;
  1286. const int KeyPress::numberPadDivide = 0x3002d;
  1287. const int KeyPress::numberPadSeparator = 0x3002e;
  1288. const int KeyPress::numberPadDecimalPoint = 0x3002f;
  1289. const int KeyPress::numberPadEquals = 0x30030;
  1290. const int KeyPress::numberPadDelete = 0x30031;
  1291. const int KeyPress::playKey = 0x30000;
  1292. const int KeyPress::stopKey = 0x30001;
  1293. const int KeyPress::fastForwardKey = 0x30002;
  1294. const int KeyPress::rewindKey = 0x30003;
  1295. #endif