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/Element.h> 31 #include <WebCore/FrameView.h> 32 #include <WebCore/RenderObject.h> 33 34 #include "MemoryStream.h" 35 #include "WebError.h" 36 #include "WebURLResponse.h" 37 38 using namespace WebCore; 39 40 PassRefPtr<EmbeddedWidget> EmbeddedWidget::create(IWebEmbeddedView* view, Element* 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 48 EmbeddedWidget::~EmbeddedWidget() 49 { 50 if (m_window) 51 DestroyWindow(m_window); 52 } 53 54 bool 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 71 void 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 80 void 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 91 void EmbeddedWidget::frameRectsChanged() 92 { 93 if (!parent()) 94 return; 95 96 ASSERT(parent()->isFrameView()); 97 FrameView* frameView = static_cast<FrameView*>(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.right(), m_clipRect.bottom()); 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.right(), m_clipRect.bottom()); 132 ::SetWindowRgn(m_window, rgn, TRUE); 133 } 134 } 135 136 void EmbeddedWidget::setFocus() 137 { 138 if (m_window) 139 SetFocus(m_window); 140 141 Widget::setFocus(); 142 } 143 144 void 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 154 void 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 164 IntRect 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 RenderLayer* layer = m_element->renderer()->enclosingLayer(); 171 FrameView* parentView = m_element->document()->view(); 172 clipRect.intersect(parentView->windowClipRectForLayer(layer, true)); 173 174 return clipRect; 175 } 176 177 void EmbeddedWidget::setParent(ScrollView* parent) 178 { 179 Widget::setParent(parent); 180 181 if (!m_window) 182 return; 183 184 if (parent) 185 return; 186 187 // If the embedded window or one of its children have the focus, we need to 188 // clear it to prevent the web view window from being focused because that can 189 // trigger a layout while the plugin element is being detached. 190 HWND focusedWindow = ::GetFocus(); 191 if (m_window == focusedWindow || ::IsChild(m_window, focusedWindow)) 192 ::SetFocus(0); 193 } 194 195 void EmbeddedWidget::attachToWindow() 196 { 197 if (m_attachedToWindow) 198 return; 199 200 m_attachedToWindow = true; 201 if (m_isVisible && m_window) 202 ShowWindow(m_window, SW_SHOWNA); 203 } 204 205 void EmbeddedWidget::detachFromWindow() 206 { 207 if (!m_attachedToWindow) 208 return; 209 210 if (m_isVisible && m_window) 211 ShowWindow(m_window, SW_HIDE); 212 m_attachedToWindow = false; 213 } 214 215 void EmbeddedWidget::didReceiveResponse(const ResourceResponse& response) 216 { 217 ASSERT(m_view); 218 219 COMPtr<IWebURLResponse> urlResponse(AdoptCOM, WebURLResponse::createInstance(response)); 220 m_view->didReceiveResponse(urlResponse.get()); 221 } 222 223 void EmbeddedWidget::didReceiveData(const char* data, int length) 224 { 225 COMPtr<MemoryStream> stream = MemoryStream::createInstance(SharedBuffer::create(data, length)); 226 m_view->didReceiveData(stream.get()); 227 } 228 229 void EmbeddedWidget::didFinishLoading() 230 { 231 m_view->didFinishLoading(); 232 } 233 234 void EmbeddedWidget::didFail(const ResourceError& error) 235 { 236 COMPtr<IWebError> webError(AdoptCOM, WebError::createInstance(error)); 237 m_view->didFail(webError.get()); 238 } 239