• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
create(IWebEmbeddedView * view,Element * element,HWND parentWindow,const IntSize & size)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 
~EmbeddedWidget()48 EmbeddedWidget::~EmbeddedWidget()
49 {
50     if (m_window)
51         DestroyWindow(m_window);
52 }
53 
createWindow(HWND parentWindow,const IntSize & size)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 
invalidateRect(const IntRect & rect)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 
setFrameRect(const IntRect & rect)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 
frameRectsChanged()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.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 
setFocus(bool focused)136 void EmbeddedWidget::setFocus(bool focused)
137 {
138     if (m_window && focused)
139         SetFocus(m_window);
140 
141     Widget::setFocus(focused);
142 }
143 
show()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 
hide()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 
windowClipRect() const164 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 
setParent(ScrollView * parent)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 
attachToWindow()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 
detachFromWindow()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 
didReceiveResponse(const ResourceResponse & response)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 
didReceiveData(const char * data,int length)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 
didFinishLoading()229 void EmbeddedWidget::didFinishLoading()
230 {
231     m_view->didFinishLoading();
232 }
233 
didFail(const ResourceError & error)234 void EmbeddedWidget::didFail(const ResourceError& error)
235 {
236     COMPtr<IWebError> webError(AdoptCOM, WebError::createInstance(error));
237     m_view->didFail(webError.get());
238 }
239