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.

212 lines
8.2KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 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. extern HWND juce_messageWindowHandle;
  19. typedef bool (*CheckEventBlockedByModalComps) (const MSG&);
  20. CheckEventBlockedByModalComps isEventBlockedByModalComps = nullptr;
  21. //==============================================================================
  22. namespace WindowsMessageHelpers
  23. {
  24. const unsigned int specialId = WM_APP + 0x4400;
  25. const unsigned int broadcastId = WM_APP + 0x4403;
  26. const unsigned int specialCallbackId = WM_APP + 0x4402;
  27. const TCHAR messageWindowName[] = _T("JUCEWindow");
  28. ScopedPointer<HiddenMessageWindow> messageWindow;
  29. //==============================================================================
  30. LRESULT CALLBACK messageWndProc (HWND h, const UINT message, const WPARAM wParam, const LPARAM lParam) noexcept
  31. {
  32. JUCE_TRY
  33. {
  34. if (h == juce_messageWindowHandle)
  35. {
  36. if (message == specialCallbackId)
  37. {
  38. MessageCallbackFunction* const func = (MessageCallbackFunction*) wParam;
  39. return (LRESULT) (*func) ((void*) lParam);
  40. }
  41. else if (message == specialId)
  42. {
  43. // these are trapped early in the dispatch call, but must also be checked
  44. // here in case there are windows modal dialog boxes doing their own
  45. // dispatch loop and not calling our version
  46. Message* const message = reinterpret_cast <Message*> (lParam);
  47. MessageManager::getInstance()->deliverMessage (message);
  48. message->decReferenceCount();
  49. return 0;
  50. }
  51. else if (message == broadcastId)
  52. {
  53. const ScopedPointer <String> messageString ((String*) lParam);
  54. MessageManager::getInstance()->deliverBroadcastMessage (*messageString);
  55. return 0;
  56. }
  57. else if (message == WM_COPYDATA && ((const COPYDATASTRUCT*) lParam)->dwData == broadcastId)
  58. {
  59. const COPYDATASTRUCT* data = (COPYDATASTRUCT*) lParam;
  60. const String messageString (CharPointer_UTF32 ((const CharPointer_UTF32::CharType*) data->lpData),
  61. data->cbData / sizeof (CharPointer_UTF32::CharType));
  62. PostMessage (juce_messageWindowHandle, broadcastId, 0, (LPARAM) new String (messageString));
  63. return 0;
  64. }
  65. }
  66. }
  67. JUCE_CATCH_EXCEPTION
  68. return DefWindowProc (h, message, wParam, lParam);
  69. }
  70. BOOL CALLBACK broadcastEnumWindowProc (HWND hwnd, LPARAM lParam)
  71. {
  72. if (hwnd != juce_messageWindowHandle)
  73. reinterpret_cast <Array<HWND>*> (lParam)->add (hwnd);
  74. return TRUE;
  75. }
  76. }
  77. //==============================================================================
  78. bool MessageManager::dispatchNextMessageOnSystemQueue (const bool returnIfNoPendingMessages)
  79. {
  80. using namespace WindowsMessageHelpers;
  81. MSG m;
  82. if (returnIfNoPendingMessages && ! PeekMessage (&m, (HWND) 0, 0, 0, 0))
  83. return false;
  84. if (GetMessage (&m, (HWND) 0, 0, 0) >= 0)
  85. {
  86. if (m.message == specialId && m.hwnd == juce_messageWindowHandle)
  87. {
  88. Message* const message = reinterpret_cast <Message*> (m.lParam);
  89. MessageManager::getInstance()->deliverMessage (message);
  90. message->decReferenceCount();
  91. }
  92. else if (m.message == WM_QUIT)
  93. {
  94. if (JUCEApplicationBase::getInstance() != nullptr)
  95. JUCEApplicationBase::getInstance()->systemRequestedQuit();
  96. }
  97. else if (isEventBlockedByModalComps == nullptr || ! isEventBlockedByModalComps (m))
  98. {
  99. if ((m.message == WM_LBUTTONDOWN || m.message == WM_RBUTTONDOWN)
  100. && ! JuceWindowIdentifier::isJUCEWindow (m.hwnd))
  101. {
  102. // if it's someone else's window being clicked on, and the focus is
  103. // currently on a juce window, pass the kb focus over..
  104. HWND currentFocus = GetFocus();
  105. if (currentFocus == 0 || JuceWindowIdentifier::isJUCEWindow (currentFocus))
  106. SetFocus (m.hwnd);
  107. }
  108. TranslateMessage (&m);
  109. DispatchMessage (&m);
  110. }
  111. }
  112. return true;
  113. }
  114. bool MessageManager::postMessageToSystemQueue (Message* message)
  115. {
  116. message->incReferenceCount();
  117. return PostMessage (juce_messageWindowHandle, WindowsMessageHelpers::specialId, 0, (LPARAM) message) != 0;
  118. }
  119. void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* callback, void* userData)
  120. {
  121. if (MessageManager::getInstance()->isThisTheMessageThread())
  122. {
  123. return (*callback) (userData);
  124. }
  125. else
  126. {
  127. // If a thread has a MessageManagerLock and then tries to call this method, it'll
  128. // deadlock because the message manager is blocked from running, and can't
  129. // call your function..
  130. jassert (! MessageManager::getInstance()->currentThreadHasLockedMessageManager());
  131. return (void*) SendMessage (juce_messageWindowHandle,
  132. WindowsMessageHelpers::specialCallbackId,
  133. (WPARAM) callback,
  134. (LPARAM) userData);
  135. }
  136. }
  137. void MessageManager::broadcastMessage (const String& value)
  138. {
  139. Array<HWND> windows;
  140. EnumWindows (&WindowsMessageHelpers::broadcastEnumWindowProc, (LPARAM) &windows);
  141. const String localCopy (value);
  142. COPYDATASTRUCT data;
  143. data.dwData = WindowsMessageHelpers::broadcastId;
  144. data.cbData = (localCopy.length() + 1) * sizeof (CharPointer_UTF32::CharType);
  145. data.lpData = (void*) localCopy.toUTF32().getAddress();
  146. for (int i = windows.size(); --i >= 0;)
  147. {
  148. HWND hwnd = windows.getUnchecked(i);
  149. TCHAR windowName [64]; // no need to read longer strings than this
  150. GetWindowText (hwnd, windowName, 64);
  151. windowName [63] = 0;
  152. if (String (windowName) == WindowsMessageHelpers::messageWindowName)
  153. {
  154. DWORD_PTR result;
  155. SendMessageTimeout (hwnd, WM_COPYDATA,
  156. (WPARAM) juce_messageWindowHandle,
  157. (LPARAM) &data,
  158. SMTO_BLOCK | SMTO_ABORTIFHUNG, 8000, &result);
  159. }
  160. }
  161. }
  162. //==============================================================================
  163. void MessageManager::doPlatformSpecificInitialisation()
  164. {
  165. OleInitialize (0);
  166. using namespace WindowsMessageHelpers;
  167. messageWindow = new HiddenMessageWindow (messageWindowName, (WNDPROC) messageWndProc);
  168. juce_messageWindowHandle = messageWindow->getHWND();
  169. }
  170. void MessageManager::doPlatformSpecificShutdown()
  171. {
  172. WindowsMessageHelpers::messageWindow = nullptr;
  173. OleUninitialize();
  174. }