[Chromium] Add PagePopup implementation
authortkent@chromium.org <tkent@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 12 Apr 2012 09:59:33 +0000 (09:59 +0000)
committertkent@chromium.org <tkent@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 12 Apr 2012 09:59:33 +0000 (09:59 +0000)
https://bugs.webkit.org/show_bug.cgi?id=81081

Reviewed by Adam Barth.

Add WebPagePopupImpl class, which is an implementation of
WebCore::PagePopup interface and WebKit::WebPagePopup interface. It's a
WebWidget which has a Page object.

No new tests because this makes no behavior change yet.

* WebKit.gyp: Add WebPagePopupImpl.h.
* src/ChromeClientImpl.cpp:
(WebKit::ChromeClientImpl::hasOpenedPopup): Supports the PagePopup.
(WebKit::ChromeClientImpl::openPagePopup):
just delegate to WebViewImpl::openPagePopup().
(WebKit::ChromeClientImpl::closePagePopup): ditto.

* src/WebPagePopupImpl.cpp:
(PagePopupChromeClient):
This is a light implementation of ChromeClient for the page in
WebPagePopupImpl. This is a friend of WebPagePopupImpl becase of ease of
access to its members.
(WebKit::PagePopupChromeClient::PagePopupChromeClient):
(WebKit::WebPagePopupImpl::WebPagePopupImpl):
(WebKit::WebPagePopupImpl::~WebPagePopupImpl):
(WebKit::WebPagePopupImpl::init):
(WebKit::WebPagePopupImpl::initPage):
(WebKit::WebPagePopupImpl::size):
(WebKit::WebPagePopupImpl::animate): Calls PageWidgetDelegate::animate().
(WebKit::WebPagePopupImpl::composite):
(WebKit::WebPagePopupImpl::layout): Calls PageWidgetDelegate::layout().
(WebKit::WebPagePopupImpl::paint): Calls PageWidgetDelegate::paint().
(WebKit::WebPagePopupImpl::resize):
(WebKit::WebPagePopupImpl::handleKeyEvent):
(WebKit::WebPagePopupImpl::handleCharEvent):
(WebKit::WebPagePopupImpl::handleGestureEvent):
(WebKit::WebPagePopupImpl::handleInputEvent):
(WebKit::WebPagePopupImpl::setFocus):
(WebKit::WebPagePopupImpl::close): Delete the page, and kill itself.
(WebKit::WebPagePopupImpl::closePopup):
(WebKit::WebPagePopup::create):
* src/WebPagePopupImpl.h: Added.

* src/WebViewImpl.cpp:
(WebKit::WebViewImpl::WebViewImpl): Initialize m_pagePopup.
(WebKit::WebViewImpl::handleKeyEvent):
Renamed from keyEvent(). Forward key events to a PagePopup if it is open.
(WebKit::WebViewImpl::handleCharEvent):
Renamed from charEvent(). Forward char events to a PagePopup if it is open.
(WebKit::WebViewImpl::openPagePopup):
Added. Instantiate a WebPagePopupImpl, calculates a good bounding
rectangle of the page popup from the specified element rectangle,
initialize the WebPagePopupImpl, and stop caret blink.
(WebKit::WebViewImpl::closePagePopup):
Close the popup, clear m_pagePopup, and resume caret blink.
(WebKit::WebViewImpl::setFocus): Hide all the popups.
(WebKit::WebViewImpl::hidePopups): Hide the page popup too.
* src/WebViewImpl.h:
(WebKit::WebViewImpl::hasOpenedPopup): Checks the page popup too.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@113956 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/WebKit.gyp
Source/WebKit/chromium/src/ChromeClientImpl.cpp
Source/WebKit/chromium/src/WebPagePopupImpl.cpp
Source/WebKit/chromium/src/WebPagePopupImpl.h [new file with mode: 0644]
Source/WebKit/chromium/src/WebViewImpl.cpp
Source/WebKit/chromium/src/WebViewImpl.h

index 2fc3c13..9dd5dd4 100644 (file)
@@ -1,5 +1,68 @@
 2012-04-12  Kent Tamura  <tkent@chromium.org>
 
