[Qt] [WK2] Implement popup menus in QDesktopWebView using QComboBox
authorcaio.oliveira@openbossa.org <caio.oliveira@openbossa.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 19 Sep 2011 17:14:19 +0000 (17:14 +0000)
committercaio.oliveira@openbossa.org <caio.oliveira@openbossa.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 19 Sep 2011 17:14:19 +0000 (17:14 +0000)
https://bugs.webkit.org/show_bug.cgi?id=67938

Reviewed by Andreas Kling.

Implement a WebPopupMenuProxy that uses QtWebComboBox (a QComboBox subclass we
have for WK1). Then use this WebPopupMenuProxy in QDesktopWebView. The implementation
explicitly avoids running a nested mainloop.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::showPopupMenu):
Since we don't run a nested mainloop, we need to keep the client pointer to call
valueChangedForPopupMenu().

* UIProcess/qt/WebPopupMenuProxyQtDesktop.cpp: Added.
(WebKit::WebPopupMenuProxyQtDesktop::WebPopupMenuProxyQtDesktop):
(WebKit::WebPopupMenuProxyQtDesktop::~WebPopupMenuProxyQtDesktop):
(WebKit::WebPopupMenuProxyQtDesktop::showPopupMenu):
(WebKit::WebPopupMenuProxyQtDesktop::hidePopupMenu):
(WebKit::WebPopupMenuProxyQtDesktop::setSelectedIndex):
(WebKit::WebPopupMenuProxyQtDesktop::onPopupMenuHidden):
(WebKit::WebPopupMenuProxyQtDesktop::populate):
* UIProcess/qt/WebPopupMenuProxyQtDesktop.h: Added.
(WebKit::WebPopupMenuProxyQtDesktop::create):
* UIProcess/qt/qdesktopwebpageproxy.cpp:
(QDesktopWebPageProxy::createPopupMenuProxy):
* UIProcess/qt/qdesktopwebpageproxy.h:
* WebKit2.pro:

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

Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/WebPageProxy.cpp
Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQtDesktop.cpp [new file with mode: 0644]
Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQtDesktop.h [new file with mode: 0644]
Source/WebKit2/UIProcess/qt/qdesktopwebpageproxy.cpp
Source/WebKit2/UIProcess/qt/qdesktopwebpageproxy.h
Source/WebKit2/WebKit2.pro

index 14229a8..66038d6 100644 (file)
@@ -1,3 +1,34 @@
+2011-09-14  Caio Marcelo de Oliveira Filho  <caio.oliveira@openbossa.org>
+
+        [Qt] [WK2] Implement popup menus in QDesktopWebView using QComboBox
+        https://bugs.webkit.org/show_bug.cgi?id=67938
+
+        Reviewed by Andreas Kling.
+
+        Implement a WebPopupMenuProxy that uses QtWebComboBox (a QComboBox subclass we
+        have for WK1). Then use this WebPopupMenuProxy in QDesktopWebView. The implementation
+        explicitly avoids running a nested mainloop.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::showPopupMenu):
+        Since we don't run a nested mainloop, we need to keep the client pointer to call
+        valueChangedForPopupMenu().
+
+        * UIProcess/qt/WebPopupMenuProxyQtDesktop.cpp: Added.
+        (WebKit::WebPopupMenuProxyQtDesktop::WebPopupMenuProxyQtDesktop):
+        (WebKit::WebPopupMenuProxyQtDesktop::~WebPopupMenuProxyQtDesktop):
+        (WebKit::WebPopupMenuProxyQtDesktop::showPopupMenu):
+        (WebKit::WebPopupMenuProxyQtDesktop::hidePopupMenu):
+        (WebKit::WebPopupMenuProxyQtDesktop::setSelectedIndex):
+        (WebKit::WebPopupMenuProxyQtDesktop::onPopupMenuHidden):
+        (WebKit::WebPopupMenuProxyQtDesktop::populate):
+        * UIProcess/qt/WebPopupMenuProxyQtDesktop.h: Added.
+        (WebKit::WebPopupMenuProxyQtDesktop::create):
+        * UIProcess/qt/qdesktopwebpageproxy.cpp:
+        (QDesktopWebPageProxy::createPopupMenuProxy):
+        * UIProcess/qt/qdesktopwebpageproxy.h:
+        * WebKit2.pro:
+
 2011-09-19  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         [GTK] Fix distcheck build
index 1a35dc8..5789e14 100644 (file)
@@ -2309,7 +2309,11 @@ void WebPageProxy::showPopupMenu(const IntRect& rect, uint64_t textDirection, co
     RefPtr<WebPopupMenuProxy> protectedActivePopupMenu = m_activePopupMenu;
 
     protectedActivePopupMenu->showPopupMenu(rect, static_cast<TextDirection>(textDirection), m_pageScaleFactor, items, data, selectedIndex);
+
+    // Since Qt doesn't use a nested mainloop the show the popup and get the answer, we need to keep the client pointer valid.
+#if !PLATFORM(QT)
     protectedActivePopupMenu->invalidate();
+#endif
     protectedActivePopupMenu = 0;
 }
 
