WebKit Bugzilla
Attachment 346198 Details for
Bug 188172
: [WinCairo] <select> elements do not popup options
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-188172-20180731133047.patch (text/plain), 53.41 KB, created by
Stephan Szabo
on 2018-07-31 13:30:48 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Stephan Szabo
Created:
2018-07-31 13:30:48 PDT
Size:
53.41 KB
patch
obsolete
>Subversion Revision: 234426 >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index 713ea7341df292025245b0a6b3a5e84829e0d24c..a80c68e90f1f48a32a180132d53467524ef8aa57 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,81 @@ >+2018-07-31 Stephan Szabo <stephan.szabo@sony.com> >+ >+ [WinCairo] <select> elements do not popup options >+ https://bugs.webkit.org/show_bug.cgi?id=188172 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * PlatformWin.cmake: Add WebPopupMenuProxyWin >+ * Shared/PlatformPopupMenuData.cpp: >+ (WebKit::PlatformPopupMenuData::encode const): Encode >+ windows parameters >+ (WebKit::PlatformPopupMenuData::decode): Decode windows >+ parameters >+ * Shared/PlatformPopupMenuData.h: Add the windows specific >+ parameters (based on removed Windows implementation) >+ * UIProcess/win/PageClientImpl.cpp: >+ (WebKit::PageClientImpl::createPopupMenuProxy): >+ * UIProcess/win/WebPopupMenuProxyWin.cpp: Added. (based on >+ removed Windows implementation plus some fixes/api changes >+ since the removal) >+ (WebKit::isASCIIPrintable): >+ (WebKit::translatePoint): >+ (WebKit::WebPopupMenuProxyWin::WebPopupMenuProxyWndProc): >+ (WebKit::WebPopupMenuProxyWin::wndProc): >+ (WebKit::WebPopupMenuProxyWin::registerWindowClass): >+ (WebKit::WebPopupMenuProxyWin::WebPopupMenuProxyWin): >+ (WebKit::WebPopupMenuProxyWin::~WebPopupMenuProxyWin): >+ (WebKit::WebPopupMenuProxyWin::showPopupMenu): >+ (WebKit::WebPopupMenuProxyWin::hidePopupMenu): >+ (WebKit::WebPopupMenuProxyWin::calculatePositionAndSize): >+ (WebKit::WebPopupMenuProxyWin::clientRect const): >+ (WebKit::WebPopupMenuProxyWin::invalidateItem): >+ (WebKit::WebPopupMenuProxyWin::scrollSize const): >+ (WebKit::WebPopupMenuProxyWin::setScrollOffset): >+ (WebKit::WebPopupMenuProxyWin::visibleSize const): >+ (WebKit::WebPopupMenuProxyWin::contentsSize const): >+ (WebKit::WebPopupMenuProxyWin::scrollableAreaBoundingBox const): >+ (WebKit::WebPopupMenuProxyWin::scrollTo): >+ (WebKit::WebPopupMenuProxyWin::invalidateScrollbarRect): >+ (WebKit::WebPopupMenuProxyWin::onMouseActivate): >+ (WebKit::WebPopupMenuProxyWin::onSize): >+ (WebKit::WebPopupMenuProxyWin::onKeyDown): >+ (WebKit::WebPopupMenuProxyWin::onChar): >+ (WebKit::WebPopupMenuProxyWin::onMouseMove): >+ (WebKit::WebPopupMenuProxyWin::onLButtonDown): >+ (WebKit::WebPopupMenuProxyWin::onLButtonUp): >+ (WebKit::WebPopupMenuProxyWin::onMouseWheel): >+ (WebKit::WebPopupMenuProxyWin::onPaint): >+ (WebKit::WebPopupMenuProxyWin::onPrintClient): >+ (WebKit::WebPopupMenuProxyWin::down): >+ (WebKit::WebPopupMenuProxyWin::up): >+ (WebKit::WebPopupMenuProxyWin::paint): >+ (WebKit::WebPopupMenuProxyWin::setFocusedIndex): >+ (WebKit::WebPopupMenuProxyWin::visibleItems const): >+ (WebKit::WebPopupMenuProxyWin::listIndexAtPoint const): >+ (WebKit::WebPopupMenuProxyWin::focusedIndex const): >+ (WebKit::WebPopupMenuProxyWin::focusFirst): >+ (WebKit::WebPopupMenuProxyWin::focusLast): >+ (WebKit::WebPopupMenuProxyWin::incrementWheelDelta): >+ (WebKit::WebPopupMenuProxyWin::reduceWheelDelta): >+ (WebKit::WebPopupMenuProxyWin::scrollToRevealSelection): >+ * UIProcess/win/WebPopupMenuProxyWin.h: Added. (based on >+ removed Windows implementation plus some fixes/api changes >+ since then) >+ (WebKit::WebPopupMenuProxyWin::create): >+ (WebKit::WebPopupMenuProxyWin::hide): >+ (WebKit::WebPopupMenuProxyWin::scrollbar const): >+ (WebKit::WebPopupMenuProxyWin::itemHeight const): >+ (WebKit::WebPopupMenuProxyWin::windowRect const): >+ (WebKit::WebPopupMenuProxyWin::wheelDelta const): >+ (WebKit::WebPopupMenuProxyWin::setWasClicked): >+ (WebKit::WebPopupMenuProxyWin::wasClicked const): >+ (WebKit::WebPopupMenuProxyWin::scrollbarCapturingMouse const): >+ (WebKit::WebPopupMenuProxyWin::setScrollbarCapturingMouse): >+ * WebProcess/WebCoreSupport/win/WebPopupMenuWin.cpp: >+ (WebKit::WebPopupMenu::setUpPlatformData): Make the data to >+ pass between processes. >+ > 2018-07-31 Rob Buis <rbuis@igalia.com> > > Remove ResourceResponse::cacheBodyKey API >diff --git a/Source/WebKit/PlatformWin.cmake b/Source/WebKit/PlatformWin.cmake >index fd2456392eae4922365f1d84b01da4b84c0d1af2..acf6775077df3f84ee25e3bcc45064452131438f 100644 >--- a/Source/WebKit/PlatformWin.cmake >+++ b/Source/WebKit/PlatformWin.cmake >@@ -52,6 +52,7 @@ list(APPEND WebKit_SOURCES > UIProcess/win/WebContextMenuProxyWin.cpp > UIProcess/win/WebInspectorProxyWin.cpp > UIProcess/win/WebPageProxyWin.cpp >+ UIProcess/win/WebPopupMenuProxyWin.cpp > UIProcess/win/WebPreferencesWin.cpp > UIProcess/win/WebProcessPoolWin.cpp > UIProcess/win/WebView.cpp >diff --git a/Source/WebKit/Shared/PlatformPopupMenuData.cpp b/Source/WebKit/Shared/PlatformPopupMenuData.cpp >index 9ef12042786081178d12bb721034137907d820b6..2c066913606eb73086c4ce159344b91aa8619bd9 100644 >--- a/Source/WebKit/Shared/PlatformPopupMenuData.cpp >+++ b/Source/WebKit/Shared/PlatformPopupMenuData.cpp >@@ -41,6 +41,21 @@ void PlatformPopupMenuData::encode(IPC::Encoder& encoder) const > encoder << shouldPopOver; > encoder << hideArrows; > encoder.encodeEnum(menuSize); >+#elif PLATFORM(WIN) >+ encoder << m_clientPaddingLeft; >+ encoder << m_clientPaddingRight; >+ encoder << m_clientInsetLeft; >+ encoder << m_clientInsetRight; >+ encoder << m_popupWidth; >+ encoder << m_itemHeight; >+ >+ ShareableBitmap::Handle notSelectedBackingStoreHandle; >+ m_notSelectedBackingStore->createHandle(notSelectedBackingStoreHandle); >+ encoder << notSelectedBackingStoreHandle; >+ >+ ShareableBitmap::Handle selectedBackingStoreHandle; >+ m_selectedBackingStore->createHandle(selectedBackingStoreHandle); >+ encoder << selectedBackingStoreHandle; > #else > UNUSED_PARAM(encoder); > #endif >@@ -57,6 +72,29 @@ bool PlatformPopupMenuData::decode(IPC::Decoder& decoder, PlatformPopupMenuData& > return false; > if (!decoder.decodeEnum(data.menuSize)) > return false; >+#elif PLATFORM(WIN) >+ if (!decoder.decode(data.m_clientPaddingLeft)) >+ return false; >+ if (!decoder.decode(data.m_clientPaddingRight)) >+ return false; >+ if (!decoder.decode(data.m_clientInsetLeft)) >+ return false; >+ if (!decoder.decode(data.m_clientInsetRight)) >+ return false; >+ if (!decoder.decode(data.m_popupWidth)) >+ return false; >+ if (!decoder.decode(data.m_itemHeight)) >+ return false; >+ >+ ShareableBitmap::Handle notSelectedBackingStoreHandle; >+ if (!decoder.decode(notSelectedBackingStoreHandle)) >+ return false; >+ data.m_notSelectedBackingStore = ShareableBitmap::create(notSelectedBackingStoreHandle); >+ >+ ShareableBitmap::Handle selectedBackingStoreHandle; >+ if (!decoder.decode(selectedBackingStoreHandle)) >+ return false; >+ data.m_selectedBackingStore = ShareableBitmap::create(selectedBackingStoreHandle); > #else > UNUSED_PARAM(decoder); > UNUSED_PARAM(data); >diff --git a/Source/WebKit/Shared/PlatformPopupMenuData.h b/Source/WebKit/Shared/PlatformPopupMenuData.h >index 13991f335b5d273a2b1fcea0bd843e3a8048dd85..b295a67c5ac1d776bc042b9982069f8e56e7093f 100644 >--- a/Source/WebKit/Shared/PlatformPopupMenuData.h >+++ b/Source/WebKit/Shared/PlatformPopupMenuData.h >@@ -49,6 +49,15 @@ struct PlatformPopupMenuData { > bool shouldPopOver; > bool hideArrows; > WebCore::PopupMenuStyle::PopupMenuSize menuSize; >+#elif PLATFORM(WIN) >+ int m_clientPaddingLeft { 0 }; >+ int m_clientPaddingRight { 0 }; >+ int m_clientInsetLeft { 0 }; >+ int m_clientInsetRight { 0 }; >+ int m_popupWidth { 0 }; >+ int m_itemHeight { 0 }; >+ RefPtr<ShareableBitmap> m_notSelectedBackingStore; >+ RefPtr<ShareableBitmap> m_selectedBackingStore; > #endif > }; > >diff --git a/Source/WebKit/UIProcess/win/PageClientImpl.cpp b/Source/WebKit/UIProcess/win/PageClientImpl.cpp >index a7328ae891bd6caa874970026c6702b219431242..aa4ae181a48c3f20560287a20f49ac65ec5b8bf5 100644 >--- a/Source/WebKit/UIProcess/win/PageClientImpl.cpp >+++ b/Source/WebKit/UIProcess/win/PageClientImpl.cpp >@@ -31,6 +31,7 @@ > #include "NotImplemented.h" > #include "WebContextMenuProxyWin.h" > #include "WebPageProxy.h" >+#include "WebPopupMenuProxyWin.h" > #include "WebView.h" > > using namespace WebCore; >@@ -170,7 +171,7 @@ void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool > > RefPtr<WebPopupMenuProxy> PageClientImpl::createPopupMenuProxy(WebPageProxy& page) > { >- return nullptr; >+ return WebPopupMenuProxyWin::create(&m_view, page); > } > > #if ENABLE(CONTEXT_MENUS) >diff --git a/Source/WebKit/UIProcess/win/WebPopupMenuProxyWin.cpp b/Source/WebKit/UIProcess/win/WebPopupMenuProxyWin.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..522454c198005c7e42fec23f91c7510f47696dda >--- /dev/null >+++ b/Source/WebKit/UIProcess/win/WebPopupMenuProxyWin.cpp >@@ -0,0 +1,966 @@ >+/* >+ * Copyright (C) 2010 Apple Inc. All rights reserved. >+ * Copyright (C) 2018 Sony Interactive Entertainment Inc. >+ * >+ * 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. >+ */ >+ >+// NOTE: This implementation is very similar to the implementation of popups in WebCore::PopupMenuWin. >+// We should try and factor out the common bits and share them. >+ >+#include "config.h" >+#include "WebPopupMenuProxyWin.h" >+ >+#include "NativeWebMouseEvent.h" >+#include "PlatformPopupMenuData.h" >+#include "WebView.h" >+#include <WebCore/BitmapInfo.h> >+#include <WebCore/GDIUtilities.h> >+#include <WebCore/HWndDC.h> >+#include <WebCore/PlatformMouseEvent.h> >+#include <WebCore/ScrollbarTheme.h> >+#include <WebCore/ScrollbarThemeWin.h> >+#include <WebCore/WebCoreInstanceHandle.h> >+#include <windowsx.h> >+ >+using namespace WebCore; >+ >+namespace WebKit { >+ >+static const LPCWSTR kWebKit2WebPopupMenuProxyWindowClassName = L"WebKit2WebPopupMenuProxyWindowClass"; >+ >+static constexpr int defaultAnimationDuration = 200; >+static constexpr int maxPopupHeight = 320; >+static constexpr int popupWindowBorderWidth = 1; >+static constexpr int separatorPadding = 4; >+static constexpr int separatorHeight = 1; >+ >+// This is used from within our custom message pump when we want to send a >+// message to the web view and not have our message stolen and sent to >+// the popup window. >+static constexpr UINT WM_HOST_WINDOW_FIRST = WM_USER; >+static constexpr UINT WM_HOST_WINDOW_CHAR = WM_USER + WM_CHAR; >+static constexpr UINT WM_HOST_WINDOW_MOUSEMOVE = WM_USER + WM_MOUSEMOVE; >+ >+static inline bool isASCIIPrintable(unsigned c) >+{ >+ return c >= 0x20 && c <= 0x7E; >+} >+ >+static void translatePoint(LPARAM& lParam, HWND from, HWND to) >+{ >+ POINT pt; >+ pt.x = static_cast<short>(GET_X_LPARAM(lParam)); >+ pt.y = static_cast<short>(GET_Y_LPARAM(lParam)); >+ ::MapWindowPoints(from, to, &pt, 1); >+ lParam = MAKELPARAM(pt.x, pt.y); >+} >+ >+LRESULT CALLBACK WebPopupMenuProxyWin::WebPopupMenuProxyWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) >+{ >+ LONG_PTR longPtr = ::GetWindowLongPtr(hWnd, 0); >+ >+ if (WebPopupMenuProxyWin* popupMenuProxy = reinterpret_cast<WebPopupMenuProxyWin*>(longPtr)) >+ return popupMenuProxy->wndProc(hWnd, message, wParam, lParam); >+ >+ if (message == WM_CREATE) { >+ LPCREATESTRUCT createStruct = reinterpret_cast<LPCREATESTRUCT>(lParam); >+ >+ // Associate the WebView with the window. >+ ::SetWindowLongPtr(hWnd, 0, (LONG_PTR)createStruct->lpCreateParams); >+ return 0; >+ } >+ >+ return ::DefWindowProc(hWnd, message, wParam, lParam); >+} >+ >+LRESULT WebPopupMenuProxyWin::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) >+{ >+ LRESULT lResult = 0; >+ bool handled = true; >+ >+ switch (message) { >+ case WM_MOUSEACTIVATE: >+ lResult = onMouseActivate(hWnd, message, wParam, lParam, handled); >+ break; >+ case WM_SIZE: >+ lResult = onSize(hWnd, message, wParam, lParam, handled); >+ break; >+ case WM_KEYDOWN: >+ lResult = onKeyDown(hWnd, message, wParam, lParam, handled); >+ break; >+ case WM_CHAR: >+ lResult = onChar(hWnd, message, wParam, lParam, handled); >+ break; >+ case WM_MOUSEMOVE: >+ lResult = onMouseMove(hWnd, message, wParam, lParam, handled); >+ break; >+ case WM_LBUTTONDOWN: >+ lResult = onLButtonDown(hWnd, message, wParam, lParam, handled); >+ break; >+ case WM_LBUTTONUP: >+ lResult = onLButtonUp(hWnd, message, wParam, lParam, handled); >+ break; >+ case WM_MOUSEWHEEL: >+ lResult = onMouseWheel(hWnd, message, wParam, lParam, handled); >+ break; >+ case WM_PAINT: >+ lResult = onPaint(hWnd, message, wParam, lParam, handled); >+ break; >+ case WM_PRINTCLIENT: >+ lResult = onPrintClient(hWnd, message, wParam, lParam, handled); >+ break; >+ default: >+ handled = false; >+ break; >+ } >+ >+ if (!handled) >+ lResult = ::DefWindowProc(hWnd, message, wParam, lParam); >+ >+ return lResult; >+} >+ >+bool WebPopupMenuProxyWin::registerWindowClass() >+{ >+ static bool haveRegisteredWindowClass = false; >+ if (haveRegisteredWindowClass) >+ return true; >+ haveRegisteredWindowClass = true; >+ >+ WNDCLASSEX wcex; >+ wcex.cbSize = sizeof(WNDCLASSEX); >+ wcex.style = CS_DROPSHADOW; >+ wcex.lpfnWndProc = WebPopupMenuProxyWin::WebPopupMenuProxyWndProc; >+ wcex.cbClsExtra = 0; >+ wcex.cbWndExtra = sizeof(WebPopupMenuProxyWin*); >+ wcex.hInstance = instanceHandle(); >+ wcex.hIcon = 0; >+ wcex.hCursor = ::LoadCursor(0, IDC_ARROW); >+ wcex.hbrBackground = 0; >+ wcex.lpszMenuName = 0; >+ wcex.lpszClassName = kWebKit2WebPopupMenuProxyWindowClassName; >+ wcex.hIconSm = 0; >+ >+ return !!::RegisterClassEx(&wcex); >+} >+ >+WebPopupMenuProxyWin::WebPopupMenuProxyWin(WebView* webView, WebPopupMenuProxy::Client& client) >+ : WebPopupMenuProxy(client) >+ , m_webView(webView) >+{ >+} >+ >+WebPopupMenuProxyWin::~WebPopupMenuProxyWin() >+{ >+ if (m_popup) >+ ::DestroyWindow(m_popup); >+ if (m_scrollbar) >+ m_scrollbar->setParent(0); >+} >+ >+void WebPopupMenuProxyWin::showPopupMenu(const IntRect& rect, TextDirection, double pageScaleFactor, const Vector<WebPopupItem>& items, const PlatformPopupMenuData& data, int32_t selectedIndex) >+{ >+ m_items = items; >+ m_data = data; >+ m_newSelectedIndex = selectedIndex; >+ m_scaleFactor = pageScaleFactor; >+ >+ calculatePositionAndSize(rect); >+ if (clientRect().isEmpty()) >+ return; >+ >+ HWND hostWindow = m_webView->window(); >+ >+ if (!m_scrollbar && visibleItems() < m_items.size()) { >+ m_scrollbar = Scrollbar::createNativeScrollbar(*this, VerticalScrollbar, SmallScrollbar); >+ m_scrollbar->styleChanged(); >+ } >+ >+ if (!m_popup) { >+ registerWindowClass(); >+ >+ DWORD exStyle = WS_EX_LTRREADING; >+ >+ m_popup = ::CreateWindowEx(exStyle, kWebKit2WebPopupMenuProxyWindowClassName, TEXT("PopupMenu"), >+ WS_POPUP | WS_BORDER, >+ m_windowRect.x(), m_windowRect.y(), m_windowRect.width(), m_windowRect.height(), >+ hostWindow, 0, instanceHandle(), this); >+ >+ if (!m_popup) >+ return; >+ } >+ >+ BOOL shouldAnimate = FALSE; >+ >+ if (selectedIndex > 0) >+ setFocusedIndex(selectedIndex); >+ >+ if (!::SystemParametersInfo(SPI_GETCOMBOBOXANIMATION, 0, &shouldAnimate, 0)) >+ shouldAnimate = FALSE; >+ >+ if (shouldAnimate) { >+ RECT viewRect = {0}; >+ ::GetWindowRect(hostWindow, &viewRect); >+ >+ if (!::IsRectEmpty(&viewRect)) { >+ // Popups should slide into view away from the <select> box >+ // NOTE: This may have to change for Vista >+ DWORD slideDirection = (m_windowRect.y() < viewRect.top + rect.location().y()) ? AW_VER_NEGATIVE : AW_VER_POSITIVE; >+ >+ ::AnimateWindow(m_popup, defaultAnimationDuration, AW_SLIDE | slideDirection); >+ } >+ } else >+ ::ShowWindow(m_popup, SW_SHOWNOACTIVATE); >+ >+ m_showPopup = true; >+ >+ // Protect the popup menu in case its owner is destroyed while we're running the message pump. >+ RefPtr<WebPopupMenuProxyWin> protectedThis(this); >+ >+ ::SetCapture(hostWindow); >+ >+ MSG msg; >+ HWND activeWindow; >+ >+ while (::GetMessage(&msg, 0, 0, 0)) { >+ switch (msg.message) { >+ case WM_HOST_WINDOW_MOUSEMOVE: >+ case WM_HOST_WINDOW_CHAR: >+ if (msg.hwnd == m_popup) { >+ // This message should be sent to the host window. >+ msg.hwnd = hostWindow; >+ msg.message -= WM_HOST_WINDOW_FIRST; >+ } >+ break; >+ >+ // Steal mouse messages. >+ case WM_NCMOUSEMOVE: >+ case WM_NCLBUTTONDOWN: >+ case WM_NCLBUTTONUP: >+ case WM_NCLBUTTONDBLCLK: >+ case WM_NCRBUTTONDOWN: >+ case WM_NCRBUTTONUP: >+ case WM_NCRBUTTONDBLCLK: >+ case WM_NCMBUTTONDOWN: >+ case WM_NCMBUTTONUP: >+ case WM_NCMBUTTONDBLCLK: >+ case WM_MOUSEWHEEL: >+ msg.hwnd = m_popup; >+ break; >+ >+ // These mouse messages use client coordinates so we need to convert them. >+ case WM_MOUSEMOVE: >+ case WM_LBUTTONDOWN: >+ case WM_LBUTTONUP: >+ case WM_LBUTTONDBLCLK: >+ case WM_RBUTTONDOWN: >+ case WM_RBUTTONUP: >+ case WM_RBUTTONDBLCLK: >+ case WM_MBUTTONDOWN: >+ case WM_MBUTTONUP: >+ case WM_MBUTTONDBLCLK: { >+ // Translate the coordinate. >+ translatePoint(msg.lParam, msg.hwnd, m_popup); >+ msg.hwnd = m_popup; >+ break; >+ } >+ >+ // Steal all keyboard messages. >+ case WM_KEYDOWN: >+ case WM_KEYUP: >+ case WM_CHAR: >+ case WM_DEADCHAR: >+ case WM_SYSKEYUP: >+ case WM_SYSCHAR: >+ case WM_SYSDEADCHAR: >+ msg.hwnd = m_popup; >+ break; >+ } >+ >+ ::TranslateMessage(&msg); >+ ::DispatchMessage(&msg); >+ >+ if (!m_showPopup) >+ break; >+ activeWindow = ::GetActiveWindow(); >+ if (activeWindow != hostWindow && !::IsChild(activeWindow, hostWindow)) >+ break; >+ if (::GetCapture() != hostWindow) >+ break; >+ } >+ >+ if (::GetCapture() == hostWindow) >+ ::ReleaseCapture(); >+ >+ m_showPopup = false; >+ ::ShowWindow(m_popup, SW_HIDE); >+ >+ if (!WebPopupMenuProxy::m_client) >+ return; >+ >+ WebPopupMenuProxy::m_client->valueChangedForPopupMenu(this, m_newSelectedIndex); >+ >+ // <https://bugs.webkit.org/show_bug.cgi?id=57904> In order to properly call the onClick() >+ // handler on a <select> element, we need to fake a mouse up event in the main window. >+ // The main window already received the mouse down, which showed this popup, but upon >+ // selection of an item the mouse up gets eaten by the popup menu. So we take the mouse down >+ // event, change the message type to a mouse up event, and post that in the message queue. >+ // Thus, we are virtually clicking at the >+ // same location where the mouse down event occurred. This allows the hit test to select >+ // the correct element, and thereby call the onClick() JS handler. >+ if (!WebPopupMenuProxy::m_client->currentlyProcessedMouseDownEvent()) >+ return; >+ >+ const MSG* initiatingWinEvent = WebPopupMenuProxy::m_client->currentlyProcessedMouseDownEvent()->nativeEvent(); >+ MSG fakeEvent = *initiatingWinEvent; >+ fakeEvent.message = WM_LBUTTONUP; >+ ::PostMessage(fakeEvent.hwnd, fakeEvent.message, fakeEvent.wParam, fakeEvent.lParam); >+} >+ >+void WebPopupMenuProxyWin::hidePopupMenu() >+{ >+ if (!m_showPopup) >+ return; >+ m_showPopup = false; >+ >+ ::ShowWindow(m_popup, SW_HIDE); >+ >+ // Post a WM_NULL message to wake up the message pump if necessary. >+ ::PostMessage(m_popup, WM_NULL, 0, 0); >+} >+ >+void WebPopupMenuProxyWin::calculatePositionAndSize(const IntRect& rect) >+{ >+ IntRect rectInScreenCoords(rect); >+ rectInScreenCoords.scale(m_scaleFactor); >+ >+ POINT location(rectInScreenCoords .location()); >+ if (!::ClientToScreen(m_webView->window(), &location)) >+ return; >+ rectInScreenCoords.setLocation(location); >+ >+ int itemCount = m_items.size(); >+ m_itemHeight = m_data.m_itemHeight; >+ >+ int naturalHeight = m_itemHeight * itemCount; >+ int popupHeight = std::min(maxPopupHeight, naturalHeight); >+ >+ // The popup should show an integral number of items (i.e. no partial items should be visible) >+ popupHeight -= popupHeight % m_itemHeight; >+ >+ // Next determine its width >+ int popupWidth = m_data.m_popupWidth; >+ >+ if (naturalHeight > maxPopupHeight) { >+ // We need room for a scrollbar >+ popupWidth += ScrollbarTheme::theme().scrollbarThickness(SmallScrollbar); >+ } >+ >+ popupHeight += 2 * popupWindowBorderWidth; >+ >+ // The popup should be at least as wide as the control on the page >+ popupWidth = std::max(rectInScreenCoords.width() - m_data.m_clientInsetLeft - m_data.m_clientInsetRight, popupWidth); >+ >+ // Always left-align items in the popup. This matches popup menus on the mac. >+ int popupX = rectInScreenCoords.x() + m_data.m_clientInsetLeft; >+ >+ IntRect popupRect(popupX, rectInScreenCoords.maxY(), popupWidth, popupHeight); >+ >+ // The popup needs to stay within the bounds of the screen and not overlap any toolbars >+ HMONITOR monitor = ::MonitorFromWindow(m_webView->window(), MONITOR_DEFAULTTOPRIMARY); >+ MONITORINFOEX monitorInfo; >+ monitorInfo.cbSize = sizeof(MONITORINFOEX); >+ ::GetMonitorInfo(monitor, &monitorInfo); >+ FloatRect screen = static_cast<IntRect>(monitorInfo.rcWork); >+ >+ // Check that we don't go off the screen vertically >+ if (popupRect.maxY() > screen.height()) { >+ // The popup will go off the screen, so try placing it above the client >+ if (rectInScreenCoords.y() - popupRect.height() < 0) { >+ // The popup won't fit above, either, so place it whereever's bigger and resize it to fit >+ if ((rectInScreenCoords.y() + rectInScreenCoords.height() / 2) < (screen.height() / 2)) { >+ // Below is bigger >+ popupRect.setHeight(screen.height() - popupRect.y()); >+ } else { >+ // Above is bigger >+ popupRect.setY(0); >+ popupRect.setHeight(rectInScreenCoords.y()); >+ } >+ } else { >+ // The popup fits above, so reposition it >+ popupRect.setY(rectInScreenCoords.y() - popupRect.height()); >+ } >+ } >+ >+ // Check that we don't go off the screen horizontally >+ if (popupRect.x() < screen.x()) { >+ popupRect.setWidth(popupRect.width() - (screen.x() - popupRect.x())); >+ popupRect.setX(screen.x()); >+ } >+ >+ m_windowRect = popupRect; >+} >+ >+IntRect WebPopupMenuProxyWin::clientRect() const >+{ >+ IntRect clientRect = m_windowRect; >+ clientRect.inflate(-popupWindowBorderWidth); >+ clientRect.setLocation(IntPoint(0, 0)); >+ return clientRect; >+} >+ >+void WebPopupMenuProxyWin::invalidateItem(int index) >+{ >+ if (!m_popup) >+ return; >+ >+ IntRect damageRect(clientRect()); >+ damageRect.setY(m_itemHeight * (index - m_scrollOffset)); >+ damageRect.setHeight(m_itemHeight); >+ if (m_scrollbar) >+ damageRect.setWidth(damageRect.width() - m_scrollbar->frameRect().width()); >+ >+ RECT r = damageRect; >+ ::InvalidateRect(m_popup, &r, TRUE); >+} >+ >+int WebPopupMenuProxyWin::scrollSize(ScrollbarOrientation orientation) const >+{ >+ return ((orientation == VerticalScrollbar) && m_scrollbar) ? (m_scrollbar->totalSize() - m_scrollbar->visibleSize()) : 0; >+} >+ >+void WebPopupMenuProxyWin::setScrollOffset(const IntPoint& offset) >+{ >+ scrollTo(offset.y()); >+} >+ >+IntSize WebPopupMenuProxyWin::visibleSize() const >+{ >+ int scrollbarWidth = m_scrollbar ? m_scrollbar->frameRect().width() : 0; >+ return IntSize(contentsSize().width() - scrollbarWidth, m_scrollbar ? m_scrollbar->visibleSize() : contentsSize().height()); >+} >+ >+WebCore::IntSize WebPopupMenuProxyWin::contentsSize() const >+{ >+ return IntSize(m_windowRect.width(), m_scrollbar ? m_scrollbar->totalSize() : m_windowRect.height()); >+} >+ >+WebCore::IntRect WebPopupMenuProxyWin::scrollableAreaBoundingBox(bool*) const >+{ >+ return m_windowRect; >+} >+ >+void WebPopupMenuProxyWin::scrollTo(int offset) >+{ >+ ASSERT(m_scrollbar); >+ >+ if (!m_popup) >+ return; >+ >+ if (m_scrollOffset == offset) >+ return; >+ >+ int scrolledLines = m_scrollOffset - offset; >+ m_scrollOffset = offset; >+ >+ UINT flags = SW_INVALIDATE; >+ >+#ifdef CAN_SET_SMOOTH_SCROLLING_DURATION >+ BOOL shouldSmoothScroll = FALSE; >+ ::SystemParametersInfo(SPI_GETLISTBOXSMOOTHSCROLLING, 0, &shouldSmoothScroll, 0); >+ if (shouldSmoothScroll) >+ flags |= MAKEWORD(SW_SMOOTHSCROLL, smoothScrollAnimationDuration); >+#endif >+ >+ IntRect listRect = clientRect(); >+ if (m_scrollbar) >+ listRect.setWidth(listRect.width() - m_scrollbar->frameRect().width()); >+ RECT r = listRect; >+ ::ScrollWindowEx(m_popup, 0, scrolledLines * m_itemHeight, &r, 0, 0, 0, flags); >+ if (m_scrollbar) { >+ r = m_scrollbar->frameRect(); >+ ::InvalidateRect(m_popup, &r, TRUE); >+ } >+ ::UpdateWindow(m_popup); >+} >+ >+void WebPopupMenuProxyWin::invalidateScrollbarRect(Scrollbar& scrollbar, const IntRect& rect) >+{ >+ IntRect scrollRect = rect; >+ scrollRect.move(scrollbar.x(), scrollbar.y()); >+ RECT r = scrollRect; >+ ::InvalidateRect(m_popup, &r, false); >+} >+ >+// Message pump messages. >+ >+LRESULT WebPopupMenuProxyWin::onMouseActivate(HWND hWnd, UINT message, WPARAM, LPARAM, bool& handled) >+{ >+ handled = true; >+ return MA_NOACTIVATE; >+} >+ >+LRESULT WebPopupMenuProxyWin::onSize(HWND hWnd, UINT message, WPARAM, LPARAM lParam, bool& handled) >+{ >+ handled = true; >+ if (!scrollbar()) >+ return 0; >+ >+ IntSize size(LOWORD(lParam), HIWORD(lParam)); >+ scrollbar()->setFrameRect(IntRect(size.width() - scrollbar()->width(), 0, scrollbar()->width(), size.height())); >+ >+ int visibleItems = this->visibleItems(); >+ scrollbar()->setEnabled(visibleItems < m_items.size()); >+ scrollbar()->setSteps(1, std::max(1, visibleItems - 1)); >+ scrollbar()->setProportion(visibleItems, m_items.size()); >+ return 0; >+} >+ >+LRESULT WebPopupMenuProxyWin::onKeyDown(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled) >+{ >+ handled = true; >+ >+ LRESULT lResult = 0; >+ switch (LOWORD(wParam)) { >+ case VK_DOWN: >+ case VK_RIGHT: >+ down(); >+ break; >+ case VK_UP: >+ case VK_LEFT: >+ up(); >+ break; >+ case VK_HOME: >+ focusFirst(); >+ break; >+ case VK_END: >+ focusLast(); >+ break; >+ case VK_PRIOR: >+ if (focusedIndex() != scrollOffset(VerticalScrollbar)) { >+ // Set the selection to the first visible item >+ int firstVisibleItem = scrollOffset(VerticalScrollbar); >+ up(focusedIndex() - firstVisibleItem); >+ } else { >+ // The first visible item is selected, so move the selection back one page >+ up(visibleItems()); >+ } >+ break; >+ case VK_NEXT: { >+ int lastVisibleItem = scrollOffset(VerticalScrollbar) + visibleItems() - 1; >+ if (focusedIndex() != lastVisibleItem) { >+ // Set the selection to the last visible item >+ down(lastVisibleItem - focusedIndex()); >+ } else { >+ // The last visible item is selected, so move the selection forward one page >+ down(visibleItems()); >+ } >+ break; >+ } >+ case VK_TAB: >+ ::SendMessage(m_webView->window(), message, wParam, lParam); >+ hide(); >+ break; >+ case VK_ESCAPE: >+ hide(); >+ break; >+ default: >+ if (isASCIIPrintable(wParam)) { >+ // Send the keydown to the WebView so it can be used for type-to-select. >+ // Since we know that the virtual key is ASCII printable, it's OK to convert this to >+ // a WM_CHAR message. (We don't want to call TranslateMessage because that will post a >+ // WM_CHAR message that will be stolen and redirected to the popup HWND. >+ ::PostMessage(m_popup, WM_HOST_WINDOW_CHAR, wParam, lParam); >+ } else >+ lResult = 1; >+ break; >+ } >+ >+ return lResult; >+} >+ >+LRESULT WebPopupMenuProxyWin::onChar(HWND hWnd, UINT message, WPARAM wParam, LPARAM, bool& handled) >+{ >+ handled = true; >+ >+ LRESULT lResult = 0; >+ int index; >+ switch (wParam) { >+ case 0x0D: // Enter/Return >+ hide(); >+ index = focusedIndex(); >+ ASSERT(index >= 0); >+ // FIXME: Do we need to send back the index right away? >+ m_newSelectedIndex = index; >+ break; >+ case 0x1B: // Escape >+ hide(); >+ break; >+ case 0x09: // TAB >+ case 0x08: // Backspace >+ case 0x0A: // Linefeed >+ default: // Character >+ lResult = 1; >+ break; >+ } >+ >+ return lResult; >+} >+ >+LRESULT WebPopupMenuProxyWin::onMouseMove(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled) >+{ >+ handled = true; >+ >+ IntPoint mousePoint(MAKEPOINTS(lParam)); >+ if (scrollbar()) { >+ IntRect scrollBarRect = scrollbar()->frameRect(); >+ if (scrollbarCapturingMouse() || scrollBarRect.contains(mousePoint)) { >+ // Put the point into coordinates relative to the scroll bar >+ mousePoint.move(-scrollBarRect.x(), -scrollBarRect.y()); >+ PlatformMouseEvent event(hWnd, message, wParam, makeScaledPoint(mousePoint, m_scaleFactor)); >+ scrollbar()->mouseMoved(event); >+ return 0; >+ } >+ } >+ >+ BOOL shouldHotTrack = FALSE; >+ if (!::SystemParametersInfo(SPI_GETCOMBOBOXANIMATION, 0, &shouldHotTrack, 0)) >+ shouldHotTrack = FALSE; >+ >+ RECT bounds; >+ ::GetClientRect(m_popup, &bounds); >+ if (!::PtInRect(&bounds, mousePoint) && !(wParam & MK_LBUTTON)) { >+ // When the mouse is not inside the popup menu and the left button isn't down, just >+ // repost the message to the web view. >+ >+ // Translate the coordinate. >+ translatePoint(lParam, m_popup, m_webView->window()); >+ >+ ::PostMessage(m_popup, WM_HOST_WINDOW_MOUSEMOVE, wParam, lParam); >+ return 0; >+ } >+ >+ if ((shouldHotTrack || wParam & MK_LBUTTON) && ::PtInRect(&bounds, mousePoint)) { >+ setFocusedIndex(listIndexAtPoint(mousePoint), true); >+ m_hoveredIndex = listIndexAtPoint(mousePoint); >+ } >+ >+ return 0; >+} >+ >+LRESULT WebPopupMenuProxyWin::onLButtonDown(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled) >+{ >+ handled = true; >+ >+ IntPoint mousePoint(MAKEPOINTS(lParam)); >+ if (scrollbar()) { >+ IntRect scrollBarRect = scrollbar()->frameRect(); >+ if (scrollBarRect.contains(mousePoint)) { >+ // Put the point into coordinates relative to the scroll bar >+ mousePoint.move(-scrollBarRect.x(), -scrollBarRect.y()); >+ PlatformMouseEvent event(hWnd, message, wParam, makeScaledPoint(mousePoint, m_scaleFactor)); >+ scrollbar()->mouseDown(event); >+ setScrollbarCapturingMouse(true); >+ return 0; >+ } >+ } >+ >+ // If the mouse is inside the window, update the focused index. Otherwise, >+ // hide the popup. >+ RECT bounds; >+ ::GetClientRect(m_popup, &bounds); >+ if (::PtInRect(&bounds, mousePoint)) { >+ setFocusedIndex(listIndexAtPoint(mousePoint), true); >+ m_hoveredIndex = listIndexAtPoint(mousePoint); >+ } else >+ hide(); >+ >+ return 0; >+} >+ >+ >+LRESULT WebPopupMenuProxyWin::onLButtonUp(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled) >+{ >+ handled = true; >+ >+ IntPoint mousePoint(MAKEPOINTS(lParam)); >+ if (scrollbar()) { >+ IntRect scrollBarRect = scrollbar()->frameRect(); >+ if (scrollbarCapturingMouse() || scrollBarRect.contains(mousePoint)) { >+ setScrollbarCapturingMouse(false); >+ // Put the point into coordinates relative to the scroll bar >+ mousePoint.move(-scrollBarRect.x(), -scrollBarRect.y()); >+ PlatformMouseEvent event(hWnd, message, wParam, makeScaledPoint(mousePoint, m_scaleFactor)); >+ scrollbar()->mouseUp(event); >+ // FIXME: This is a hack to work around Scrollbar not invalidating correctly when it doesn't have a parent widget >+ RECT r = scrollBarRect; >+ ::InvalidateRect(m_popup, &r, TRUE); >+ return 0; >+ } >+ } >+ // Only hide the popup if the mouse is inside the popup window. >+ RECT bounds; >+ ::GetClientRect(m_popup, &bounds); >+ if (::PtInRect(&bounds, mousePoint)) { >+ hide(); >+ int index = m_hoveredIndex; >+ if (!m_items[index].m_isEnabled) >+ index = m_focusedIndex; >+ >+ if (index >= 0) { >+ // FIXME: Do we need to send back the index right away? >+ m_newSelectedIndex = index; >+ } >+ } >+ >+ return 0; >+} >+ >+LRESULT WebPopupMenuProxyWin::onMouseWheel(HWND hWnd, UINT message, WPARAM wParam, LPARAM, bool& handled) >+{ >+ handled = true; >+ >+ if (!scrollbar()) >+ return 0; >+ >+ int i = 0; >+ for (incrementWheelDelta(GET_WHEEL_DELTA_WPARAM(wParam)); abs(wheelDelta()) >= WHEEL_DELTA; reduceWheelDelta(WHEEL_DELTA)) { >+ if (wheelDelta() > 0) >+ ++i; >+ else >+ --i; >+ } >+ >+ ScrollableArea::scroll(i > 0 ? ScrollUp : ScrollDown, ScrollByLine, abs(i)); >+ return 0; >+} >+ >+LRESULT WebPopupMenuProxyWin::onPaint(HWND hWnd, UINT message, WPARAM, LPARAM, bool& handled) >+{ >+ handled = true; >+ >+ PAINTSTRUCT paintStruct; >+ ::BeginPaint(m_popup, &paintStruct); >+ paint(paintStruct.rcPaint, paintStruct.hdc); >+ ::EndPaint(m_popup, &paintStruct); >+ >+ return 0; >+} >+ >+LRESULT WebPopupMenuProxyWin::onPrintClient(HWND hWnd, UINT, WPARAM wParam, LPARAM, bool& handled) >+{ >+ handled = true; >+ >+ HDC hdc = reinterpret_cast<HDC>(wParam); >+ paint(clientRect(), hdc); >+ >+ return 0; >+} >+ >+bool WebPopupMenuProxyWin::down(unsigned lines) >+{ >+ int size = m_items.size(); >+ >+ int lastSelectableIndex, selectedListIndex; >+ lastSelectableIndex = selectedListIndex = focusedIndex(); >+ for (int i = selectedListIndex + 1; i >= 0 && i < size; ++i) { >+ if (m_items[i].m_isEnabled) { >+ lastSelectableIndex = i; >+ if (i >= selectedListIndex + (int)lines) >+ break; >+ } >+ } >+ >+ return setFocusedIndex(lastSelectableIndex); >+} >+ >+bool WebPopupMenuProxyWin::up(unsigned lines) >+{ >+ int size = m_items.size(); >+ >+ int lastSelectableIndex, selectedListIndex; >+ lastSelectableIndex = selectedListIndex = focusedIndex(); >+ for (int i = selectedListIndex - 1; i >= 0 && i < size; --i) { >+ if (m_items[i].m_isEnabled) { >+ lastSelectableIndex = i; >+ if (i <= selectedListIndex - (int)lines) >+ break; >+ } >+ } >+ >+ return setFocusedIndex(lastSelectableIndex); >+} >+ >+void WebPopupMenuProxyWin::paint(const IntRect& damageRect, HDC hdc) >+{ >+ if (!m_popup) >+ return; >+ >+ if (!m_DC) { >+ m_DC = adoptGDIObject(::CreateCompatibleDC(HWndDC(m_popup))); >+ if (!m_DC) >+ return; >+ } >+ >+ if (m_bmp) { >+ bool keepBitmap = false; >+ BITMAP bitmap; >+ if (::GetObject(m_bmp.get(), sizeof(bitmap), &bitmap)) >+ keepBitmap = bitmap.bmWidth == clientRect().width() && bitmap.bmHeight == clientRect().height(); >+ if (!keepBitmap) >+ m_bmp.clear(); >+ } >+ if (!m_bmp) { >+ BitmapInfo bitmapInfo = BitmapInfo::createBottomUp(clientRect().size()); >+ void* pixels = 0; >+ m_bmp = adoptGDIObject(::CreateDIBSection(m_DC.get(), &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0)); >+ if (!m_bmp) >+ return; >+ >+ ::SelectObject(m_DC.get(), m_bmp.get()); >+ } >+ >+ GraphicsContext context(m_DC.get()); >+ >+ IntRect translatedDamageRect = damageRect; >+ translatedDamageRect.move(IntSize(0, m_scrollOffset * m_itemHeight)); >+ m_data.m_notSelectedBackingStore->paint(context, damageRect.location(), translatedDamageRect); >+ >+ IntRect selectedIndexRectInBackingStore(0, focusedIndex() * m_itemHeight, m_data.m_selectedBackingStore->size().width(), m_itemHeight); >+ IntPoint selectedIndexDstPoint = selectedIndexRectInBackingStore.location(); >+ selectedIndexDstPoint.move(0, -m_scrollOffset * m_itemHeight); >+ >+ m_data.m_selectedBackingStore->paint(context, selectedIndexDstPoint, selectedIndexRectInBackingStore); >+ >+ if (m_scrollbar) >+ m_scrollbar->paint(context, damageRect); >+ >+ >+ HWndDC hWndDC; >+ HDC localDC = hdc ? hdc : hWndDC.setHWnd(m_popup); >+ >+ ::BitBlt(localDC, damageRect.x(), damageRect.y(), damageRect.width(), damageRect.height(), m_DC.get(), damageRect.x(), damageRect.y(), SRCCOPY); >+} >+ >+bool WebPopupMenuProxyWin::setFocusedIndex(int i, bool hotTracking) >+{ >+ if (i < 0 || i >= m_items.size() || i == focusedIndex()) >+ return false; >+ >+ if (!m_items[i].m_isEnabled) >+ return false; >+ >+ invalidateItem(focusedIndex()); >+ invalidateItem(i); >+ >+ m_focusedIndex = i; >+ >+ if (!hotTracking) { >+ if (WebPopupMenuProxy::m_client) >+ WebPopupMenuProxy::m_client->setTextFromItemForPopupMenu(this, i); >+ } >+ >+ scrollToRevealSelection(); >+ >+ return true; >+} >+ >+int WebPopupMenuProxyWin::visibleItems() const >+{ >+ return clientRect().height() / m_itemHeight; >+} >+ >+int WebPopupMenuProxyWin::listIndexAtPoint(const IntPoint& point) const >+{ >+ return m_scrollOffset + point.y() / m_itemHeight; >+} >+ >+int WebPopupMenuProxyWin::focusedIndex() const >+{ >+ return m_focusedIndex; >+} >+ >+void WebPopupMenuProxyWin::focusFirst() >+{ >+ int size = m_items.size(); >+ >+ for (int i = 0; i < size; ++i) { >+ if (m_items[i].m_isEnabled) { >+ setFocusedIndex(i); >+ break; >+ } >+ } >+} >+ >+void WebPopupMenuProxyWin::focusLast() >+{ >+ int size = m_items.size(); >+ >+ for (int i = size - 1; i > 0; --i) { >+ if (m_items[i].m_isEnabled) { >+ setFocusedIndex(i); >+ break; >+ } >+ } >+} >+ >+ >+void WebPopupMenuProxyWin::incrementWheelDelta(int delta) >+{ >+ m_wheelDelta += delta; >+} >+ >+void WebPopupMenuProxyWin::reduceWheelDelta(int delta) >+{ >+ ASSERT(delta >= 0); >+ ASSERT(delta <= abs(m_wheelDelta)); >+ >+ if (m_wheelDelta > 0) >+ m_wheelDelta -= delta; >+ else if (m_wheelDelta < 0) >+ m_wheelDelta += delta; >+ else >+ return; >+} >+ >+bool WebPopupMenuProxyWin::scrollToRevealSelection() >+{ >+ if (!m_scrollbar) >+ return false; >+ >+ int index = focusedIndex(); >+ >+ if (index < m_scrollOffset) { >+ ScrollableArea::scrollToOffsetWithoutAnimation(VerticalScrollbar, index); >+ return true; >+ } >+ >+ if (index >= m_scrollOffset + visibleItems()) { >+ ScrollableArea::scrollToOffsetWithoutAnimation(VerticalScrollbar, index - visibleItems() + 1); >+ return true; >+ } >+ >+ return false; >+} >+ >+} // namespace WebKit >diff --git a/Source/WebKit/UIProcess/win/WebPopupMenuProxyWin.h b/Source/WebKit/UIProcess/win/WebPopupMenuProxyWin.h >new file mode 100644 >index 0000000000000000000000000000000000000000..0292d96c928612acc2919f8ca7cf5fe223d8ee6e >--- /dev/null >+++ b/Source/WebKit/UIProcess/win/WebPopupMenuProxyWin.h >@@ -0,0 +1,148 @@ >+/* >+ * Copyright (C) 2010 Apple Inc. All rights reserved. >+ * Copyright (C) 2018 Sony Interactive Entertainment Inc. >+ * >+ * 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. >+ */ >+ >+#pragma once >+ >+#include "PlatformPopupMenuData.h" >+#include "WebPopupItem.h" >+#include "WebPopupMenuProxy.h" >+#include <OleAcc.h> >+#include <WebCore/ScrollableArea.h> >+#include <WebCore/Scrollbar.h> >+ >+namespace WebKit { >+ >+class WebView; >+ >+class WebPopupMenuProxyWin : public WebPopupMenuProxy, private WebCore::ScrollableArea { >+public: >+ static Ref<WebPopupMenuProxyWin> create(WebView* webView, WebPopupMenuProxy::Client& client) >+ { >+ return adoptRef(*new WebPopupMenuProxyWin(webView, client)); >+ } >+ ~WebPopupMenuProxyWin(); >+ >+ virtual void showPopupMenu(const WebCore::IntRect&, WebCore::TextDirection, double pageScaleFactor, const Vector<WebPopupItem>&, const PlatformPopupMenuData&, int32_t selectedIndex); >+ virtual void hidePopupMenu(); >+ >+ bool setFocusedIndex(int index, bool hotTracking = false); >+ >+ void hide() { hidePopupMenu(); } >+ >+private: >+ WebPopupMenuProxyWin(WebView*, WebPopupMenuProxy::Client&); >+ >+ WebCore::Scrollbar* scrollbar() const { return m_scrollbar.get(); } >+ >+ // ScrollableArea >+ int scrollSize(WebCore::ScrollbarOrientation) const override; >+ void setScrollOffset(const WebCore::IntPoint&) override; >+ int scrollOffset(WebCore::ScrollbarOrientation) const override { return m_scrollOffset; } >+ >+ void invalidateScrollbarRect(WebCore::Scrollbar&, const WebCore::IntRect&) override; >+ void invalidateScrollCornerRect(const WebCore::IntRect&) override { } >+ bool isActive() const override { return true; } >+ bool isScrollCornerVisible() const override { return false; } >+ WebCore::IntRect scrollCornerRect() const override { return WebCore::IntRect(); } >+ WebCore::Scrollbar* verticalScrollbar() const override { return m_scrollbar.get(); } >+ WebCore::ScrollableArea* enclosingScrollableArea() const override { return 0; } >+ WebCore::IntSize visibleSize() const override; >+ WebCore::IntSize contentsSize() const override; >+ WebCore::IntRect scrollableAreaBoundingBox(bool* = nullptr) const override; >+ bool shouldPlaceBlockDirectionScrollbarOnLeft() const override { return false; } >+ bool forceUpdateScrollbarsOnMainThreadForPerformanceTesting() const override { return false; } >+ bool isScrollableOrRubberbandable() override { return true; } >+ bool hasScrollableOrRubberbandableAncestor() override { return true; } >+ >+ // NOTE: This should only be called by the overriden setScrollOffset from ScrollableArea. >+ void scrollTo(int offset); >+ >+ static bool registerWindowClass(); >+ static LRESULT CALLBACK WebPopupMenuProxyWndProc(HWND, UINT, WPARAM, LPARAM); >+ LRESULT wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); >+ >+ // Message pump messages. >+ LRESULT onMouseActivate(HWND, UINT message, WPARAM, LPARAM, bool& handled); >+ LRESULT onSize(HWND, UINT message, WPARAM, LPARAM, bool& handled); >+ LRESULT onKeyDown(HWND, UINT message, WPARAM, LPARAM, bool& handled); >+ LRESULT onChar(HWND, UINT message, WPARAM, LPARAM, bool& handled); >+ LRESULT onMouseMove(HWND, UINT message, WPARAM, LPARAM, bool& handled); >+ LRESULT onLButtonDown(HWND, UINT message, WPARAM, LPARAM, bool& handled); >+ LRESULT onLButtonUp(HWND, UINT message, WPARAM, LPARAM, bool& handled); >+ LRESULT onMouseWheel(HWND, UINT message, WPARAM, LPARAM, bool& handled); >+ LRESULT onPaint(HWND, UINT message, WPARAM, LPARAM, bool& handled); >+ LRESULT onPrintClient(HWND, UINT message, WPARAM, LPARAM, bool& handled); >+ LRESULT onGetObject(HWND, UINT message, WPARAM, LPARAM, bool &handled); >+ >+ void calculatePositionAndSize(const WebCore::IntRect&); >+ WebCore::IntRect clientRect() const; >+ void invalidateItem(int index); >+ >+ >+ int itemHeight() const { return m_itemHeight; } >+ const WebCore::IntRect& windowRect() const { return m_windowRect; } >+ int wheelDelta() const { return m_wheelDelta; } >+ void setWasClicked(bool b = true) { m_wasClicked = b; } >+ bool wasClicked() const { return m_wasClicked; } >+ bool scrollbarCapturingMouse() const { return m_scrollbarCapturingMouse; } >+ void setScrollbarCapturingMouse(bool b) { m_scrollbarCapturingMouse = b; } >+ >+ bool up(unsigned lines = 1); >+ bool down(unsigned lines = 1); >+ >+ void paint(const WebCore::IntRect& damageRect, HDC = 0); >+ int visibleItems() const; >+ int listIndexAtPoint(const WebCore::IntPoint&) const; >+ int focusedIndex() const; >+ void focusFirst(); >+ void focusLast(); >+ bool scrollToRevealSelection(); >+ void incrementWheelDelta(int delta); >+ void reduceWheelDelta(int delta); >+ >+ WebView* m_webView; >+ Vector<WebPopupItem> m_items; >+ PlatformPopupMenuData m_data; >+ int m_newSelectedIndex { 0 }; >+ >+ RefPtr<WebCore::Scrollbar> m_scrollbar; >+ GDIObject<HDC> m_DC; >+ GDIObject<HBITMAP> m_bmp; >+ HWND m_popup { nullptr }; >+ WebCore::IntRect m_windowRect; >+ >+ int m_itemHeight { 0 }; >+ int m_scrollOffset { 0 }; >+ int m_wheelDelta { 0 }; >+ int m_focusedIndex { 0 }; >+ int m_hoveredIndex { 0 }; >+ bool m_wasClicked { false }; >+ bool m_scrollbarCapturingMouse { false }; >+ bool m_showPopup { false }; >+ int m_scaleFactor { 1 }; >+}; >+ >+} // namespace WebKit >diff --git a/Source/WebKit/WebProcess/WebCoreSupport/win/WebPopupMenuWin.cpp b/Source/WebKit/WebProcess/WebCoreSupport/win/WebPopupMenuWin.cpp >index e876c6ea2ea924e56aefa8d1bd758de337920ff0..9a917ed1f7a0af20c694f45c8863ab12b67036dc 100644 >--- a/Source/WebKit/WebProcess/WebCoreSupport/win/WebPopupMenuWin.cpp >+++ b/Source/WebKit/WebProcess/WebCoreSupport/win/WebPopupMenuWin.cpp >@@ -27,15 +27,124 @@ > #include "WebPopupMenu.h" > > #include "PlatformPopupMenuData.h" >-#include <WebCore/NotImplemented.h> >+#include <WebCore/LengthFunctions.h> >+#include <WebCore/PopupMenuClient.h> >+#include <WebCore/RenderTheme.h> > > using namespace WebCore; > > namespace WebKit { > >-void WebPopupMenu::setUpPlatformData(const IntRect&, PlatformPopupMenuData&) >+static const int separatorPadding = 4; >+static const int separatorHeight = 1; >+static const int popupWindowBorderWidth = 1; >+ >+void WebPopupMenu::setUpPlatformData(const WebCore::IntRect& pageCoordinates, PlatformPopupMenuData& data) > { >- notImplemented(); >+ int itemCount = m_popupClient->listSize(); >+ >+ auto font = m_popupClient->menuStyle().font(); >+ >+ data.m_clientPaddingLeft = m_popupClient->clientPaddingLeft(); >+ data.m_clientPaddingRight = m_popupClient->clientPaddingRight(); >+ data.m_clientInsetLeft = m_popupClient->clientInsetLeft(); >+ data.m_clientInsetRight = m_popupClient->clientInsetRight(); >+ data.m_itemHeight = font.fontMetrics().height() + 1; >+ >+ int popupWidth = 0; >+ for (size_t i = 0; i < itemCount; ++i) { >+ String text = m_popupClient->itemText(i); >+ if (text.isEmpty()) >+ continue; >+ >+ auto itemFontCascade = font; >+ if (m_popupClient->itemIsLabel(i)) { >+ auto d = itemFontCascade.fontDescription(); >+ d.setWeight(boldWeightValue()); >+ itemFontCascade = FontCascade(WTFMove(d), itemFontCascade.letterSpacing(), itemFontCascade.wordSpacing()); >+ itemFontCascade.update(m_popupClient->fontSelector()); >+ } >+ >+ popupWidth = std::max<float>(popupWidth, ceilf(itemFontCascade.width(TextRun(text)))); >+ } >+ >+ // FIXME: popupWidth should probably take into account monitor constraints as is done with WebPopupMenuProxyWin::calculatePositionAndSize. >+ popupWidth += std::max(0, data.m_clientPaddingRight - data.m_clientInsetRight) + std::max(0, data.m_clientPaddingLeft - data.m_clientInsetLeft); >+ popupWidth += 2 * popupWindowBorderWidth; >+ data.m_popupWidth = popupWidth; >+ >+ // The backing stores should be drawn at least as wide as the control on the page to match the width of the popup window we'll create. >+ int backingStoreWidth = std::max(pageCoordinates.width() - m_popupClient->clientInsetLeft() - m_popupClient->clientInsetRight(), popupWidth); >+ >+ IntSize backingStoreSize(backingStoreWidth, (itemCount * data.m_itemHeight)); >+ data.m_notSelectedBackingStore = ShareableBitmap::createShareable(backingStoreSize, { }); >+ data.m_selectedBackingStore = ShareableBitmap::createShareable(backingStoreSize, { }); >+ >+ std::unique_ptr<GraphicsContext> notSelectedBackingStoreContext = data.m_notSelectedBackingStore->createGraphicsContext(); >+ std::unique_ptr<GraphicsContext> selectedBackingStoreContext = data.m_selectedBackingStore->createGraphicsContext(); >+ >+ Color activeOptionBackgroundColor = RenderTheme::singleton().activeListBoxSelectionBackgroundColor({ }); >+ Color activeOptionTextColor = RenderTheme::singleton().activeListBoxSelectionForegroundColor({ }); >+ >+ for (int y = 0; y < backingStoreSize.height(); y += data.m_itemHeight) { >+ int index = y / data.m_itemHeight; >+ >+ PopupMenuStyle itemStyle = m_popupClient->itemStyle(index); >+ >+ Color optionBackgroundColor = itemStyle.backgroundColor(); >+ Color optionTextColor = itemStyle.foregroundColor(); >+ >+ IntRect itemRect(0, y, backingStoreWidth, data.m_itemHeight); >+ >+ // Draw the background for this menu item >+ if (itemStyle.isVisible()) { >+ notSelectedBackingStoreContext->fillRect(itemRect, optionBackgroundColor); >+ selectedBackingStoreContext->fillRect(itemRect, activeOptionBackgroundColor); >+ } >+ >+ if (m_popupClient->itemIsSeparator(index)) { >+ IntRect separatorRect(itemRect.x() + separatorPadding, itemRect.y() + (itemRect.height() - separatorHeight) / 2, itemRect.width() - 2 * separatorPadding, separatorHeight); >+ >+ notSelectedBackingStoreContext->fillRect(separatorRect, optionTextColor); >+ selectedBackingStoreContext->fillRect(separatorRect, activeOptionTextColor); >+ continue; >+ } >+ >+ String itemText = m_popupClient->itemText(index); >+ >+ TextDirection direction = itemText.defaultWritingDirection() == U_RIGHT_TO_LEFT ? RTL : LTR; >+ TextRun textRun(itemText, 0, 0, AllowTrailingExpansion, itemStyle.textDirection(), itemStyle.hasTextDirectionOverride()); >+ >+ notSelectedBackingStoreContext->setFillColor(optionTextColor); >+ selectedBackingStoreContext->setFillColor(activeOptionTextColor); >+ >+ auto itemFontCascade = font; >+ if (m_popupClient->itemIsLabel(index)) { >+ auto d = itemFontCascade.fontDescription(); >+ d.setWeight(boldWeightValue()); >+ itemFontCascade = FontCascade(WTFMove(d), itemFontCascade.letterSpacing(), itemFontCascade.wordSpacing()); >+ itemFontCascade.update(m_popupClient->fontSelector()); >+ } >+ >+ // Draw the item text >+ if (itemStyle.isVisible()) { >+ int textX = 0; >+ if (m_popupClient->menuStyle().textDirection() == LTR) { >+ textX = std::max<int>(0, m_popupClient->clientPaddingLeft() - m_popupClient->clientInsetLeft()); >+ if (RenderTheme::singleton().popupOptionSupportsTextIndent()) >+ textX += minimumIntValueForLength(itemStyle.textIndent(), itemRect.width()); >+ } else { >+ textX = itemRect.width() - m_popupClient->menuStyle().font().width(textRun); >+ textX = std::min<int>(textX, textX - m_popupClient->clientPaddingRight() + m_popupClient->clientInsetRight()); >+ if (RenderTheme::singleton().popupOptionSupportsTextIndent()) >+ textX -= minimumIntValueForLength(itemStyle.textIndent(), itemRect.width()); >+ } >+ int textY = itemRect.y() + itemFontCascade.fontMetrics().ascent() + (itemRect.height() - itemFontCascade.fontMetrics().height()) / 2; >+ >+ notSelectedBackingStoreContext->drawBidiText(itemFontCascade, textRun, IntPoint(textX, textY)); >+ selectedBackingStoreContext->drawBidiText(itemFontCascade, textRun, IntPoint(textX, textY)); >+ } >+ } > } > > } // namespace WebKit
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 188172
:
346069
| 346198