Add TAL-Reverb-II plugin to test
[juce-lv2.git] / juce / source / src / native / windows / juce_win32_Messaging.cpp
blob5b237f40de0c1d99c801cd5014d51343cd26b04d
1 /*
2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 // (This file gets included by juce_win32_NativeCode.cpp, rather than being
27 // compiled on its own).
28 #if JUCE_INCLUDED_FILE
31 //==============================================================================
32 class HiddenMessageWindow
34 public:
35 HiddenMessageWindow (const TCHAR* const messageWindowName, WNDPROC wndProc)
37 String className ("JUCE_");
38 className << String::toHexString (Time::getHighResolutionTicks());
40 HMODULE moduleHandle = (HMODULE) PlatformUtilities::getCurrentModuleInstanceHandle();
42 WNDCLASSEX wc = { 0 };
43 wc.cbSize = sizeof (wc);
44 wc.lpfnWndProc = wndProc;
45 wc.cbWndExtra = 4;
46 wc.hInstance = moduleHandle;
47 wc.lpszClassName = className.toWideCharPointer();
49 atom = RegisterClassEx (&wc);
50 jassert (atom != 0);
52 hwnd = CreateWindow (getClassNameFromAtom(), messageWindowName,
53 0, 0, 0, 0, 0, 0, 0, moduleHandle, 0);
54 jassert (hwnd != 0);
57 ~HiddenMessageWindow()
59 DestroyWindow (hwnd);
60 UnregisterClass (getClassNameFromAtom(), 0);
63 inline HWND getHWND() const noexcept { return hwnd; }
65 private:
66 ATOM atom;
67 HWND hwnd;
69 LPCTSTR getClassNameFromAtom() noexcept { return (LPCTSTR) MAKELONG (atom, 0); }
73 //==============================================================================
74 HWND juce_messageWindowHandle = 0; // (this is referred to by other parts of the codebase)
76 //==============================================================================
77 class JuceWindowIdentifier
79 public:
80 static bool isJUCEWindow (HWND hwnd) noexcept
82 return GetWindowLong (hwnd, GWLP_USERDATA) == improbableWindowNumber;
85 static void setAsJUCEWindow (HWND hwnd, bool isJuceWindow) noexcept
87 SetWindowLongPtr (hwnd, GWLP_USERDATA, isJuceWindow ? improbableWindowNumber : 0);
90 private:
91 enum { improbableWindowNumber = 0xf965aa01 };
95 //==============================================================================
96 namespace WindowsMessageHelpers
98 const unsigned int specialId = WM_APP + 0x4400;
99 const unsigned int broadcastId = WM_APP + 0x4403;
100 const unsigned int specialCallbackId = WM_APP + 0x4402;
102 const TCHAR messageWindowName[] = _T("JUCEWindow");
103 ScopedPointer<HiddenMessageWindow> messageWindow;
105 //==============================================================================
106 LRESULT CALLBACK messageWndProc (HWND h, const UINT message, const WPARAM wParam, const LPARAM lParam) noexcept
108 JUCE_TRY
110 if (h == juce_messageWindowHandle)
112 if (message == specialCallbackId)
114 MessageCallbackFunction* const func = (MessageCallbackFunction*) wParam;
115 return (LRESULT) (*func) ((void*) lParam);
117 else if (message == specialId)
119 // these are trapped early in the dispatch call, but must also be checked
120 // here in case there are windows modal dialog boxes doing their own
121 // dispatch loop and not calling our version
123 Message* const message = reinterpret_cast <Message*> (lParam);
124 MessageManager::getInstance()->deliverMessage (message);
125 message->decReferenceCount();
126 return 0;
128 else if (message == broadcastId)
130 const ScopedPointer <String> messageString ((String*) lParam);
131 MessageManager::getInstance()->deliverBroadcastMessage (*messageString);
132 return 0;
134 else if (message == WM_COPYDATA && ((const COPYDATASTRUCT*) lParam)->dwData == broadcastId)
136 const COPYDATASTRUCT* data = (COPYDATASTRUCT*) lParam;
138 const String messageString (CharPointer_UTF32 ((const CharPointer_UTF32::CharType*) data->lpData),
139 data->cbData / sizeof (CharPointer_UTF32::CharType));
141 PostMessage (juce_messageWindowHandle, broadcastId, 0, (LPARAM) new String (messageString));
142 return 0;
146 JUCE_CATCH_EXCEPTION
148 return DefWindowProc (h, message, wParam, lParam);
151 bool isHWNDBlockedByModalComponents (HWND h) noexcept
153 for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;)
155 Component* const c = Desktop::getInstance().getComponent (i);
157 if (c != nullptr
158 && (! c->isCurrentlyBlockedByAnotherModalComponent())
159 && IsChild ((HWND) c->getWindowHandle(), h))
160 return false;
163 return true;
166 bool isEventBlockedByModalComps (MSG& m)
168 if (Component::getNumCurrentlyModalComponents() == 0 || JuceWindowIdentifier::isJUCEWindow (m.hwnd))
169 return false;
171 switch (m.message)
173 case WM_MOUSEMOVE:
174 case WM_NCMOUSEMOVE:
175 case 0x020A: /* WM_MOUSEWHEEL */
176 case 0x020E: /* WM_MOUSEHWHEEL */
177 case WM_KEYUP:
178 case WM_SYSKEYUP:
179 case WM_CHAR:
180 case WM_APPCOMMAND:
181 case WM_LBUTTONUP:
182 case WM_MBUTTONUP:
183 case WM_RBUTTONUP:
184 case WM_MOUSEACTIVATE:
185 case WM_NCMOUSEHOVER:
186 case WM_MOUSEHOVER:
187 return isHWNDBlockedByModalComponents (m.hwnd);
189 case WM_NCLBUTTONDOWN:
190 case WM_NCLBUTTONDBLCLK:
191 case WM_NCRBUTTONDOWN:
192 case WM_NCRBUTTONDBLCLK:
193 case WM_NCMBUTTONDOWN:
194 case WM_NCMBUTTONDBLCLK:
195 case WM_LBUTTONDOWN:
196 case WM_LBUTTONDBLCLK:
197 case WM_MBUTTONDOWN:
198 case WM_MBUTTONDBLCLK:
199 case WM_RBUTTONDOWN:
200 case WM_RBUTTONDBLCLK:
201 case WM_KEYDOWN:
202 case WM_SYSKEYDOWN:
203 if (isHWNDBlockedByModalComponents (m.hwnd))
205 Component* const modal = Component::getCurrentlyModalComponent (0);
206 if (modal != nullptr)
207 modal->inputAttemptWhenModal();
209 return true;
211 break;
213 default:
214 break;
217 return false;
220 BOOL CALLBACK broadcastEnumWindowProc (HWND hwnd, LPARAM lParam)
222 if (hwnd != juce_messageWindowHandle)
223 reinterpret_cast <Array<HWND>*> (lParam)->add (hwnd);
225 return TRUE;
229 //==============================================================================
230 bool MessageManager::dispatchNextMessageOnSystemQueue (const bool returnIfNoPendingMessages)
232 using namespace WindowsMessageHelpers;
233 MSG m;
235 if (returnIfNoPendingMessages && ! PeekMessage (&m, (HWND) 0, 0, 0, 0))
236 return false;
238 if (GetMessage (&m, (HWND) 0, 0, 0) >= 0)
240 if (m.message == specialId && m.hwnd == juce_messageWindowHandle)
242 Message* const message = reinterpret_cast <Message*> (m.lParam);
243 MessageManager::getInstance()->deliverMessage (message);
244 message->decReferenceCount();
246 else if (m.message == WM_QUIT)
248 if (JUCEApplication::getInstance() != nullptr)
249 JUCEApplication::getInstance()->systemRequestedQuit();
251 else if (! WindowsMessageHelpers::isEventBlockedByModalComps (m))
253 if ((m.message == WM_LBUTTONDOWN || m.message == WM_RBUTTONDOWN)
254 && ! JuceWindowIdentifier::isJUCEWindow (m.hwnd))
256 // if it's someone else's window being clicked on, and the focus is
257 // currently on a juce window, pass the kb focus over..
258 HWND currentFocus = GetFocus();
260 if (currentFocus == 0 || JuceWindowIdentifier::isJUCEWindow (currentFocus))
261 SetFocus (m.hwnd);
264 TranslateMessage (&m);
265 DispatchMessage (&m);
269 return true;
272 bool MessageManager::postMessageToSystemQueue (Message* message)
274 message->incReferenceCount();
275 return PostMessage (juce_messageWindowHandle, WindowsMessageHelpers::specialId, 0, (LPARAM) message) != 0;
278 void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* callback,
279 void* userData)
281 if (MessageManager::getInstance()->isThisTheMessageThread())
283 return (*callback) (userData);
285 else
287 // If a thread has a MessageManagerLock and then tries to call this method, it'll
288 // deadlock because the message manager is blocked from running, and can't
289 // call your function..
290 jassert (! MessageManager::getInstance()->currentThreadHasLockedMessageManager());
292 return (void*) SendMessage (juce_messageWindowHandle,
293 WindowsMessageHelpers::specialCallbackId,
294 (WPARAM) callback,
295 (LPARAM) userData);
299 void MessageManager::broadcastMessage (const String& value)
301 Array<HWND> windows;
302 EnumWindows (&WindowsMessageHelpers::broadcastEnumWindowProc, (LPARAM) &windows);
304 const String localCopy (value);
306 COPYDATASTRUCT data;
307 data.dwData = WindowsMessageHelpers::broadcastId;
308 data.cbData = (localCopy.length() + 1) * sizeof (CharPointer_UTF32::CharType);
309 data.lpData = (void*) localCopy.toUTF32().getAddress();
311 for (int i = windows.size(); --i >= 0;)
313 HWND hwnd = windows.getUnchecked(i);
315 TCHAR windowName [64]; // no need to read longer strings than this
316 GetWindowText (hwnd, windowName, 64);
317 windowName [63] = 0;
319 if (String (windowName) == WindowsMessageHelpers::messageWindowName)
321 DWORD_PTR result;
322 SendMessageTimeout (hwnd, WM_COPYDATA,
323 (WPARAM) juce_messageWindowHandle,
324 (LPARAM) &data,
325 SMTO_BLOCK | SMTO_ABORTIFHUNG, 8000, &result);
330 //==============================================================================
331 void MessageManager::doPlatformSpecificInitialisation()
333 OleInitialize (0);
335 using namespace WindowsMessageHelpers;
336 messageWindow = new HiddenMessageWindow (messageWindowName, (WNDPROC) messageWndProc);
337 juce_messageWindowHandle = messageWindow->getHWND();
340 void MessageManager::doPlatformSpecificShutdown()
342 WindowsMessageHelpers::messageWindow = nullptr;
344 OleUninitialize();
347 //==============================================================================
348 class DeviceChangeDetector // (Used by various audio classes)
350 public:
351 DeviceChangeDetector (const wchar_t* const name)
352 : messageWindow (name, (WNDPROC) deviceChangeEventCallback)
354 SetWindowLongPtr (messageWindow.getHWND(), GWLP_USERDATA, (LONG_PTR) this);
357 virtual ~DeviceChangeDetector() {}
359 protected:
360 virtual void systemDeviceChanged() = 0;
362 private:
363 HiddenMessageWindow messageWindow;
365 static LRESULT CALLBACK deviceChangeEventCallback (HWND h, const UINT message,
366 const WPARAM wParam, const LPARAM lParam)
368 if (message == WM_DEVICECHANGE
369 && (wParam == 0x8000 /*DBT_DEVICEARRIVAL*/
370 || wParam == 0x8004 /*DBT_DEVICEREMOVECOMPLETE*/
371 || wParam == 0x0007 /*DBT_DEVNODES_CHANGED*/))
373 ((DeviceChangeDetector*) GetWindowLongPtr (h, GWLP_USERDATA))->systemDeviceChanged();
376 return DefWindowProc (h, message, wParam, lParam);
380 #endif