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.

674 lines
21KB

  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. #include "../../../../juce_core/basics/juce_StandardHeader.h"
  24. BEGIN_JUCE_NAMESPACE
  25. #include "../../../application/juce_Application.h"
  26. #include "../juce_Component.h"
  27. #include "../juce_ComponentDeletionWatcher.h"
  28. #include "../juce_Desktop.h"
  29. #include "../../../events/juce_MessageManager.h"
  30. #include "../../../../juce_core/basics/juce_Time.h"
  31. #include "../../../../juce_core/basics/juce_Random.h"
  32. #include "../layout/juce_ComponentBoundsConstrainer.h"
  33. //#define JUCE_ENABLE_REPAINT_DEBUGGING 1
  34. //==============================================================================
  35. // these are over in juce_component.cpp
  36. extern int64 juce_recentMouseDownTimes[4];
  37. extern int juce_recentMouseDownX [4];
  38. extern int juce_recentMouseDownY [4];
  39. extern Component* juce_recentMouseDownComponent [4];
  40. extern int juce_LastMousePosX;
  41. extern int juce_LastMousePosY;
  42. extern int juce_MouseClickCounter;
  43. extern bool juce_MouseHasMovedSignificantlySincePressed;
  44. static const int fakeMouseMoveMessage = 0x7fff00ff;
  45. static VoidArray heavyweightPeers (4);
  46. //==============================================================================
  47. ComponentPeer::ComponentPeer (Component* const component_,
  48. const int styleFlags_)
  49. : component (component_),
  50. styleFlags (styleFlags_),
  51. lastPaintTime (0),
  52. constrainer (0),
  53. lastFocusedComponent (0),
  54. fakeMouseMessageSent (false),
  55. isWindowMinimised (false)
  56. {
  57. heavyweightPeers.add (this);
  58. }
  59. ComponentPeer::~ComponentPeer()
  60. {
  61. heavyweightPeers.removeValue (this);
  62. }
  63. //==============================================================================
  64. int ComponentPeer::getNumPeers() throw()
  65. {
  66. return heavyweightPeers.size();
  67. }
  68. ComponentPeer* ComponentPeer::getPeer (const int index) throw()
  69. {
  70. return (ComponentPeer*) heavyweightPeers [index];
  71. }
  72. ComponentPeer* ComponentPeer::getPeerFor (const Component* const component) throw()
  73. {
  74. for (int i = heavyweightPeers.size(); --i >= 0;)
  75. {
  76. ComponentPeer* const peer = (ComponentPeer*) heavyweightPeers.getUnchecked(i);
  77. if (peer->getComponent() == component)
  78. return peer;
  79. }
  80. return 0;
  81. }
  82. bool ComponentPeer::isValidPeer (const ComponentPeer* const peer) throw()
  83. {
  84. return heavyweightPeers.contains (const_cast <ComponentPeer*> (peer));
  85. }
  86. void ComponentPeer::updateCurrentModifiers()
  87. {
  88. ModifierKeys::updateCurrentModifiers();
  89. }
  90. //==============================================================================
  91. void ComponentPeer::handleMouseEnter (int x, int y, const int64 time)
  92. {
  93. jassert (component->isValidComponent());
  94. updateCurrentModifiers();
  95. Component* c = component->getComponentAt (x, y);
  96. const ComponentDeletionWatcher deletionChecker (component);
  97. if (c != Component::componentUnderMouse && Component::componentUnderMouse != 0)
  98. {
  99. jassert (Component::componentUnderMouse->isValidComponent());
  100. const int oldX = x;
  101. const int oldY = y;
  102. component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y);
  103. Component::componentUnderMouse->internalMouseExit (x, y, time);
  104. Component::componentUnderMouse = 0;
  105. if (deletionChecker.hasBeenDeleted())
  106. return;
  107. c = component->getComponentAt (oldX, oldY);
  108. }
  109. Component::componentUnderMouse = c;
  110. if (Component::componentUnderMouse != 0)
  111. {
  112. component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y);
  113. Component::componentUnderMouse->internalMouseEnter (x, y, time);
  114. }
  115. }
  116. void ComponentPeer::handleMouseMove (int x, int y, const int64 time)
  117. {
  118. jassert (component->isValidComponent());
  119. updateCurrentModifiers();
  120. fakeMouseMessageSent = false;
  121. const ComponentDeletionWatcher deletionChecker (component);
  122. Component* c = component->getComponentAt (x, y);
  123. if (c != Component::componentUnderMouse)
  124. {
  125. const int oldX = x;
  126. const int oldY = y;
  127. if (Component::componentUnderMouse != 0)
  128. {
  129. component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y);
  130. Component::componentUnderMouse->internalMouseExit (x, y, time);
  131. x = oldX;
  132. y = oldY;
  133. Component::componentUnderMouse = 0;
  134. if (deletionChecker.hasBeenDeleted())
  135. return; // if this window has just been deleted..
  136. c = component->getComponentAt (x, y);
  137. }
  138. Component::componentUnderMouse = c;
  139. if (c != 0)
  140. {
  141. component->relativePositionToOtherComponent (c, x, y);
  142. c->internalMouseEnter (x, y, time);
  143. x = oldX;
  144. y = oldY;
  145. if (deletionChecker.hasBeenDeleted())
  146. return; // if this window has just been deleted..
  147. }
  148. }
  149. if (Component::componentUnderMouse != 0)
  150. {
  151. component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y);
  152. Component::componentUnderMouse->internalMouseMove (x, y, time);
  153. }
  154. }
  155. void ComponentPeer::handleMouseDown (int x, int y, const int64 time)
  156. {
  157. ++juce_MouseClickCounter;
  158. updateCurrentModifiers();
  159. int numMouseButtonsDown = 0;
  160. if (ModifierKeys::getCurrentModifiers().isLeftButtonDown())
  161. ++numMouseButtonsDown;
  162. if (ModifierKeys::getCurrentModifiers().isRightButtonDown())
  163. ++numMouseButtonsDown;
  164. if (ModifierKeys::getCurrentModifiers().isMiddleButtonDown())
  165. ++numMouseButtonsDown;
  166. if (numMouseButtonsDown == 1)
  167. {
  168. Component::componentUnderMouse = component->getComponentAt (x, y);
  169. if (Component::componentUnderMouse != 0)
  170. {
  171. // can't set these in the mouseDownInt() method, because it's re-entrant, so do it here..
  172. for (int i = numElementsInArray (juce_recentMouseDownTimes); --i > 0;)
  173. {
  174. juce_recentMouseDownTimes [i] = juce_recentMouseDownTimes [i - 1];
  175. juce_recentMouseDownX [i] = juce_recentMouseDownX [i - 1];
  176. juce_recentMouseDownY [i] = juce_recentMouseDownY [i - 1];
  177. juce_recentMouseDownComponent [i] = juce_recentMouseDownComponent [i - 1];
  178. }
  179. juce_recentMouseDownTimes[0] = time;
  180. juce_recentMouseDownX[0] = x;
  181. juce_recentMouseDownY[0] = y;
  182. juce_recentMouseDownComponent[0] = Component::componentUnderMouse;
  183. relativePositionToGlobal (juce_recentMouseDownX[0], juce_recentMouseDownY[0]);
  184. juce_MouseHasMovedSignificantlySincePressed = false;
  185. component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y);
  186. Component::componentUnderMouse->internalMouseDown (x, y);
  187. }
  188. }
  189. }
  190. void ComponentPeer::handleMouseDrag (int x, int y, const int64 time)
  191. {
  192. updateCurrentModifiers();
  193. if (Component::componentUnderMouse != 0)
  194. {
  195. component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y);
  196. Component::componentUnderMouse->internalMouseDrag (x, y, time);
  197. }
  198. }
  199. void ComponentPeer::handleMouseUp (const int oldModifiers, int x, int y, const int64 time)
  200. {
  201. updateCurrentModifiers();
  202. int numMouseButtonsDown = 0;
  203. if ((oldModifiers & ModifierKeys::leftButtonModifier) != 0)
  204. ++numMouseButtonsDown;
  205. if ((oldModifiers & ModifierKeys::rightButtonModifier) != 0)
  206. ++numMouseButtonsDown;
  207. if ((oldModifiers & ModifierKeys::middleButtonModifier) != 0)
  208. ++numMouseButtonsDown;
  209. if (numMouseButtonsDown == 1)
  210. {
  211. const ComponentDeletionWatcher deletionChecker (component);
  212. Component* c = component->getComponentAt (x, y);
  213. if (c != Component::componentUnderMouse)
  214. {
  215. const int oldX = x;
  216. const int oldY = y;
  217. if (Component::componentUnderMouse != 0)
  218. {
  219. component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y);
  220. Component::componentUnderMouse->internalMouseUp (oldModifiers, x, y, time);
  221. x = oldX;
  222. y = oldY;
  223. if (Component::componentUnderMouse != 0)
  224. Component::componentUnderMouse->internalMouseExit (x, y, time);
  225. if (deletionChecker.hasBeenDeleted())
  226. return;
  227. c = component->getComponentAt (oldX, oldY);
  228. }
  229. Component::componentUnderMouse = c;
  230. if (Component::componentUnderMouse != 0)
  231. {
  232. component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y);
  233. Component::componentUnderMouse->internalMouseEnter (x, y, time);
  234. }
  235. }
  236. else
  237. {
  238. if (Component::componentUnderMouse != 0)
  239. {
  240. component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y);
  241. Component::componentUnderMouse->internalMouseUp (oldModifiers, x, y, time);
  242. }
  243. }
  244. }
  245. }
  246. void ComponentPeer::handleMouseExit (int x, int y, const int64 time)
  247. {
  248. jassert (component->isValidComponent());
  249. updateCurrentModifiers();
  250. if (Component::componentUnderMouse != 0)
  251. {
  252. component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y);
  253. Component::componentUnderMouse->internalMouseExit (x, y, time);
  254. Component::componentUnderMouse = 0;
  255. }
  256. }
  257. void ComponentPeer::handleMouseWheel (const int amountX, const int amountY, const int64 time)
  258. {
  259. updateCurrentModifiers();
  260. if (Component::componentUnderMouse != 0)
  261. Component::componentUnderMouse->internalMouseWheel (amountX, amountY, time);
  262. }
  263. void ComponentPeer::sendFakeMouseMove() throw()
  264. {
  265. if ((! fakeMouseMessageSent)
  266. && component->flags.hasHeavyweightPeerFlag
  267. && ! ModifierKeys::getCurrentModifiers().isAnyMouseButtonDown())
  268. {
  269. int realX, realY, realW, realH;
  270. getBounds (realX, realY, realW, realH);
  271. component->bounds_.setBounds (realX, realY, realW, realH);
  272. int x, y;
  273. component->getMouseXYRelative (x, y);
  274. if (x >= 0
  275. && y >= 0
  276. && x < component->getWidth()
  277. && y < component->getHeight()
  278. && contains (x, y, false))
  279. {
  280. postMessage (new Message (fakeMouseMoveMessage, x, y, 0));
  281. }
  282. fakeMouseMessageSent = true;
  283. }
  284. }
  285. void ComponentPeer::handleMessage (const Message& message)
  286. {
  287. if (message.intParameter1 == fakeMouseMoveMessage)
  288. {
  289. handleMouseMove (message.intParameter2,
  290. message.intParameter3,
  291. Time::currentTimeMillis());
  292. }
  293. }
  294. //==============================================================================
  295. void ComponentPeer::handlePaint (LowLevelGraphicsContext& contextToPaintTo)
  296. {
  297. Graphics g (&contextToPaintTo);
  298. #if JUCE_ENABLE_REPAINT_DEBUGGING
  299. g.saveState();
  300. #endif
  301. JUCE_TRY
  302. {
  303. component->paintEntireComponent (g);
  304. }
  305. JUCE_CATCH_EXCEPTION
  306. #if JUCE_ENABLE_REPAINT_DEBUGGING
  307. // enabling this code will fill all areas that get repainted with a colour overlay, to show
  308. // clearly when things are being repainted.
  309. {
  310. g.restoreState();
  311. g.fillAll (Colour ((uint8) Random::getSystemRandom().nextInt (255),
  312. (uint8) Random::getSystemRandom().nextInt (255),
  313. (uint8) Random::getSystemRandom().nextInt (255),
  314. (uint8) 0x50));
  315. }
  316. #endif
  317. }
  318. bool ComponentPeer::handleKeyPress (const int keyCode,
  319. const juce_wchar textCharacter)
  320. {
  321. updateCurrentModifiers();
  322. Component* target = Component::currentlyFocusedComponent->isValidComponent()
  323. ? Component::currentlyFocusedComponent
  324. : component;
  325. if (target->isCurrentlyBlockedByAnotherModalComponent())
  326. {
  327. Component* const currentModalComp = Component::getCurrentlyModalComponent();
  328. if (currentModalComp != 0)
  329. target = currentModalComp;
  330. }
  331. const KeyPress keyInfo (keyCode,
  332. ModifierKeys::getCurrentModifiers().getRawFlags()
  333. & ModifierKeys::allKeyboardModifiers,
  334. textCharacter);
  335. bool keyWasUsed = false;
  336. while (target != 0)
  337. {
  338. const ComponentDeletionWatcher deletionChecker (target);
  339. keyWasUsed = target->keyPressed (keyInfo);
  340. if (keyWasUsed || deletionChecker.hasBeenDeleted())
  341. break;
  342. if (target->keyListeners_ != 0)
  343. {
  344. for (int i = target->keyListeners_->size(); --i >= 0;)
  345. {
  346. keyWasUsed = ((KeyListener*) target->keyListeners_->getUnchecked(i))->keyPressed (keyInfo, target);
  347. if (keyWasUsed || deletionChecker.hasBeenDeleted())
  348. return keyWasUsed;
  349. i = jmin (i, target->keyListeners_->size());
  350. }
  351. }
  352. if (keyInfo.isKeyCode (KeyPress::tabKey) && Component::getCurrentlyFocusedComponent() != 0)
  353. {
  354. Component::getCurrentlyFocusedComponent()
  355. ->moveKeyboardFocusToSibling (! keyInfo.getModifiers().isShiftDown());
  356. keyWasUsed = true;
  357. break;
  358. }
  359. target = target->parentComponent_;
  360. }
  361. return keyWasUsed;
  362. }
  363. bool ComponentPeer::handleKeyUpOrDown()
  364. {
  365. updateCurrentModifiers();
  366. Component* target = Component::currentlyFocusedComponent->isValidComponent()
  367. ? Component::currentlyFocusedComponent
  368. : component;
  369. if (target->isCurrentlyBlockedByAnotherModalComponent())
  370. {
  371. Component* const currentModalComp = Component::getCurrentlyModalComponent();
  372. if (currentModalComp != 0)
  373. target = currentModalComp;
  374. }
  375. bool keyWasUsed = false;
  376. while (target != 0)
  377. {
  378. const ComponentDeletionWatcher deletionChecker (target);
  379. keyWasUsed = target->keyStateChanged();
  380. if (keyWasUsed || deletionChecker.hasBeenDeleted())
  381. break;
  382. if (target->keyListeners_ != 0)
  383. {
  384. for (int i = target->keyListeners_->size(); --i >= 0;)
  385. {
  386. keyWasUsed = ((KeyListener*) target->keyListeners_->getUnchecked(i))->keyStateChanged (target);
  387. if (keyWasUsed || deletionChecker.hasBeenDeleted())
  388. return keyWasUsed;
  389. i = jmin (i, target->keyListeners_->size());
  390. }
  391. }
  392. target = target->parentComponent_;
  393. }
  394. return keyWasUsed;
  395. }
  396. void ComponentPeer::handleModifierKeysChange()
  397. {
  398. updateCurrentModifiers();
  399. Component* target = Component::getComponentUnderMouse();
  400. if (target == 0)
  401. target = Component::getCurrentlyFocusedComponent();
  402. if (target == 0)
  403. target = component;
  404. if (target->isValidComponent())
  405. target->internalModifierKeysChanged();
  406. }
  407. //==============================================================================
  408. void ComponentPeer::handleBroughtToFront()
  409. {
  410. updateCurrentModifiers();
  411. if (component != 0)
  412. component->internalBroughtToFront();
  413. }
  414. void ComponentPeer::setConstrainer (ComponentBoundsConstrainer* newConstrainer)
  415. {
  416. constrainer = newConstrainer;
  417. }
  418. void ComponentPeer::handleMovedOrResized()
  419. {
  420. jassert (component->isValidComponent());
  421. updateCurrentModifiers();
  422. const bool nowMinimised = isMinimised();
  423. if (component->flags.hasHeavyweightPeerFlag && ! nowMinimised)
  424. {
  425. const ComponentDeletionWatcher deletionChecker (component);
  426. int realX, realY, realW, realH;
  427. getBounds (realX, realY, realW, realH);
  428. const bool wasMoved = (component->getX() != realX || component->getY() != realY);
  429. const bool wasResized = (component->getWidth() != realW || component->getHeight() != realH);
  430. if (wasMoved || wasResized)
  431. {
  432. component->bounds_.setBounds (realX, realY, realW, realH);
  433. if (wasResized)
  434. component->repaint();
  435. component->sendMovedResizedMessages (wasMoved, wasResized);
  436. if (deletionChecker.hasBeenDeleted())
  437. return;
  438. }
  439. }
  440. if (isWindowMinimised != nowMinimised)
  441. {
  442. isWindowMinimised = nowMinimised;
  443. component->minimisationStateChanged (nowMinimised);
  444. component->sendVisibilityChangeMessage();
  445. }
  446. if (! isFullScreen())
  447. lastNonFullscreenBounds = component->getBounds();
  448. }
  449. void ComponentPeer::handleFocusGain()
  450. {
  451. updateCurrentModifiers();
  452. if (component->isParentOf (lastFocusedComponent))
  453. {
  454. Component::currentlyFocusedComponent = lastFocusedComponent;
  455. Desktop::getInstance().triggerFocusCallback();
  456. lastFocusedComponent->internalFocusGain (Component::focusChangedDirectly);
  457. }
  458. else
  459. {
  460. if (! component->isCurrentlyBlockedByAnotherModalComponent())
  461. {
  462. component->grabKeyboardFocus();
  463. }
  464. else
  465. {
  466. Component* const currentModalComp = Component::getCurrentlyModalComponent();
  467. if (currentModalComp != 0)
  468. currentModalComp->toFront (! currentModalComp->hasKeyboardFocus (true));
  469. }
  470. }
  471. }
  472. void ComponentPeer::handleFocusLoss()
  473. {
  474. updateCurrentModifiers();
  475. if (component->hasKeyboardFocus (true))
  476. {
  477. lastFocusedComponent = Component::currentlyFocusedComponent;
  478. if (lastFocusedComponent != 0)
  479. {
  480. Component::currentlyFocusedComponent = 0;
  481. Desktop::getInstance().triggerFocusCallback();
  482. lastFocusedComponent->internalFocusLoss (Component::focusChangedByMouseClick);
  483. }
  484. }
  485. }
  486. Component* ComponentPeer::getLastFocusedSubcomponent() const
  487. {
  488. return (component->isParentOf (lastFocusedComponent) && lastFocusedComponent->isShowing())
  489. ? lastFocusedComponent
  490. : component;
  491. }
  492. void ComponentPeer::handleScreenSizeChange()
  493. {
  494. updateCurrentModifiers();
  495. component->parentSizeChanged();
  496. handleMovedOrResized();
  497. }
  498. //==============================================================================
  499. void ComponentPeer::handleFilesDropped (int x, int y, const StringArray& files)
  500. {
  501. updateCurrentModifiers();
  502. component->internalFilesDropped (x, y, files);
  503. }
  504. void ComponentPeer::handleUserClosingWindow()
  505. {
  506. updateCurrentModifiers();
  507. component->userTriedToCloseWindow();
  508. }
  509. //==============================================================================
  510. void ComponentPeer::clearMaskedRegion()
  511. {
  512. maskedRegion.clear();
  513. }
  514. void ComponentPeer::addMaskedRegion (int x, int y, int w, int h)
  515. {
  516. maskedRegion.add (x, y, w, h);
  517. }
  518. END_JUCE_NAMESPACE