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.

219 lines
7.6KB

  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 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. if (message == broadcastId)
  50. {
  51. const ScopedPointer<String> messageString ((String*) lParam);
  52. MessageManager::getInstance()->deliverBroadcastMessage (*messageString);
  53. return 0;
  54. }
  55. 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, PM_NOREMOVE))
  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. if (JUCEApplicationBase* const app = JUCEApplicationBase::getInstance())
  92. app->systemRequestedQuit();
  93. }
  94. else if (isEventBlockedByModalComps == nullptr || ! isEventBlockedByModalComps (m))
  95. {
  96. if ((m.message == WM_LBUTTONDOWN || m.message == WM_RBUTTONDOWN)
  97. && ! JuceWindowIdentifier::isJUCEWindow (m.hwnd))
  98. {
  99. // if it's someone else's window being clicked on, and the focus is
  100. // currently on a juce window, pass the kb focus over..
  101. HWND currentFocus = GetFocus();
  102. if (currentFocus == 0 || JuceWindowIdentifier::isJUCEWindow (currentFocus))
  103. SetFocus (m.hwnd);
  104. }
  105. TranslateMessage (&m);
  106. DispatchMessage (&m);
  107. }
  108. }
  109. return true;
  110. }
  111. bool MessageManager::postMessageToSystemQueue (MessageManager::MessageBase* const message)
  112. {
  113. message->incReferenceCount();
  114. return PostMessage (juce_messageWindowHandle, WindowsMessageHelpers::specialId, 0, (LPARAM) message) != 0;
  115. }
  116. void MessageManager::broadcastMessage (const String& value)
  117. {
  118. Array<HWND> windows;
  119. EnumWindows (&WindowsMessageHelpers::broadcastEnumWindowProc, (LPARAM) &windows);
  120. const String localCopy (value);
  121. COPYDATASTRUCT data;
  122. data.dwData = WindowsMessageHelpers::broadcastId;
  123. data.cbData = (localCopy.length() + 1) * sizeof (CharPointer_UTF32::CharType);
  124. data.lpData = (void*) localCopy.toUTF32().getAddress();
  125. for (int i = windows.size(); --i >= 0;)
  126. {
  127. HWND hwnd = windows.getUnchecked(i);
  128. TCHAR windowName[64] = { 0 }; // no need to read longer strings than this
  129. GetWindowText (hwnd, windowName, 63);
  130. if (String (windowName) == WindowsMessageHelpers::messageWindowName)
  131. {
  132. DWORD_PTR result;
  133. SendMessageTimeout (hwnd, WM_COPYDATA,
  134. (WPARAM) juce_messageWindowHandle,
  135. (LPARAM) &data,
  136. SMTO_BLOCK | SMTO_ABORTIFHUNG, 8000, &result);
  137. }
  138. }
  139. }
  140. //==============================================================================
  141. void MessageManager::doPlatformSpecificInitialisation()
  142. {
  143. OleInitialize (0);
  144. using namespace WindowsMessageHelpers;
  145. messageWindow = new HiddenMessageWindow (messageWindowName, (WNDPROC) messageWndProc);
  146. juce_messageWindowHandle = messageWindow->getHWND();
  147. }
  148. void MessageManager::doPlatformSpecificShutdown()
  149. {
  150. WindowsMessageHelpers::messageWindow = nullptr;
  151. OleUninitialize();
  152. }
  153. //==============================================================================
  154. struct MountedVolumeListChangeDetector::Pimpl : private DeviceChangeDetector
  155. {
  156. Pimpl (MountedVolumeListChangeDetector& d) : DeviceChangeDetector (L"MountedVolumeList"), owner (d)
  157. {
  158. File::findFileSystemRoots (lastVolumeList);
  159. }
  160. void systemDeviceChanged() override
  161. {
  162. Array<File> newList;
  163. File::findFileSystemRoots (newList);
  164. if (lastVolumeList != newList)
  165. {
  166. lastVolumeList = newList;
  167. owner.mountedVolumeListChanged();
  168. }
  169. }
  170. MountedVolumeListChangeDetector& owner;
  171. Array<File> lastVolumeList;
  172. };
  173. MountedVolumeListChangeDetector::MountedVolumeListChangeDetector() { pimpl = new Pimpl (*this); }
  174. MountedVolumeListChangeDetector::~MountedVolumeListChangeDetector() {}