Audio plugin host https://kx.studio/carla
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.

221 lines
7.7KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2015 - ROLI 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 customMessageID = WM_USER + 123;
  24. const unsigned int broadcastMessageMagicNumber = 0xc403;
  25. const TCHAR messageWindowName[] = _T("JUCEWindow");
  26. ScopedPointer<HiddenMessageWindow> messageWindow;
  27. void dispatchMessageFromLParam (LPARAM lParam)
  28. {
  29. if (MessageManager::MessageBase* message = reinterpret_cast<MessageManager::MessageBase*> (lParam))
  30. {
  31. JUCE_TRY
  32. {
  33. message->messageCallback();
  34. }
  35. JUCE_CATCH_EXCEPTION
  36. message->decReferenceCount();
  37. }
  38. }
  39. BOOL CALLBACK broadcastEnumWindowProc (HWND hwnd, LPARAM lParam)
  40. {
  41. if (hwnd != juce_messageWindowHandle)
  42. {
  43. TCHAR windowName[64] = { 0 }; // no need to read longer strings than this
  44. GetWindowText (hwnd, windowName, 63);
  45. if (String (windowName) == messageWindowName)
  46. reinterpret_cast<Array<HWND>*> (lParam)->add (hwnd);
  47. }
  48. return TRUE;
  49. }
  50. void handleBroadcastMessage (const COPYDATASTRUCT* const data)
  51. {
  52. if (data != nullptr && data->dwData == broadcastMessageMagicNumber)
  53. {
  54. struct BroadcastMessage : public CallbackMessage
  55. {
  56. BroadcastMessage (CharPointer_UTF32 text, size_t length) : message (text, length) {}
  57. void messageCallback() override { MessageManager::getInstance()->deliverBroadcastMessage (message); }
  58. String message;
  59. };
  60. (new BroadcastMessage (CharPointer_UTF32 ((const CharPointer_UTF32::CharType*) data->lpData),
  61. data->cbData / sizeof (CharPointer_UTF32::CharType)))
  62. ->post();
  63. }
  64. }
  65. //==============================================================================
  66. LRESULT CALLBACK messageWndProc (HWND h, const UINT message, const WPARAM wParam, const LPARAM lParam) noexcept
  67. {
  68. if (h == juce_messageWindowHandle)
  69. {
  70. if (message == customMessageID)
  71. {
  72. // (These are trapped early in our dispatch loop, but must also be checked
  73. // here in case some 3rd-party code is running the dispatch loop).
  74. dispatchMessageFromLParam (lParam);
  75. return 0;
  76. }
  77. if (message == WM_COPYDATA)
  78. {
  79. handleBroadcastMessage (reinterpret_cast<const COPYDATASTRUCT*> (lParam));
  80. return 0;
  81. }
  82. }
  83. return DefWindowProc (h, message, wParam, lParam);
  84. }
  85. }
  86. //==============================================================================
  87. bool MessageManager::dispatchNextMessageOnSystemQueue (const bool returnIfNoPendingMessages)
  88. {
  89. using namespace WindowsMessageHelpers;
  90. MSG m;
  91. if (returnIfNoPendingMessages && ! PeekMessage (&m, (HWND) 0, 0, 0, PM_NOREMOVE))
  92. return false;
  93. if (GetMessage (&m, (HWND) 0, 0, 0) >= 0)
  94. {
  95. if (m.message == customMessageID && m.hwnd == juce_messageWindowHandle)
  96. {
  97. dispatchMessageFromLParam (m.lParam);
  98. }
  99. else if (m.message == WM_QUIT)
  100. {
  101. if (JUCEApplicationBase* const app = JUCEApplicationBase::getInstance())
  102. app->systemRequestedQuit();
  103. }
  104. else if (isEventBlockedByModalComps == nullptr || ! isEventBlockedByModalComps (m))
  105. {
  106. if ((m.message == WM_LBUTTONDOWN || m.message == WM_RBUTTONDOWN)
  107. && ! JuceWindowIdentifier::isJUCEWindow (m.hwnd))
  108. {
  109. // if it's someone else's window being clicked on, and the focus is
  110. // currently on a juce window, pass the kb focus over..
  111. HWND currentFocus = GetFocus();
  112. if (currentFocus == 0 || JuceWindowIdentifier::isJUCEWindow (currentFocus))
  113. SetFocus (m.hwnd);
  114. }
  115. TranslateMessage (&m);
  116. DispatchMessage (&m);
  117. }
  118. }
  119. return true;
  120. }
  121. bool MessageManager::postMessageToSystemQueue (MessageManager::MessageBase* const message)
  122. {
  123. message->incReferenceCount();
  124. return PostMessage (juce_messageWindowHandle, WindowsMessageHelpers::customMessageID, 0, (LPARAM) message) != 0;
  125. }
  126. void MessageManager::broadcastMessage (const String& value)
  127. {
  128. const String localCopy (value);
  129. Array<HWND> windows;
  130. EnumWindows (&WindowsMessageHelpers::broadcastEnumWindowProc, (LPARAM) &windows);
  131. for (int i = windows.size(); --i >= 0;)
  132. {
  133. COPYDATASTRUCT data;
  134. data.dwData = WindowsMessageHelpers::broadcastMessageMagicNumber;
  135. data.cbData = (localCopy.length() + 1) * sizeof (CharPointer_UTF32::CharType);
  136. data.lpData = (void*) localCopy.toUTF32().getAddress();
  137. DWORD_PTR result;
  138. SendMessageTimeout (windows.getUnchecked(i), WM_COPYDATA,
  139. (WPARAM) juce_messageWindowHandle,
  140. (LPARAM) &data,
  141. SMTO_BLOCK | SMTO_ABORTIFHUNG, 8000, &result);
  142. }
  143. }
  144. //==============================================================================
  145. void MessageManager::doPlatformSpecificInitialisation()
  146. {
  147. OleInitialize (0);
  148. using namespace WindowsMessageHelpers;
  149. messageWindow = new HiddenMessageWindow (messageWindowName, (WNDPROC) messageWndProc);
  150. juce_messageWindowHandle = messageWindow->getHWND();
  151. }
  152. void MessageManager::doPlatformSpecificShutdown()
  153. {
  154. WindowsMessageHelpers::messageWindow = nullptr;
  155. OleUninitialize();
  156. }
  157. //==============================================================================
  158. struct MountedVolumeListChangeDetector::Pimpl : private DeviceChangeDetector
  159. {
  160. Pimpl (MountedVolumeListChangeDetector& d) : DeviceChangeDetector (L"MountedVolumeList"), owner (d)
  161. {
  162. File::findFileSystemRoots (lastVolumeList);
  163. }
  164. void systemDeviceChanged() override
  165. {
  166. Array<File> newList;
  167. File::findFileSystemRoots (newList);
  168. if (lastVolumeList != newList)
  169. {
  170. lastVolumeList = newList;
  171. owner.mountedVolumeListChanged();
  172. }
  173. }
  174. MountedVolumeListChangeDetector& owner;
  175. Array<File> lastVolumeList;
  176. };
  177. MountedVolumeListChangeDetector::MountedVolumeListChangeDetector() { pimpl = new Pimpl (*this); }
  178. MountedVolumeListChangeDetector::~MountedVolumeListChangeDetector() {}