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.

192 lines
6.8KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. extern HWND juce_messageWindowHandle;
  18. typedef bool (*CheckEventBlockedByModalComps) (const MSG&);
  19. CheckEventBlockedByModalComps isEventBlockedByModalComps = nullptr;
  20. //==============================================================================
  21. namespace WindowsMessageHelpers
  22. {
  23. const unsigned int specialId = WM_APP + 0x4400;
  24. const unsigned int broadcastId = WM_APP + 0x4403;
  25. const TCHAR messageWindowName[] = _T("JUCEWindow");
  26. ScopedPointer<HiddenMessageWindow> messageWindow;
  27. void dispatchMessageFromLParam (LPARAM lParam)
  28. {
  29. MessageManager::MessageBase* const message = reinterpret_cast <MessageManager::MessageBase*> (lParam);
  30. JUCE_TRY
  31. {
  32. message->messageCallback();
  33. }
  34. JUCE_CATCH_EXCEPTION
  35. message->decReferenceCount();
  36. }
  37. //==============================================================================
  38. LRESULT CALLBACK messageWndProc (HWND h, const UINT message, const WPARAM wParam, const LPARAM lParam) noexcept
  39. {
  40. if (h == juce_messageWindowHandle)
  41. {
  42. if (message == specialId)
  43. {
  44. // (These are trapped early in our dispatch loop, but must also be checked
  45. // here in case some 3rd-party code is running the dispatch loop).
  46. dispatchMessageFromLParam (lParam);
  47. return 0;
  48. }
  49. else if (message == broadcastId)
  50. {
  51. const ScopedPointer<String> messageString ((String*) lParam);
  52. MessageManager::getInstance()->deliverBroadcastMessage (*messageString);
  53. return 0;
  54. }
  55. else if (message == WM_COPYDATA)
  56. {
  57. const COPYDATASTRUCT* const data = reinterpret_cast <const COPYDATASTRUCT*> (lParam);
  58. if (data->dwData == broadcastId)
  59. {
  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. return DefWindowProc (h, message, wParam, lParam);
  68. }
  69. BOOL CALLBACK broadcastEnumWindowProc (HWND hwnd, LPARAM lParam)
  70. {
  71. if (hwnd != juce_messageWindowHandle)
  72. reinterpret_cast <Array<HWND>*> (lParam)->add (hwnd);
  73. return TRUE;
  74. }
  75. }
  76. //==============================================================================
  77. bool MessageManager::dispatchNextMessageOnSystemQueue (const bool returnIfNoPendingMessages)
  78. {
  79. using namespace WindowsMessageHelpers;
  80. MSG m;
  81. if (returnIfNoPendingMessages && ! PeekMessage (&m, (HWND) 0, 0, 0, 0))
  82. return false;
  83. if (GetMessage (&m, (HWND) 0, 0, 0) >= 0)
  84. {
  85. if (m.message == specialId && m.hwnd == juce_messageWindowHandle)
  86. {
  87. dispatchMessageFromLParam (m.lParam);
  88. }
  89. else if (m.message == WM_QUIT)
  90. {
  91. JUCEApplicationBase* const app = JUCEApplicationBase::getInstance();
  92. if (app != nullptr)
  93. app->systemRequestedQuit();
  94. }
  95. else if (isEventBlockedByModalComps == nullptr || ! isEventBlockedByModalComps (m))
  96. {
  97. if ((m.message == WM_LBUTTONDOWN || m.message == WM_RBUTTONDOWN)
  98. && ! JuceWindowIdentifier::isJUCEWindow (m.hwnd))
  99. {
  100. // if it's someone else's window being clicked on, and the focus is
  101. // currently on a juce window, pass the kb focus over..
  102. HWND currentFocus = GetFocus();
  103. if (currentFocus == 0 || JuceWindowIdentifier::isJUCEWindow (currentFocus))
  104. SetFocus (m.hwnd);
  105. }
  106. TranslateMessage (&m);
  107. DispatchMessage (&m);
  108. }
  109. }
  110. return true;
  111. }
  112. bool MessageManager::postMessageToSystemQueue (MessageManager::MessageBase* const message)
  113. {
  114. message->incReferenceCount();
  115. return PostMessage (juce_messageWindowHandle, WindowsMessageHelpers::specialId, 0, (LPARAM) message) != 0;
  116. }
  117. void MessageManager::broadcastMessage (const String& value)
  118. {
  119. Array<HWND> windows;
  120. EnumWindows (&WindowsMessageHelpers::broadcastEnumWindowProc, (LPARAM) &windows);
  121. const String localCopy (value);
  122. COPYDATASTRUCT data;
  123. data.dwData = WindowsMessageHelpers::broadcastId;
  124. data.cbData = (localCopy.length() + 1) * sizeof (CharPointer_UTF32::CharType);
  125. data.lpData = (void*) localCopy.toUTF32().getAddress();
  126. for (int i = windows.size(); --i >= 0;)
  127. {
  128. HWND hwnd = windows.getUnchecked(i);
  129. TCHAR windowName [64]; // no need to read longer strings than this
  130. GetWindowText (hwnd, windowName, 64);
  131. windowName [63] = 0;
  132. if (String (windowName) == WindowsMessageHelpers::messageWindowName)
  133. {
  134. DWORD_PTR result;
  135. SendMessageTimeout (hwnd, WM_COPYDATA,
  136. (WPARAM) juce_messageWindowHandle,
  137. (LPARAM) &data,
  138. SMTO_BLOCK | SMTO_ABORTIFHUNG, 8000, &result);
  139. }
  140. }
  141. }
  142. //==============================================================================
  143. void MessageManager::doPlatformSpecificInitialisation()
  144. {
  145. OleInitialize (0);
  146. using namespace WindowsMessageHelpers;
  147. messageWindow = new HiddenMessageWindow (messageWindowName, (WNDPROC) messageWndProc);
  148. juce_messageWindowHandle = messageWindow->getHWND();
  149. }
  150. void MessageManager::doPlatformSpecificShutdown()
  151. {
  152. WindowsMessageHelpers::messageWindow = nullptr;
  153. OleUninitialize();
  154. }