Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / web / ExternalPopupMenu.cpp
index 3226b49..52d6052 100644 (file)
  */
 
 #include "config.h"
-#include "ExternalPopupMenu.h"
-
-#include "WebExternalPopupMenu.h"
-#include "WebMenuItemInfo.h"
-#include "WebPopupMenuInfo.h"
-#include "WebViewClient.h"
-#include "WebViewImpl.h"
-#include "core/frame/Frame.h"
+#include "web/ExternalPopupMenu.h"
+
 #include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
 #include "platform/PopupMenuClient.h"
 #include "platform/geometry/FloatQuad.h"
 #include "platform/geometry/IntPoint.h"
 #include "platform/text/TextDirection.h"
 #include "public/platform/WebVector.h"
-
-using namespace WebCore;
+#include "public/web/WebExternalPopupMenu.h"
+#include "public/web/WebMenuItemInfo.h"
+#include "public/web/WebPopupMenuInfo.h"
+#include "public/web/WebViewClient.h"
+#include "web/WebViewImpl.h"
 
 namespace blink {
 
-ExternalPopupMenu::ExternalPopupMenu(Frame& frame, PopupMenuClient* popupMenuClient, WebViewImpl& webView)
+ExternalPopupMenu::ExternalPopupMenu(LocalFrame& frame, PopupMenuClient* popupMenuClient, WebViewImpl& webView)
     : m_popupMenuClient(popupMenuClient)
     , m_frameView(frame.view())
     , m_webView(webView)
@@ -64,9 +62,12 @@ ExternalPopupMenu::~ExternalPopupMenu()
 void ExternalPopupMenu::show(const FloatQuad& controlPosition, const IntSize&, int index)
 {
     IntRect rect(controlPosition.enclosingBoundingBox());
-    // WebCore reuses the PopupMenu of a page.
+    // WebCore reuses the PopupMenu of an element.
     // For simplicity, we do recreate the actual external popup everytime.
-    hide();
+    if (m_webExternalPopupMenu) {
+        m_webExternalPopupMenu->close();
+        m_webExternalPopupMenu = 0;
+    }
 
     WebPopupMenuInfo info;
     getPopupMenuInfo(&info);
@@ -81,7 +82,7 @@ void ExternalPopupMenu::show(const FloatQuad& controlPosition, const IntSize&, i
             m_syntheticEvent = adoptPtr(new WebMouseEvent);
             *m_syntheticEvent = *static_cast<const WebMouseEvent*>(currentEvent);
             m_syntheticEvent->type = WebInputEvent::MouseUp;
-            m_dispatchEventTimer.startOneShot(0);
+            m_dispatchEventTimer.startOneShot(0, FROM_HERE);
             // FIXME: show() is asynchronous. If preparing a popup is slow and
             // a user released the mouse button before showing the popup,
             // mouseup and click events are correctly dispatched. Dispatching
@@ -123,7 +124,7 @@ void ExternalPopupMenu::disconnectClient()
 void ExternalPopupMenu::didChangeSelection(int index)
 {
     if (m_popupMenuClient)
-        m_popupMenuClient->selectionChanged(index);
+        m_popupMenuClient->selectionChanged(toPopupMenuItemIndex(index));
 }
 
 void ExternalPopupMenu::didAcceptIndex(int index)
@@ -131,14 +132,12 @@ void ExternalPopupMenu::didAcceptIndex(int index)
     // Calling methods on the PopupMenuClient might lead to this object being
     // derefed. This ensures it does not get deleted while we are running this
     // method.
+    int popupMenuItemIndex = toPopupMenuItemIndex(index);
     RefPtr<ExternalPopupMenu> guard(this);
 
     if (m_popupMenuClient) {
-        m_popupMenuClient->valueChanged(index);
-        // The call to valueChanged above might have lead to a call to
-        // disconnectClient, so we might not have a PopupMenuClient anymore.
-        if (m_popupMenuClient)
-            m_popupMenuClient->popupDidHide();
+        m_popupMenuClient->popupDidHide();
+        m_popupMenuClient->valueChanged(popupMenuItemIndex);
     }
     m_webExternalPopupMenu = 0;
 }
@@ -156,10 +155,10 @@ void ExternalPopupMenu::didAcceptIndices(const WebVector<int>& indices)
     RefPtr<ExternalPopupMenu> protect(this);
 
     if (!indices.size())
-        m_popupMenuClient->valueChanged(-1, true);
+        m_popupMenuClient->valueChanged(static_cast<unsigned>(-1), true);
     else {
         for (size_t i = 0; i < indices.size(); ++i)
-            m_popupMenuClient->listBoxSelectItem(indices[i], (i > 0), false, (i == indices.size() - 1));
+            m_popupMenuClient->listBoxSelectItem(toPopupMenuItemIndex(indices[i]), (i > 0), false, (i == indices.size() - 1));
     }
 
     // The call to valueChanged above might have lead to a call to
@@ -183,9 +182,14 @@ void ExternalPopupMenu::didCancel()
 void ExternalPopupMenu::getPopupMenuInfo(WebPopupMenuInfo* info)
 {
     int itemCount = m_popupMenuClient->listSize();
-    WebVector<WebMenuItemInfo> items(static_cast<size_t>(itemCount));
+    int count = 0;
+    Vector<WebMenuItemInfo> items(static_cast<size_t>(itemCount));
     for (int i = 0; i < itemCount; ++i) {
-        WebMenuItemInfo& popupItem = items[i];
+        PopupMenuStyle style = m_popupMenuClient->itemStyle(i);
+        if (style.isDisplayNone())
+            continue;
+
+        WebMenuItemInfo& popupItem = items[count++];
         popupItem.label = m_popupMenuClient->itemText(i);
         popupItem.toolTip = m_popupMenuClient->itemToolTip(i);
         if (m_popupMenuClient->itemIsSeparator(i))
@@ -196,20 +200,51 @@ void ExternalPopupMenu::getPopupMenuInfo(WebPopupMenuInfo* info)
             popupItem.type = WebMenuItemInfo::Option;
         popupItem.enabled = m_popupMenuClient->itemIsEnabled(i);
         popupItem.checked = m_popupMenuClient->itemIsSelected(i);
-        PopupMenuStyle style = m_popupMenuClient->itemStyle(i);
-        if (style.textDirection() == WebCore::RTL)
-            popupItem.textDirection = WebTextDirectionRightToLeft;
-        else
-            popupItem.textDirection = WebTextDirectionLeftToRight;
+        popupItem.textDirection = toWebTextDirection(style.textDirection());
         popupItem.hasTextDirectionOverride = style.hasTextDirectionOverride();
     }
 
     info->itemHeight = m_popupMenuClient->menuStyle().font().fontMetrics().height();
     info->itemFontSize = static_cast<int>(m_popupMenuClient->menuStyle().font().fontDescription().computedSize());
-    info->selectedIndex = m_popupMenuClient->selectedIndex();
-    info->rightAligned = m_popupMenuClient->menuStyle().textDirection() == WebCore::RTL;
+    info->selectedIndex = toExternalPopupMenuItemIndex(m_popupMenuClient->selectedIndex());
+    info->rightAligned = m_popupMenuClient->menuStyle().textDirection() == RTL;
     info->allowMultipleSelection = m_popupMenuClient->multiple();
-    info->items.swap(items);
+    info->items = items;
 }
 
+int ExternalPopupMenu::toPopupMenuItemIndex(int externalPopupMenuItemIndex)
+{
+    ASSERT(m_popupMenuClient);
+    if (externalPopupMenuItemIndex < 0)
+        return externalPopupMenuItemIndex;
+
+    int itemCount = m_popupMenuClient->listSize();
+    int indexTracker = 0;
+    for (int i = 0; i < itemCount ; ++i) {
+        if (m_popupMenuClient->itemStyle(i).isDisplayNone())
+            continue;
+        if (indexTracker++ == externalPopupMenuItemIndex)
+            return i;
+    }
+    return -1;
 }
+
+int ExternalPopupMenu::toExternalPopupMenuItemIndex(int popupMenuItemIndex)
+{
+    ASSERT(m_popupMenuClient);
+    if (popupMenuItemIndex < 0)
+        return popupMenuItemIndex;
+
+    int itemCount = m_popupMenuClient->listSize();
+    int indexTracker = 0;
+    for (int i = 0; i < itemCount; ++i) {
+        if (m_popupMenuClient->itemStyle(i).isDisplayNone())
+            continue;
+        if (popupMenuItemIndex == i)
+            return indexTracker;
+        ++indexTracker;
+    }
+    return -1;
+}
+
+} // namespace blink