Home | History | Annotate | Download | only in WebCoreSupport
      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