зеркало из https://github.com/mozilla/pjs.git
Bug 605648 Support high resolution scrolling on Windows r=jimm+smaug
This commit is contained in:
Родитель
00b9850cdd
Коммит
ab50ce059f
|
@ -1394,6 +1394,12 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
|||
handler.OnQueryDOMWidgetHittest(static_cast<nsQueryContentEvent*>(aEvent));
|
||||
}
|
||||
break;
|
||||
case NS_QUERY_SCROLL_TARGET_INFO:
|
||||
{
|
||||
DoQueryScrollTargetInfo(static_cast<nsQueryContentEvent*>(aEvent),
|
||||
aTargetFrame);
|
||||
break;
|
||||
}
|
||||
case NS_SELECTION_SET:
|
||||
{
|
||||
nsSelectionEvent *selectionEvent =
|
||||
|
@ -2564,7 +2570,8 @@ nsresult
|
|||
nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame,
|
||||
nsMouseScrollEvent* aMouseEvent,
|
||||
nsIScrollableFrame::ScrollUnit aScrollQuantity,
|
||||
PRBool aAllowScrollSpeedOverride)
|
||||
PRBool aAllowScrollSpeedOverride,
|
||||
nsQueryContentEvent* aQueryEvent)
|
||||
{
|
||||
nsIScrollableFrame* frameToScroll = nsnull;
|
||||
nsIFrame* scrollFrame = aTargetFrame;
|
||||
|
@ -2643,6 +2650,19 @@ nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame,
|
|||
}
|
||||
|
||||
if (!passToParent && frameToScroll) {
|
||||
if (aQueryEvent) {
|
||||
nscoord appUnitsPerDevPixel =
|
||||
aTargetFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
aQueryEvent->mReply.mLineHeight =
|
||||
frameToScroll->GetLineScrollAmount().height / appUnitsPerDevPixel;
|
||||
aQueryEvent->mReply.mPageHeight =
|
||||
frameToScroll->GetPageScrollAmount().height / appUnitsPerDevPixel;
|
||||
aQueryEvent->mReply.mPageWidth =
|
||||
frameToScroll->GetPageScrollAmount().width / appUnitsPerDevPixel;
|
||||
aQueryEvent->mSucceeded = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aScrollQuantity == nsIScrollableFrame::LINES) {
|
||||
numLines =
|
||||
nsMouseWheelTransaction::AccelerateWheelDelta(numLines, isHorizontal,
|
||||
|
@ -2670,7 +2690,9 @@ nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame,
|
|||
nsIScrollableFrame::ScrollMode mode;
|
||||
if (aMouseEvent->scrollFlags & nsMouseScrollEvent::kNoDefer) {
|
||||
mode = nsIScrollableFrame::INSTANT;
|
||||
} else if (aScrollQuantity != nsIScrollableFrame::DEVICE_PIXELS) {
|
||||
} else if (aScrollQuantity != nsIScrollableFrame::DEVICE_PIXELS ||
|
||||
(aMouseEvent->scrollFlags &
|
||||
nsMouseScrollEvent::kAllowSmoothScroll) != 0) {
|
||||
mode = nsIScrollableFrame::SMOOTH;
|
||||
} else {
|
||||
mode = nsIScrollableFrame::NORMAL;
|
||||
|
@ -2688,7 +2710,7 @@ nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame,
|
|||
aTargetFrame->PresContext()->FrameManager()->GetRootFrame());
|
||||
if (newFrame)
|
||||
return DoScrollText(newFrame, aMouseEvent, aScrollQuantity,
|
||||
aAllowScrollSpeedOverride);
|
||||
aAllowScrollSpeedOverride, aQueryEvent);
|
||||
}
|
||||
|
||||
aMouseEvent->scrollOverflow = numLines;
|
||||
|
@ -3051,7 +3073,7 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
|
|||
}
|
||||
|
||||
if (aEvent->message == NS_MOUSE_PIXEL_SCROLL) {
|
||||
if (action == MOUSE_SCROLL_N_LINES ||
|
||||
if (action == MOUSE_SCROLL_N_LINES || action == MOUSE_SCROLL_PAGE ||
|
||||
(msEvent->scrollFlags & nsMouseScrollEvent::kIsMomentum)) {
|
||||
action = MOUSE_SCROLL_PIXELS;
|
||||
} else {
|
||||
|
@ -3059,7 +3081,7 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
|
|||
action = -1;
|
||||
}
|
||||
} else if (msEvent->scrollFlags & nsMouseScrollEvent::kHasPixels) {
|
||||
if (action == MOUSE_SCROLL_N_LINES ||
|
||||
if (useSysNumLines || action == MOUSE_SCROLL_N_LINES ||
|
||||
(msEvent->scrollFlags & nsMouseScrollEvent::kIsMomentum)) {
|
||||
// Don't scroll lines when a pixel scroll event will follow.
|
||||
// Also, don't do history scrolling or zooming for momentum scrolls.
|
||||
|
@ -4646,6 +4668,20 @@ nsEventStateManager::DoContentCommandScrollEvent(nsContentCommandEvent* aEvent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsEventStateManager::DoQueryScrollTargetInfo(nsQueryContentEvent* aEvent,
|
||||
nsIFrame* aTargetFrame)
|
||||
{
|
||||
nsMouseScrollEvent* msEvent = aEvent->mInput.mMouseScrollEvent;
|
||||
nsIScrollableFrame::ScrollUnit unit;
|
||||
if (msEvent->scrollFlags & nsMouseScrollEvent::kIsFullPage) {
|
||||
unit = nsIScrollableFrame::PAGES;
|
||||
} else {
|
||||
unit = nsIScrollableFrame::LINES;
|
||||
}
|
||||
DoScrollText(aTargetFrame, msEvent, unit, PR_FALSE, aEvent);
|
||||
}
|
||||
|
||||
void
|
||||
nsEventStateManager::SetActiveManager(nsEventStateManager* aNewESM,
|
||||
nsIContent* aContent)
|
||||
|
|
|
@ -324,10 +324,19 @@ protected:
|
|||
nsMouseScrollEvent* aEvent,
|
||||
nsPresContext* aPresContext,
|
||||
nsEventStatus* aStatus);
|
||||
/**
|
||||
* @param aQueryEvent If you set vailid pointer for this, DoScrollText()
|
||||
* computes the line-height and page size of current
|
||||
* mouse wheel scroll target and sets it to the event.
|
||||
* And then, this method does NOT scroll any scrollable
|
||||
* elements. I.e., you can just query the scroll target
|
||||
* information.
|
||||
*/
|
||||
nsresult DoScrollText(nsIFrame* aTargetFrame,
|
||||
nsMouseScrollEvent* aMouseEvent,
|
||||
nsIScrollableFrame::ScrollUnit aScrollQuantity,
|
||||
PRBool aAllowScrollSpeedOverride);
|
||||
PRBool aAllowScrollSpeedOverride,
|
||||
nsQueryContentEvent* aQueryEvent = nsnull);
|
||||
void DoScrollHistory(PRInt32 direction);
|
||||
void DoScrollZoom(nsIFrame *aTargetFrame, PRInt32 adjustment);
|
||||
nsresult GetMarkupDocumentViewer(nsIMarkupDocumentViewer** aMv);
|
||||
|
@ -397,6 +406,9 @@ protected:
|
|||
nsresult DoContentCommandEvent(nsContentCommandEvent* aEvent);
|
||||
nsresult DoContentCommandScrollEvent(nsContentCommandEvent* aEvent);
|
||||
|
||||
void DoQueryScrollTargetInfo(nsQueryContentEvent* aEvent,
|
||||
nsIFrame* aTargetFrame);
|
||||
|
||||
PRBool RemoteQueryContentEvent(nsEvent *aEvent);
|
||||
mozilla::dom::TabParent *GetCrossProcessTarget();
|
||||
PRBool IsTargetCrossProcess(nsGUIEvent *aEvent);
|
||||
|
|
|
@ -415,6 +415,12 @@ class nsHashKey;
|
|||
// Query if the DOM element under nsEvent::refPoint belongs to our widget
|
||||
// or not.
|
||||
#define NS_QUERY_DOM_WIDGET_HITTEST (NS_QUERY_CONTENT_EVENT_START + 9)
|
||||
// Query for some information about mouse wheel event's target
|
||||
// XXX This is used only for supporting high resolution mouse scroll on Windows
|
||||
// and it's going to be reimplemented with another approach. At that time,
|
||||
// this even is going to be removed. Therefore, DON'T use this event for
|
||||
// other purpose.
|
||||
#define NS_QUERY_SCROLL_TARGET_INFO (NS_QUERY_CONTENT_EVENT_START + 99)
|
||||
|
||||
// Video events
|
||||
#ifdef MOZ_MEDIA
|
||||
|
@ -1188,9 +1194,11 @@ public:
|
|||
// as needed.
|
||||
kNoDefer = 1 << 5, // For scrollable views, indicates scroll should not
|
||||
// occur asynchronously.
|
||||
kIsMomentum = 1 << 6 // Marks scroll events that aren't controlled by the
|
||||
kIsMomentum = 1 << 6, // Marks scroll events that aren't controlled by the
|
||||
// user but fire automatically as the result of a
|
||||
// "momentum" scroll.
|
||||
kAllowSmoothScroll = 1 << 7 // Allow smooth scroll for the pixel scroll
|
||||
// event.
|
||||
};
|
||||
|
||||
nsMouseScrollEvent(PRBool isTrusted, PRUint32 msg, nsIWidget *w)
|
||||
|
@ -1285,6 +1293,13 @@ public:
|
|||
refPoint = aPoint;
|
||||
}
|
||||
|
||||
void InitForQueryScrollTargetInfo(nsMouseScrollEvent* aEvent)
|
||||
{
|
||||
NS_ASSERTION(message == NS_QUERY_SCROLL_TARGET_INFO,
|
||||
"wrong initializer is called");
|
||||
mInput.mMouseScrollEvent = aEvent;
|
||||
}
|
||||
|
||||
PRUint32 GetSelectionStart(void) const
|
||||
{
|
||||
NS_ASSERTION(message == NS_QUERY_SELECTED_TEXT,
|
||||
|
@ -1304,6 +1319,8 @@ public:
|
|||
struct {
|
||||
PRUint32 mOffset;
|
||||
PRUint32 mLength;
|
||||
// used by NS_QUERY_SCROLL_TARGET_INFO
|
||||
nsMouseScrollEvent* mMouseScrollEvent;
|
||||
} mInput;
|
||||
struct {
|
||||
void* mContentsRoot;
|
||||
|
@ -1317,6 +1334,10 @@ public:
|
|||
PRPackedBool mWidgetIsHit; // true if DOM element under mouse belongs to widget
|
||||
// used by NS_QUERY_SELECTION_AS_TRANSFERABLE
|
||||
nsCOMPtr<nsITransferable> mTransferable;
|
||||
// used by NS_QUERY_SCROLL_TARGET_INFO
|
||||
PRInt32 mLineHeight;
|
||||
PRInt32 mPageWidth;
|
||||
PRInt32 mPageHeight;
|
||||
} mReply;
|
||||
|
||||
enum {
|
||||
|
@ -1620,15 +1641,7 @@ enum nsDragDropEventStatus {
|
|||
((evnt)->message == NS_PLUGIN_FOCUS))
|
||||
|
||||
#define NS_IS_QUERY_CONTENT_EVENT(evnt) \
|
||||
(((evnt)->message == NS_QUERY_SELECTED_TEXT) || \
|
||||
((evnt)->message == NS_QUERY_TEXT_CONTENT) || \
|
||||
((evnt)->message == NS_QUERY_CARET_RECT) || \
|
||||
((evnt)->message == NS_QUERY_TEXT_RECT) || \
|
||||
((evnt)->message == NS_QUERY_EDITOR_RECT) || \
|
||||
((evnt)->message == NS_QUERY_CONTENT_STATE) || \
|
||||
((evnt)->message == NS_QUERY_SELECTION_AS_TRANSFERABLE) || \
|
||||
((evnt)->message == NS_QUERY_CHARACTER_AT_POINT) || \
|
||||
((evnt)->message == NS_QUERY_DOM_WIDGET_HITTEST))
|
||||
((evnt)->eventStructType == NS_QUERY_CONTENT_EVENT)
|
||||
|
||||
#define NS_IS_SELECTION_EVENT(evnt) \
|
||||
(((evnt)->message == NS_SELECTION_SET))
|
||||
|
@ -1670,7 +1683,8 @@ enum nsDragDropEventStatus {
|
|||
// cases, you should use NS_IS_IME_RELATED_EVENT instead.
|
||||
#define NS_IS_IME_RELATED_EVENT(evnt) \
|
||||
(NS_IS_IME_EVENT(evnt) || \
|
||||
NS_IS_QUERY_CONTENT_EVENT(evnt) || \
|
||||
(NS_IS_QUERY_CONTENT_EVENT(evnt) && \
|
||||
evnt->message != NS_QUERY_SCROLL_TARGET_INFO) || \
|
||||
NS_IS_SELECTION_EVENT(evnt))
|
||||
|
||||
/*
|
||||
|
|
|
@ -109,6 +109,50 @@ struct ParamTraits<nsInputEvent>
|
|||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<nsMouseEvent_base>
|
||||
{
|
||||
typedef nsMouseEvent_base paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, static_cast<nsInputEvent>(aParam));
|
||||
WriteParam(aMsg, aParam.button);
|
||||
WriteParam(aMsg, aParam.pressure);
|
||||
WriteParam(aMsg, aParam.inputSource);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
{
|
||||
return ReadParam(aMsg, aIter, static_cast<nsInputEvent*>(aResult)) &&
|
||||
ReadParam(aMsg, aIter, &aResult->button) &&
|
||||
ReadParam(aMsg, aIter, &aResult->pressure) &&
|
||||
ReadParam(aMsg, aIter, &aResult->inputSource);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<nsMouseScrollEvent>
|
||||
{
|
||||
typedef nsMouseScrollEvent paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, static_cast<nsMouseEvent_base>(aParam));
|
||||
WriteParam(aMsg, aParam.scrollFlags);
|
||||
WriteParam(aMsg, aParam.delta);
|
||||
WriteParam(aMsg, aParam.scrollOverflow);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
{
|
||||
return ReadParam(aMsg, aIter, static_cast<nsMouseEvent_base*>(aResult)) &&
|
||||
ReadParam(aMsg, aIter, &aResult->scrollFlags) &&
|
||||
ReadParam(aMsg, aIter, &aResult->delta) &&
|
||||
ReadParam(aMsg, aIter, &aResult->scrollOverflow);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<nsTextRangeStyle>
|
||||
{
|
||||
|
@ -235,12 +279,16 @@ struct ParamTraits<nsQueryContentEvent>
|
|||
WriteParam(aMsg, aParam.mSucceeded);
|
||||
WriteParam(aMsg, aParam.mInput.mOffset);
|
||||
WriteParam(aMsg, aParam.mInput.mLength);
|
||||
WriteParam(aMsg, *aParam.mInput.mMouseScrollEvent);
|
||||
WriteParam(aMsg, aParam.mReply.mOffset);
|
||||
WriteParam(aMsg, aParam.mReply.mString);
|
||||
WriteParam(aMsg, aParam.mReply.mRect);
|
||||
WriteParam(aMsg, aParam.mReply.mReversed);
|
||||
WriteParam(aMsg, aParam.mReply.mHasSelection);
|
||||
WriteParam(aMsg, aParam.mReply.mWidgetIsHit);
|
||||
WriteParam(aMsg, aParam.mReply.mLineHeight);
|
||||
WriteParam(aMsg, aParam.mReply.mPageHeight);
|
||||
WriteParam(aMsg, aParam.mReply.mPageWidth);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
|
@ -250,12 +298,16 @@ struct ParamTraits<nsQueryContentEvent>
|
|||
ReadParam(aMsg, aIter, &aResult->mSucceeded) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mInput.mOffset) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mInput.mLength) &&
|
||||
ReadParam(aMsg, aIter, aResult->mInput.mMouseScrollEvent) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mReply.mOffset) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mReply.mString) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mReply.mRect) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mReply.mReversed) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mReply.mHasSelection) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mReply.mWidgetIsHit);
|
||||
ReadParam(aMsg, aIter, &aResult->mReply.mWidgetIsHit) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mReply.mLineHeight) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mReply.mPageHeight) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mReply.mPageWidth);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -298,6 +298,18 @@ PRUint32 nsWindow::sOOPPPluginFocusEvent =
|
|||
|
||||
MSG nsWindow::sRedirectedKeyDown;
|
||||
|
||||
PRBool nsWindow::sNeedsToInitMouseWheelSettings = PR_TRUE;
|
||||
ULONG nsWindow::sMouseWheelScrollLines = 0;
|
||||
ULONG nsWindow::sMouseWheelScrollChars = 0;
|
||||
|
||||
HWND nsWindow::sLastMouseWheelWnd = NULL;
|
||||
PRInt32 nsWindow::sRemainingDeltaForScroll = 0;
|
||||
PRInt32 nsWindow::sRemainingDeltaForPixel = 0;
|
||||
PRBool nsWindow::sLastMouseWheelDeltaIsPositive = PR_FALSE;
|
||||
PRBool nsWindow::sLastMouseWheelOrientationIsVertical = PR_FALSE;
|
||||
PRBool nsWindow::sLastMouseWheelUnitIsPage = PR_FALSE;
|
||||
PRUint32 nsWindow::sLastMouseWheelTime = 0;
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* SECTION: globals variables
|
||||
|
@ -4524,8 +4536,6 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam,
|
|||
PRBool result = PR_FALSE; // call the default nsWindow proc
|
||||
*aRetValue = 0;
|
||||
|
||||
static PRBool getWheelInfo = PR_TRUE;
|
||||
|
||||
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
|
||||
// Glass hit testing w/custom transparent margins
|
||||
LRESULT dwmHitResult;
|
||||
|
@ -5187,7 +5197,12 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam,
|
|||
break;
|
||||
|
||||
case WM_SETTINGCHANGE:
|
||||
getWheelInfo = PR_TRUE;
|
||||
switch (wParam) {
|
||||
case SPI_SETWHEELSCROLLLINES:
|
||||
case SPI_SETWHEELSCROLLCHARS:
|
||||
sNeedsToInitMouseWheelSettings = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_INPUTLANGCHANGEREQUEST:
|
||||
|
@ -5259,8 +5274,9 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam,
|
|||
// If OnMouseWheel returns false, OnMouseWheel processed the event internally.
|
||||
// 'result' and 'aRetValue' will be set based on what we did with the event, so
|
||||
// we should fall through.
|
||||
if (OnMouseWheel(msg, wParam, lParam, getWheelInfo, result, aRetValue))
|
||||
if (OnMouseWheel(msg, wParam, lParam, result, aRetValue)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -6281,118 +6297,152 @@ PRUint16 nsWindow::GetMouseInputSource()
|
|||
return inputSource;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsWindow::InitMouseWheelScrollData()
|
||||
{
|
||||
if (!sNeedsToInitMouseWheelSettings) {
|
||||
return;
|
||||
}
|
||||
sNeedsToInitMouseWheelSettings = PR_FALSE;
|
||||
ResetRemainingWheelDelta();
|
||||
|
||||
if (!::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0,
|
||||
&sMouseWheelScrollLines, 0)) {
|
||||
NS_WARNING("Failed to get SPI_GETWHEELSCROLLLINES");
|
||||
sMouseWheelScrollLines = 3;
|
||||
} else if (sMouseWheelScrollLines > WHEEL_DELTA) {
|
||||
// sMouseWheelScrollLines usually equals 3 or 0 (for no scrolling)
|
||||
// However, if sMouseWheelScrollLines > WHEEL_DELTA, we assume that
|
||||
// the mouse driver wants a page scroll. The docs state that
|
||||
// sMouseWheelScrollLines should explicitly equal WHEEL_PAGESCROLL, but
|
||||
// since some mouse drivers use an arbitrary large number instead,
|
||||
// we have to handle that as well.
|
||||
sMouseWheelScrollLines = WHEEL_PAGESCROLL;
|
||||
}
|
||||
|
||||
if (!::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0,
|
||||
&sMouseWheelScrollChars, 0)) {
|
||||
NS_ASSERTION(!nsUXThemeData::sIsVistaOrLater,
|
||||
"Failed to get SPI_GETWHEELSCROLLCHARS");
|
||||
sMouseWheelScrollChars = 1;
|
||||
} else if (sMouseWheelScrollChars > WHEEL_DELTA) {
|
||||
// See the comments for the case sMouseWheelScrollLines > WHEEL_DELTA.
|
||||
sMouseWheelScrollChars = WHEEL_PAGESCROLL;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsWindow::ResetRemainingWheelDelta()
|
||||
{
|
||||
sRemainingDeltaForPixel = 0;
|
||||
sRemainingDeltaForScroll = 0;
|
||||
sLastMouseWheelWnd = NULL;
|
||||
}
|
||||
|
||||
static PRInt32 RoundDelta(double aDelta)
|
||||
{
|
||||
return aDelta >= 0 ? (PRInt32)NS_floor(aDelta) : (PRInt32)NS_ceil(aDelta);
|
||||
}
|
||||
|
||||
/*
|
||||
* OnMouseWheel - mouse wheel event processing. This was originally embedded
|
||||
* within the message case block. If returning true result should be returned
|
||||
* immediately (no more processing).
|
||||
*/
|
||||
PRBool nsWindow::OnMouseWheel(UINT msg, WPARAM wParam, LPARAM lParam, PRBool& getWheelInfo, PRBool& result, LRESULT *aRetValue)
|
||||
PRBool
|
||||
nsWindow::OnMouseWheel(UINT aMessage, WPARAM aWParam, LPARAM aLParam,
|
||||
PRBool& aHandled, LRESULT *aRetValue)
|
||||
{
|
||||
// Handle both flavors of mouse wheel events.
|
||||
static int iDeltaPerLine, iDeltaPerChar;
|
||||
static ULONG ulScrollLines, ulScrollChars = 1;
|
||||
static int currentVDelta, currentHDelta;
|
||||
static HWND currentWindow = 0;
|
||||
InitMouseWheelScrollData();
|
||||
|
||||
PRBool isVertical = msg == WM_MOUSEWHEEL;
|
||||
|
||||
// Get mouse wheel metrics (but only once).
|
||||
if (getWheelInfo) {
|
||||
getWheelInfo = PR_FALSE;
|
||||
|
||||
SystemParametersInfo (SPI_GETWHEELSCROLLLINES, 0, &ulScrollLines, 0);
|
||||
|
||||
// ulScrollLines usually equals 3 or 0 (for no scrolling)
|
||||
// WHEEL_DELTA equals 120, so iDeltaPerLine will be 40.
|
||||
|
||||
// However, if ulScrollLines > WHEEL_DELTA, we assume that
|
||||
// the mouse driver wants a page scroll. The docs state that
|
||||
// ulScrollLines should explicitly equal WHEEL_PAGESCROLL, but
|
||||
// since some mouse drivers use an arbitrary large number instead,
|
||||
// we have to handle that as well.
|
||||
|
||||
iDeltaPerLine = 0;
|
||||
if (ulScrollLines) {
|
||||
if (ulScrollLines <= WHEEL_DELTA) {
|
||||
iDeltaPerLine = WHEEL_DELTA / ulScrollLines;
|
||||
} else {
|
||||
ulScrollLines = WHEEL_PAGESCROLL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0,
|
||||
&ulScrollChars, 0)) {
|
||||
// Note that we may always fail to get the value before Win Vista.
|
||||
ulScrollChars = 1;
|
||||
}
|
||||
|
||||
iDeltaPerChar = 0;
|
||||
if (ulScrollChars) {
|
||||
if (ulScrollChars <= WHEEL_DELTA) {
|
||||
iDeltaPerChar = WHEEL_DELTA / ulScrollChars;
|
||||
} else {
|
||||
ulScrollChars = WHEEL_PAGESCROLL;
|
||||
}
|
||||
}
|
||||
PRBool isVertical = (aMessage == WM_MOUSEWHEEL);
|
||||
if ((isVertical && sMouseWheelScrollLines == 0) ||
|
||||
(!isVertical && sMouseWheelScrollChars == 0)) {
|
||||
// XXX I think that we should dispatch mouse wheel events even if the
|
||||
// operation will not scroll because the wheel operation really happened
|
||||
// and web application may want to handle the event for non-scroll action.
|
||||
ResetRemainingWheelDelta();
|
||||
*aRetValue = isVertical ? TRUE : FALSE; // means we don't process it
|
||||
aHandled = PR_FALSE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if ((isVertical && ulScrollLines != WHEEL_PAGESCROLL && !iDeltaPerLine) ||
|
||||
(!isVertical && ulScrollChars != WHEEL_PAGESCROLL && !iDeltaPerChar))
|
||||
return PR_FALSE; // break
|
||||
|
||||
// The mousewheel event will be dispatched to the toplevel
|
||||
// window. We need to give it to the child window.
|
||||
PRBool quit;
|
||||
if (!HandleScrollingPlugins(msg, wParam, lParam, result, aRetValue, quit))
|
||||
if (!HandleScrollingPlugins(aMessage, aWParam, aLParam,
|
||||
aHandled, aRetValue, quit)) {
|
||||
ResetRemainingWheelDelta();
|
||||
return quit; // return immediately if it's not our window
|
||||
}
|
||||
|
||||
// We should cancel the surplus delta if the current window is not
|
||||
// same as previous.
|
||||
if (currentWindow != mWnd) {
|
||||
currentVDelta = 0;
|
||||
currentHDelta = 0;
|
||||
currentWindow = mWnd;
|
||||
}
|
||||
|
||||
nsMouseScrollEvent scrollEvent(PR_TRUE, NS_MOUSE_SCROLL, this);
|
||||
scrollEvent.delta = 0;
|
||||
if (isVertical) {
|
||||
scrollEvent.scrollFlags = nsMouseScrollEvent::kIsVertical;
|
||||
if (ulScrollLines == WHEEL_PAGESCROLL) {
|
||||
scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsFullPage;
|
||||
scrollEvent.delta = (((short) HIWORD (wParam)) > 0) ? -1 : 1;
|
||||
} else {
|
||||
currentVDelta -= (short) HIWORD (wParam);
|
||||
if (PR_ABS(currentVDelta) >= iDeltaPerLine) {
|
||||
scrollEvent.delta = currentVDelta / iDeltaPerLine;
|
||||
currentVDelta %= iDeltaPerLine;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
scrollEvent.scrollFlags = nsMouseScrollEvent::kIsHorizontal;
|
||||
if (ulScrollChars == WHEEL_PAGESCROLL) {
|
||||
scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsFullPage;
|
||||
scrollEvent.delta = (((short) HIWORD (wParam)) > 0) ? 1 : -1;
|
||||
} else {
|
||||
currentHDelta += (short) HIWORD (wParam);
|
||||
if (PR_ABS(currentHDelta) >= iDeltaPerChar) {
|
||||
scrollEvent.delta = currentHDelta / iDeltaPerChar;
|
||||
currentHDelta %= iDeltaPerChar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!scrollEvent.delta) {
|
||||
// We store the wheel delta, and it will be used next wheel message, so,
|
||||
// we consume this message actually. We shouldn't call next wndproc.
|
||||
result = PR_TRUE;
|
||||
return PR_FALSE; // break
|
||||
PRInt32 nativeDelta = (short)HIWORD(aWParam);
|
||||
if (!nativeDelta) {
|
||||
*aRetValue = isVertical ? TRUE : FALSE; // means we don't process it
|
||||
aHandled = PR_FALSE;
|
||||
ResetRemainingWheelDelta();
|
||||
return PR_FALSE; // We cannot process this message
|
||||
}
|
||||
|
||||
// The event may go to a plug-in which already dispatched this message.
|
||||
// Then, the event can cause deadlock. We should unlock the sender here.
|
||||
::ReplyMessage(isVertical ? 0 : TRUE);
|
||||
|
||||
PRBool isPageScroll =
|
||||
((isVertical && sMouseWheelScrollLines == WHEEL_PAGESCROLL) ||
|
||||
(!isVertical && sMouseWheelScrollChars == WHEEL_PAGESCROLL));
|
||||
|
||||
// Discard the remaining delta if current wheel message and last one are
|
||||
// received by different window or to scroll different direction or
|
||||
// different unit scroll. Furthermore, if the last event was too old.
|
||||
PRUint32 now = PR_IntervalToMilliseconds(PR_IntervalNow());
|
||||
if (sLastMouseWheelWnd &&
|
||||
(sLastMouseWheelWnd != mWnd ||
|
||||
sLastMouseWheelDeltaIsPositive != (nativeDelta > 0) ||
|
||||
sLastMouseWheelOrientationIsVertical != isVertical ||
|
||||
sLastMouseWheelUnitIsPage != isPageScroll ||
|
||||
now - sLastMouseWheelTime > 1500)) {
|
||||
ResetRemainingWheelDelta();
|
||||
}
|
||||
sLastMouseWheelWnd = mWnd;
|
||||
sLastMouseWheelDeltaIsPositive = (nativeDelta > 0);
|
||||
sLastMouseWheelOrientationIsVertical = isVertical;
|
||||
sLastMouseWheelUnitIsPage = isPageScroll;
|
||||
sLastMouseWheelTime = now;
|
||||
|
||||
nsMouseScrollEvent testEvent(PR_TRUE, NS_MOUSE_SCROLL, this);
|
||||
InitEvent(testEvent);
|
||||
testEvent.scrollFlags = isPageScroll ? nsMouseScrollEvent::kIsFullPage : 0;
|
||||
testEvent.scrollFlags |= isVertical ? nsMouseScrollEvent::kIsVertical :
|
||||
nsMouseScrollEvent::kIsHorizontal;
|
||||
testEvent.delta = sLastMouseWheelDeltaIsPositive ? -1 : 1;
|
||||
nsQueryContentEvent queryEvent(PR_TRUE, NS_QUERY_SCROLL_TARGET_INFO, this);
|
||||
InitEvent(queryEvent);
|
||||
queryEvent.InitForQueryScrollTargetInfo(&testEvent);
|
||||
DispatchWindowEvent(&queryEvent);
|
||||
// If the necessary interger isn't larger than 0, we should assume that
|
||||
// the event failed for us.
|
||||
if (queryEvent.mSucceeded) {
|
||||
if (isPageScroll) {
|
||||
if (isVertical) {
|
||||
queryEvent.mSucceeded = (queryEvent.mReply.mPageHeight > 0);
|
||||
} else {
|
||||
queryEvent.mSucceeded = (queryEvent.mReply.mPageWidth > 0);
|
||||
}
|
||||
} else {
|
||||
queryEvent.mSucceeded = (queryEvent.mReply.mLineHeight > 0);
|
||||
}
|
||||
}
|
||||
|
||||
*aRetValue = isVertical ? FALSE : TRUE; // means we process this message
|
||||
nsModifierKeyState modKeyState;
|
||||
|
||||
// Our positive delta value means to bottom or right.
|
||||
// But positive nativeDelta value means to top or right.
|
||||
// Use orienter for computing our delta value.
|
||||
PRInt32 orienter = isVertical ? -1 : 1;
|
||||
|
||||
// Assume the Control key is down if the Elantech touchpad has sent the
|
||||
// mis-ordered WM_KEYDOWN/WM_MOUSEWHEEL messages. (See the comment in
|
||||
// OnKeyUp.)
|
||||
|
@ -6401,25 +6451,97 @@ PRBool nsWindow::OnMouseWheel(UINT msg, WPARAM wParam, LPARAM lParam, PRBool& ge
|
|||
static_cast<DWORD>(::GetMessageTime()) < mAssumeWheelIsZoomUntil) {
|
||||
isControl = PR_TRUE;
|
||||
} else {
|
||||
isControl = IS_VK_DOWN(NS_VK_CONTROL);
|
||||
isControl = modKeyState.mIsControlDown;
|
||||
}
|
||||
|
||||
scrollEvent.isShift = IS_VK_DOWN(NS_VK_SHIFT);
|
||||
scrollEvent.isControl = isControl;
|
||||
scrollEvent.isMeta = PR_FALSE;
|
||||
scrollEvent.isAlt = IS_VK_DOWN(NS_VK_ALT);
|
||||
nsMouseScrollEvent scrollEvent(PR_TRUE, NS_MOUSE_SCROLL, this);
|
||||
InitEvent(scrollEvent);
|
||||
if (nsnull != mEventCallback) {
|
||||
result = DispatchWindowEvent(&scrollEvent);
|
||||
}
|
||||
// Note that we should return zero if we process WM_MOUSEWHEEL.
|
||||
// But if we process WM_MOUSEHWHEEL, we should return non-zero.
|
||||
// If the query event failed, we cannot send pixel events.
|
||||
scrollEvent.scrollFlags =
|
||||
queryEvent.mSucceeded ? nsMouseScrollEvent::kHasPixels : 0;
|
||||
scrollEvent.isShift = modKeyState.mIsShiftDown;
|
||||
scrollEvent.isControl = isControl;
|
||||
scrollEvent.isMeta = PR_FALSE;
|
||||
scrollEvent.isAlt = modKeyState.mIsAltDown;
|
||||
|
||||
if (result)
|
||||
*aRetValue = isVertical ? 0 : TRUE;
|
||||
|
||||
return PR_FALSE; // break;
|
||||
}
|
||||
PRInt32 nativeDeltaForScroll = nativeDelta + sRemainingDeltaForScroll;
|
||||
|
||||
if (isPageScroll) {
|
||||
scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsFullPage;
|
||||
if (isVertical) {
|
||||
scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsVertical;
|
||||
} else {
|
||||
scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsHorizontal;
|
||||
}
|
||||
scrollEvent.delta = nativeDeltaForScroll * orienter / WHEEL_DELTA;
|
||||
PRInt32 recomputedNativeDelta = scrollEvent.delta * orienter / WHEEL_DELTA;
|
||||
sRemainingDeltaForScroll = nativeDeltaForScroll - recomputedNativeDelta;
|
||||
} else {
|
||||
double deltaPerUnit;
|
||||
if (isVertical) {
|
||||
scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsVertical;
|
||||
deltaPerUnit = (double)WHEEL_DELTA / sMouseWheelScrollLines;
|
||||
} else {
|
||||
scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsHorizontal;
|
||||
deltaPerUnit = (double)WHEEL_DELTA / sMouseWheelScrollChars;
|
||||
}
|
||||
scrollEvent.delta =
|
||||
RoundDelta((double)nativeDeltaForScroll * orienter / deltaPerUnit);
|
||||
PRInt32 recomputedNativeDelta =
|
||||
(PRInt32)(scrollEvent.delta * orienter * deltaPerUnit);
|
||||
sRemainingDeltaForScroll = nativeDeltaForScroll - recomputedNativeDelta;
|
||||
}
|
||||
|
||||
if (scrollEvent.delta) {
|
||||
aHandled = DispatchWindowEvent(&scrollEvent);
|
||||
if (mOnDestroyCalled) {
|
||||
ResetRemainingWheelDelta();
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// If the query event failed, we cannot send pixel events.
|
||||
if (!queryEvent.mSucceeded) {
|
||||
sRemainingDeltaForPixel = 0;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsMouseScrollEvent pixelEvent(PR_TRUE, NS_MOUSE_PIXEL_SCROLL, this);
|
||||
InitEvent(pixelEvent);
|
||||
pixelEvent.scrollFlags = nsMouseScrollEvent::kAllowSmoothScroll |
|
||||
(scrollEvent.scrollFlags & ~nsMouseScrollEvent::kHasPixels);
|
||||
pixelEvent.isShift = modKeyState.mIsShiftDown;
|
||||
pixelEvent.isControl = modKeyState.mIsControlDown;
|
||||
pixelEvent.isMeta = PR_FALSE;
|
||||
pixelEvent.isAlt = modKeyState.mIsAltDown;
|
||||
|
||||
PRInt32 nativeDeltaForPixel = nativeDelta + sRemainingDeltaForPixel;
|
||||
|
||||
double deltaPerPixel;
|
||||
if (isPageScroll) {
|
||||
if (isVertical) {
|
||||
deltaPerPixel = (double)WHEEL_DELTA / queryEvent.mReply.mPageHeight;
|
||||
} else {
|
||||
deltaPerPixel = (double)WHEEL_DELTA / queryEvent.mReply.mPageWidth;
|
||||
}
|
||||
} else {
|
||||
if (isVertical) {
|
||||
deltaPerPixel = (double)WHEEL_DELTA / sMouseWheelScrollLines;
|
||||
} else {
|
||||
deltaPerPixel = (double)WHEEL_DELTA / sMouseWheelScrollChars;
|
||||
}
|
||||
deltaPerPixel /= queryEvent.mReply.mLineHeight;
|
||||
}
|
||||
pixelEvent.delta =
|
||||
RoundDelta((double)nativeDeltaForPixel * orienter / deltaPerPixel);
|
||||
PRInt32 recomputedNativeDelta =
|
||||
(PRInt32)(pixelEvent.delta * orienter * deltaPerPixel);
|
||||
sRemainingDeltaForPixel = nativeDeltaForPixel - recomputedNativeDelta;
|
||||
if (pixelEvent.delta != 0) {
|
||||
aHandled = DispatchWindowEvent(&pixelEvent);
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
StringCaseInsensitiveEquals(const PRUnichar* aChars1, const PRUint32 aNumChars1,
|
||||
|
|
|
@ -411,8 +411,8 @@ protected:
|
|||
BOOL OnInputLangChange(HKL aHKL);
|
||||
PRBool OnPaint(HDC aDC, PRUint32 aNestingLevel);
|
||||
void OnWindowPosChanged(WINDOWPOS *wp, PRBool& aResult);
|
||||
PRBool OnMouseWheel(UINT msg, WPARAM wParam, LPARAM lParam,
|
||||
PRBool& result, PRBool& getWheelInfo,
|
||||
PRBool OnMouseWheel(UINT aMessage, WPARAM aWParam,
|
||||
LPARAM aLParam, PRBool& aHandled,
|
||||
LRESULT *aRetValue);
|
||||
void OnWindowPosChanging(LPWINDOWPOS& info);
|
||||
|
||||
|
@ -616,6 +616,20 @@ protected:
|
|||
// was reirected to SendInput() API by OnKeyDown().
|
||||
static MSG sRedirectedKeyDown;
|
||||
|
||||
static PRBool sNeedsToInitMouseWheelSettings;
|
||||
static ULONG sMouseWheelScrollLines;
|
||||
static ULONG sMouseWheelScrollChars;
|
||||
static void InitMouseWheelScrollData();
|
||||
|
||||
static HWND sLastMouseWheelWnd;
|
||||
static PRInt32 sRemainingDeltaForScroll;
|
||||
static PRInt32 sRemainingDeltaForPixel;
|
||||
static PRBool sLastMouseWheelDeltaIsPositive;
|
||||
static PRBool sLastMouseWheelOrientationIsVertical;
|
||||
static PRBool sLastMouseWheelUnitIsPage;
|
||||
static PRUint32 sLastMouseWheelTime; // in milliseconds
|
||||
static void ResetRemainingWheelDelta();
|
||||
|
||||
// If a window receives WM_KEYDOWN message or WM_SYSKEYDOWM message which is
|
||||
// redirected message, OnKeyDowm() prevents to dispatch NS_KEY_DOWN event
|
||||
// because it has been dispatched before the message was redirected.
|
||||
|
@ -649,7 +663,6 @@ protected:
|
|||
nsRefPtr<nsWindow> mWindow;
|
||||
const MSG &mMsg;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -90,6 +90,10 @@
|
|||
#define SPI_GETWHEELSCROLLCHARS 0x006C
|
||||
#endif
|
||||
|
||||
#ifndef SPI_SETWHEELSCROLLCHARS
|
||||
#define SPI_SETWHEELSCROLLCHARS 0x006D
|
||||
#endif
|
||||
|
||||
#ifndef MAPVK_VSC_TO_VK
|
||||
#define MAPVK_VK_TO_VSC 0
|
||||
#define MAPVK_VSC_TO_VK 1
|
||||
|
|
Загрузка…
Ссылка в новой задаче