18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "config.h"
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "PlatformWheelEvent.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "FloatPoint.h"
300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "FloatSize.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <windows.h>
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <windowsx.h>
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define HIGH_BIT_MASK_SHORT 0x8000
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define SPI_GETWHEELSCROLLCHARS 0x006C
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic IntPoint positionForEvent(HWND hWnd, LPARAM lParam)
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    POINT point = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ScreenToClient(hWnd, &point);
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return point;
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic IntPoint globalPositionForEvent(HWND hWnd, LPARAM lParam)
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    POINT point = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return point;
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic int horizontalScrollChars()
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static ULONG scrollChars;
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!scrollChars && !SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &scrollChars, 0))
568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        scrollChars = 1;
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return scrollChars;
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic int verticalScrollLines()
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static ULONG scrollLines;
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!scrollLines && !SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &scrollLines, 0))
648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        scrollLines = 3;
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return scrollLines;
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochPlatformWheelEvent::PlatformWheelEvent(HWND hWnd, const FloatSize& delta, const FloatPoint& location)
690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    : m_isAccepted(false)
700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    , m_shiftKey(false)
710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    , m_ctrlKey(false)
720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    , m_altKey(false)
730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    , m_metaKey(false)
740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    m_deltaX = delta.width();
760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    m_deltaY = delta.height();
770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    m_wheelTicksX = m_deltaX;
790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    m_wheelTicksY = m_deltaY;
800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // Global Position is just x, y location of event
820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    POINT point = {location.x(), location.y()};
830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    m_globalPosition = point;
840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // Position needs to be translated to our client
860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ScreenToClient(hWnd, &point);
870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    m_position = point;
880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianPlatformWheelEvent::PlatformWheelEvent(HWND hWnd, WPARAM wParam, LPARAM lParam, bool isMouseHWheel)
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    : m_position(positionForEvent(hWnd, lParam))
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_globalPosition(globalPositionForEvent(hWnd, lParam))
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_isAccepted(false)
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_shiftKey(wParam & MK_SHIFT)
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_ctrlKey(wParam & MK_CONTROL)
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_altKey(GetKeyState(VK_MENU) & HIGH_BIT_MASK_SHORT)
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_metaKey(m_altKey) // FIXME: We'll have to test other browsers
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // How many pixels should we scroll per line?  Gecko uses the height of the
1008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // current line, which means scroll distance changes as you go through the
1018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // page or go to different pages.  IE 7 is ~50 px/line, although the value
1028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // seems to vary slightly by page and zoom level.  Since IE 7 has a
1038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // smoothing algorithm on scrolling, it can get away with slightly larger
1048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // scroll values without feeling jerky.  Here we use 100 px per three lines
1058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // (the default scroll amount on Windows is three lines per wheel tick).
1068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    static const float cScrollbarPixelsPerLine = 100.0f / 3.0f;
1078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    float delta = GET_WHEEL_DELTA_WPARAM(wParam) / static_cast<float>(WHEEL_DELTA);
1088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (isMouseHWheel) {
1098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // Windows is <-- -/+ -->, WebKit wants <-- +/- -->, so we negate
1108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // |delta| after saving the original value on the wheel tick member.
1118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_wheelTicksX = delta;
1128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_wheelTicksY = 0;
1138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        delta = -delta;
1148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    } else {
1158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // Even though we use shift + vertical wheel to scroll horizontally in
1168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // WebKit, we still note it as a vertical scroll on the wheel tick
1178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // member, so that the DOM event we later construct will match the real
1188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // hardware event better.
1198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_wheelTicksX = 0;
1208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_wheelTicksY = delta;
1218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
1228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (isMouseHWheel || m_shiftKey) {
1238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_deltaX = delta * static_cast<float>(horizontalScrollChars()) * cScrollbarPixelsPerLine;
1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_deltaY = 0;
1258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_granularity = ScrollByPixelWheelEvent;
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_deltaX = 0;
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_deltaY = delta;
1298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        int verticalMultiplier = verticalScrollLines();
1308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_granularity = (verticalMultiplier == WHEEL_PAGESCROLL) ? ScrollByPageWheelEvent : ScrollByPixelWheelEvent;
1318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (m_granularity == ScrollByPixelWheelEvent)
1328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            m_deltaY *= static_cast<float>(verticalMultiplier) * cScrollbarPixelsPerLine;
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
137