+        [Chromium] Add PagePopup implementation
+        https://bugs.webkit.org/show_bug.cgi?id=81081
+
+        Reviewed by Adam Barth.
+
+        Add WebPagePopupImpl class, which is an implementation of
+        WebCore::PagePopup interface and WebKit::WebPagePopup interface. It's a
+        WebWidget which has a Page object.
+
+        No new tests because this makes no behavior change yet.
+
+        * WebKit.gyp: Add WebPagePopupImpl.h.
+        * src/ChromeClientImpl.cpp:
+        (WebKit::ChromeClientImpl::hasOpenedPopup): Supports the PagePopup.
+        (WebKit::ChromeClientImpl::openPagePopup):
+        just delegate to WebViewImpl::openPagePopup().
+        (WebKit::ChromeClientImpl::closePagePopup): ditto.
+
+        * src/WebPagePopupImpl.cpp:
+        (PagePopupChromeClient):
+        This is a light implementation of ChromeClient for the page in
+        WebPagePopupImpl. This is a friend of WebPagePopupImpl becase of ease of
+        access to its members.
+        (WebKit::PagePopupChromeClient::PagePopupChromeClient):
+        (WebKit::WebPagePopupImpl::WebPagePopupImpl):
+        (WebKit::WebPagePopupImpl::~WebPagePopupImpl):
+        (WebKit::WebPagePopupImpl::init):
+        (WebKit::WebPagePopupImpl::initPage):
+        (WebKit::WebPagePopupImpl::size):
+        (WebKit::WebPagePopupImpl::animate): Calls PageWidgetDelegate::animate().
+        (WebKit::WebPagePopupImpl::composite):
+        (WebKit::WebPagePopupImpl::layout): Calls PageWidgetDelegate::layout().
+        (WebKit::WebPagePopupImpl::paint): Calls PageWidgetDelegate::paint().
+        (WebKit::WebPagePopupImpl::resize):
+        (WebKit::WebPagePopupImpl::handleKeyEvent):
+        (WebKit::WebPagePopupImpl::handleCharEvent):
+        (WebKit::WebPagePopupImpl::handleGestureEvent):
+        (WebKit::WebPagePopupImpl::handleInputEvent):
+        (WebKit::WebPagePopupImpl::setFocus):
+        (WebKit::WebPagePopupImpl::close): Delete the page, and kill itself.
+        (WebKit::WebPagePopupImpl::closePopup):
+        (WebKit::WebPagePopup::create):
+        * src/WebPagePopupImpl.h: Added.
+
+        * src/WebViewImpl.cpp:
+        (WebKit::WebViewImpl::WebViewImpl): Initialize m_pagePopup.
+        (WebKit::WebViewImpl::handleKeyEvent):
+        Renamed from keyEvent(). Forward key events to a PagePopup if it is open.
+        (WebKit::WebViewImpl::handleCharEvent):
+        Renamed from charEvent(). Forward char events to a PagePopup if it is open.
+        (WebKit::WebViewImpl::openPagePopup):
+        Added. Instantiate a WebPagePopupImpl, calculates a good bounding
+        rectangle of the page popup from the specified element rectangle,
+        initialize the WebPagePopupImpl, and stop caret blink.
+        (WebKit::WebViewImpl::closePagePopup):
+        Close the popup, clear m_pagePopup, and resume caret blink.
+        (WebKit::WebViewImpl::setFocus): Hide all the popups.
+        (WebKit::WebViewImpl::hidePopups): Hide the page popup too.
+        * src/WebViewImpl.h:
+        (WebKit::WebViewImpl::hasOpenedPopup): Checks the page popup too.
+
+2012-04-12  Kent Tamura  <tkent@chromium.org>
+
         [Chromium] Move some code of WebViewImpl and WebFrameImpl to PageWidgetDelegate
         https://bugs.webkit.org/show_bug.cgi?id=83750
 
index 5a65f35..bceffaa 100644 (file)
                 'src/WebNotification.cpp',
                 'src/WebOptionElement.cpp',
                 'src/WebPagePopupImpl.cpp',
+                'src/WebPagePopupImpl.h',
                 'src/WebPageSerializer.cpp',
                 'src/WebPageSerializerImpl.cpp',
                 'src/WebPageSerializerImpl.h',
