/*
 * Copyright (C) 2006, 2007 Apple Inc.
 *
 * 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 "PopupMenu.h"

#include "Document.h"
#include "FloatRect.h"
#include "FontSelector.h"
#include "Frame.h"
#include "FrameView.h"
#include "GraphicsContext.h"
#include "HTMLNames.h"
#include "Page.h"
#include "PlatformMouseEvent.h"
#include "PlatformScreen.h"
#include "PlatformScrollBar.h"
#include "RenderTheme.h"
#include "RenderView.h"
#include "SimpleFontData.h"
#include <tchar.h>
#include <windows.h>

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;

static const int popupWindowAlphaPercent = 95;

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

static LPCTSTR kPopupWindowClassName = _T("PopupWindowClass");
static ATOM registerPopup();
static LRESULT CALLBACK PopupWndProc(HWND, UINT, WPARAM, LPARAM);

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

PopupMenu::PopupMenu(PopupMenuClient* client)
    : m_popupClient(client)
    , m_scrollBar(0)
    , m_popup(0)
    , m_DC(0)
    , m_bmp(0)
    , m_wasClicked(false)
    , m_itemHeight(0)
    , m_scrollOffset(0)
    , m_wheelDelta(0)
    , m_focusedIndex(0)
    , m_scrollbarCapturingMouse(false)
{
}

PopupMenu::~PopupMenu()
{
    if (m_bmp)
        ::DeleteObject(m_bmp);
    if (m_DC)
        ::DeleteObject(m_DC);
    if (m_popup)
        ::DestroyWindow(m_popup);
}

void PopupMenu::show(const IntRect& r, FrameView* v, int index)
{
    calculatePositionAndSize(r, v);
    if (clientRect().isEmpty())
        return;

    if (!m_popup) {
        registerPopup();

        DWORD exStyle = WS_EX_LAYERED | WS_EX_LTRREADING;

        // Even though we already know our size and location at this point, we pass (0,0,0,0) as our size/location here.
        // We need to wait until after the call to ::SetWindowLongPtr to set our size so that in our WM_SIZE handler we can get access to the PopupMenu object
        m_popup = ::CreateWindowEx(exStyle, kPopupWindowClassName, _T("PopupMenu"),
            WS_POPUP | WS_BORDER,
            0, 0, 0, 0,
            v->containingWindow(), 0, 0, 0);

        if (!m_popup)
            return;

        ::SetWindowLongPtr(m_popup, 0, (LONG_PTR)this);
        ::SetLayeredWindowAttributes(m_popup, 0, (255 * popupWindowAlphaPercent) / 100, LWA_ALPHA);
    }

    if (!m_scrollBar)
        if (visibleItems() < client()->listSize()) {
            // We need a scroll bar
            m_scrollBar = new PlatformScrollbar(this, VerticalScrollbar, SmallScrollbar);
            m_scrollBar->setContainingWindow(m_popup);
        }

    ::SetWindowPos(m_popup, HWND_TOP, m_windowRect.x(), m_windowRect.y(), m_windowRect.width(), m_windowRect.height(), 0);

    // 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;
#ifdef CAN_ANIMATE_TRANSPARENT_WINDOWS_SMOOTHLY
    ::SystemParametersInfo(SPI_GETCOMBOBOXANIMATION, 0, &shouldAnimate, 0);
#endif

    if (shouldAnimate) {
        RECT viewRect = {0};
        ::GetWindowRect(v->containingWindow(), &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 + v->contentsToWindow(r.location()).y()) ? AW_VER_NEGATIVE : AW_VER_POSITIVE;

            ::AnimateWindow(m_popup, defaultAnimationDuration, AW_SLIDE | slideDirection | AW_ACTIVATE);
        }
    } else
        ::ShowWindow(m_popup, SW_SHOWNORMAL);
    ::SetCapture(m_popup);

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

void PopupMenu::hide()
{
    ::ShowWindow(m_popup, SW_HIDE);
}

const int endOfLinePadding = 2;
void PopupMenu::calculatePositionAndSize(const IntRect& r, FrameView* v)
{
    // 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());

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

    rScreenCoords.setLocation(location);

    // First, determine the popup's height
    int itemCount = client()->listSize();
    m_itemHeight = client()->clientStyle()->font().height() + optionSpacingMiddle;
    int naturalHeight = m_itemHeight * itemCount;
    int popupHeight = 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;

        popupWidth = max(popupWidth, client()->clientStyle()->font().width(TextRun(text.characters(), text.length())));
    }

    if (naturalHeight > maxPopupHeight)
        // We need room for a scrollbar
        popupWidth += PlatformScrollbar::verticalScrollbarWidth(SmallScrollbar);

    // Add padding to align the popup text with the <select> text
    // Note: We can't add paddingRight() because that value includes the width
    // of the dropdown button, so we must use our own endOfLinePadding constant.
    popupWidth += max(0, endOfLinePadding - client()->clientInsetRight()) + max(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 = 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.bottom(), popupWidth, popupHeight);

    // The popup needs to stay within the bounds of the screen and not overlap any toolbars
    FloatRect screen = screenAvailableRect(v);

    // Check that we don't go off the screen vertically
    if (popupRect.bottom() > 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() < screen.x()) {
        popupRect.setWidth(popupRect.width() - (screen.x() - popupRect.x()));
        popupRect.setX(screen.x());
    }
    m_windowRect = popupRect;
    return;
}

bool PopupMenu::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 PopupMenu::visibleItems() const
{
    return clientRect().height() / m_itemHeight;
}

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

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

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

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

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

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

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

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

bool PopupMenu::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 PopupMenu::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 PopupMenu::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->frameGeometry().width());

    RECT r = damageRect;
    ::InvalidateRect(m_popup, &r, TRUE);
}

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

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

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

    int index = focusedIndex();

    if (index < m_scrollOffset) {
        m_scrollBar->setValue(index);
        return true;
    }

    if (index >= m_scrollOffset + visibleItems()) {
        m_scrollBar->setValue(index - visibleItems() + 1);
        return true;
    }

    return false;
}

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

    m_focusedIndex = client()->selectedIndex();

    ::InvalidateRect(m_popup, 0, TRUE);
    if (!scrollToRevealSelection())
        ::UpdateWindow(m_popup);
}

bool PopupMenu::itemWritingDirectionIsNatural() 
{ 
    return true; 
}

const int separatorPadding = 4;
const int separatorHeight = 1;
void PopupMenu::paint(const IntRect& damageRect, HDC hdc)
{
    if (!m_popup)
        return;

    if (!m_DC) {
        m_DC = ::CreateCompatibleDC(::GetDC(m_popup));
        if (!m_DC)
            return;
    }

    if (m_bmp) {
        bool keepBitmap = false;
        BITMAP bitmap;
        if (GetObject(m_bmp, sizeof(bitmap), &bitmap))
            keepBitmap = bitmap.bmWidth == clientRect().width()
                && bitmap.bmHeight == clientRect().height();
        if (!keepBitmap) {
            DeleteObject(m_bmp);
            m_bmp = 0;
        }
    }
    if (!m_bmp) {
        BITMAPINFO bitmapInfo;
        bitmapInfo.bmiHeader.biSize          = sizeof(BITMAPINFOHEADER);
        bitmapInfo.bmiHeader.biWidth         = clientRect().width(); 
        bitmapInfo.bmiHeader.biHeight        = -clientRect().height();
        bitmapInfo.bmiHeader.biPlanes        = 1;
        bitmapInfo.bmiHeader.biBitCount      = 32;
        bitmapInfo.bmiHeader.biCompression   = BI_RGB;
        bitmapInfo.bmiHeader.biSizeImage     = 0;
        bitmapInfo.bmiHeader.biXPelsPerMeter = 0;
        bitmapInfo.bmiHeader.biYPelsPerMeter = 0;
        bitmapInfo.bmiHeader.biClrUsed       = 0;
        bitmapInfo.bmiHeader.biClrImportant  = 0;

        void* pixels = 0;
        m_bmp = ::CreateDIBSection(m_DC, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0);
        if (!m_bmp)
            return;

        ::SelectObject(m_DC, m_bmp);
    }

    GraphicsContext context(m_DC);

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

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

    RenderStyle* clientStyle = client()->clientStyle();

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

        Color optionBackgroundColor, optionTextColor;
        RenderStyle* itemStyle = client()->itemStyle(index);
        if (index == focusedIndex()) {
            optionBackgroundColor = theme()->activeListBoxSelectionBackgroundColor();
            optionTextColor = theme()->activeListBoxSelectionForegroundColor();
        } else {
            optionBackgroundColor = client()->itemBackgroundColor(index);
            optionTextColor = itemStyle->color();
        }

        // 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->visibility() != HIDDEN)
            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);
            
        unsigned length = itemText.length();
        const UChar* string = itemText.characters();
        TextRun textRun(string, length, false, 0, 0, itemText.defaultWritingDirection() == WTF::Unicode::RightToLeft);

        context.setFillColor(optionTextColor);
        
        Font itemFont = client()->clientStyle()->font();
        if (client()->itemIsLabel(index)) {
            FontDescription d = itemFont.fontDescription();
            d.setBold(true);
            itemFont = Font(d, itemFont.letterSpacing(), itemFont.wordSpacing());
            itemFont.update(m_popupClient->fontSelector());
        }
        context.setFont(itemFont);
        
        // Draw the item text
        if (itemStyle->visibility() != HIDDEN) {
            int textX = max(0, client()->clientPaddingLeft() - client()->clientInsetLeft());
            int textY = itemRect.y() + itemFont.ascent() + (itemRect.height() - itemFont.height()) / 2;
            context.drawBidiText(textRun, IntPoint(textX, textY));
        }
    }

    if (m_scrollBar)
        m_scrollBar->paint(&context, damageRect);

    if (!hdc)
        hdc = ::GetDC(m_popup);

    ::BitBlt(hdc, damageRect.x(), damageRect.y(), damageRect.width(), damageRect.height(), m_DC, damageRect.x(), damageRect.y(), SRCCOPY);
}

void PopupMenu::valueChanged(Scrollbar* scrollBar)
{
    ASSERT(m_scrollBar);

    if (!m_popup)
        return;

    int offset = scrollBar->value();

    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->frameGeometry().width());
    RECT r = listRect;
    ::ScrollWindowEx(m_popup, 0, scrolledLines * m_itemHeight, &r, 0, 0, 0, flags);
    if (m_scrollBar) {
        r = m_scrollBar->frameGeometry();
        ::InvalidateRect(m_popup, &r, TRUE);
    }
    ::UpdateWindow(m_popup);
}

IntRect PopupMenu::windowClipRect() const
{
    return m_windowRect;
}

static ATOM registerPopup()
{
    static bool haveRegisteredWindowClass = false;

    if (haveRegisteredWindowClass)
        return true;

    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

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

    haveRegisteredWindowClass = true;

    return ::RegisterClassEx(&wcex);
}

const int smoothScrollAnimationDuration = 5000;
static LRESULT CALLBACK PopupWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    LRESULT lResult = 0;
    LONG_PTR longPtr = GetWindowLongPtr(hWnd, 0);
    PopupMenu* popup = reinterpret_cast<PopupMenu*>(longPtr);

    switch (message) {
        case WM_SIZE:
            if (popup && popup->scrollBar()) {
                IntSize size(LOWORD(lParam), HIWORD(lParam));
                popup->scrollBar()->setRect(IntRect(size.width() - popup->scrollBar()->width(), 0, popup->scrollBar()->width(), size.height()));

                int visibleItems = popup->visibleItems();
                popup->scrollBar()->setEnabled(visibleItems < popup->client()->listSize());
                popup->scrollBar()->setSteps(1, max(1, visibleItems - 1));
                popup->scrollBar()->setProportion(visibleItems, popup->client()->listSize());
            }
            break;
        case WM_ACTIVATE:
            if (popup && popup->client() && wParam == WA_INACTIVE)
                popup->client()->hidePopup();
            break;
        case WM_KILLFOCUS:
            if (popup && popup->client() && (HWND)wParam != popup->popupHandle())
                // Focus is going elsewhere, so hide
                popup->client()->hidePopup();
            break;
        case WM_KEYDOWN:
            if (popup && popup->client()) {
                lResult = 0;
                switch (LOWORD(wParam)) {
                    case VK_DOWN:
                    case VK_RIGHT:
                        popup->down();
                        break;
                    case VK_UP:
                    case VK_LEFT:
                        popup->up();
                        break;
                    case VK_HOME:
                        popup->focusFirst();
                        break;
                    case VK_END:
                        popup->focusLast();
                        break;
                    case VK_PRIOR:
                        if (popup->focusedIndex() != popup->scrollOffset()) {
                            // Set the selection to the first visible item
                            int firstVisibleItem = popup->scrollOffset();
                            popup->up(popup->focusedIndex() - firstVisibleItem);
                        } else
                            // The first visible item is selected, so move the selection back one page
                            popup->up(popup->visibleItems());
                        break;
                    case VK_NEXT:
                        if (popup) {
                            int lastVisibleItem = popup->scrollOffset() + popup->visibleItems() - 1;
                            if (popup->focusedIndex() != lastVisibleItem) {
                                // Set the selection to the last visible item
                                popup->down(lastVisibleItem - popup->focusedIndex());
                            } else
                                // The last visible item is selected, so move the selection forward one page
                                popup->down(popup->visibleItems());
                        }
                        break;
                    case VK_TAB:
                        ::SendMessage(popup->client()->clientDocument()->view()->containingWindow(), message, wParam, lParam);
                        popup->client()->hidePopup();
                        break;
                    default:
                        if (isASCIIPrintable(wParam))
                            // Send the keydown to the WebView so it can be used for type-to-select.
                            ::PostMessage(popup->client()->clientDocument()->view()->containingWindow(), message, wParam, lParam);
                        else
                            lResult = 1;
                        break;
                }
            }
            break;
        case WM_CHAR:
            if (popup && popup->client()) {
                lResult = 0;
                int index;
                switch (wParam) {
                    case 0x0D:   // Enter/Return
                        popup->client()->hidePopup();
                        index = popup->focusedIndex();
                        ASSERT(index >= 0);
                        popup->client()->valueChanged(index);
                        break;
                    case 0x1B:   // Escape
                        popup->client()->hidePopup();
                        break;
                    case 0x09:   // TAB
                    case 0x08:   // Backspace
                    case 0x0A:   // Linefeed
                    default:     // Character
                        lResult = 1;
                        break;
                }
            }
            break;
        case WM_MOUSEMOVE:
            if (popup) {
                IntPoint mousePoint(MAKEPOINTS(lParam));
                if (popup->scrollBar()) {
                    IntRect scrollBarRect = popup->scrollBar()->frameGeometry();
                    if (popup->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, MAKELPARAM(mousePoint.x(), mousePoint.y()));
                        popup->scrollBar()->handleMouseMoveEvent(event);
                        break;
                    }
                }

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

                RECT bounds;
                GetClientRect(popup->popupHandle(), &bounds);
                if ((shouldHotTrack || wParam & MK_LBUTTON) && ::PtInRect(&bounds, mousePoint))
                    popup->setFocusedIndex(popup->listIndexAtPoint(mousePoint), true);

                // Release capture if the left button isn't down, and the mousePoint is outside the popup window.
                // This way, the WebView will get future mouse events in the rest of the window.
                if (!(wParam & MK_LBUTTON) && !::PtInRect(&bounds, mousePoint)) {
                    ::ReleaseCapture();
                    break;
                }
            }
            break;
        case WM_LBUTTONDOWN:
            if (popup) {
                ::SetCapture(popup->popupHandle());
                IntPoint mousePoint(MAKEPOINTS(lParam));
                if (popup->scrollBar()) {
                    IntRect scrollBarRect = popup->scrollBar()->frameGeometry();
                    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, MAKELPARAM(mousePoint.x(), mousePoint.y()));
                        popup->scrollBar()->handleMousePressEvent(event);
                        popup->setScrollbarCapturingMouse(true);
                        break;
                    }
                }

                popup->setFocusedIndex(popup->listIndexAtPoint(mousePoint), true);
            }
            break;
        case WM_LBUTTONUP:
            if (popup) {
                IntPoint mousePoint(MAKEPOINTS(lParam));
                if (popup->scrollBar()) {
                    ::ReleaseCapture();
                    IntRect scrollBarRect = popup->scrollBar()->frameGeometry();
                    if (popup->scrollbarCapturingMouse() || scrollBarRect.contains(mousePoint)) {
                        popup->setScrollbarCapturingMouse(false);
                        // Put the point into coordinates relative to the scroll bar
                        mousePoint.move(-scrollBarRect.x(), -scrollBarRect.y());
                        PlatformMouseEvent event(hWnd, message, wParam, MAKELPARAM(mousePoint.x(), mousePoint.y()));
                        popup->scrollBar()->handleMouseReleaseEvent(event);
                        // FIXME: This is a hack to work around PlatformScrollbar not invalidating correctly when it doesn't have a parent widget
                        RECT r = scrollBarRect;
                        ::InvalidateRect(popup->popupHandle(), &r, TRUE);
                        break;
                    }
                }
                // Only release capture and hide the popup if the mouse is inside the popup window.
                RECT bounds;
                GetClientRect(popup->popupHandle(), &bounds);
                if (popup->client() && ::PtInRect(&bounds, mousePoint)) {
                    ::ReleaseCapture();
                    popup->client()->hidePopup();
                    int index = popup->focusedIndex();
                    if (index >= 0)
                        popup->client()->valueChanged(index);
                }
            }
            break;
        case WM_MOUSEWHEEL:
            if (popup && popup->scrollBar()) {
                int i = 0;
                for (popup->incrementWheelDelta(GET_WHEEL_DELTA_WPARAM(wParam)); abs(popup->wheelDelta()) >= WHEEL_DELTA; popup->reduceWheelDelta(WHEEL_DELTA))
                    if (popup->wheelDelta() > 0)
                        ++i;
                    else
                        --i;

                popup->scrollBar()->scroll(i > 0 ? ScrollUp : ScrollDown, ScrollByLine, abs(i));
            }
            break;
        case WM_PAINT:
            if (popup) {
                PAINTSTRUCT paintInfo;
                ::BeginPaint(popup->popupHandle(), &paintInfo);
                popup->paint(paintInfo.rcPaint, paintInfo.hdc);
                ::EndPaint(popup->popupHandle(), &paintInfo);
                lResult = 0;
            }
            break;
        case WM_PRINTCLIENT:
            if (popup)
                popup->paint(popup->clientRect(), (HDC)wParam);
            break;
        default:
            lResult = DefWindowProc(hWnd, message, wParam, lParam);
    }

    return lResult;
}

}
