/*
 * Copyright (C) 2006-2008, 2011, 2015 Apple Inc. All rights reserved.
 * Copyright (C) 2007-2009 Torch Mobile Inc.
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#include "config.h"
#include "PopupMenuWin.h"

#include "BString.h"
#include "BitmapInfo.h"
#include "Document.h"
#include "FloatRect.h"
#include "Font.h"
#include "FontSelector.h"
#include "Frame.h"
#include "FrameView.h"
#include "GDIUtilities.h"
#include "GraphicsContext.h"
#include "GraphicsContextWin.h"
#include "HTMLNames.h"
#include "HWndDC.h"
#include "HostWindow.h"
#include "LengthFunctions.h"
#include "NotImplemented.h"
#include "Page.h"
#include "PlatformMouseEvent.h"
#include "PlatformScreen.h"
#include "RenderMenuList.h"
#include "RenderTheme.h"
#include "RenderView.h"
#include "Scrollbar.h"
#include "ScrollbarTheme.h"
#include "ScrollbarThemeWin.h"
#include "TextRun.h"
#include "WebCoreInstanceHandle.h"
#include <wtf/HexNumber.h>
#include <wtf/WindowsExtras.h>
#include <wtf/text/StringBuilder.h>

#include <windows.h>
#include <windowsx.h>

#define HIGH_BIT_MASK_SHORT 0x8000

using std::min;

namespace WebCore {

using namespace HTMLNames;

// Default Window animation duration in milliseconds
static const int defaultAnimationDuration = 200;
// Maximum height of a popup window
static const int maxPopupHeight = 320;

const int optionSpacingMiddle = 1;
const int popupWindowBorderWidth = 1;

static LPCWSTR kPopupWindowClassName = L"PopupWindowClass";

// 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 const UINT WM_HOST_WINDOW_FIRST = WM_USER;
static const UINT WM_HOST_WINDOW_CHAR = WM_USER + WM_CHAR; 
static const UINT WM_HOST_WINDOW_MOUSEMOVE = WM_USER + WM_MOUSEMOVE;

// FIXME: Remove this as soon as practical.
static inline bool isASCIIPrintable(unsigned c)
{
    return c >= 0x20 && c <= 0x7E;
}

static void translatePoint(LPARAM& lParam, HWND from, HWND to)
{
    POINT pt;
    pt.x = (short)GET_X_LPARAM(lParam);
    pt.y = (short)GET_Y_LPARAM(lParam);    
    ::MapWindowPoints(from, to, &pt, 1);
    lParam = MAKELPARAM(pt.x, pt.y);
}

static FloatRect monitorFromHwnd(HWND hwnd)
{
    HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY);
    MONITORINFOEX monitorInfo;
    monitorInfo.cbSize = sizeof(MONITORINFOEX);
    GetMonitorInfo(monitor, &monitorInfo);
    return monitorInfo.rcWork;
}

PopupMenuWin::PopupMenuWin(PopupMenuClient* client)
    : m_popupClient(client)
{
}

PopupMenuWin::~PopupMenuWin()
{
    if (m_popup)
        ::DestroyWindow(m_popup);
    if (m_scrollbar)
        m_scrollbar->setParent(0);
}

void PopupMenuWin::disconnectClient()
{
    m_popupClient = 0;
}

LPCWSTR PopupMenuWin::popupClassName()
{
    return kPopupWindowClassName;
}

void PopupMenuWin::show(const IntRect& r, FrameView* view, int index)
{
    if (view && view->frame().page())
        m_scaleFactor = view->frame().page()->deviceScaleFactor();

    calculatePositionAndSize(r, view);
    if (clientRect().isEmpty())
        return;

    HWND hostWindow = view->hostWindow()->platformPageClient();

    if (!m_scrollbar && visibleItems() < client()->listSize()) {
        // We need a scroll bar
        m_scrollbar = client()->createScrollbar(*this, ScrollbarOrientation::Vertical, ScrollbarControlSize::Small);
        m_scrollbar->styleChanged();
    }

    // We need to reposition the popup window to its final coordinates.
    // Before calling this, the popup hwnd is currently the size of and at the location of the menu list client so it needs to be updated.
    ::MoveWindow(m_popup, m_windowRect.x(), m_windowRect.y(), m_windowRect.width(), m_windowRect.height(), false);

    // Determine whether we should animate our popups
    // Note: Must use 'BOOL' and 'FALSE' instead of 'bool' and 'false' to avoid stack corruption with SystemParametersInfo
    BOOL shouldAnimate = FALSE;

    if (client()) {
        int index = client()->selectedIndex();
        if (index >= 0)
            setFocusedIndex(index);
    }

    if (!::SystemParametersInfo(SPI_GETCOMBOBOXANIMATION, 0, &shouldAnimate, 0))
        shouldAnimate = FALSE;

    if (shouldAnimate) {
        RECT viewRect { };
        ::GetWindowRect(hostWindow, &viewRect);
        if (!::IsRectEmpty(&viewRect))
            ::AnimateWindow(m_popup, defaultAnimationDuration, AW_BLEND);
    } 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<PopupMenu> 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_SYSKEYDOWN:
            case WM_SYSKEYUP:
            case WM_SYSCHAR:
            case WM_SYSDEADCHAR:
                msg.hwnd = m_popup;
                break;
        }

        ::TranslateMessage(&msg);
        ::DispatchMessage(&msg);

        if (!m_popupClient)
            break;

        if (!m_showPopup)
            break;
        activeWindow = ::GetActiveWindow();
        if (activeWindow != hostWindow && !::IsChild(activeWindow, hostWindow))
            break;
        if (::GetCapture() != hostWindow)
            break;
    }

    if (::GetCapture() == hostWindow)
        ::ReleaseCapture();

    // We're done, hide the popup if necessary.
    hide();
}

void PopupMenuWin::hide()
{
    if (!m_showPopup)
        return;

    m_showPopup = false;

    ::ShowWindow(m_popup, SW_HIDE);

    if (client())
        client()->popupDidHide();

    // Post a WM_NULL message to wake up the message pump if necessary.
    ::PostMessage(m_popup, WM_NULL, 0, 0);
}

// The screen that the popup is placed on should be whichever one the popup menu button lies on.
// We fake an hwnd (here we use the popup's hwnd) on top of the button which we can then use to determine the screen.
// We can then proceed with our final position/size calculations.
void PopupMenuWin::calculatePositionAndSize(const IntRect& r, FrameView* v)
{
    // First get the screen coordinates of the popup menu client.
    HWND hostWindow = v->hostWindow()->platformPageClient();
    IntRect absoluteBounds = ((RenderMenuList*)m_popupClient)->absoluteBoundingBoxRect();
    IntRect absoluteScreenCoords(v->contentsToWindow(absoluteBounds.location()), absoluteBounds.size());
    POINT absoluteLocation(absoluteScreenCoords.location());
    if (!::ClientToScreen(hostWindow, &absoluteLocation))
        return;
    absoluteScreenCoords.setLocation(absoluteLocation);

    // Now set the popup menu's location temporarily to these coordinates so we can determine which screen the popup should lie on.
    // We create or move m_popup as necessary.
    if (!m_popup) {
        registerClass();
        DWORD exStyle = WS_EX_LTRREADING;
        m_popup = ::CreateWindowExW(exStyle, kPopupWindowClassName, L"PopupMenu",
            WS_POPUP | WS_BORDER,
            absoluteScreenCoords.x(), absoluteScreenCoords.y(), absoluteScreenCoords.width(), absoluteScreenCoords.height(),
            hostWindow, 0, WebCore::instanceHandle(), this);

        if (!m_popup)
            return;
    } else
        ::MoveWindow(m_popup, absoluteScreenCoords.x(), absoluteScreenCoords.y(), absoluteScreenCoords.width(), absoluteScreenCoords.height(), false);

    FloatRect screen = monitorFromHwnd(m_popup);
    
    // Now we determine the actual location and measurements of the popup itself.
    // r is in absolute document coordinates, but we want to be in screen coordinates.

    // First, move to WebView coordinates
    IntRect rScreenCoords(v->contentsToWindow(r.location()), r.size());
    if (Page* page = v->frame().page())
        rScreenCoords.scale(page->deviceScaleFactor());

    // Then, translate to screen coordinates
    POINT location(rScreenCoords.location());
    if (!::ClientToScreen(hostWindow, &location))
        return;

    rScreenCoords.setLocation(location);

    m_font = client()->menuStyle().font();
    auto d = m_font.fontDescription();
    d.setComputedSize(d.computedSize() * m_scaleFactor);
    m_font = FontCascade(WTFMove(d), m_font.letterSpacing(), m_font.wordSpacing());
    m_font.update(m_popupClient->fontSelector());

    // First, determine the popup's height
    int itemCount = client()->listSize();
    m_itemHeight = m_font.fontMetrics().height() + optionSpacingMiddle;

    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 = 0;
    for (int i = 0; i < itemCount; ++i) {
        String text = client()->itemText(i);
        if (text.isEmpty())
            continue;

        FontCascade itemFont = m_font;
        if (client()->itemIsLabel(i)) {
            auto d = itemFont.fontDescription();
            d.setWeight(d.bolderWeight());
            itemFont = FontCascade(WTFMove(d), itemFont.letterSpacing(), itemFont.wordSpacing());
            itemFont.update(m_popupClient->fontSelector());
        }

        popupWidth = std::max(popupWidth, static_cast<int>(ceilf(itemFont.width(TextRun(text)))));
    }

    if (naturalHeight > maxPopupHeight)
        // We need room for a scrollbar
        popupWidth += ScrollbarTheme::theme().scrollbarThickness(ScrollbarControlSize::Small);

    // Add padding to align the popup text with the <select> text
    popupWidth += std::max<int>(0, client()->clientPaddingRight() - client()->clientInsetRight()) + std::max<int>(0, client()->clientPaddingLeft() - client()->clientInsetLeft());

    // Leave room for the border
    popupWidth += 2 * popupWindowBorderWidth;
    popupHeight += 2 * popupWindowBorderWidth;

    // The popup should be at least as wide as the control on the page
    popupWidth = std::max(rScreenCoords.width() - client()->clientInsetLeft() - client()->clientInsetRight(), popupWidth);

    // Always left-align items in the popup.  This matches popup menus on the mac.
    int popupX = rScreenCoords.x() + client()->clientInsetLeft();

    IntRect popupRect(popupX, rScreenCoords.maxY(), popupWidth, popupHeight);

    // 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 (rScreenCoords.y() - popupRect.height() < 0) {
            // The popup won't fit above, either, so place it whereever's bigger and resize it to fit
            if ((rScreenCoords.y() + rScreenCoords.height() / 2) < (screen.height() / 2)) {
                // Below is bigger
                popupRect.setHeight(screen.height() - popupRect.y());
            } else {
                // Above is bigger
                popupRect.setY(0);
                popupRect.setHeight(rScreenCoords.y());
            }
        } else {
            // The popup fits above, so reposition it
            popupRect.setY(rScreenCoords.y() - popupRect.height());
        }
    }

    // Check that we don't go off the screen horizontally
    if (popupRect.x() + popupRect.width() > screen.width() + screen.x())
        popupRect.setX(screen.x() + screen.width() - popupRect.width());
    if (popupRect.x() < screen.x())
        popupRect.setX(screen.x());

    m_windowRect = popupRect;
    return;
}

bool PopupMenuWin::setFocusedIndex(int i, bool hotTracking)
{
    if (i < 0 || i >= client()->listSize() || i == focusedIndex())
        return false;

    if (!client()->itemIsEnabled(i))
        return false;

    invalidateItem(focusedIndex());
    invalidateItem(i);

    m_focusedIndex = i;

    if (!hotTracking)
        client()->setTextFromItem(i);

    if (!scrollToRevealSelection())
        ::UpdateWindow(m_popup);

    return true;
}

int PopupMenuWin::visibleItems() const
{
    return clientRect().height() / m_itemHeight;
}

int PopupMenuWin::listIndexAtPoint(const IntPoint& point) const
{
    return m_scrollOffset + point.y() / m_itemHeight;
}

int PopupMenuWin::focusedIndex() const
{
    return m_focusedIndex;
}

void PopupMenuWin::focusFirst()
{
    if (!client())
        return;

    int size = client()->listSize();

    for (int i = 0; i < size; ++i)
        if (client()->itemIsEnabled(i)) {
            setFocusedIndex(i);
            break;
        }
}

void PopupMenuWin::focusLast()
{
    if (!client())
        return;

    int size = client()->listSize();

    for (int i = size - 1; i > 0; --i)
        if (client()->itemIsEnabled(i)) {
            setFocusedIndex(i);
            break;
        }
}

bool PopupMenuWin::down(unsigned lines)
{
    if (!client())
        return false;

    int size = client()->listSize();

    int lastSelectableIndex, selectedListIndex;
    lastSelectableIndex = selectedListIndex = focusedIndex();
    for (int i = selectedListIndex + 1; i >= 0 && i < size; ++i)
        if (client()->itemIsEnabled(i)) {
            lastSelectableIndex = i;
            if (i >= selectedListIndex + (int)lines)
                break;
        }

    return setFocusedIndex(lastSelectableIndex);
}

bool PopupMenuWin::up(unsigned lines)
{
    if (!client())
        return false;

    int size = client()->listSize();

    int lastSelectableIndex, selectedListIndex;
    lastSelectableIndex = selectedListIndex = focusedIndex();
    for (int i = selectedListIndex - 1; i >= 0 && i < size; --i)
        if (client()->itemIsEnabled(i)) {
            lastSelectableIndex = i;
            if (i <= selectedListIndex - (int)lines)
                break;
        }

    return setFocusedIndex(lastSelectableIndex);
}

void PopupMenuWin::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);
}

IntRect PopupMenuWin::clientRect() const
{
    IntRect clientRect = m_windowRect;
    clientRect.inflate(-popupWindowBorderWidth);
    clientRect.setLocation(IntPoint(0, 0));
    return clientRect;
}

void PopupMenuWin::incrementWheelDelta(int delta)
{
    m_wheelDelta += delta;
}

void PopupMenuWin::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 PopupMenuWin::scrollToRevealSelection()
{
    if (!m_scrollbar)
        return false;

    int index = focusedIndex();

    if (index < m_scrollOffset) {
        ScrollableArea::scrollToOffsetWithoutAnimation(ScrollbarOrientation::Vertical, index);
        return true;
    }

    if (index >= m_scrollOffset + visibleItems()) {
        ScrollableArea::scrollToOffsetWithoutAnimation(ScrollbarOrientation::Vertical, index - visibleItems() + 1);
        return true;
    }

    return false;
}

void PopupMenuWin::updateFromElement()
{
    if (!m_popup)
        return;

    m_focusedIndex = client()->selectedIndex();

    ::InvalidateRect(m_popup, 0, TRUE);
    scrollToRevealSelection();
}

const int separatorPadding = 4;
const int separatorHeight = 1;
void PopupMenuWin::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());
    }

    GraphicsContextWin context(m_DC.get());

    // listRect is the damageRect translated into the coordinates of the entire menu list (which is listSize * m_itemHeight pixels tall)
    IntRect listRect = damageRect;
    listRect.move(IntSize(0, m_scrollOffset * m_itemHeight));

    for (int y = listRect.y(); y < listRect.maxY(); y += m_itemHeight) {
        int index = y / m_itemHeight;

        Color optionBackgroundColor, optionTextColor;
        PopupMenuStyle itemStyle = client()->itemStyle(index);
        if (index == focusedIndex()) {
            optionBackgroundColor = RenderTheme::singleton().activeListBoxSelectionBackgroundColor({ });
            optionTextColor = RenderTheme::singleton().activeListBoxSelectionForegroundColor({ });
        } else {
            optionBackgroundColor = itemStyle.backgroundColor();
            optionTextColor = itemStyle.foregroundColor();
        }

        // itemRect is in client coordinates
        IntRect itemRect(0, (index - m_scrollOffset) * m_itemHeight, damageRect.width(), m_itemHeight);

        // Draw the background for this menu item
        if (itemStyle.isVisible())
            context.fillRect(itemRect, optionBackgroundColor);

        if (client()->itemIsSeparator(index)) {
            IntRect separatorRect(itemRect.x() + separatorPadding, itemRect.y() + (itemRect.height() - separatorHeight) / 2, itemRect.width() - 2 * separatorPadding, separatorHeight);
            context.fillRect(separatorRect, optionTextColor);
            continue;
        }

        String itemText = client()->itemText(index);

        TextRun textRun(itemText, 0, 0, AllowLeftExpansion, itemStyle.textDirection(), itemStyle.hasTextDirectionOverride());
        context.setFillColor(optionTextColor);

        FontCascade itemFont = m_font;
        if (client()->itemIsLabel(index)) {
            auto d = itemFont.fontDescription();
            d.setWeight(d.bolderWeight());
            itemFont = FontCascade(WTFMove(d), itemFont.letterSpacing(), itemFont.wordSpacing());
            itemFont.update(m_popupClient->fontSelector());
        }
        
        // Draw the item text
        if (itemStyle.isVisible()) {
            int textX = 0;
            if (client()->menuStyle().textDirection() == TextDirection::LTR) {
                textX = std::max<int>(0, client()->clientPaddingLeft() - client()->clientInsetLeft());
                if (RenderTheme::singleton().popupOptionSupportsTextIndent())
                    textX += minimumIntValueForLength(itemStyle.textIndent(), itemRect.width());
            } else {
                textX = itemRect.width() - client()->menuStyle().font().width(textRun);
                textX = std::min<int>(textX, textX - client()->clientPaddingRight() + client()->clientInsetRight());
                if (RenderTheme::singleton().popupOptionSupportsTextIndent())
                    textX -= minimumIntValueForLength(itemStyle.textIndent(), itemRect.width());
            }
            int textY = itemRect.y() + itemFont.fontMetrics().ascent() + (itemRect.height() - itemFont.fontMetrics().height()) / 2;
            context.drawBidiText(itemFont, textRun, IntPoint(textX, textY));
        }
    }

    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);
}

ScrollPosition PopupMenuWin::scrollPosition() const
{
    return { 0, m_scrollOffset };
}

void PopupMenuWin::setScrollOffset(const IntPoint& offset)
{
    scrollTo(offset.y());
}

void PopupMenuWin::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 PopupMenuWin::invalidateScrollbarRect(Scrollbar& scrollbar, const IntRect& rect)
{
    IntRect scrollRect = rect;
    scrollRect.move(scrollbar.x(), scrollbar.y());
    RECT r = scrollRect;
    ::InvalidateRect(m_popup, &r, false);
}

IntSize PopupMenuWin::visibleSize() const
{
    return IntSize(m_windowRect.width(), m_scrollbar ? m_scrollbar->visibleSize() : m_windowRect.height());
}

IntSize PopupMenuWin::contentsSize() const
{
    return IntSize(m_windowRect.width(), m_scrollbar ? m_scrollbar->totalSize() : m_windowRect.height());
}

IntRect PopupMenuWin::scrollableAreaBoundingBox(bool*) const
{
    return m_windowRect;
}

bool PopupMenuWin::onGetObject(WPARAM wParam, LPARAM lParam, LRESULT& lResult)
{
    lResult = 0;

    if (static_cast<LONG>(lParam) != OBJID_CLIENT)
        return false;

    if (!m_accessiblePopupMenu)
        m_accessiblePopupMenu = new AccessiblePopupMenu(*this);

    static HMODULE accessibilityLib = nullptr;
    if (!accessibilityLib) {
        if (!(accessibilityLib = ::LoadLibraryW(L"oleacc.dll")))
            return false;
    }

    static LPFNLRESULTFROMOBJECT procPtr = reinterpret_cast<LPFNLRESULTFROMOBJECT>(::GetProcAddress(accessibilityLib, "LresultFromObject"));
    if (!procPtr)
        return false;

    // LresultFromObject returns a reference to the accessible object, stored
    // in an LRESULT. If this call is not successful, Windows will handle the
    // request through DefWindowProc.
    return SUCCEEDED(lResult = procPtr(__uuidof(IAccessible), wParam, m_accessiblePopupMenu.get()));
}

void PopupMenuWin::registerClass()
{
    static bool haveRegisteredWindowClass = false;

    if (haveRegisteredWindowClass)
        return;

    WNDCLASSEX wcex;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.hIconSm        = 0;
    wcex.style          = CS_DROPSHADOW;

    wcex.lpfnWndProc    = PopupMenuWndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = sizeof(PopupMenu*); // For the PopupMenu pointer
    wcex.hInstance      = WebCore::instanceHandle();
    wcex.hIcon          = 0;
    wcex.hCursor        = LoadCursor(0, IDC_ARROW);
    wcex.hbrBackground  = 0;
    wcex.lpszMenuName   = 0;
    wcex.lpszClassName  = kPopupWindowClassName;

    haveRegisteredWindowClass = true;

    RegisterClassEx(&wcex);
}


LRESULT CALLBACK PopupMenuWin::PopupMenuWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    if (PopupMenuWin* popup = static_cast<PopupMenuWin*>(getWindowPointer(hWnd, 0)))
        return popup->wndProc(hWnd, message, wParam, lParam);

    if (message == WM_CREATE) {
        LPCREATESTRUCT createStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);

        // Associate the PopupMenu with the window.
        setWindowPointer(hWnd, 0, createStruct->lpCreateParams);
        return 0;
    }

    return ::DefWindowProc(hWnd, message, wParam, lParam);
}

LRESULT PopupMenuWin::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    LRESULT lResult = 0;

    switch (message) {
        case WM_MOUSEACTIVATE:
            return MA_NOACTIVATE;
        case WM_SIZE: {
            if (!scrollbar())
                break;

            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 < client()->listSize());
            scrollbar()->setSteps(1, std::max(1, visibleItems - 1));
            scrollbar()->setProportion(visibleItems, client()->listSize());

            break;
        }
        case WM_SYSKEYDOWN:
        case WM_KEYDOWN: {
            if (!client())
                break;

            bool altKeyPressed = GetKeyState(VK_MENU) & HIGH_BIT_MASK_SHORT;
            bool ctrlKeyPressed = GetKeyState(VK_CONTROL) & HIGH_BIT_MASK_SHORT;

            lResult = 0;
            switch (LOWORD(wParam)) {
                case VK_F4: {
                    if (!altKeyPressed && !ctrlKeyPressed) {
                        int index = focusedIndex();
                        ASSERT(index >= 0);
                        client()->valueChanged(index);
                        hide();
                    }
                    break;
                }
                case VK_DOWN:
                    if (altKeyPressed) {
                        int index = focusedIndex();
                        ASSERT(index >= 0);
                        client()->valueChanged(index);
                        hide();
                    } else
                        down();
                    break;
                case VK_RIGHT:
                    down();
                    break;
                case VK_UP:
                    if (altKeyPressed) {
                        int index = focusedIndex();
                        ASSERT(index >= 0);
                        client()->valueChanged(index);
                        hide();
                    } else
                        up();
                    break;
                case VK_LEFT:
                    up();
                    break;
                case VK_HOME:
                    focusFirst();
                    break;
                case VK_END:
                    focusLast();
                    break;
                case VK_PRIOR:
                    if (focusedIndex() != m_scrollOffset) {
                        // Set the selection to the first visible item
                        int firstVisibleItem = m_scrollOffset;
                        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 = m_scrollOffset + 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(client()->hostWindow()->platformPageClient(), 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;
            }
            break;
        }
        case WM_CHAR: {
            if (!client())
                break;

            lResult = 0;
            int index;
            switch (wParam) {
                case 0x0D:   // Enter/Return
                    hide();
                    index = focusedIndex();
                    ASSERT(index >= 0);
                    client()->valueChanged(index);
                    break;
                case 0x1B:   // Escape
                    hide();
                    break;
                case 0x09:   // TAB
                case 0x08:   // Backspace
                case 0x0A:   // Linefeed
                default:     // Character
                    lResult = 1;
                    break;
            }
            break;
        }
        case WM_MOUSEMOVE: {
            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);
                    break;
                }
            }

            BOOL shouldHotTrack = FALSE;
            if (!::SystemParametersInfo(SPI_GETHOTTRACKING, 0, &shouldHotTrack, 0))
                shouldHotTrack = FALSE;

            RECT bounds;
            GetClientRect(popupHandle(), &bounds);
            if (!::PtInRect(&bounds, mousePoint) && !(wParam & MK_LBUTTON) && client()) {
                // 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, client()->hostWindow()->platformPageClient());

                ::PostMessage(m_popup, WM_HOST_WINDOW_MOUSEMOVE, wParam, lParam);
                break;
            }

            if ((shouldHotTrack || wParam & MK_LBUTTON) && ::PtInRect(&bounds, mousePoint)) {
                setFocusedIndex(listIndexAtPoint(mousePoint), true);
                m_hoveredIndex = listIndexAtPoint(mousePoint);
            }

            break;
        }
        case WM_LBUTTONDOWN: {
            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);
                    break;
                }
            }

            // 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();
            break;
        }
        case WM_LBUTTONUP: {
            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(popupHandle(), &r, TRUE);
                    break;
                }
            }
            // Only hide the popup if the mouse is inside the popup window.
            RECT bounds;
            GetClientRect(popupHandle(), &bounds);
            if (client() && ::PtInRect(&bounds, mousePoint)) {
                hide();
                int index = m_hoveredIndex;
                if (!client()->itemIsEnabled(index))
                    index = client()->selectedIndex();
                if (index >= 0)
                    client()->valueChanged(index);
            }
            break;
        }

        case WM_MOUSEWHEEL: {
            if (!scrollbar())
                break;

            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, ScrollGranularity::Line, abs(i));
            break;
        }

        case WM_PAINT: {
            PAINTSTRUCT paintInfo;
            ::BeginPaint(popupHandle(), &paintInfo);
            paint(paintInfo.rcPaint, paintInfo.hdc);
            ::EndPaint(popupHandle(), &paintInfo);
            lResult = 0;
            break;
        }
        case WM_PRINTCLIENT:
            paint(clientRect(), (HDC)wParam);
            break;
        case WM_GETOBJECT:
            onGetObject(wParam, lParam, lResult);
            break;
        default:
            lResult = DefWindowProc(hWnd, message, wParam, lParam);
    }

    return lResult;
}

String PopupMenuWin::debugDescription() const
{
    return makeString("PopupMenuWin 0x", hex(reinterpret_cast<uintptr_t>(this), Lowercase));
}

AccessiblePopupMenu::AccessiblePopupMenu(const PopupMenuWin& popupMenu)
    : m_popupMenu(popupMenu)
{
}

AccessiblePopupMenu::~AccessiblePopupMenu() = default;

HRESULT AccessiblePopupMenu::QueryInterface(_In_ REFIID riid, _COM_Outptr_ void** ppvObject)
{
    if (!ppvObject)
        return E_POINTER;
    if (IsEqualGUID(riid, __uuidof(IAccessible)))
        *ppvObject = static_cast<IAccessible*>(this);
    else if (IsEqualGUID(riid, __uuidof(IDispatch)))
        *ppvObject = static_cast<IAccessible*>(this);
    else if (IsEqualGUID(riid, __uuidof(IUnknown)))
        *ppvObject = static_cast<IAccessible*>(this);
    else {
        *ppvObject = nullptr;
        return E_NOINTERFACE;
    }
    AddRef();
    return S_OK;
}

ULONG AccessiblePopupMenu::AddRef()
{
    return ++m_refCount;
}

ULONG AccessiblePopupMenu::Release()
{
    int refCount = --m_refCount;
    if (!refCount)
        delete this;
    return refCount;
}

HRESULT AccessiblePopupMenu::GetTypeInfoCount(_Out_ UINT* count)
{
    if (!count)
        return E_POINTER;
    *count = 0;
    notImplemented();
    return E_NOTIMPL;
}

HRESULT AccessiblePopupMenu::GetTypeInfo(UINT, LCID, _COM_Outptr_opt_ ITypeInfo** ppTInfo)
{
    if (!ppTInfo)
        return E_POINTER;
    *ppTInfo = nullptr;
    notImplemented();
    return E_NOTIMPL;
}

HRESULT AccessiblePopupMenu::GetIDsOfNames(_In_ REFIID, __in_ecount(cNames) LPOLESTR*, UINT cNames, LCID, __out_ecount_full(cNames) DISPID*)
{
    notImplemented();
    return E_NOTIMPL;
}

HRESULT AccessiblePopupMenu::Invoke(DISPID, REFIID, LCID, WORD, DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT*)
{
    notImplemented();
    return E_NOTIMPL;
}

HRESULT AccessiblePopupMenu::get_accParent(_COM_Outptr_opt_ IDispatch** parent)
{
    if (!parent)
        return E_POINTER;
    *parent = nullptr;
    notImplemented();
    return E_NOTIMPL;
}

HRESULT AccessiblePopupMenu::get_accChildCount(_Out_ long* count)
{
    if (!count)
        return E_POINTER;

    *count = m_popupMenu.visibleItems();
    return S_OK;
}

HRESULT AccessiblePopupMenu::get_accChild(VARIANT vChild, _COM_Outptr_opt_ IDispatch** ppChild)
{
    if (!ppChild)
        return E_POINTER;

    *ppChild = nullptr;

    if (vChild.vt != VT_I4)
        return E_INVALIDARG;

    notImplemented();
    return S_FALSE;
}

HRESULT AccessiblePopupMenu::get_accName(VARIANT vChild, __deref_out_opt BSTR* name)
{
    return get_accValue(vChild, name);
}

HRESULT AccessiblePopupMenu::get_accValue(VARIANT vChild, __deref_out_opt BSTR* value)
{
    if (!value)
        return E_POINTER;

    *value = nullptr;

    if (vChild.vt != VT_I4)
        return E_INVALIDARG;

    int index = vChild.lVal - 1;

    if (index < 0)
        return E_INVALIDARG;

    BString itemText(m_popupMenu.client()->itemText(index));
    *value = itemText.release();

    return S_OK;
}

HRESULT AccessiblePopupMenu::get_accDescription(VARIANT, __deref_out_opt BSTR*)
{
    notImplemented();
    return E_NOTIMPL;
}

HRESULT AccessiblePopupMenu::get_accRole(VARIANT vChild, _Out_ VARIANT* pvRole)
{
    if (!pvRole)
        return E_POINTER;
    if (vChild.vt != VT_I4)
        return E_INVALIDARG;

    // Scrollbar parts are encoded as negative values.
    if (vChild.lVal < 0) {
        V_VT(pvRole) = VT_I4;
        V_I4(pvRole) = ROLE_SYSTEM_SCROLLBAR;
    } else {
        V_VT(pvRole) = VT_I4;
        V_I4(pvRole) = ROLE_SYSTEM_LISTITEM;
    }

    return S_OK;
}

HRESULT AccessiblePopupMenu::get_accState(VARIANT vChild, _Out_ VARIANT* pvState)
{
    if (!pvState)
        return E_POINTER;

    if (vChild.vt != VT_I4)
        return E_INVALIDARG;

    V_VT(pvState) = VT_I4;
    V_I4(pvState) = 0; // STATE_SYSTEM_NORMAL
    
    return S_OK;
}

HRESULT AccessiblePopupMenu::get_accHelp(VARIANT vChild, __deref_out_opt BSTR* helpText)
{
    notImplemented();
    return E_NOTIMPL;
}

HRESULT AccessiblePopupMenu::get_accKeyboardShortcut(VARIANT vChild, __deref_out_opt BSTR*)
{
    notImplemented();
    return E_NOTIMPL;
}

HRESULT AccessiblePopupMenu::get_accFocus(_Out_ VARIANT* pvFocusedChild)
{
    notImplemented();
    return E_NOTIMPL;
}

HRESULT AccessiblePopupMenu::get_accSelection(_Out_ VARIANT* pvSelectedChild)
{
    notImplemented();
    return E_NOTIMPL;
}

HRESULT AccessiblePopupMenu::get_accDefaultAction(VARIANT vChild, __deref_out_opt BSTR* actionDescription)
{
    notImplemented();
    return E_NOTIMPL;
}

HRESULT AccessiblePopupMenu::accSelect(long selectionFlags, VARIANT vChild)
{
    notImplemented();
    return E_NOTIMPL;
}

HRESULT AccessiblePopupMenu::accLocation(_Out_ long* left, _Out_ long* top, _Out_ long* width, _Out_ long* height, VARIANT vChild)
{
    if (!left || !top || !width || !height)
        return E_POINTER;

    if (vChild.vt != VT_I4)
        return E_INVALIDARG;

    const IntRect& windowRect = m_popupMenu.windowRect();

    // Scrollbar parts are encoded as negative values.
    if (vChild.lVal < 0) {
        if (!m_popupMenu.scrollbar())
            return E_FAIL;

        Scrollbar& scrollbar = *m_popupMenu.scrollbar();
        WebCore::ScrollbarPart part = static_cast<WebCore::ScrollbarPart>(-vChild.lVal);

        ScrollbarThemeWin& theme = static_cast<ScrollbarThemeWin&>(scrollbar.theme());

        IntRect partRect;

        switch (part) {
        case BackTrackPart:
        case BackButtonStartPart:
            partRect = theme.backButtonRect(scrollbar, WebCore::BackTrackPart);
            break;
        case ThumbPart:
            partRect = theme.thumbRect(scrollbar);
            break;
        case ForwardTrackPart:
        case ForwardButtonEndPart:
            partRect = theme.forwardButtonRect(scrollbar, WebCore::ForwardTrackPart);
            break;
        case ScrollbarBGPart:
            partRect = theme.trackRect(scrollbar);
            break;
        default:
            return E_FAIL;
        }

        partRect.move(windowRect.x(), windowRect.y());

        *left = partRect.x();
        *top = partRect.y();
        *width = partRect.width();
        *height = partRect.height();

        return S_OK;
    }

    int index = vChild.lVal - 1;

    if (index < 0)
        return E_INVALIDARG;

    *left = windowRect.x();
    *top = windowRect.y() + (index - m_popupMenu.m_scrollOffset) * m_popupMenu.itemHeight();
    *width = windowRect.width();
    *height = m_popupMenu.itemHeight();

    return S_OK;
}

HRESULT AccessiblePopupMenu::accNavigate(long direction, VARIANT vFromChild, _Out_ VARIANT* pvNavigatedTo)
{
    notImplemented();
    return E_NOTIMPL;
}

HRESULT AccessiblePopupMenu::accHitTest(long x, long y, _Out_ VARIANT* pvChildAtPoint)
{
    if (!pvChildAtPoint)
        return E_POINTER;

    ::VariantInit(pvChildAtPoint);

    IntRect windowRect = m_popupMenu.windowRect();

    IntPoint pt(x - windowRect.x(), y - windowRect.y());

    IntRect scrollRect;

    if (m_popupMenu.scrollbar())
        scrollRect = m_popupMenu.scrollbar()->frameRect();

    if (m_popupMenu.scrollbar() && scrollRect.contains(pt)) {
        Scrollbar& scrollbar = *m_popupMenu.scrollbar();

        pt.move(-scrollRect.x(), -scrollRect.y());

        WebCore::ScrollbarPart part = scrollbar.theme().hitTest(scrollbar, pt);

        V_VT(pvChildAtPoint) = VT_I4;
        V_I4(pvChildAtPoint) = -part; // Scrollbar parts are encoded as negative, to avoid mixup with item indexes.
        return S_OK;
    }

    int index = m_popupMenu.listIndexAtPoint(pt);

    if (index < 0) {
        V_VT(pvChildAtPoint) = VT_EMPTY;
        return S_OK;
    }

    V_VT(pvChildAtPoint) = VT_I4;
    V_I4(pvChildAtPoint) = index + 1; // CHILDID_SELF is 0, need to add 1.

    return S_OK;
}

HRESULT AccessiblePopupMenu::accDoDefaultAction(VARIANT vChild)
{
    notImplemented();
    return E_NOTIMPL;
}

HRESULT AccessiblePopupMenu::put_accName(VARIANT, BSTR)
{
    notImplemented();
    return E_NOTIMPL;
}

HRESULT AccessiblePopupMenu::put_accValue(VARIANT, BSTR)
{
    notImplemented();
    return E_NOTIMPL;
}

HRESULT AccessiblePopupMenu::get_accHelpTopic(BSTR* helpFile, VARIANT, _Out_ long* topicID)
{
    notImplemented();
    return E_NOTIMPL;
}

}