index 42735a4..1992cd4 100644 (file)
@@ -977,7 +977,7 @@ bool ChromeClientImpl::selectItemAlignmentFollowsMenuWritingDirection()
 
 bool ChromeClientImpl::hasOpenedPopup() const
 {
-    return !!m_webView->selectPopup();
+    return m_webView->hasOpenedPopup();
 }
 
 PassRefPtr<PopupMenu> ChromeClientImpl::createPopupMenu(PopupMenuClient* client) const
@@ -994,15 +994,14 @@ PassRefPtr<SearchPopupMenu> ChromeClientImpl::createSearchPopupMenu(PopupMenuCli
 }
 
 #if ENABLE(PAGE_POPUP)
-PagePopup* ChromeClientImpl::openPagePopup(PagePopupClient*, const IntRect&)
+PagePopup* ChromeClientImpl::openPagePopup(PagePopupClient* client, const IntRect& originBoundsInRootView)
 {
-    // FIXME: Impelement this.
-    return 0;
+    return m_webView->openPagePopup(client, originBoundsInRootView);
 }
 
-void ChromeClientImpl::closePagePopup(PagePopup*)
+void ChromeClientImpl::closePagePopup(PagePopup* popup)
 {
-    // FIXME: Implement this.
+    m_webView->closePagePopup(popup);
 }
 #endif
 
index bc810c7..0c2cc6d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
  */
 
 #include "config.h"
+#include "WebPagePopupImpl.h"
 
+#include "EmptyClients.h"
+#include "FileChooser.h"
+#include "FocusController.h"
+#include "FormState.h"
+#include "FrameView.h"
+#include "HTMLFormElement.h"
+#include "Page.h"
+#include "PagePopupClient.h"
+#include "PageWidgetDelegate.h"
+#include "Settings.h"
+#include "WebInputEvent.h"
+#include "WebInputEventConversion.h"
 #include "WebPagePopup.h"
