1/* 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "EmbeddedWidget.h" 28 29#include <WebCore/Document.h> 30#include <WebCore/FrameView.h> 31#include <WebCore/HTMLPlugInElement.h> 32#include <WebCore/RenderObject.h> 33 34#include "MemoryStream.h" 35#include "WebError.h" 36#include "WebURLResponse.h" 37 38using namespace WebCore; 39 40PassRefPtr<EmbeddedWidget> EmbeddedWidget::create(IWebEmbeddedView* view, HTMLPlugInElement* element, HWND parentWindow, const IntSize& size) 41{ 42 RefPtr<EmbeddedWidget> widget = adoptRef(new EmbeddedWidget(view, element)); 43 44 widget->createWindow(parentWindow, size); 45 return widget.release(); 46} 47 48EmbeddedWidget::~EmbeddedWidget() 49{ 50 if (m_window) 51 DestroyWindow(m_window); 52} 53 54bool EmbeddedWidget::createWindow(HWND parentWindow, const IntSize& size) 55{ 56 ASSERT(!m_window); 57 58 HWND window; 59 60 SIZE pluginSize(size); 61 62 HRESULT hr = m_view->createViewWindow((OLE_HANDLE)parentWindow, &pluginSize, (OLE_HANDLE*)&window); 63 64 if (FAILED(hr) || !window) 65 return false; 66 67 m_window = window; 68 return true; 69} 70 71void EmbeddedWidget::invalidateRect(const IntRect& rect) 72{ 73 if (!m_window) 74 return; 75 76 RECT r = rect; 77 ::InvalidateRect(m_window, &r, false); 78} 79 80void EmbeddedWidget::setFrameRect(const IntRect& rect) 81{ 82 if (m_element->document()->printing()) 83 return; 84 85 if (rect != frameRect()) 86 Widget::setFrameRect(rect); 87 88 frameRectsChanged(); 89} 90 91void EmbeddedWidget::frameRectsChanged() 92{ 93 if (!parent()) 94 return; 95 96 ASSERT(parent()->isFrameView()); 97 FrameView* frameView = toFrameView(parent()); 98 99 IntRect oldWindowRect = m_windowRect; 100 IntRect oldClipRect = m_clipRect; 101 102 m_windowRect = IntRect(frameView->contentsToWindow(frameRect().location()), frameRect().size()); 103 m_clipRect = windowClipRect(); 104 m_clipRect.move(-m_windowRect.x(), -m_windowRect.y()); 105 106 if (!m_window) 107 return; 108 109 if (m_windowRect == oldWindowRect && m_clipRect == oldClipRect) 110 return; 111 112 HRGN rgn; 113 114 // To prevent flashes while scrolling, we disable drawing during the window 115 // update process by clipping the window to the zero rect. 116 117 bool clipToZeroRect = true; 118 119 if (clipToZeroRect) { 120 rgn = ::CreateRectRgn(0, 0, 0, 0); 121 ::SetWindowRgn(m_window, rgn, FALSE); 122 } else { 123 rgn = ::CreateRectRgn(m_clipRect.x(), m_clipRect.y(), m_clipRect.maxX(), m_clipRect.maxY()); 124 ::SetWindowRgn(m_window, rgn, TRUE); 125 } 126 127 if (m_windowRect != oldWindowRect) 128 ::MoveWindow(m_window, m_windowRect.x(), m_windowRect.y(), m_windowRect.width(), m_windowRect.height(), TRUE); 129 130 if (clipToZeroRect) { 131 rgn = ::CreateRectRgn(m_clipRect.x(), m_clipRect.y(), m_clipRect.maxX(), m_clipRect.maxY()); 132 ::SetWindowRgn(m_window, rgn, TRUE); 133 } 134} 135 136void EmbeddedWidget::setFocus(bool focused) 137{ 138 if (m_window && focused) 139 SetFocus(m_window); 140 141 Widget::setFocus(focused); 142} 143 144void EmbeddedWidget::show() 145{ 146 m_isVisible = true; 147 148 if (m_attachedToWindow && m_window) 149 ShowWindow(m_window, SW_SHOWNA); 150 151 Widget::show(); 152} 153 154void EmbeddedWidget::hide() 155{ 156 m_isVisible = false; 157 158 if (m_attachedToWindow && m_window) 159 ShowWindow(m_window, SW_HIDE); 160 161 Widget::hide(); 162} 163 164IntRect EmbeddedWidget::windowClipRect() const 165{ 166 // Start by clipping to our bounds. 167 IntRect clipRect(m_windowRect); 168 169 // Take our element and get the clip rect from the enclosing layer and frame view. 170 FrameView* parentView = m_element->document()->view(); 171 clipRect.intersect(parentView->windowClipRectForFrameOwner(m_element, true)); 172 173 return clipRect; 174} 175 176void EmbeddedWidget::setParent(ScrollView* parent) 177{ 178 Widget::setParent(parent); 179 180 if (!m_window) 181 return; 182 183 if (parent) 184 return; 185 186 // If the embedded window or one of its children have the focus, we need to 187 // clear it to prevent the web view window from being focused because that can 188 // trigger a layout while the plugin element is being detached. 189 HWND focusedWindow = ::GetFocus(); 190 if (m_window == focusedWindow || ::IsChild(m_window, focusedWindow)) 191 ::SetFocus(0); 192} 193 194void EmbeddedWidget::attachToWindow() 195{ 196 if (m_attachedToWindow) 197 return; 198 199 m_attachedToWindow = true; 200 if (m_isVisible && m_window) 201 ShowWindow(m_window, SW_SHOWNA); 202} 203 204void EmbeddedWidget::detachFromWindow() 205{ 206 if (!m_attachedToWindow) 207 return; 208 209 if (m_isVisible && m_window) 210 ShowWindow(m_window, SW_HIDE); 211 m_attachedToWindow = false; 212} 213 214void EmbeddedWidget::didReceiveResponse(const ResourceResponse& response) 215{ 216 ASSERT(m_view); 217 218 COMPtr<IWebURLResponse> urlResponse(AdoptCOM, WebURLResponse::createInstance(response)); 219 m_view->didReceiveResponse(urlResponse.get()); 220} 221 222void EmbeddedWidget::didReceiveData(const char* data, int length) 223{ 224 COMPtr<MemoryStream> stream = MemoryStream::createInstance(SharedBuffer::create(data, length)); 225 m_view->didReceiveData(stream.get()); 226} 227 228void EmbeddedWidget::didFinishLoading() 229{ 230 m_view->didFinishLoading(); 231} 232 233void EmbeddedWidget::didFail(const ResourceError& error) 234{ 235 COMPtr<IWebError> webError(AdoptCOM, WebError::createInstance(error)); 236 m_view->didFail(webError.get()); 237} 238