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.

193 lines
7.0KB

  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 TCHAR messageWindowName[] = _T("JUCEWindow");
  27. ScopedPointer<HiddenMessageWindow> messageWindow;
  28. void dispatchMessageFromLParam (LPARAM lParam)
  29. {
  30. MessageManager::MessageBase* const message = reinterpret_cast <MessageManager::MessageBase*> (lParam);
  31. JUCE_TRY
  32. {
  33. message->messageCallback();
  34. }
  35. JUCE_CATCH_EXCEPTION
  36. message->decReferenceCount();
  37. }
  38. //==============================================================================
  39. LRESULT CALLBACK messageWndProc (HWND h, const UINT message, const WPARAM wParam, const LPARAM lParam) noexcept
  40. {
  41. if (h == juce_messageWindowHandle)
  42. {
  43. if (message == specialId)
  44. {
  45. // (These are trapped early in our dispatch loop, but must also be checked
  46. // here in case some 3rd-party code is running the dispatch loop).
  47. dispatchMessageFromLParam (lParam);
  48. return 0;
  49. }
  50. else if (message == broadcastId)
  51. {
  52. const ScopedPointer<String> messageString ((String*) lParam);
  53. MessageManager::getInstance()->deliverBroadcastMessage (*messageString);
  54. return 0;
  55. }
  56. else if (message == WM_COPYDATA)
  57. {
  58. const COPYDATASTRUCT* const data = reinterpret_cast <const COPYDATASTRUCT*> (lParam);
  59. if (data->dwData == broadcastId)
  60. {
  61. const String messageString (CharPointer_UTF32 ((const CharPointer_UTF32::CharType*) data->lpData),
  62. data->cbData / sizeof (CharPointer_UTF32::CharType));
  63. PostMessage (juce_messageWindowHandle, broadcastId, 0, (LPARAM) new String (messageString));
  64. return 0;
  65. }
  66. }
  67. }
  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. dispatchMessageFromLParam (m.lParam);
  89. }
  90. else if (m.message == WM_QUIT)
  91. {
  92. JUCEApplicationBase* const app = JUCEApplicationBase::getInstance();
  93. if (app != nullptr)
  94. app->systemRequestedQuit();
  95. }
  96. else if (isEventBlockedByModalComps == nullptr || ! isEventBlockedByModalComps (m))
  97. {
  98. if ((m.message == WM_LBUTTONDOWN || m.message == WM_RBUTTONDOWN)
  99. && ! JuceWindowIdentifier::isJUCEWindow (m.hwnd))
  100. {
  101. // if it's someone else's window being clicked on, and the focus is
  102. // currently on a juce window, pass the kb focus over..
  103. HWND currentFocus = GetFocus();
  104. if (currentFocus == 0 || JuceWindowIdentifier::isJUCEWindow (currentFocus))
  105. SetFocus (m.hwnd);
  106. }
  107. TranslateMessage (&m);
  108. DispatchMessage (&m);
  109. }
  110. }
  111. return true;
  112. }
  113. bool MessageManager::postMessageToSystemQueue (MessageManager::MessageBase* const message)
  114. {
  115. message->incReferenceCount();
  116. return PostMessage (juce_messageWindowHandle, WindowsMessageHelpers::specialId, 0, (LPARAM) message) != 0;
  117. }
  118. void MessageManager::broadcastMessage (const String& value)
  119. {
  120. Array<HWND> windows;
  121. EnumWindows (&WindowsMessageHelpers::broadcastEnumWindowProc, (LPARAM) &windows);
  122. const String localCopy (value);
  123. COPYDATASTRUCT data;
  124. data.dwData = WindowsMessageHelpers::broadcastId;
  125. data.cbData = (localCopy.length() + 1) * sizeof (CharPointer_UTF32::CharType);
  126. data.lpData = (void*) localCopy.toUTF32().getAddress();
  127. for (int i = windows.size(); --i >= 0;)
  128. {
  129. HWND hwnd = windows.getUnchecked(i);
  130. TCHAR windowName [64]; // no need to read longer strings than this
  131. GetWindowText (hwnd, windowName, 64);
  132. windowName [63] = 0;
  133. if (String (windowName) == WindowsMessageHelpers::messageWindowName)
  134. {
  135. DWORD_PTR result;
  136. SendMessageTimeout (hwnd, WM_COPYDATA,
  137. (WPARAM) juce_messageWindowHandle,
  138. (LPARAM) &data,
  139. SMTO_BLOCK | SMTO_ABORTIFHUNG, 8000, &result);
  140. }
  141. }
  142. }
  143. //==============================================================================
  144. void MessageManager::doPlatformSpecificInitialisation()
  145. {
  146. OleInitialize (0);
  147. using namespace WindowsMessageHelpers;
  148. messageWindow = new HiddenMessageWindow (messageWindowName, (WNDPROC) messageWndProc);
  149. juce_messageWindowHandle = messageWindow->getHWND();
  150. }
  151. void MessageManager::doPlatformSpecificShutdown()
  152. {
  153. WindowsMessageHelpers::messageWindow = nullptr;
  154. OleUninitialize();
  155. }