+#include "WebWidgetClient.h"
+
+using namespace WebCore;
 
 namespace WebKit {
 
+#if ENABLE(PAGE_POPUP)
+
+class PagePopupChromeClient : public EmptyChromeClient {
+    WTF_MAKE_NONCOPYABLE(PagePopupChromeClient);
+    WTF_MAKE_FAST_ALLOCATED;
+
+public:
+    explicit PagePopupChromeClient(WebPagePopupImpl* popup)
+        : m_popup(popup)
+    {
+        ASSERT(m_popup->widgetClient());
+    }
+
+private:
+    virtual void closeWindowSoon() OVERRIDE
+    {
+        m_popup->closePopup();
+    }
+
+    virtual FloatRect windowRect() OVERRIDE
+    {
+        return FloatRect(m_popup->m_windowRectInScreen.x, m_popup->m_windowRectInScreen.y, m_popup->m_windowRectInScreen.width, m_popup->m_windowRectInScreen.height);
+    }
+
+    virtual void setWindowRect(const FloatRect& rect) OVERRIDE
+    {
+        m_popup->m_windowRectInScreen = IntRect(rect);
+        m_popup->widgetClient()->setWindowRect(m_popup->m_windowRectInScreen);
+    }
+
+    virtual void addMessageToConsole(MessageSource, MessageType, MessageLevel, const String& message, unsigned int lineNumber, const String&) OVERRIDE
+    {
+#ifndef NDEBUG
+        fprintf(stderr, "CONSOLE MESSSAGE:%u: %s\n", lineNumber, message.utf8().data());
+#else
+        UNUSED_PARAM(message);
+        UNUSED_PARAM(lineNumber);
+#endif
+    }
+
+    virtual void invalidateContentsAndRootView(const IntRect& paintRect, bool) OVERRIDE
+    {
+        if (paintRect.isEmpty())
+            return;
+        m_popup->widgetClient()->didInvalidateRect(paintRect);
+    }
+
+    virtual void scroll(const IntSize& scrollDelta, const IntRect& scrollRect, const IntRect& clipRect) OVERRIDE
+    {
+        m_popup->widgetClient()->didScrollRect(scrollDelta.width(), scrollDelta.height(), intersection(scrollRect, clipRect));
+    }
+
+    virtual void invalidateContentsForSlowScroll(const IntRect& updateRect, bool immediate) OVERRIDE
+    {
+        invalidateContentsAndRootView(updateRect, immediate);
+    }
+
+    virtual void scheduleAnimation() OVERRIDE
+    {
+        m_popup->widgetClient()->scheduleAnimation();
+    }
+
+    virtual void* webView() const OVERRIDE
+    {
+        return m_popup->m_webView;
+    }
+
+    WebPagePopupImpl* m_popup;
+};
+
 // WebPagePopupImpl ----------------------------------------------------------------
 
-// FIXME: WebPagePopupImpl implementation will be written here.
+WebPagePopupImpl::WebPagePopupImpl(WebWidgetClient* client)
+    : m_widgetClient(client)
+{
+    ASSERT(client);
+}
+
+WebPagePopupImpl::~WebPagePopupImpl()
+{
+    ASSERT(!m_page);
+}
+
+bool WebPagePopupImpl::init(WebViewImpl* webView, PagePopupClient* popupClient, const IntRect& boundsInScreen)
+{
+    ASSERT(webView);
+    ASSERT(popupClient);
+    m_webView = webView;
+    m_popupClient = popupClient;
+
+    m_widgetClient->setWindowRect(boundsInScreen);
+    m_windowRectInScreen = boundsInScreen;
+    if (!initPage())
+        return false;
+    m_widgetClient->show(WebNavigationPolicy());
+
+    setFocus(true);
+
+    return true;
+}
+
+bool WebPagePopupImpl::initPage()
+{
+    Page::PageClients pageClients;
+    fillWithEmptyClients(pageClients);
+    m_chromeClient = adoptPtr(new PagePopupChromeClient(this));
+    pageClients.chromeClient = m_chromeClient.get();
+
+    m_page = adoptPtr(new Page(pageClients));
+    m_page->settings()->setScriptEnabled(true);
+    m_page->settings()->setAllowScriptsToCloseWindows(true);
+
+    static FrameLoaderClient* emptyFrameLoaderClient =  new EmptyFrameLoaderClient;
+    RefPtr<Frame> frame = Frame::create(m_page.get(), 0, emptyFrameLoaderClient);
+    frame->setView(FrameView::create(frame.get()));
+    frame->init();
+    frame->view()->resize(m_popupClient->contentSize());
+    frame->view()->setTransparent(false);
+
+    DocumentWriter* writer = frame->loader()->activeDocumentLoader()->writer();
+    writer->setMIMEType("text/html");
+    writer->setEncoding("UTF-8", false);
+    writer->begin();
+    m_popupClient->writeDocument(*writer);
+    writer->end();
+
+    frame->script()->installFunctionsForPagePopup(frame.get(), m_popupClient);
+    return true;
+}
+
+WebSize WebPagePopupImpl::size()
+{
+    return m_popupClient->contentSize();
+}
+
+void WebPagePopupImpl::animate(double)
+{
+    PageWidgetDelegate::animate(m_page.get(), monotonicallyIncreasingTime());
+}
+
+void WebPagePopupImpl::composite(bool)
+{
+}
+
+void WebPagePopupImpl::layout()
+{
+    PageWidgetDelegate::layout(m_page.get());
+}
+
+void WebPagePopupImpl::paint(WebCanvas* canvas, const WebRect& rect)
+{
+    PageWidgetDelegate::paint(m_page.get(), 0, canvas, rect);
+}
+
+void WebPagePopupImpl::resize(const WebSize& newSize)
+{
+    if (m_page)
+        m_page->mainFrame()->view()->resize(newSize);
+    m_widgetClient->didInvalidateRect(WebRect(0, 0, newSize.width, newSize.height));
+}
+
+bool WebPagePopupImpl::handleKeyEvent(const WebKeyboardEvent&)
+{
+    // The main WebView receives key events and forward them to this via handleKeyEvent().
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+bool WebPagePopupImpl::handleCharEvent(const WebKeyboardEvent&)
+{
+    // The main WebView receives key events and forward them to this via handleKeyEvent().
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+#if ENABLE(GESTURE_EVENTS)
+bool WebPagePopupImpl::handleGestureEvent(const WebGestureEvent& event)
+{
+    if (!m_page || !m_page->mainFrame() || !m_page->mainFrame()->view())
+        return false;
+    Frame& frame = *m_page->mainFrame();
+    return frame.eventHandler()->handleGestureEvent(PlatformGestureEventBuilder(frame.view(), event));
+}
+#endif
+
+bool WebPagePopupImpl::handleInputEvent(const WebInputEvent& event)
+{
+    return PageWidgetDelegate::handleInputEvent(m_page.get(), *this, event);
+}
+
+bool WebPagePopupImpl::handleKeyEvent(const PlatformKeyboardEvent& event)
+{
+    if (!m_page->mainFrame() || !m_page->mainFrame()->view())
+        return false;
+    return m_page->mainFrame()->eventHandler()->keyEvent(event);
+}
+
+void WebPagePopupImpl::setFocus(bool enable)
+{
+    if (!m_page)
+        return;
+    m_page->focusController()->setFocused(enable);
+    if (enable)
+        m_page->focusController()->setActive(true);
+}
+
+void WebPagePopupImpl::close()
+{
+    m_page.clear();
+    delete this;
+}
+
+void WebPagePopupImpl::closePopup()
+{
+    if (m_page) {
+        m_page->setGroupName(String());
+        m_page->mainFrame()->loader()->stopAllLoaders();
+        m_page->mainFrame()->loader()->stopLoading(UnloadEventPolicyNone);
+    }
+    // closeWidgetSoon() will call this->close() later.
+    m_widgetClient->closeWidgetSoon();
+
+    m_popupClient->didClosePopup();
+}
+
+#endif // ENABLE(PAGE_POPUP)
 
 // WebPagePopup ----------------------------------------------------------------
 
-WebPagePopup* WebPagePopup::create(WebWidgetClient*)
+WebPagePopup* WebPagePopup::create(WebWidgetClient* client)
 {
-    // FIXME: Returns a WebPagePopupImpl object.
+#if ENABLE(PAGE_POPUP)
+    if (!client)
+        CRASH();
+    return new WebPagePopupImpl(client);
+#else
+    UNUSED_PARAM(client);
     return 0;
+#endif
 }
 
 } // namespace WebKit
diff --git a/Source/WebKit/chromium/src/WebPagePopupImpl.h b/Source/WebKit/chromium/src/WebPagePopupImpl.h
new file mode 100644 (file)
index 0000000..25afcb4
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2012 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER OR 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 WebPagePopupImpl_h
+#define WebPagePopupImpl_h
+
+#if ENABLE(PAGE_POPUP)
+
+#include "PagePopup.h"
+#include "PageWidgetDelegate.h"
+#include "WebPagePopup.h"
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+class Page;
+class PagePopupClient;
+class PlatformKeyboardEvent;
+}
+
+namespace WebKit {
+
+class PagePopupChromeClient;
+class WebViewImpl;
+
+class WebPagePopupImpl : public WebPagePopup,
+                         public PageWidgetEventHandler,
+                         public WebCore::PagePopup {
+    WTF_MAKE_NONCOPYABLE(WebPagePopupImpl);
+    WTF_MAKE_FAST_ALLOCATED;
+
+public:
+    bool init(WebViewImpl*, WebCore::PagePopupClient*, const WebCore::IntRect& boundsInScreen);
+    bool handleKeyEvent(const WebCore::PlatformKeyboardEvent&);
+    void closePopup();
+    WebWidgetClient* widgetClient() const { return m_widgetClient; }
+
+private:
+    // WebWidget functions
+    virtual WebSize size() OVERRIDE;
+    virtual void animate(double) OVERRIDE;
+    virtual void composite(bool) OVERRIDE;
+    virtual void layout() OVERRIDE;
+    virtual void paint(WebCanvas*, const WebRect&) OVERRIDE;
+    virtual void resize(const WebSize&) OVERRIDE;
+    virtual void close() OVERRIDE;
+    virtual bool handleInputEvent(const WebInputEvent&) OVERRIDE;
+    virtual void setFocus(bool) OVERRIDE;
+
+    // PageWidgetEventHandler functions
+    virtual bool handleKeyEvent(const WebKeyboardEvent&) OVERRIDE;
+    virtual bool handleCharEvent(const WebKeyboardEvent&) OVERRIDE;
+#if ENABLE(GESTURE_EVENTS)
+    virtual bool handleGestureEvent(const WebGestureEvent&) OVERRIDE;
+#endif
+
+    explicit WebPagePopupImpl(WebWidgetClient*);
+    virtual ~WebPagePopupImpl();
+    bool initPage();
+
+    WebWidgetClient* m_widgetClient;
+    WebRect m_windowRectInScreen;
+    WebViewImpl* m_webView;
+    OwnPtr<WebCore::Page> m_page;
+    OwnPtr<PagePopupChromeClient> m_chromeClient;
+    WebCore::PagePopupClient* m_popupClient;
+
+    friend class WebPagePopup;
+    friend class PagePopupChromeClient;
+};
+
+} // namespace WebKit
+#endif // ENABLE(PAGE_POPUP)
+#endif // WebPagePopupImpl_h
index bcf6d81..1b1672b 100644 (file)
@@ -88,6 +88,7 @@
 #include "Page.h"
 #include "PageGroup.h"
 #include "PageGroupLoadDeferrer.h"
+#include "PagePopupClient.h"
 #include "PageWidgetDelegate.h"
 #include "Pasteboard.h"
 #include "PlatformContextSkia.h"
 #include "WebKit.h"
 #include "WebMediaPlayerAction.h"
 #include "WebNode.h"
+#include "WebPagePopupImpl.h"
 #include "WebPlugin.h"
 #include "WebPluginAction.h"
 #include "WebPluginContainerImpl.h"
@@ -370,6 +372,7 @@ WebViewImpl::WebViewImpl(WebViewClient* client)
     , m_dragOperation(WebDragOperationNone)
     , m_autofillPopupShowing(false)
     , m_autofillPopup(0)
+    , m_pagePopup(0)
     , m_isTransparent(false)
     , m_tabsToLinks(false)
     , m_dragScrollTimer(adoptPtr(new DragScrollTimer))
@@ -715,6 +718,16 @@ bool WebViewImpl::handleKeyEvent(const WebKeyboardEvent& event)
     // not the page.
     if (m_selectPopup)
         return m_selectPopup->handleKeyEvent(PlatformKeyboardEventBuilder(event));
+#if ENABLE(PAGE_POPUP)
+    if (m_pagePopup) {
+        m_pagePopup->handleKeyEvent(PlatformKeyboardEventBuilder(event));
+        // We need to ignore the next Char event after this otherwise pressing
+        // enter when selecting an item in the popup will go to the page.
+        if (WebInputEvent::RawKeyDown == event.type)
+            m_suppressNextKeypressEvent = true;
+        return true;
+    }
+#endif
 
     // Give Autocomplete a chance to consume the key events it is interested in.
     if (autocompleteHandleKeyEvent(event))
@@ -827,6 +840,10 @@ bool WebViewImpl::handleCharEvent(const WebKeyboardEvent& event)
     // not the page.
     if (m_selectPopup)
         return m_selectPopup->handleKeyEvent(PlatformKeyboardEventBuilder(event));
+#if ENABLE(PAGE_POPUP)
+    if (m_pagePopup)
+        return m_pagePopup->handleKeyEvent(PlatformKeyboardEventBuilder(event));
+#endif
 
     Frame* frame = focusedWebCoreFrame();
     if (!frame)
@@ -1177,6 +1194,49 @@ void  WebViewImpl::popupClosed(WebCore::PopupContainer* popupContainer)
     }
 }
 