diff --git a/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQtDesktop.cpp b/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQtDesktop.cpp
new file mode 100644 (file)
index 0000000..dc0f206
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+#include "config.h"
+#include "WebPopupMenuProxyQtDesktop.h"
+
+#include "PlatformPopupMenuData.h"
+#include "WebPopupItem.h"
+#include <QtDeclarative/QSGCanvas>
+#include <QtDeclarative/QSGItem>
+#include <QtGui/QStandardItemModel>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+WebPopupMenuProxyQtDesktop::WebPopupMenuProxyQtDesktop(WebPopupMenuProxy::Client* client, QSGItem* webViewItem)
+    : QObject()
+    , WebPopupMenuProxy(client)
+    , m_comboBox(new QtWebComboBox)
+    , m_webViewItem(webViewItem)
+    , m_selectedIndex(-1)
+{
+    QtWebComboBox* comboBox = m_comboBox.data();
+    comboBox->setParent(m_webViewItem->canvas());
+    connect(comboBox, SIGNAL(activated(int)), SLOT(setSelectedIndex(int)));
+    connect(comboBox, SIGNAL(didHide()), SLOT(onPopupMenuHidden()), Qt::QueuedConnection);
+}
+
+WebPopupMenuProxyQtDesktop::~WebPopupMenuProxyQtDesktop()
+{
+    delete m_comboBox.data();
+}
+
+void WebPopupMenuProxyQtDesktop::showPopupMenu(const IntRect& rect, WebCore::TextDirection, double, const Vector<WebPopupItem>& items, const PlatformPopupMenuData&, int32_t selectedIndex)
+{
+    QtWebComboBox* comboBox = m_comboBox.data();
+    m_selectedIndex = selectedIndex;
+    populate(items);
+    comboBox->setCurrentIndex(selectedIndex);
+    comboBox->setGeometry(m_webViewItem->mapRectToScene(QRect(rect)).toRect());
+    comboBox->showPopupAtCursorPosition();
+}
+
+void WebPopupMenuProxyQtDesktop::hidePopupMenu()
+{
+    if (m_comboBox)
+        m_comboBox.data()->hidePopup();
+}
+
+void WebPopupMenuProxyQtDesktop::setSelectedIndex(int index)
+{
+    m_selectedIndex = index;
+}
+
+void WebPopupMenuProxyQtDesktop::onPopupMenuHidden()
+{
+    if (m_client)
+        m_client->valueChangedForPopupMenu(this, m_selectedIndex);
+}
+
+void WebPopupMenuProxyQtDesktop::populate(const Vector<WebPopupItem>& items)
+{
+    QtWebComboBox* comboBox = m_comboBox.data();
+    Q_ASSERT(comboBox);
+
+    comboBox->clear();
+
+    QStandardItemModel* model = qobject_cast<QStandardItemModel*>(comboBox->model());
+    Q_ASSERT(model);
+
+    for (size_t i = 0; i < items.size(); ++i) {
+        const WebPopupItem& item = items.at(i);
+        if (item.m_type == WebPopupItem::Separator) {
+            comboBox->insertSeparator(i);
+            continue;
+        }
+        comboBox->insertItem(i, item.m_text);
+        model->item(i)->setToolTip(item.m_toolTip);
+        model->item(i)->setEnabled(item.m_isEnabled);
+    }
+}
+
+#include "moc_WebPopupMenuProxyQtDesktop.cpp"
+
+} // namespace WebKit
diff --git a/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQtDesktop.h b/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQtDesktop.h
new file mode 100644 (file)
index 0000000..883ebc7
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 WebPopupMenuProxyQtDesktop_h
+#define WebPopupMenuProxyQtDesktop_h
+
+#include "QtWebComboBox.h"
+#include "WebPopupMenuProxy.h"
+#include <QtCore/QObject>
+#include <QtCore/QWeakPointer>
+
+class QSGItem;
+
+namespace WebCore {
+class QtWebComboBox;
+}
+
+namespace WebKit {
+
+class WebPopupMenuProxyQtDesktop : public QObject, public WebPopupMenuProxy {
+    Q_OBJECT
+
+public:
+    virtual ~WebPopupMenuProxyQtDesktop();
+
+    static PassRefPtr<WebPopupMenuProxyQtDesktop> create(WebPopupMenuProxy::Client* client, QSGItem* webViewItem)
+    {
+        return adoptRef(new WebPopupMenuProxyQtDesktop(client, webViewItem));
+    }
+
+    virtual void showPopupMenu(const WebCore::IntRect&, WebCore::TextDirection, double pageScaleFactor, const Vector<WebPopupItem>&, const PlatformPopupMenuData&, int32_t selectedIndex);
+    virtual void hidePopupMenu();
+
+private Q_SLOTS:
+    void setSelectedIndex(int);
+    void onPopupMenuHidden();
+
+private:
+    WebPopupMenuProxyQtDesktop(WebPopupMenuProxy::Client*, QSGItem* webViewItem);
+    void populate(const Vector<WebPopupItem>&);
+
+    // Qt guarded pointer because QWidgets have their own memory management and
+    // when closing the UI the combobox will be deleted before we are.
+    QWeakPointer<WebCore::QtWebComboBox> m_comboBox;
+    QSGItem* m_webViewItem;
+    int32_t m_selectedIndex;
+};
+
+} // namespace WebKit
+
+#endif // WebPopupMenuProxyQtDesktop_h
index 48bc980..04f90bf 100644 (file)
  *
  */
 
