/*
 * 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, VerticalScrollbar, 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(VerticalScrollbar, index);
        return true;
    }

    if (index >= m_scrollOffset + visibleItems()) {
        ScrollableArea::scrollToOffsetWithoutAnimation(VerticalScrollbar, 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, ScrollByLine, 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;
}

}
