mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-05-13 08:57:27 +00:00
Bug 485101 - Implement panning feedback for touch enabled displays with win7. r+sr=smaug r=blassey.
This commit is contained in:
parent
1df3c7cf23
commit
b7f1e1335d
@ -2879,13 +2879,14 @@ nsEventStateManager::SendPixelScrollEvent(nsIFrame* aTargetFrame,
|
||||
nsresult
|
||||
nsEventStateManager::DoScrollText(nsPresContext* aPresContext,
|
||||
nsIFrame* aTargetFrame,
|
||||
nsInputEvent* aEvent,
|
||||
PRInt32 aNumLines,
|
||||
PRBool aScrollHorizontal,
|
||||
nsMouseScrollEvent* aMouseEvent,
|
||||
ScrollQuantity aScrollQuantity)
|
||||
{
|
||||
nsIScrollableView* scrollView = nsnull;
|
||||
nsIFrame* scrollFrame = aTargetFrame;
|
||||
PRInt32 numLines = aMouseEvent->delta;
|
||||
PRBool isHorizontal = aMouseEvent->scrollFlags & nsMouseScrollEvent::kIsHorizontal;
|
||||
aMouseEvent->scrollOverflow = 0;
|
||||
|
||||
// If the user recently scrolled with the mousewheel, then they probably want
|
||||
// to scroll the same view as before instead of the view under the cursor.
|
||||
@ -2899,7 +2900,7 @@ nsEventStateManager::DoScrollText(nsPresContext* aPresContext,
|
||||
if (lastScrollFrame) {
|
||||
nsIScrollableViewProvider* svp = do_QueryFrame(lastScrollFrame);
|
||||
if (svp && (scrollView = svp->GetScrollableView())) {
|
||||
nsMouseWheelTransaction::UpdateTransaction(aNumLines, aScrollHorizontal);
|
||||
nsMouseWheelTransaction::UpdateTransaction(numLines, isHorizontal);
|
||||
// When the scroll event will not scroll any views, UpdateTransaction
|
||||
// fired MozMouseScrollFailed event which is for automated testing.
|
||||
// In the event handler, the target frame might be destroyed. Then,
|
||||
@ -2928,7 +2929,7 @@ nsEventStateManager::DoScrollText(nsPresContext* aPresContext,
|
||||
nsPresContext::ScrollbarStyles ss =
|
||||
nsLayoutUtils::ScrollbarStylesOfView(scrollView);
|
||||
if (NS_STYLE_OVERFLOW_HIDDEN ==
|
||||
(aScrollHorizontal ? ss.mHorizontal : ss.mVertical)) {
|
||||
(isHorizontal ? ss.mHorizontal : ss.mVertical)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -2937,10 +2938,10 @@ nsEventStateManager::DoScrollText(nsPresContext* aPresContext,
|
||||
scrollView->GetLineHeight(&lineHeight);
|
||||
|
||||
if (lineHeight != 0) {
|
||||
if (CanScrollOn(scrollView, aNumLines, aScrollHorizontal)) {
|
||||
if (CanScrollOn(scrollView, numLines, isHorizontal)) {
|
||||
passToParent = PR_FALSE;
|
||||
nsMouseWheelTransaction::BeginTransaction(scrollFrame,
|
||||
aNumLines, aScrollHorizontal);
|
||||
numLines, isHorizontal);
|
||||
}
|
||||
|
||||
// Comboboxes need special care.
|
||||
@ -2973,13 +2974,13 @@ nsEventStateManager::DoScrollText(nsPresContext* aPresContext,
|
||||
if (lineHeight) {
|
||||
nsSize pageScrollDistances(0, 0);
|
||||
scrollView->GetPageScrollDistances(&pageScrollDistances);
|
||||
nscoord pageScroll = aScrollHorizontal ?
|
||||
nscoord pageScroll = isHorizontal ?
|
||||
pageScrollDistances.width : pageScrollDistances.height;
|
||||
|
||||
if (PR_ABS(aNumLines) * lineHeight > pageScroll) {
|
||||
if (PR_ABS(numLines) * lineHeight > pageScroll) {
|
||||
nscoord maxLines = (pageScroll / lineHeight);
|
||||
if (maxLines >= 1) {
|
||||
aNumLines = ((aNumLines < 0) ? -1 : 1) * maxLines;
|
||||
numLines = ((numLines < 0) ? -1 : 1) * maxLines;
|
||||
} else {
|
||||
aScrollQuantity = eScrollByPage;
|
||||
}
|
||||
@ -2988,34 +2989,52 @@ nsEventStateManager::DoScrollText(nsPresContext* aPresContext,
|
||||
}
|
||||
|
||||
PRInt32 scrollX = 0;
|
||||
PRInt32 scrollY = aNumLines;
|
||||
PRInt32 scrollY = numLines;
|
||||
|
||||
if (aScrollQuantity == eScrollByPage)
|
||||
scrollY = (scrollY > 0) ? 1 : -1;
|
||||
|
||||
if (aScrollHorizontal) {
|
||||
if (isHorizontal) {
|
||||
scrollX = scrollY;
|
||||
scrollY = 0;
|
||||
}
|
||||
|
||||
if (aScrollQuantity == eScrollByPage)
|
||||
scrollView->ScrollByPages(scrollX, scrollY, NS_VMREFRESH_SMOOTHSCROLL);
|
||||
else if (aScrollQuantity == eScrollByPixel)
|
||||
scrollView->ScrollByPixels(scrollX, scrollY, NS_VMREFRESH_DEFERRED);
|
||||
PRBool noDefer = aMouseEvent->scrollFlags & nsMouseScrollEvent::kNoDefer;
|
||||
PRInt32 overflowX = 0, overflowY = 0;
|
||||
|
||||
if (aScrollQuantity == eScrollByPage) {
|
||||
scrollView->ScrollByPages(scrollX, scrollY,
|
||||
(noDefer ? NS_VMREFRESH_IMMEDIATE : NS_VMREFRESH_SMOOTHSCROLL));
|
||||
}
|
||||
else if (aScrollQuantity == eScrollByPixel) {
|
||||
scrollView->ScrollByPixels(scrollX, scrollY, overflowX, overflowY,
|
||||
(noDefer ? NS_VMREFRESH_IMMEDIATE : NS_VMREFRESH_DEFERRED));
|
||||
}
|
||||
else {
|
||||
scrollView->ScrollByLinesWithOverflow(scrollX, scrollY, overflowX, overflowY,
|
||||
(noDefer ? NS_VMREFRESH_IMMEDIATE : NS_VMREFRESH_SMOOTHSCROLL));
|
||||
}
|
||||
|
||||
if (isHorizontal)
|
||||
aMouseEvent->scrollOverflow = overflowX;
|
||||
else
|
||||
scrollView->ScrollByLines(scrollX, scrollY, NS_VMREFRESH_SMOOTHSCROLL);
|
||||
aMouseEvent->scrollOverflow = overflowY;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (passToParent) {
|
||||
nsresult rv;
|
||||
nsIFrame* newFrame = nsnull;
|
||||
nsCOMPtr<nsPresContext> newPresContext;
|
||||
rv = GetParentScrollingView(aEvent, aPresContext, newFrame,
|
||||
rv = GetParentScrollingView(aMouseEvent, aPresContext, newFrame,
|
||||
*getter_AddRefs(newPresContext));
|
||||
if (NS_SUCCEEDED(rv) && newFrame)
|
||||
return DoScrollText(newPresContext, newFrame, aEvent, aNumLines,
|
||||
aScrollHorizontal, aScrollQuantity);
|
||||
return DoScrollText(newPresContext, newFrame, aMouseEvent, aScrollQuantity);
|
||||
}
|
||||
|
||||
aMouseEvent->scrollOverflow = numLines;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -3275,39 +3294,23 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
|
||||
|
||||
switch (action) {
|
||||
case MOUSE_SCROLL_N_LINES:
|
||||
{
|
||||
DoScrollText(presContext, aTargetFrame, msEvent, msEvent->delta,
|
||||
!!(msEvent->scrollFlags & nsMouseScrollEvent::kIsHorizontal),
|
||||
eScrollByLine);
|
||||
}
|
||||
DoScrollText(presContext, aTargetFrame, msEvent, eScrollByLine);
|
||||
break;
|
||||
|
||||
case MOUSE_SCROLL_PAGE:
|
||||
{
|
||||
DoScrollText(presContext, aTargetFrame, msEvent, msEvent->delta,
|
||||
!!(msEvent->scrollFlags & nsMouseScrollEvent::kIsHorizontal),
|
||||
eScrollByPage);
|
||||
}
|
||||
DoScrollText(presContext, aTargetFrame, msEvent, eScrollByPage);
|
||||
break;
|
||||
|
||||
case MOUSE_SCROLL_PIXELS:
|
||||
{
|
||||
DoScrollText(presContext, aTargetFrame, msEvent, msEvent->delta,
|
||||
!!(msEvent->scrollFlags & nsMouseScrollEvent::kIsHorizontal),
|
||||
eScrollByPixel);
|
||||
}
|
||||
DoScrollText(presContext, aTargetFrame, msEvent, eScrollByPixel);
|
||||
break;
|
||||
|
||||
case MOUSE_SCROLL_HISTORY:
|
||||
{
|
||||
DoScrollHistory(msEvent->delta);
|
||||
}
|
||||
DoScrollHistory(msEvent->delta);
|
||||
break;
|
||||
|
||||
case MOUSE_SCROLL_ZOOM:
|
||||
{
|
||||
DoScrollZoom(aTargetFrame, msEvent->delta);
|
||||
}
|
||||
DoScrollZoom(aTargetFrame, msEvent->delta);
|
||||
break;
|
||||
|
||||
default: // Including -1 (do nothing)
|
||||
|
@ -312,9 +312,7 @@ protected:
|
||||
} ScrollQuantity;
|
||||
nsresult DoScrollText(nsPresContext* aPresContext,
|
||||
nsIFrame* aTargetFrame,
|
||||
nsInputEvent* aEvent,
|
||||
PRInt32 aNumLines,
|
||||
PRBool aScrollHorizontal,
|
||||
nsMouseScrollEvent* aMouseEvent,
|
||||
ScrollQuantity aScrollQuantity);
|
||||
void DoScrollHistory(PRInt32 direction);
|
||||
void DoScrollZoom(nsIFrame *aTargetFrame, PRInt32 adjustment);
|
||||
|
@ -147,6 +147,20 @@ public:
|
||||
*/
|
||||
NS_IMETHOD ScrollByLines(PRInt32 aNumLinesX, PRInt32 aNumLinexY,
|
||||
PRUint32 aUpdateFlags = 0) = 0;
|
||||
/**
|
||||
* Identical to ScrollByLines while also returning overscroll values.
|
||||
* @param aNumLinesX number of lines to scroll the view horizontally
|
||||
* @param aNumLinesY number of lines to scroll the view vertically
|
||||
* @param aOverflowX returns the number of pixels that could not
|
||||
* be scrolled due to scroll bounds.
|
||||
* @param aOverflowY returns the number of pixels that could not
|
||||
* be scrolled due to scroll bounds.
|
||||
* @param aUpdateFlags indicate smooth or async scrolling
|
||||
* @return error status
|
||||
*/
|
||||
NS_IMETHOD ScrollByLinesWithOverflow(PRInt32 aNumLinesX, PRInt32 aNumLinexY,
|
||||
PRInt32& aOverflowX, PRInt32& aOverflowY,
|
||||
PRUint32 aUpdateFlags = 0) = 0;
|
||||
|
||||
/**
|
||||
* Get the desired size of a page scroll in each dimension.
|
||||
@ -181,12 +195,17 @@ public:
|
||||
* Scroll the view left or right by aNumLinesX pixels. Positive values move
|
||||
* right. Scroll the view up or down by aNumLinesY pixels. Positive values
|
||||
* move down. Prevents scrolling off the end of the view.
|
||||
* @param aNumLinesX number of lines to scroll the view horizontally
|
||||
* @param aNumLinesY number of lines to scroll the view vertically
|
||||
* @param aUpdateFlags indicate smooth or async scrolling
|
||||
* @param aNumPixelsX number of pixels to scroll the view horizontally
|
||||
* @param aNumPixelsY number of pixels to scroll the view vertically
|
||||
* @param aOverflowX returns the number of pixels that could not
|
||||
* be scrolled due to scroll bounds.
|
||||
* @param aOverflowY returns the number of pixels that could not
|
||||
* be scrolled due to scroll bounds.
|
||||
* @param aUpdateFlags indicate smooth, async, or immediate scrolling
|
||||
* @return error status
|
||||
*/
|
||||
NS_IMETHOD ScrollByPixels(PRInt32 aNumPixelsX, PRInt32 aNumPixelsY,
|
||||
PRInt32& aOverflowX, PRInt32& aOverflowY,
|
||||
PRUint32 aUpdateFlags = 0) = 0;
|
||||
|
||||
/**
|
||||
|
@ -208,7 +208,7 @@ static void ComputeVelocities(PRInt32 aCurVelocity, nscoord aCurPos, nscoord aDs
|
||||
}
|
||||
|
||||
static nsresult ClampScrollValues(nscoord& aX, nscoord& aY, nsScrollPortView* aThis) {
|
||||
// make sure the new position in in bounds
|
||||
// make sure the new position is in bounds
|
||||
nsView* scrolledView = aThis->GetScrolledView();
|
||||
if (!scrolledView) return NS_ERROR_FAILURE;
|
||||
|
||||
@ -396,7 +396,44 @@ NS_IMETHODIMP nsScrollPortView::GetLineHeight(nscoord *aHeight)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsScrollPortView::ScrollByLines(PRInt32 aNumLinesX, PRInt32 aNumLinesY,
|
||||
nsresult
|
||||
nsScrollPortView::CalcScrollOverflow(nscoord aX, nscoord aY,
|
||||
PRInt32& aPixelOverflowX, PRInt32& aPixelOverflowY)
|
||||
{
|
||||
// make sure the new position is in bounds
|
||||
nsView* scrolledView = GetScrolledView();
|
||||
if (!scrolledView) return NS_ERROR_FAILURE;
|
||||
|
||||
nsRect scrolledRect;
|
||||
scrolledView->GetDimensions(scrolledRect);
|
||||
|
||||
nsSize portSize;
|
||||
this->GetDimensions(portSize);
|
||||
|
||||
nscoord maxX = scrolledRect.XMost() - portSize.width;
|
||||
nscoord maxY = scrolledRect.YMost() - portSize.height;
|
||||
|
||||
nsCOMPtr<nsIDeviceContext> dev;
|
||||
mViewManager->GetDeviceContext(*getter_AddRefs(dev));
|
||||
float p2a = (float)dev->AppUnitsPerDevPixel();
|
||||
|
||||
if (maxX != 0 && aX > maxX)
|
||||
aPixelOverflowX = NSAppUnitsToIntPixels(aX - maxX, p2a);
|
||||
|
||||
if (maxY != 0 && aY > maxY)
|
||||
aPixelOverflowY = NSAppUnitsToIntPixels(aY - maxY, p2a);
|
||||
|
||||
if (maxX != 0 && aX < scrolledRect.x)
|
||||
aPixelOverflowX = NSAppUnitsToIntPixels(scrolledRect.x - aX, p2a);
|
||||
|
||||
if (maxY != 0 && aY < scrolledRect.y)
|
||||
aPixelOverflowY = NSAppUnitsToIntPixels(scrolledRect.y - aY, p2a);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsScrollPortView::ScrollByLines(PRInt32 aNumLinesX,
|
||||
PRInt32 aNumLinesY,
|
||||
PRUint32 aUpdateFlags)
|
||||
{
|
||||
nscoord dx = mLineHeight*aNumLinesX;
|
||||
@ -405,6 +442,20 @@ NS_IMETHODIMP nsScrollPortView::ScrollByLines(PRInt32 aNumLinesX, PRInt32 aNumLi
|
||||
return ScrollTo(mDestinationX + dx, mDestinationY + dy, aUpdateFlags);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsScrollPortView::ScrollByLinesWithOverflow(PRInt32 aNumLinesX,
|
||||
PRInt32 aNumLinesY,
|
||||
PRInt32& aOverflowX,
|
||||
PRInt32& aOverflowY,
|
||||
PRUint32 aUpdateFlags)
|
||||
{
|
||||
nscoord dx = mLineHeight*aNumLinesX;
|
||||
nscoord dy = mLineHeight*aNumLinesY;
|
||||
|
||||
CalcScrollOverflow(mDestinationX + dx, mDestinationY + dy, aOverflowX, aOverflowY);
|
||||
|
||||
return ScrollTo(mDestinationX + dx, mDestinationY + dy, aUpdateFlags);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsScrollPortView::GetPageScrollDistances(nsSize *aDistances)
|
||||
{
|
||||
nsSize size;
|
||||
@ -451,6 +502,8 @@ NS_IMETHODIMP nsScrollPortView::ScrollByWhole(PRBool aTop,
|
||||
|
||||
NS_IMETHODIMP nsScrollPortView::ScrollByPixels(PRInt32 aNumPixelsX,
|
||||
PRInt32 aNumPixelsY,
|
||||
PRInt32& aOverflowX,
|
||||
PRInt32& aOverflowY,
|
||||
PRUint32 aUpdateFlags)
|
||||
{
|
||||
nsCOMPtr<nsIDeviceContext> dev;
|
||||
@ -460,6 +513,8 @@ NS_IMETHODIMP nsScrollPortView::ScrollByPixels(PRInt32 aNumPixelsX,
|
||||
nscoord dx = NSIntPixelsToAppUnits(aNumPixelsX, p2a);
|
||||
nscoord dy = NSIntPixelsToAppUnits(aNumPixelsY, p2a);
|
||||
|
||||
CalcScrollOverflow(mDestinationX + dx, mDestinationY + dy, aOverflowX, aOverflowY);
|
||||
|
||||
return ScrollTo(mDestinationX + dx, mDestinationY + dy, aUpdateFlags);
|
||||
}
|
||||
|
||||
@ -614,7 +669,7 @@ NS_IMETHODIMP nsScrollPortView::ScrollToImpl(nscoord aX, nscoord aY)
|
||||
aX = NSIntPixelsToAppUnits(xPixels, p2a);
|
||||
aY = NSIntPixelsToAppUnits(yPixels, p2a);
|
||||
|
||||
// do nothing if the we aren't scrolling.
|
||||
// do nothing if we aren't scrolling.
|
||||
// this needs to be rechecked because of the clamping and
|
||||
// rounding
|
||||
if (aX == mOffsetX && aY == mOffsetY) {
|
||||
|
@ -73,11 +73,15 @@ public:
|
||||
NS_IMETHOD GetLineHeight(nscoord *aHeight);
|
||||
NS_IMETHOD ScrollByLines(PRInt32 aNumLinesX, PRInt32 aNumLinesY,
|
||||
PRUint32 aUpdateFlags = 0);
|
||||
NS_IMETHOD ScrollByLinesWithOverflow(PRInt32 aNumLinesX, PRInt32 aNumLinesY,
|
||||
PRInt32& aOverflowX, PRInt32& aOverflowY,
|
||||
PRUint32 aUpdateFlags = 0);
|
||||
NS_IMETHOD GetPageScrollDistances(nsSize *aDistances);
|
||||
NS_IMETHOD ScrollByPages(PRInt32 aNumPagesX, PRInt32 aNumPagesY,
|
||||
PRUint32 aUpdateFlags = 0);
|
||||
NS_IMETHOD ScrollByWhole(PRBool aTop, PRUint32 aUpdateFlags = 0);
|
||||
NS_IMETHOD ScrollByPixels(PRInt32 aNumPixelsX, PRInt32 aNumPixelsY,
|
||||
PRInt32& aOverflowX, PRInt32& aOverflowY,
|
||||
PRUint32 aUpdateFlags = 0);
|
||||
NS_IMETHOD CanScroll(PRBool aHorizontal, PRBool aForward, PRBool &aResult);
|
||||
|
||||
@ -107,6 +111,7 @@ protected:
|
||||
//private
|
||||
void Scroll(nsView *aScrolledView, nsPoint aTwipsDelta, nsIntPoint aPixDelta, nscoord aP2A);
|
||||
PRBool CannotBitBlt(nsView* aScrolledView);
|
||||
nsresult CalcScrollOverflow(nscoord aX, nscoord aY, PRInt32& aOverflowX, PRInt32& aOverflowY);
|
||||
|
||||
nscoord mOffsetX, mOffsetY;
|
||||
nscoord mDestinationX, mDestinationY;
|
||||
|
@ -1061,21 +1061,24 @@ public:
|
||||
// When kHasPixels is set, the event is guaranteed to
|
||||
// be followed up by an event that contains pixel
|
||||
// scrolling information.
|
||||
kNoLines = 1 << 4 // Marks pixel scroll events that will not be
|
||||
kNoLines = 1 << 4, // Marks pixel scroll events that will not be
|
||||
// followed by a line scroll events. EventStateManager
|
||||
// will compute the appropriate height/width based on
|
||||
// view lineHeight and generate line scroll events
|
||||
// as needed.
|
||||
kNoDefer = 1 << 5 // For scrollable views, indicates scroll should not
|
||||
// occur asynchronously.
|
||||
};
|
||||
|
||||
nsMouseScrollEvent(PRBool isTrusted, PRUint32 msg, nsIWidget *w)
|
||||
: nsMouseEvent_base(isTrusted, msg, w, NS_MOUSE_SCROLL_EVENT),
|
||||
scrollFlags(0), delta(0)
|
||||
scrollFlags(0), delta(0), scrollOverflow(0)
|
||||
{
|
||||
}
|
||||
|
||||
PRInt32 scrollFlags;
|
||||
PRInt32 delta;
|
||||
PRInt32 scrollOverflow;
|
||||
};
|
||||
|
||||
class nsQueryContentEvent : public nsGUIEvent
|
||||
|
@ -52,18 +52,27 @@
|
||||
#endif
|
||||
|
||||
const PRUnichar nsWinGesture::kGestureLibraryName[] = L"user32.dll";
|
||||
const PRUnichar nsWinGesture::kThemeLibraryName[] = L"uxtheme.dll";
|
||||
HMODULE nsWinGesture::sLibraryHandle = nsnull;
|
||||
nsWinGesture::GetGestureInfoPtr nsWinGesture::getGestureInfo = nsnull;
|
||||
nsWinGesture::CloseGestureInfoHandlePtr nsWinGesture::closeGestureInfoHandle = nsnull;
|
||||
nsWinGesture::GetGestureExtraArgsPtr nsWinGesture::getGestureExtraArgs = nsnull;
|
||||
nsWinGesture::SetGestureConfigPtr nsWinGesture::setGestureConfig = nsnull;
|
||||
nsWinGesture::GetGestureConfigPtr nsWinGesture::getGestureConfig = nsnull;
|
||||
nsWinGesture::BeginPanningFeedbackPtr nsWinGesture::beginPanningFeedback = nsnull;
|
||||
nsWinGesture::EndPanningFeedbackPtr nsWinGesture::endPanningFeedback = nsnull;
|
||||
nsWinGesture::UpdatePanningFeedbackPtr nsWinGesture::updatePanningFeedback = nsnull;
|
||||
static PRBool gEnableSingleFingerPanEvents = PR_FALSE;
|
||||
|
||||
nsWinGesture::nsWinGesture() :
|
||||
mAvailable(PR_FALSE)
|
||||
mFeedbackActive(PR_FALSE),
|
||||
mXAxisFeedback(PR_FALSE),
|
||||
mYAxisFeedback(PR_FALSE),
|
||||
mPanActive(PR_FALSE),
|
||||
mPanInertiaActive(PR_FALSE)
|
||||
{
|
||||
(void)InitLibrary();
|
||||
mPixelScrollOverflow = 0;
|
||||
}
|
||||
|
||||
nsWinGesture::~nsWinGesture()
|
||||
@ -79,13 +88,15 @@ PRBool nsWinGesture::InitLibrary()
|
||||
return PR_FALSE;
|
||||
#else
|
||||
if (getGestureInfo) {
|
||||
mAvailable = PR_TRUE;
|
||||
return PR_TRUE;
|
||||
} else if (sLibraryHandle) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
sLibraryHandle = ::LoadLibraryW(kGestureLibraryName);
|
||||
HMODULE hTheme = ::LoadLibraryW(kThemeLibraryName);
|
||||
|
||||
// gesture interfaces
|
||||
if (sLibraryHandle) {
|
||||
getGestureInfo = (GetGestureInfoPtr)GetProcAddress(sLibraryHandle, "GetGestureInfo");
|
||||
closeGestureInfoHandle = (CloseGestureInfoHandlePtr)GetProcAddress(sLibraryHandle, "CloseGestureInfoHandle");
|
||||
@ -95,17 +106,27 @@ PRBool nsWinGesture::InitLibrary()
|
||||
}
|
||||
|
||||
if (!getGestureInfo || !closeGestureInfoHandle || !getGestureExtraArgs ||
|
||||
!setGestureConfig || !getGestureConfig) {
|
||||
!setGestureConfig || !getGestureConfig) {
|
||||
getGestureInfo = nsnull;
|
||||
closeGestureInfoHandle = nsnull;
|
||||
getGestureExtraArgs = nsnull;
|
||||
setGestureConfig = nsnull;
|
||||
getGestureConfig = nsnull;
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
mAvailable = PR_TRUE;
|
||||
// panning feedback interfaces
|
||||
if (hTheme) {
|
||||
beginPanningFeedback = (BeginPanningFeedbackPtr)GetProcAddress(hTheme, "BeginPanningFeedback");
|
||||
endPanningFeedback = (EndPanningFeedbackPtr)GetProcAddress(hTheme, "EndPanningFeedback");
|
||||
updatePanningFeedback = (UpdatePanningFeedbackPtr)GetProcAddress(hTheme, "UpdatePanningFeedback");
|
||||
}
|
||||
|
||||
if (!beginPanningFeedback || !endPanningFeedback || !updatePanningFeedback) {
|
||||
beginPanningFeedback = nsnull;
|
||||
endPanningFeedback = nsnull;
|
||||
updatePanningFeedback = nsnull;
|
||||
}
|
||||
|
||||
// Check to see if we want single finger gesture input. Only do this once
|
||||
// for the app so we don't have to look it up on every window create.
|
||||
@ -127,14 +148,15 @@ PRBool nsWinGesture::InitLibrary()
|
||||
|
||||
void nsWinGesture::ShutdownLibrary()
|
||||
{
|
||||
mAvailable = PR_FALSE;
|
||||
getGestureInfo = nsnull;
|
||||
beginPanningFeedback = nsnull;
|
||||
}
|
||||
|
||||
#define GCOUNT 5
|
||||
|
||||
PRBool nsWinGesture::InitWinGestureSupport(HWND hWnd)
|
||||
{
|
||||
if (!mAvailable)
|
||||
if (!getGestureInfo)
|
||||
return PR_FALSE;
|
||||
|
||||
GESTURECONFIG config[GCOUNT];
|
||||
@ -168,8 +190,8 @@ PRBool nsWinGesture::InitWinGestureSupport(HWND hWnd)
|
||||
config[3].dwID = GID_TWOFINGERTAP;
|
||||
config[3].dwBlock = 0;
|
||||
|
||||
config[4].dwWant = GC_ROLLOVER;
|
||||
config[4].dwID = GID_ROLLOVER;
|
||||
config[4].dwWant = GC_PRESSANDTAP;
|
||||
config[4].dwID = GID_PRESSANDTAP;
|
||||
config[4].dwBlock = 0;
|
||||
|
||||
return SetGestureConfig(hWnd, GCOUNT, (PGESTURECONFIG)&config);
|
||||
@ -179,12 +201,12 @@ PRBool nsWinGesture::InitWinGestureSupport(HWND hWnd)
|
||||
|
||||
PRBool nsWinGesture::IsAvailable()
|
||||
{
|
||||
return mAvailable;
|
||||
return getGestureInfo != nsnull;
|
||||
}
|
||||
|
||||
PRBool nsWinGesture::GetGestureInfo(HGESTUREINFO hGestureInfo, PGESTUREINFO pGestureInfo)
|
||||
{
|
||||
if (!mAvailable || !hGestureInfo || !pGestureInfo)
|
||||
if (!getGestureInfo || !hGestureInfo || !pGestureInfo)
|
||||
return PR_FALSE;
|
||||
|
||||
ZeroMemory(pGestureInfo, sizeof(GESTUREINFO));
|
||||
@ -195,7 +217,7 @@ PRBool nsWinGesture::GetGestureInfo(HGESTUREINFO hGestureInfo, PGESTUREINFO pGes
|
||||
|
||||
PRBool nsWinGesture::CloseGestureInfoHandle(HGESTUREINFO hGestureInfo)
|
||||
{
|
||||
if (!mAvailable || !hGestureInfo)
|
||||
if (!getGestureInfo || !hGestureInfo)
|
||||
return PR_FALSE;
|
||||
|
||||
return closeGestureInfoHandle(hGestureInfo);
|
||||
@ -203,7 +225,7 @@ PRBool nsWinGesture::CloseGestureInfoHandle(HGESTUREINFO hGestureInfo)
|
||||
|
||||
PRBool nsWinGesture::GetGestureExtraArgs(HGESTUREINFO hGestureInfo, UINT cbExtraArgs, PBYTE pExtraArgs)
|
||||
{
|
||||
if (!mAvailable || !hGestureInfo || !pExtraArgs)
|
||||
if (!getGestureInfo || !hGestureInfo || !pExtraArgs)
|
||||
return PR_FALSE;
|
||||
|
||||
return getGestureExtraArgs(hGestureInfo, cbExtraArgs, pExtraArgs);
|
||||
@ -211,7 +233,7 @@ PRBool nsWinGesture::GetGestureExtraArgs(HGESTUREINFO hGestureInfo, UINT cbExtra
|
||||
|
||||
PRBool nsWinGesture::SetGestureConfig(HWND hWnd, UINT cIDs, PGESTURECONFIG pGestureConfig)
|
||||
{
|
||||
if (!mAvailable || !pGestureConfig)
|
||||
if (!getGestureInfo || !pGestureConfig)
|
||||
return PR_FALSE;
|
||||
|
||||
return setGestureConfig(hWnd, 0, cIDs, pGestureConfig, sizeof(GESTURECONFIG));
|
||||
@ -219,12 +241,36 @@ PRBool nsWinGesture::SetGestureConfig(HWND hWnd, UINT cIDs, PGESTURECONFIG pGest
|
||||
|
||||
PRBool nsWinGesture::GetGestureConfig(HWND hWnd, DWORD dwFlags, PUINT pcIDs, PGESTURECONFIG pGestureConfig)
|
||||
{
|
||||
if (!mAvailable || !pGestureConfig)
|
||||
if (!getGestureInfo || !pGestureConfig)
|
||||
return PR_FALSE;
|
||||
|
||||
return getGestureConfig(hWnd, 0, dwFlags, pcIDs, pGestureConfig, sizeof(GESTURECONFIG));
|
||||
}
|
||||
|
||||
PRBool nsWinGesture::BeginPanningFeedback(HWND hWnd)
|
||||
{
|
||||
if (!beginPanningFeedback)
|
||||
return PR_FALSE;
|
||||
|
||||
return beginPanningFeedback(hWnd);
|
||||
}
|
||||
|
||||
PRBool nsWinGesture::EndPanningFeedback(HWND hWnd)
|
||||
{
|
||||
if (!beginPanningFeedback)
|
||||
return PR_FALSE;
|
||||
|
||||
return endPanningFeedback(hWnd, TRUE);
|
||||
}
|
||||
|
||||
PRBool nsWinGesture::UpdatePanningFeedback(HWND hWnd, LONG offsetX, LONG offsetY, BOOL fInInertia)
|
||||
{
|
||||
if (!beginPanningFeedback)
|
||||
return PR_FALSE;
|
||||
|
||||
return updatePanningFeedback(hWnd, offsetX, offsetY, fInInertia);
|
||||
}
|
||||
|
||||
PRBool nsWinGesture::IsPanEvent(LPARAM lParam)
|
||||
{
|
||||
GESTUREINFO gi;
|
||||
@ -341,9 +387,9 @@ nsWinGesture::ProcessGestureMessage(HWND hWnd, WPARAM wParam, LPARAM lParam, nsS
|
||||
}
|
||||
break;
|
||||
|
||||
case GID_ROLLOVER:
|
||||
case GID_PRESSANDTAP:
|
||||
{
|
||||
// Two finger drum roll. Defaults to right click if it falls through.
|
||||
// Two finger right click. Defaults to right click if it falls through.
|
||||
evt.message = NS_SIMPLE_GESTURE_PRESSTAP;
|
||||
}
|
||||
break;
|
||||
@ -366,8 +412,10 @@ nsWinGesture::ProcessPanMessage(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
||||
|
||||
// The coordinates of this event
|
||||
nsPointWin coord;
|
||||
coord = gi.ptsLocation;
|
||||
coord.ScreenToClient(hWnd);
|
||||
coord = mPanRefPoint = gi.ptsLocation;
|
||||
// We want screen coordinates in our local offsets as client coordinates will change
|
||||
// when feedback is taking place. Gui events though require client coordinates.
|
||||
mPanRefPoint.ScreenToClient(hWnd);
|
||||
|
||||
switch(gi.dwID)
|
||||
{
|
||||
@ -383,10 +431,30 @@ nsWinGesture::ProcessPanMessage(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
||||
if (gi.dwFlags & GF_BEGIN) {
|
||||
mPanIntermediate = coord;
|
||||
mPixelScrollDelta = 0;
|
||||
} else {
|
||||
mPanActive = PR_TRUE;
|
||||
mPanInertiaActive = PR_FALSE;
|
||||
}
|
||||
else {
|
||||
|
||||
#ifdef DBG_jimm
|
||||
PRInt32 deltaX = mPanIntermediate.x - coord.x;
|
||||
PRInt32 deltaY = mPanIntermediate.y - coord.y;
|
||||
printf("coordX=%d coordY=%d deltaX=%d deltaY=%d x:%d y:%d\n", coord.x,
|
||||
coord.y, deltaX, deltaY, mXAxisFeedback, mYAxisFeedback);
|
||||
#endif
|
||||
|
||||
mPixelScrollDelta.x = mPanIntermediate.x - coord.x;
|
||||
mPixelScrollDelta.y = mPanIntermediate.y - coord.y;
|
||||
mPanIntermediate = coord;
|
||||
|
||||
if (gi.dwFlags & GF_INERTIA)
|
||||
mPanInertiaActive = PR_TRUE;
|
||||
|
||||
if (gi.dwFlags & GF_END) {
|
||||
mPanActive = PR_FALSE;
|
||||
mPanInertiaActive = PR_FALSE;
|
||||
PanFeedbackFinalize(hWnd, PR_TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -394,15 +462,112 @@ nsWinGesture::ProcessPanMessage(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
inline PRBool TestTransition(PRInt32 a, PRInt32 b)
|
||||
{
|
||||
// If a is zero, overflow is zero, implying the cursor has moved back to the start position.
|
||||
// If b is zero, cached overscroll is zero, implying feedback just begun.
|
||||
if (a == 0 || b == 0) return PR_TRUE;
|
||||
// Test for different signs.
|
||||
return (a < 0) == (b < 0);
|
||||
}
|
||||
|
||||
void
|
||||
nsWinGesture::UpdatePanFeedbackX(HWND hWnd, nsMouseScrollEvent& evt, PRBool& endFeedback)
|
||||
{
|
||||
// If scroll overflow was returned indicating we panned past the bounds of
|
||||
// the scrollable view port, start feeback.
|
||||
if (evt.scrollOverflow != 0) {
|
||||
if (!mFeedbackActive) {
|
||||
BeginPanningFeedback(hWnd);
|
||||
mFeedbackActive = PR_TRUE;
|
||||
}
|
||||
endFeedback = PR_FALSE;
|
||||
mXAxisFeedback = PR_TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mXAxisFeedback) {
|
||||
PRInt32 newOverflow = mPixelScrollOverflow.x - mPixelScrollDelta.x;
|
||||
|
||||
// Detect a reverse transition past the starting drag point. This tells us the user
|
||||
// has panned all the way back so we can stop providing feedback for this axis.
|
||||
if (!TestTransition(newOverflow, mPixelScrollOverflow.x) || newOverflow == 0)
|
||||
return;
|
||||
|
||||
// Cache the total over scroll in pixels.
|
||||
mPixelScrollOverflow.x = newOverflow;
|
||||
endFeedback = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsWinGesture::UpdatePanFeedbackY(HWND hWnd, nsMouseScrollEvent& evt, PRBool& endFeedback)
|
||||
{
|
||||
// If scroll overflow was returned indicating we panned past the bounds of
|
||||
// the scrollable view port, start feeback.
|
||||
if (evt.scrollOverflow != 0) {
|
||||
if (!mFeedbackActive) {
|
||||
BeginPanningFeedback(hWnd);
|
||||
mFeedbackActive = PR_TRUE;
|
||||
}
|
||||
endFeedback = PR_FALSE;
|
||||
mYAxisFeedback = PR_TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mYAxisFeedback) {
|
||||
PRInt32 newOverflow = mPixelScrollOverflow.y - mPixelScrollDelta.y;
|
||||
|
||||
// Detect a reverse transition past the starting drag point. This tells us the user
|
||||
// has panned all the way back so we can stop providing feedback for this axis.
|
||||
if (!TestTransition(newOverflow, mPixelScrollOverflow.y) || newOverflow == 0)
|
||||
return;
|
||||
|
||||
// Cache the total over scroll in pixels.
|
||||
mPixelScrollOverflow.y = newOverflow;
|
||||
endFeedback = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsWinGesture::PanFeedbackFinalize(HWND hWnd, PRBool endFeedback)
|
||||
{
|
||||
if (!mFeedbackActive)
|
||||
return;
|
||||
|
||||
if (endFeedback) {
|
||||
mFeedbackActive = PR_FALSE;
|
||||
mXAxisFeedback = PR_FALSE;
|
||||
mYAxisFeedback = PR_FALSE;
|
||||
mPixelScrollOverflow = 0;
|
||||
EndPanningFeedback(hWnd);
|
||||
return;
|
||||
}
|
||||
|
||||
UpdatePanningFeedback(hWnd, mPixelScrollOverflow.x, mPixelScrollOverflow.y, mPanInertiaActive);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsWinGesture::PanDeltaToPixelScrollX(nsMouseScrollEvent& evt)
|
||||
{
|
||||
evt.delta = 0;
|
||||
evt.scrollOverflow = 0;
|
||||
|
||||
// Don't scroll the view if we are currently at a bounds, or, if we are
|
||||
// panning back from a max feedback position. This keeps the original drag point
|
||||
// constant.
|
||||
if (mXAxisFeedback)
|
||||
return PR_FALSE;
|
||||
|
||||
if (mPixelScrollDelta.x != 0)
|
||||
{
|
||||
evt.scrollFlags = nsMouseScrollEvent::kIsHorizontal|nsMouseScrollEvent::kHasPixels|nsMouseScrollEvent::kNoLines;
|
||||
evt.scrollFlags = nsMouseScrollEvent::kIsHorizontal|
|
||||
nsMouseScrollEvent::kHasPixels|
|
||||
nsMouseScrollEvent::kNoLines|
|
||||
nsMouseScrollEvent::kNoDefer;
|
||||
evt.delta = mPixelScrollDelta.x;
|
||||
evt.refPoint.x = mPanIntermediate.x;
|
||||
evt.refPoint.y = mPanIntermediate.y;
|
||||
evt.refPoint.x = mPanRefPoint.x;
|
||||
evt.refPoint.y = mPanRefPoint.y;
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
@ -411,12 +576,24 @@ nsWinGesture::PanDeltaToPixelScrollX(nsMouseScrollEvent& evt)
|
||||
PRBool
|
||||
nsWinGesture::PanDeltaToPixelScrollY(nsMouseScrollEvent& evt)
|
||||
{
|
||||
evt.delta = 0;
|
||||
evt.scrollOverflow = 0;
|
||||
|
||||
// Don't scroll the view if we are currently at a bounds, or, if we are
|
||||
// panning back from a max feedback position. This keeps the original drag point
|
||||
// constant.
|
||||
if (mYAxisFeedback)
|
||||
return PR_FALSE;
|
||||
|
||||
if (mPixelScrollDelta.y != 0)
|
||||
{
|
||||
evt.scrollFlags = nsMouseScrollEvent::kIsVertical|nsMouseScrollEvent::kHasPixels|nsMouseScrollEvent::kNoLines;
|
||||
evt.scrollFlags = nsMouseScrollEvent::kIsVertical|
|
||||
nsMouseScrollEvent::kHasPixels|
|
||||
nsMouseScrollEvent::kNoLines|
|
||||
nsMouseScrollEvent::kNoDefer;
|
||||
evt.delta = mPixelScrollDelta.y;
|
||||
evt.refPoint.x = mPanIntermediate.x;
|
||||
evt.refPoint.y = mPanIntermediate.y;
|
||||
evt.refPoint.x = mPanRefPoint.x;
|
||||
evt.refPoint.y = mPanRefPoint.y;
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
|
@ -44,7 +44,6 @@
|
||||
#include "nsPoint.h"
|
||||
#include "nsGUIEvent.h"
|
||||
|
||||
|
||||
#if !defined(NTDDI_WIN7) || NTDDI_VERSION < NTDDI_WIN7
|
||||
|
||||
DECLARE_HANDLE(HGESTUREINFO);
|
||||
@ -131,7 +130,7 @@ typedef struct tagGESTURENOTIFYSTRUCT {
|
||||
|
||||
#define GC_TWOFINGERTAP 0x00000001
|
||||
|
||||
#define GC_ROLLOVER 0x00000001
|
||||
#define GC_PRESSANDTAP 0x00000001
|
||||
|
||||
/*
|
||||
* Gesture IDs
|
||||
@ -142,7 +141,7 @@ typedef struct tagGESTURENOTIFYSTRUCT {
|
||||
#define GID_PAN 4
|
||||
#define GID_ROTATE 5
|
||||
#define GID_TWOFINGERTAP 6
|
||||
#define GID_ROLLOVER 7
|
||||
#define GID_PRESSANDTAP 7
|
||||
|
||||
// Maximum number of gestures that can be included
|
||||
// in a single call to SetGestureConfig / GetGestureConfig
|
||||
@ -204,6 +203,9 @@ public:
|
||||
PRBool ProcessPanMessage(HWND hWnd, WPARAM wParam, LPARAM lParam);
|
||||
PRBool PanDeltaToPixelScrollX(nsMouseScrollEvent& evt);
|
||||
PRBool PanDeltaToPixelScrollY(nsMouseScrollEvent& evt);
|
||||
void UpdatePanFeedbackX(HWND hWnd, nsMouseScrollEvent& evt, PRBool& endFeedback);
|
||||
void UpdatePanFeedbackY(HWND hWnd, nsMouseScrollEvent& evt, PRBool& endFeedback);
|
||||
void PanFeedbackFinalize(HWND hWnd, PRBool endFeedback);
|
||||
|
||||
public:
|
||||
// Helpers
|
||||
@ -212,6 +214,9 @@ public:
|
||||
PRBool GetGestureExtraArgs(HGESTUREINFO hGestureInfo, UINT cbExtraArgs, PBYTE pExtraArgs);
|
||||
PRBool SetGestureConfig(HWND hWnd, UINT cIDs, PGESTURECONFIG pGestureConfig);
|
||||
PRBool GetGestureConfig(HWND hWnd, DWORD dwFlags, PUINT pcIDs, PGESTURECONFIG pGestureConfig);
|
||||
PRBool BeginPanningFeedback(HWND hWnd);
|
||||
PRBool EndPanningFeedback(HWND hWnd);
|
||||
PRBool UpdatePanningFeedback(HWND hWnd, LONG offsetX, LONG offsetY, BOOL fInInertia);
|
||||
|
||||
protected:
|
||||
|
||||
@ -222,6 +227,9 @@ private:
|
||||
typedef BOOL (WINAPI * GetGestureExtraArgsPtr)(HGESTUREINFO hGestureInfo, UINT cbExtraArgs, PBYTE pExtraArgs);
|
||||
typedef BOOL (WINAPI * SetGestureConfigPtr)(HWND hwnd, DWORD dwReserved, UINT cIDs, PGESTURECONFIG pGestureConfig, UINT cbSize);
|
||||
typedef BOOL (WINAPI * GetGestureConfigPtr)(HWND hwnd, DWORD dwReserved, DWORD dwFlags, PUINT pcIDs, PGESTURECONFIG pGestureConfig, UINT cbSize);
|
||||
typedef BOOL (WINAPI * BeginPanningFeedbackPtr)(HWND hWnd);
|
||||
typedef BOOL (WINAPI * EndPanningFeedbackPtr)(HWND hWnd, BOOL fAnimateBack);
|
||||
typedef BOOL (WINAPI * UpdatePanningFeedbackPtr)(HWND hWnd, LONG offsetX, LONG offsetY, BOOL fInInertia);
|
||||
|
||||
// Static function pointers
|
||||
static GetGestureInfoPtr getGestureInfo;
|
||||
@ -229,6 +237,9 @@ private:
|
||||
static GetGestureExtraArgsPtr getGestureExtraArgs;
|
||||
static SetGestureConfigPtr setGestureConfig;
|
||||
static GetGestureConfigPtr getGestureConfig;
|
||||
static BeginPanningFeedbackPtr beginPanningFeedback;
|
||||
static EndPanningFeedbackPtr endPanningFeedback;
|
||||
static UpdatePanningFeedbackPtr updatePanningFeedback;
|
||||
|
||||
// Delay load info
|
||||
PRBool InitLibrary();
|
||||
@ -236,12 +247,18 @@ private:
|
||||
|
||||
static HMODULE sLibraryHandle;
|
||||
static const PRUnichar kGestureLibraryName[];
|
||||
static const PRUnichar kThemeLibraryName[];
|
||||
|
||||
PRBool mAvailable;
|
||||
|
||||
// Pan state
|
||||
// Pan and feedback state
|
||||
nsPointWin mPanIntermediate;
|
||||
nsPointWin mPanRefPoint;
|
||||
nsPointWin mPixelScrollDelta;
|
||||
PRPackedBool mPanActive;
|
||||
PRPackedBool mFeedbackActive;
|
||||
PRPackedBool mXAxisFeedback;
|
||||
PRPackedBool mYAxisFeedback;
|
||||
PRPackedBool mPanInertiaActive;
|
||||
nsPointWin mPixelScrollOverflow;
|
||||
|
||||
// Zoom state
|
||||
double mZoomIntermediate;
|
||||
|
@ -5221,13 +5221,18 @@ PRBool nsWindow::ProcessGestureMessage(WPARAM wParam, LPARAM lParam)
|
||||
event.button = 0;
|
||||
event.time = ::GetMessageTime();
|
||||
|
||||
PRBool endFeedback = PR_TRUE;
|
||||
|
||||
if (mGesture.PanDeltaToPixelScrollX(event)) {
|
||||
DispatchEvent(&event, status);
|
||||
}
|
||||
mGesture.UpdatePanFeedbackX(mWnd, event, endFeedback);
|
||||
|
||||
if (mGesture.PanDeltaToPixelScrollY(event)) {
|
||||
DispatchEvent(&event, status);
|
||||
}
|
||||
|
||||
mGesture.UpdatePanFeedbackY(mWnd, event, endFeedback);
|
||||
mGesture.PanFeedbackFinalize(mWnd, endFeedback);
|
||||
mGesture.CloseGestureInfoHandle((HGESTUREINFO)lParam);
|
||||
|
||||
return PR_TRUE;
|
||||
|
Loading…
x
Reference in New Issue
Block a user