+#if ENABLE(PAGE_POPUP)
+PagePopup* WebViewImpl::openPagePopup(PagePopupClient* client, const IntRect& originBoundsInRootView)
+{
+    ASSERT(client);
+    if (hasOpenedPopup())
+        hidePopups();
+    ASSERT(!m_pagePopup);
+
+    WebWidget* popupWidget = m_client->createPopupMenu(WebPopupTypePage);
+    ASSERT(popupWidget);
+    m_pagePopup = static_cast<WebPagePopupImpl*>(popupWidget);
+    WebSize rootViewSize = size();
+    IntSize popupSize = client->contentSize();
+    IntRect popupBoundsInRootView(IntPoint(max(0, originBoundsInRootView.x()), max(0, originBoundsInRootView.maxY())), popupSize);
+    if (popupBoundsInRootView.maxY() > rootViewSize.height)
+        popupBoundsInRootView.setY(max(0, originBoundsInRootView.y() - popupSize.height()));
+    if (popupBoundsInRootView.maxX() > rootViewSize.width)
+        popupBoundsInRootView.setX(max(0, rootViewSize.width - popupSize.width()));
+    if (!m_pagePopup->init(this, client, m_chromeClientImpl.rootViewToScreen(popupBoundsInRootView))) {
+        m_pagePopup->closePopup();
+        m_pagePopup = 0;
+    }
+
+    if (Frame* frame = focusedWebCoreFrame())
+        frame->selection()->setCaretVisible(false);
+    return m_pagePopup;
+}
+
+void WebViewImpl::closePagePopup(PagePopup* popup)
+{
+    ASSERT(popup);
+    WebPagePopupImpl* popupImpl = static_cast<WebPagePopupImpl*>(popup);
+    ASSERT(m_pagePopup == popupImpl);
+    if (m_pagePopup != popupImpl)
+        return;
+    m_pagePopup->closePopup();
+    m_pagePopup = 0;
+
+    if (Frame* frame = focusedWebCoreFrame())
+        frame->selection()->pageActivationChanged();
+}
+#endif
+
 void WebViewImpl::hideAutofillPopup()
 {
     if (m_autofillPopupShowing) {
@@ -1644,8 +1704,7 @@ void WebViewImpl::setFocus(bool enable)
         }
         m_imeAcceptEvents = true;
     } else {
-        hideAutofillPopup();
-        hideSelectPopup();
+        hidePopups();
 
         // Clear focus on the currently focused frame if any.
         if (!m_page)
@@ -2734,6 +2793,10 @@ void WebViewImpl::hidePopups()
 {
     hideSelectPopup();
     hideAutofillPopup();
+#if ENABLE(PAGE_POPUP)
+    if (m_pagePopup)
+        closePagePopup(m_pagePopup);
+#endif
 }
 
 void WebViewImpl::performCustomContextMenuAction(unsigned action)
index 7202a47..32379dd 100644 (file)
@@ -69,6 +69,8 @@ class HistoryItem;
 class HitTestResult;
 class KeyboardEvent;
 class Page;
+class PagePopup;
+class PagePopupClient;
 class PlatformGestureCurveTarget;
 class PlatformKeyboardEvent;
 class PopupContainer;
@@ -97,6 +99,7 @@ class WebDevToolsAgentClient;
 class WebDevToolsAgentPrivate;
 class WebFrameImpl;
 class WebGestureEvent;
+class WebPagePopupImpl;
 class WebImage;
 class WebKeyboardEvent;
 class WebMouseEvent;
@@ -447,6 +450,10 @@ public:
     // Notification that a popup was opened/closed.
     void popupOpened(WebCore::PopupContainer* popupContainer);
     void popupClosed(WebCore::PopupContainer* popupContainer);
+#if ENABLE(PAGE_POPUP)
+    WebCore::PagePopup* openPagePopup(WebCore::PagePopupClient*, const WebCore::IntRect& originBoundsInRootView);
+    void closePagePopup(WebCore::PagePopup*);
+#endif
 
     void hideAutofillPopup();
 
@@ -485,6 +492,11 @@ public:
     virtual void setVisibilityState(WebPageVisibilityState, bool);
 
     WebCore::PopupContainer* selectPopup() const { return m_selectPopup.get(); }
+#if ENABLE(PAGE_POPUP)
+    bool hasOpenedPopup() const { return m_selectPopup || m_pagePopup; }
+#else
+    bool hasOpenedPopup() const { return m_selectPopup; }
+#endif
 
     // Returns true if the event leads to scrolling.
     static bool mapKeyCodeForScroll(int keyCode,
@@ -696,6 +708,11 @@ private:
     // The popup associated with a select element.
     RefPtr<WebCore::PopupContainer> m_selectPopup;
 
+#if ENABLE(PAGE_POPUP)
+    // The popup associated with an input element.
+    WebPagePopupImpl* m_pagePopup;
+#endif
+
     OwnPtr<WebDevToolsAgentPrivate> m_devToolsAgent;
     OwnPtr<PageOverlayList> m_pageOverlays;