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.

1587 lines
47KB

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