WebCore:
Add WindowMessageBroadcaster
This class is used to listen in on messages sent to HWNDs. Multiple
WindowMessageListeners can be notified about messages sent to a single
HWND, and one WindowMessageListener can listen to messages from
multiple HWNDs.
Reviewed by Ada.
* WebCore.vcproj/WebCore.vcproj: Added new files to project.
* platform/win/WindowMessageBroadcaster.cpp: Added.
(WebCore::instancesMap): Static helper.
(WebCore::WindowMessageBroadcaster::addListener): Registers a listener
for a particular HWND.
(WebCore::WindowMessageBroadcaster::removeListener): Removes a
listener for a particular HWND.
(WebCore::WindowMessageBroadcaster::WindowMessageBroadcaster):
(WebCore::WindowMessageBroadcaster::~WindowMessageBroadcaster):
(WebCore::WindowMessageBroadcaster::destroy): Removes this broadcaster
from the instancesMap, removes all of its listeners, unsubclasses the
window, and deletes the broadcaster.
(WebCore::WindowMessageBroadcaster::unsubclassWindow): Unsubclasses
the window (which means that SubclassedWndProc won't be called again
for this window).
(WebCore::WindowMessageBroadcaster::SubclassedWndProc): Notifies all
the listeners about every message sent to the HWND
* platform/win/WindowMessageBroadcaster.h: Added.
(WebCore::WindowMessageBroadcaster::listeners):
(WebCore::WindowMessageBroadcaster::originalWndProc):
* platform/win/WindowMessageListener.h: Added.
WebKit/win:
Fix <rdar://
5346832> Infinite recursion when opening Web Inspector on more than one tab
The bug was that multiple WebNodeHighlights would subclass the same
browser window, leading to infinite recursion within
SubclassedWndProc.
WebNodeHighlight is now a WindowMessageListener, and lets
WindowMessageBroadcaster handle subclassing the window.
Reviewed by Ada.
* WebNodeHighlight.cpp:
(WebNodeHighlight::WebNodeHighlight): Initialize m_observedWindow
member.
(WebNodeHighlight::~WebNodeHighlight): Unregister as a listener for
m_observedWindow.
(WebNodeHighlight::highlight): Register as a listener.
(WebNodeHighlight::windowReceivedMessage): Do the work that used to be
done in SubclassedWndProc.
* WebNodeHighlight.h: Made WebNodeHighlight a WindowMessageListener,
and renamed m_subclassedWindow to m_observedWindow.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@27765
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2007-11-13 Adam Roben <aroben@apple.com>
+
+ Add WindowMessageBroadcaster
+
+ This class is used to listen in on messages sent to HWNDs. Multiple
+ WindowMessageListeners can be notified about messages sent to a single
+ HWND, and one WindowMessageListener can listen to messages from
+ multiple HWNDs.
+
+ Reviewed by Ada.
+
+ * WebCore.vcproj/WebCore.vcproj: Added new files to project.
+ * platform/win/WindowMessageBroadcaster.cpp: Added.
+ (WebCore::instancesMap): Static helper.
+ (WebCore::WindowMessageBroadcaster::addListener): Registers a listener
+ for a particular HWND.
+ (WebCore::WindowMessageBroadcaster::removeListener): Removes a
+ listener for a particular HWND.
+ (WebCore::WindowMessageBroadcaster::WindowMessageBroadcaster):
+ (WebCore::WindowMessageBroadcaster::~WindowMessageBroadcaster):
+ (WebCore::WindowMessageBroadcaster::destroy): Removes this broadcaster
+ from the instancesMap, removes all of its listeners, unsubclasses the
+ window, and deletes the broadcaster.
+ (WebCore::WindowMessageBroadcaster::unsubclassWindow): Unsubclasses
+ the window (which means that SubclassedWndProc won't be called again
+ for this window).
+ (WebCore::WindowMessageBroadcaster::SubclassedWndProc): Notifies all
+ the listeners about every message sent to the HWND
+ * platform/win/WindowMessageBroadcaster.h: Added.
+ (WebCore::WindowMessageBroadcaster::listeners):
+ (WebCore::WindowMessageBroadcaster::originalWndProc):
+ * platform/win/WindowMessageListener.h: Added.
+
2007-11-13 Geoffrey Garen <ggaren@apple.com>
Reviewed by Sam Weinig.
RelativePath="..\platform\win\WidgetWin.cpp"\r
>\r
</File>\r
+ <File\r
+ RelativePath="..\platform\win\WindowMessageBroadcaster.cpp"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="..\platform\win\WindowMessageBroadcaster.h"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="..\platform\win\WindowMessageListener.h"\r
+ >\r
+ </File>\r
</Filter>\r
<Filter\r
Name="cf"\r
--- /dev/null
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WindowMessageBroadcaster.h"
+
+#include "WindowMessageListener.h"
+
+namespace WebCore {
+
+typedef HashMap<HWND, WindowMessageBroadcaster*> InstanceMap;
+
+static InstanceMap& instancesMap()
+{
+ static InstanceMap instances;
+ return instances;
+}
+
+void WindowMessageBroadcaster::addListener(HWND hwnd, WindowMessageListener* listener)
+{
+ WindowMessageBroadcaster* broadcaster = instancesMap().get(hwnd);
+ if (!broadcaster) {
+ broadcaster = new WindowMessageBroadcaster(hwnd);
+ instancesMap().add(hwnd, broadcaster);
+ }
+
+ broadcaster->addListener(listener);
+}
+
+void WindowMessageBroadcaster::removeListener(HWND hwnd, WindowMessageListener* listener)
+{
+ WindowMessageBroadcaster* broadcaster = instancesMap().get(hwnd);
+ if (!broadcaster)
+ return;
+
+ broadcaster->removeListener(listener);
+}
+
+WindowMessageBroadcaster::WindowMessageBroadcaster(HWND hwnd)
+ : m_subclassedWindow(hwnd)
+ , m_originalWndProc(0)
+{
+ ASSERT_ARG(hwnd, IsWindow(hwnd));
+}
+
+WindowMessageBroadcaster::~WindowMessageBroadcaster()
+{
+}
+
+void WindowMessageBroadcaster::addListener(WindowMessageListener* listener)
+{
+ if (!m_originalWndProc) {
+#pragma warning(disable: 4244 4312)
+ m_originalWndProc = reinterpret_cast<WNDPROC>(SetWindowLongPtr(m_subclassedWindow, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SubclassedWndProc)));
+ ASSERT(m_originalWndProc);
+ }
+
+ m_listeners.add(listener);
+}
+
+void WindowMessageBroadcaster::removeListener(WindowMessageListener* listener)
+{
+ ListenerSet::iterator found = m_listeners.find(listener);
+ if (found == m_listeners.end())
+ return;
+
+ m_listeners.remove(found);
+
+ if (m_listeners.isEmpty())
+ destroy();
+}
+
+void WindowMessageBroadcaster::destroy()
+{
+ m_listeners.clear();
+ unsubclassWindow();
+ instancesMap().remove(m_subclassedWindow);
+ delete this;
+}
+
+void WindowMessageBroadcaster::unsubclassWindow()
+{
+ ASSERT(m_originalWndProc);
+
+ SetWindowLongPtr(m_subclassedWindow, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(m_originalWndProc));
+ m_originalWndProc = 0;
+}
+
+LRESULT CALLBACK WindowMessageBroadcaster::SubclassedWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ WindowMessageBroadcaster* broadcaster = instancesMap().get(hwnd);
+ ASSERT(broadcaster);
+
+ ListenerSet::const_iterator end = broadcaster->listeners().end();
+ for (ListenerSet::const_iterator it = broadcaster->listeners().begin(); it != end; ++it)
+ (*it)->windowReceivedMessage(hwnd, message, wParam, lParam);
+
+ WNDPROC originalWndProc = broadcaster->originalWndProc();
+
+ // This will delete broadcaster.
+ if (message == WM_DESTROY)
+ broadcaster->destroy();
+
+ return CallWindowProc(originalWndProc, hwnd, message, wParam, lParam);
+}
+
+} // namespace WebCore
--- /dev/null
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WindowMessageBroadcaster_h
+#define WindowMessageBroadcaster_h
+
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+ class WindowMessageListener;
+
+ class WindowMessageBroadcaster : Noncopyable {
+ public:
+ static void addListener(HWND, WindowMessageListener*);
+ static void removeListener(HWND, WindowMessageListener*);
+
+ private:
+ typedef HashSet<WindowMessageListener*> ListenerSet;
+
+ static LRESULT CALLBACK SubclassedWndProc(HWND, UINT, WPARAM, LPARAM);
+
+ WindowMessageBroadcaster(HWND);
+ ~WindowMessageBroadcaster();
+
+ void addListener(WindowMessageListener*);
+ void removeListener(WindowMessageListener*);
+ const ListenerSet& listeners() const { return m_listeners; }
+
+ void destroy();
+ void unsubclassWindow();
+
+ WNDPROC originalWndProc() const { return m_originalWndProc; }
+
+ HWND m_subclassedWindow;
+ WNDPROC m_originalWndProc;
+ ListenerSet m_listeners;
+ };
+
+} // namespace WebCore
+
+#endif // WindowMessageBroadcaster_h
--- /dev/null
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WindowMessageListener_h
+#define WindowMessageListener_h
+
+typedef struct HWND__* HWND;
+typedef long LPARAM;
+typedef unsigned UINT;
+typedef unsigned WPARAM;
+
+namespace WebCore {
+
+ class WindowMessageListener {
+ public:
+ virtual void windowReceivedMessage(HWND, UINT message, WPARAM, LPARAM) = 0;
+ };
+
+} // namespace WebCore
+
+#endif // WindowMessageListener_h
+2007-11-13 Adam Roben <aroben@apple.com>
+
+ Fix <rdar://5346832> Infinite recursion when opening Web Inspector on more than one tab
+
+ The bug was that multiple WebNodeHighlights would subclass the same
+ browser window, leading to infinite recursion within
+ SubclassedWndProc.
+
+ WebNodeHighlight is now a WindowMessageListener, and lets
+ WindowMessageBroadcaster handle subclassing the window.
+
+ Reviewed by Ada.
+
+ * WebNodeHighlight.cpp:
+ (WebNodeHighlight::WebNodeHighlight): Initialize m_observedWindow
+ member.
+ (WebNodeHighlight::~WebNodeHighlight): Unregister as a listener for
+ m_observedWindow.
+ (WebNodeHighlight::highlight): Register as a listener.
+ (WebNodeHighlight::windowReceivedMessage): Do the work that used to be
+ done in SubclassedWndProc.
+ * WebNodeHighlight.h: Made WebNodeHighlight a WindowMessageListener,
+ and renamed m_subclassedWindow to m_observedWindow.
+
2007-11-13 Adam Roben <aroben@apple.com>
Build fix for systems that don't have Cygwin in their PATH
#include "config.h"
#include "WebNodeHighlight.h"
-#include <wtf/OwnPtr.h>
-
#pragma warning(push, 0)
#include <WebCore/Color.h>
#include <WebCore/GraphicsContext.h>
+#include <WebCore/WindowMessageBroadcaster.h>
#pragma warning(pop)
+#include <wtf/OwnPtr.h>
+#include <wtf/HashSet.h>
using namespace WebCore;
WebNodeHighlight::WebNodeHighlight(HWND webView)
: m_webView(webView)
, m_overlay(0)
+ , m_observedWindow(0)
{
}
WebNodeHighlight::~WebNodeHighlight()
{
- if (m_overlay) {
- ::RemoveProp(m_overlay, kWebNodeHighlightPointerProp);
- ::DestroyWindow(m_overlay);
- }
+ if (m_observedWindow)
+ WindowMessageBroadcaster::removeListener(m_observedWindow, this);
- removeSubclass();
+ if (m_overlay)
+ ::DestroyWindow(m_overlay);
}
void WebNodeHighlight::highlight(const IntRect& rect)
::SetProp(m_overlay, kWebNodeHighlightPointerProp, reinterpret_cast<HANDLE>(this));
::SetWindowPos(m_overlay, m_webView, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
- m_subclassedWindow = ::GetAncestor(m_webView, GA_ROOT);
- ::SetProp(m_subclassedWindow, kWebNodeHighlightPointerProp, reinterpret_cast<HANDLE>(this));
-#pragma warning(disable: 4244 4312)
- m_originalWndProc = (WNDPROC)::SetWindowLongPtr(m_subclassedWindow, GWLP_WNDPROC, (LONG_PTR)SubclassedWndProc);
+ m_observedWindow = GetAncestor(m_webView, GA_ROOT);
+ WindowMessageBroadcaster::addListener(m_observedWindow, this);
}
m_rect = rect;
::DeleteDC(hdc);
}
-void WebNodeHighlight::removeSubclass()
-{
- if (!m_subclassedWindow)
- return;
-
- ::RemoveProp(m_subclassedWindow, kWebNodeHighlightPointerProp);
-#pragma warning(disable: 4244 4312)
- ::SetWindowLongPtr(m_subclassedWindow, GWLP_WNDPROC, (LONG_PTR)m_originalWndProc);
-
- m_subclassedWindow = 0;
- m_originalWndProc = 0;
-}
-
static ATOM registerOverlayClass()
{
static bool haveRegisteredWindowClass = false;
return ::DefWindowProc(hwnd, msg, wParam, lParam);
}
-LRESULT CALLBACK SubclassedWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+void WebNodeHighlight::windowReceivedMessage(HWND, UINT msg, WPARAM, LPARAM)
{
- WebNodeHighlight* highlight = reinterpret_cast<WebNodeHighlight*>(::GetProp(hwnd, kWebNodeHighlightPointerProp));
- ASSERT(highlight);
-
switch (msg) {
case WM_WINDOWPOSCHANGED:
- if (highlight->visible())
- highlight->updateWindow();
- break;
- case WM_DESTROY:
- highlight->removeSubclass();
+ if (visible())
+ updateWindow();
break;
default:
break;
}
-
- return ::CallWindowProc(highlight->m_originalWndProc, hwnd, msg, wParam, lParam);
}
#pragma warning(push, 0)
#include <WebCore/IntRect.h>
+#include <WebCore/WindowMessageListener.h>
#pragma warning(pop)
#include <windows.h>
-class WebNodeHighlight {
+class WebNodeHighlight : WebCore::WindowMessageListener {
public:
WebNodeHighlight(HWND webView);
~WebNodeHighlight();
bool visible() const;
private:
- void removeSubclass();
+ virtual void windowReceivedMessage(HWND, UINT message, WPARAM, LPARAM);
HWND m_webView;
- HWND m_subclassedWindow;
HWND m_overlay;
+ HWND m_observedWindow;
WebCore::IntRect m_rect;
- WNDPROC m_originalWndProc;
-
friend static LRESULT CALLBACK OverlayWndProc(HWND, UINT, WPARAM, LPARAM);
- friend static LRESULT CALLBACK SubclassedWndProc(HWND, UINT, WPARAM, LPARAM);
};
#endif // !defined(WebNodeHighlight_h)