-#include "qdesktopwebview_p.h"
 #include "qdesktopwebpageproxy.h"
+
+#include "qdesktopwebview.h"
+#include "qdesktopwebview_p.h"
 #include "DrawingAreaProxyImpl.h"
 #include "NativeWebMouseEvent.h"
 #include "NativeWebWheelEvent.h"
+#include "WebPopupMenuProxyQtDesktop.h"
 #include <QApplication>
 #include <QEvent>
 #include <QGraphicsSceneDragDropEvent>
@@ -78,6 +81,12 @@ void QDesktopWebPageProxy::doneWithTouchEvent(const NativeWebTouchEvent&, bool w
 }
 #endif
 
+PassRefPtr<WebPopupMenuProxy> QDesktopWebPageProxy::createPopupMenuProxy(WebPageProxy*)
+{
+    QSGItem* webViewItem = static_cast<QDesktopWebViewPrivate*>(m_viewInterface)->q;
+    return WebPopupMenuProxyQtDesktop::create(m_webPageProxy.get(), webViewItem);
+}
+
 bool QDesktopWebPageProxy::handleEvent(QEvent* ev)
 {
     switch (ev->type()) {
index 83d073a..71de769 100644 (file)
@@ -47,6 +47,8 @@ private:
     virtual void doneWithTouchEvent(const NativeWebTouchEvent&, bool wasEventHandled);
 #endif
 
+    virtual PassRefPtr<WebKit::WebPopupMenuProxy> createPopupMenuProxy(WebKit::WebPageProxy*);
+
     virtual void timerEvent(QTimerEvent*);
 
     bool handleMouseMoveEvent(QGraphicsSceneMouseEvent*);
index 96b210d..08ffb4b 100644 (file)
@@ -20,6 +20,12 @@ QT += declarative
 # Build both debug and release configurations
 mac: CONFIG += build_all
 
+WEBKIT1_HEADERS_SHARED_WITH_WEBKIT2= \
+    $$PWD/../WebKit/qt/WebCoreSupport/QtWebComboBox.h
+
+WEBKIT1_SOURCES_SHARED_WITH_WEBKIT2 = \
+    $$PWD/../WebKit/qt/WebCoreSupport/QtWebComboBox.cpp
+
 WEBKIT2_GENERATED_HEADERS = \
     $$WEBKIT2_GENERATED_SOURCES_DIR/AuthenticationManagerMessages.h \
     $$WEBKIT2_GENERATED_SOURCES_DIR/DownloadProxyMessages.h \
@@ -259,6 +265,7 @@ HEADERS += \
     UIProcess/qt/WebUndoCommandQt.h \
     UIProcess/qt/WebContextMenuProxyQt.h \
     UIProcess/qt/WebPopupMenuProxyQt.h \
+    UIProcess/qt/WebPopupMenuProxyQtDesktop.h \
     WebProcess/ApplicationCache/WebApplicationCacheManager.h \
     WebProcess/Authentication/AuthenticationManager.h \
     WebProcess/Cookies/WebCookieManager.h \
@@ -323,7 +330,8 @@ HEADERS += \
     WebProcess/WebPage/WebPage.h \
     WebProcess/WebPage/WebPageGroupProxy.h \
     WebProcess/WebProcess.h \
-    $$WEBKIT2_GENERATED_HEADERS
+    $$WEBKIT2_GENERATED_HEADERS \
+    $$WEBKIT1_HEADERS_SHARED_WITH_WEBKIT2
 
 SOURCES += \
     Platform/CoreIPC/ArgumentCoders.cpp \
@@ -493,6 +501,7 @@ SOURCES += \
     UIProcess/qt/WebInspectorProxyQt.cpp \
     UIProcess/qt/WebPageProxyQt.cpp \
     UIProcess/qt/WebPopupMenuProxyQt.cpp \
+    UIProcess/qt/WebPopupMenuProxyQtDesktop.cpp \
     UIProcess/qt/WebPreferencesQt.cpp \
     WebProcess/ApplicationCache/WebApplicationCacheManager.cpp \
     WebProcess/Authentication/AuthenticationManager.cpp \
@@ -581,7 +590,8 @@ SOURCES += \
     WebProcess/WebProcess.cpp \
     WebProcess/qt/WebProcessMainQt.cpp \
     WebProcess/qt/WebProcessQt.cpp \
-    $$WEBKIT2_GENERATED_SOURCES
+    $$WEBKIT2_GENERATED_SOURCES \
+    $$WEBKIT1_SOURCES_SHARED_WITH_WEBKIT2
 
 contains(DEFINES, ENABLE_NETSCAPE_PLUGIN_API=0) {
     DEFINES += PLUGIN_ARCHITECTURE_UNSUPPORTED