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.

1558 lines
46KB

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