mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-29 03:44:37 +00:00
Bug 171680, modifier keys have no effect on mouse wheel (Mac). Handle modifier keys for scrollwheel events. Bug 255415, scroll wheel doesn't scroll the right scrollable thing until the mouse is moved. Walk the widget hierarchy to find out what's under the mouse. r=mano sr=smfr
This commit is contained in:
parent
2a2163f012
commit
793f191702
@ -786,6 +786,7 @@ pref("mousewheel.withnokey.sysnumlines",true);
|
||||
pref("mousewheel.withcontrolkey.action",0);
|
||||
pref("mousewheel.withcontrolkey.numlines",1);
|
||||
pref("mousewheel.withcontrolkey.sysnumlines",true);
|
||||
// mousewheel.withshiftkey, see the Mac note below.
|
||||
pref("mousewheel.withshiftkey.action",0);
|
||||
pref("mousewheel.withshiftkey.numlines",1);
|
||||
pref("mousewheel.withshiftkey.sysnumlines",true);
|
||||
@ -800,6 +801,13 @@ pref("mousewheel.withaltkey.sysnumlines",false);
|
||||
#endif
|
||||
#ifdef XP_MACOSX
|
||||
#define HORIZSCROLL_AVAILABLE
|
||||
// The Mac does interesting things with horizontal scrolling. If a
|
||||
// scroll event comes from a pointing device with a scroll wheel for
|
||||
// the vertical axis, and the user is holding the shift key, the event
|
||||
// comes through as a horizontal scroll event with the shift key
|
||||
// (mousewheel.horizscroll.withshiftkey) and not mousewheel.withshiftkey.
|
||||
// These events should map to horizontal scroll to maintain platform
|
||||
// UI consistency.
|
||||
#endif
|
||||
#ifdef XP_OS2
|
||||
#define HORIZSCROLL_AVAILABLE
|
||||
|
@ -89,56 +89,10 @@ PRBool nsMacEventHandler::sMouseInWidgetHit = PR_FALSE;
|
||||
|
||||
nsMacEventDispatchHandler gEventDispatchHandler;
|
||||
|
||||
static nsEventStatus HandleScrollEvent ( EventMouseWheelAxis inAxis, PRBool inByLine, PRInt32 inDelta,
|
||||
Point inMouseLoc, nsIWidget* inWidget ) ;
|
||||
static void ConvertKeyEventToContextMenuEvent(const nsKeyEvent* inKeyEvent, nsMouseEvent* outCMEvent);
|
||||
static inline PRBool IsContextMenuKey(const nsKeyEvent& inKeyEvent);
|
||||
|
||||
|
||||
//
|
||||
// HandleScrollEvent
|
||||
//
|
||||
// Actually dispatch the mouseWheel scroll event to the appropriate widget. If |inByLine| is false,
|
||||
// then scroll by a full page. |inMouseLoc| is in OS local coordinates. We convert it to widget-relative
|
||||
// coordinates before sending it into Gecko.
|
||||
//
|
||||
static nsEventStatus
|
||||
HandleScrollEvent ( EventMouseWheelAxis inAxis, PRBool inByLine, PRInt32 inDelta,
|
||||
Point inMouseLoc, nsIWidget* inWidget )
|
||||
{
|
||||
NS_ASSERTION(inWidget, "HandleScrollEvent doesn't work with a null widget");
|
||||
if (!inWidget)
|
||||
return nsEventStatus_eIgnore;
|
||||
|
||||
nsMouseScrollEvent scrollEvent(PR_TRUE, NS_MOUSE_SCROLL, inWidget);
|
||||
|
||||
scrollEvent.scrollFlags =
|
||||
(inAxis == kEventMouseWheelAxisX) ? nsMouseScrollEvent::kIsHorizontal : nsMouseScrollEvent::kIsVertical;
|
||||
if ( !inByLine )
|
||||
scrollEvent.scrollFlags |= nsMouseScrollEvent::kIsFullPage;
|
||||
|
||||
// convert window-relative (local) mouse coordinates to widget-relative
|
||||
// coords for Gecko.
|
||||
nsPoint mouseLocRelativeToWidget(inMouseLoc.h, inMouseLoc.v);
|
||||
nsRect bounds;
|
||||
inWidget->GetBounds(bounds);
|
||||
nsPoint widgetOrigin(bounds.x, bounds.y);
|
||||
inWidget->ConvertToDeviceCoordinates(widgetOrigin.x, widgetOrigin.y);
|
||||
mouseLocRelativeToWidget.MoveBy(-widgetOrigin.x, -widgetOrigin.y);
|
||||
|
||||
scrollEvent.delta = inDelta;
|
||||
scrollEvent.refPoint.x = mouseLocRelativeToWidget.x;
|
||||
scrollEvent.refPoint.y = mouseLocRelativeToWidget.y;
|
||||
scrollEvent.time = PR_IntervalNow();
|
||||
|
||||
// dispatch scroll event
|
||||
nsEventStatus rv;
|
||||
scrollEvent.widget->DispatchEvent(&scrollEvent, rv);
|
||||
return rv;
|
||||
|
||||
} // HandleScrollEvent
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
@ -1083,7 +1037,7 @@ PRUint32 nsMacEventHandler::ConvertKeyEventToUnicode(EventRecord& aOSEvent)
|
||||
|
||||
PRBool nsMacEventHandler::HandleKeyEvent(EventRecord& aOSEvent)
|
||||
{
|
||||
nsresult result;
|
||||
nsresult result = NS_ERROR_UNEXPECTED;
|
||||
nsWindow* checkFocusedWidget;
|
||||
|
||||
// get the focused widget
|
||||
@ -1198,7 +1152,7 @@ IsContextMenuKey(const nsKeyEvent& inKeyEvent)
|
||||
//-------------------------------------------------------------------------
|
||||
PRBool nsMacEventHandler::HandleUKeyEvent(const PRUnichar* text, long charCount, EventRecord& aOSEvent)
|
||||
{
|
||||
nsresult result;
|
||||
nsresult result = NS_ERROR_UNEXPECTED;
|
||||
// get the focused widget
|
||||
nsWindow* focusedWidget = gEventDispatchHandler.GetActive();
|
||||
if (!focusedWidget)
|
||||
@ -1291,7 +1245,7 @@ if (KeyDown(0x39)) // press [caps lock] to start the profile
|
||||
#endif
|
||||
|
||||
OSErr err;
|
||||
Boolean isActive;
|
||||
Boolean isActive = true;
|
||||
|
||||
switch (aOSEvent.what)
|
||||
{
|
||||
@ -1427,23 +1381,57 @@ PRBool nsMacEventHandler::ResizeEvent ( WindowRef inWindow )
|
||||
// Called from a mouseWheel carbon event, tell Gecko to scroll.
|
||||
//
|
||||
PRBool
|
||||
nsMacEventHandler :: Scroll ( EventMouseWheelAxis inAxis, PRInt32 inDelta, const Point& inMouseLoc )
|
||||
{
|
||||
// figure out which widget should be scrolled. First try the widget the mouse is under,
|
||||
// then try the last focussed widget.
|
||||
nsIWidget* widgetToScroll = gEventDispatchHandler.GetWidgetPointed();
|
||||
if ( !widgetToScroll )
|
||||
widgetToScroll = gEventDispatchHandler.GetActive();
|
||||
|
||||
// the direction we get from the carbon event is opposite from the way mozilla looks at
|
||||
// it. Reverse the direction. Also, scroll by 3 lines at a time. |inDelta| represents the
|
||||
// number of groups of lines to scroll, not the exact number of lines to scroll.
|
||||
inDelta *= -3;
|
||||
|
||||
HandleScrollEvent ( inAxis, PR_TRUE, inDelta, inMouseLoc, widgetToScroll );
|
||||
|
||||
return PR_TRUE;
|
||||
|
||||
nsMacEventHandler::Scroll(EventMouseWheelAxis inAxis, PRInt32 inDelta,
|
||||
const Point& inMouseLoc, nsWindow* inWindow,
|
||||
PRUint32 inModifiers) {
|
||||
// Figure out which widget should be scrolled by traversing the widget
|
||||
// hierarchy beginning at the root nsWindow. inMouseLoc should be
|
||||
// relative to the origin of this nsWindow. If the scroll event came
|
||||
// from an nsMacWindow, then inWindow should refer to that nsMacWindow.
|
||||
nsIWidget* widgetToScroll = inWindow->FindWidgetHit(inMouseLoc);
|
||||
|
||||
nsMouseScrollEvent scrollEvent(PR_TRUE, NS_MOUSE_SCROLL, widgetToScroll);
|
||||
|
||||
// The direction we get from the carbon event is opposite from the way
|
||||
// mozilla looks at it. Reverse the direction. Also, scroll by 3 lines
|
||||
// at a time. |inDelta| represents the number of groups of lines to scroll,
|
||||
// not the exact number of lines to scroll.
|
||||
scrollEvent.delta = inDelta * -3;
|
||||
|
||||
// If the scroll event comes from a mouse that only has a scroll wheel for
|
||||
// the vertical axis, and the shift key is held down, the system presents
|
||||
// it as a horizontal scroll and doesn't clear the shift key bit from
|
||||
// inModifiers. The Mac is supposed to scroll horizontally in such a case.
|
||||
//
|
||||
// If the scroll event comes from a mouse that can scroll both axes, the
|
||||
// system doesn't apply any of this shift-key fixery.
|
||||
scrollEvent.scrollFlags =
|
||||
(inAxis == kEventMouseWheelAxisX) ? nsMouseScrollEvent::kIsHorizontal :
|
||||
nsMouseScrollEvent::kIsVertical;
|
||||
|
||||
// convert window-relative (local) mouse coordinates to widget-relative
|
||||
// coords for Gecko.
|
||||
nsPoint mouseLocRelativeToWidget(inMouseLoc.h, inMouseLoc.v);
|
||||
nsRect bounds;
|
||||
widgetToScroll->GetBounds(bounds);
|
||||
nsPoint widgetOrigin(bounds.x, bounds.y);
|
||||
widgetToScroll->ConvertToDeviceCoordinates(widgetOrigin.x, widgetOrigin.y);
|
||||
mouseLocRelativeToWidget.MoveBy(-widgetOrigin.x, -widgetOrigin.y);
|
||||
|
||||
scrollEvent.refPoint.x = mouseLocRelativeToWidget.x;
|
||||
scrollEvent.refPoint.y = mouseLocRelativeToWidget.y;
|
||||
scrollEvent.time = PR_IntervalNow();
|
||||
|
||||
// Translate OS event modifiers into Gecko event modifiers
|
||||
scrollEvent.isShift = ((inModifiers & shiftKey) != 0);
|
||||
scrollEvent.isControl = ((inModifiers & controlKey) != 0);
|
||||
scrollEvent.isAlt = ((inModifiers & optionKey) != 0);
|
||||
scrollEvent.isMeta = ((inModifiers & cmdKey) != 0);
|
||||
|
||||
nsEventStatus status;
|
||||
widgetToScroll->DispatchEvent(&scrollEvent, status);
|
||||
|
||||
return nsWindow::ConvertStatus(status);
|
||||
} // Scroll
|
||||
|
||||
|
||||
|
@ -138,7 +138,7 @@ public:
|
||||
//
|
||||
virtual PRBool UpdateEvent ( ) ;
|
||||
virtual PRBool ResizeEvent ( WindowRef inWindow ) ;
|
||||
virtual PRBool Scroll ( EventMouseWheelAxis inAxis, PRInt32 inDelta, const Point& inMouseLoc );
|
||||
virtual PRBool Scroll ( EventMouseWheelAxis inAxis, PRInt32 inDelta, const Point& inMouseLoc, nsWindow* inWindow, PRUint32 inModifiers );
|
||||
|
||||
protected:
|
||||
#if 1
|
||||
|
@ -20,6 +20,7 @@
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mark Mentovai <mark@moxienet.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -118,7 +119,7 @@ static void PrintPortState(WindowPtr inWindow, const char* label)
|
||||
#pragma mark -
|
||||
|
||||
pascal OSErr
|
||||
nsMacWindow :: DragTrackingHandler ( DragTrackingMessage theMessage, WindowPtr theWindow,
|
||||
nsMacWindow::DragTrackingHandler ( DragTrackingMessage theMessage, WindowPtr theWindow,
|
||||
void *handlerRefCon, DragReference theDrag)
|
||||
{
|
||||
static nsCOMPtr<nsIDragHelperService> sDragHelper;
|
||||
@ -168,7 +169,7 @@ nsMacWindow :: DragTrackingHandler ( DragTrackingMessage theMessage, WindowPtr t
|
||||
|
||||
|
||||
pascal OSErr
|
||||
nsMacWindow :: DragReceiveHandler (WindowPtr theWindow, void *handlerRefCon,
|
||||
nsMacWindow::DragReceiveHandler (WindowPtr theWindow, void *handlerRefCon,
|
||||
DragReference theDragRef)
|
||||
{
|
||||
nsCOMPtr<nsIEventSink> windowEventSink;
|
||||
@ -609,38 +610,45 @@ nsresult nsMacWindow::StandardCreate(nsIWidget *aParent,
|
||||
|
||||
|
||||
pascal OSStatus
|
||||
nsMacWindow :: ScrollEventHandler ( EventHandlerCallRef inHandlerChain, EventRef inEvent, void* userData )
|
||||
nsMacWindow::ScrollEventHandler ( EventHandlerCallRef inHandlerChain, EventRef inEvent, void* userData )
|
||||
{
|
||||
OSStatus retVal = eventNotHandledErr;
|
||||
EventMouseWheelAxis axis = kEventMouseWheelAxisY;
|
||||
SInt32 delta = 0;
|
||||
Point mouseLoc;
|
||||
OSErr err1 = ::GetEventParameter ( inEvent, kEventParamMouseWheelAxis, typeMouseWheelAxis,
|
||||
NULL, sizeof(EventMouseWheelAxis), NULL, &axis );
|
||||
OSErr err2 = ::GetEventParameter ( inEvent, kEventParamMouseWheelDelta, typeLongInteger,
|
||||
NULL, sizeof(SInt32), NULL, &delta );
|
||||
OSErr err3 = ::GetEventParameter ( inEvent, kEventParamMouseLocation, typeQDPoint,
|
||||
NULL, sizeof(Point), NULL, &mouseLoc );
|
||||
|
||||
if ( err1 == noErr && err2 == noErr && err3 == noErr ) {
|
||||
UInt32 modifiers = 0;
|
||||
if (::GetEventParameter(inEvent, kEventParamMouseWheelAxis,
|
||||
typeMouseWheelAxis, NULL,
|
||||
sizeof(EventMouseWheelAxis), NULL, &axis) == noErr &&
|
||||
::GetEventParameter(inEvent, kEventParamMouseWheelDelta,
|
||||
typeLongInteger, NULL,
|
||||
sizeof(SInt32), NULL, &delta) == noErr &&
|
||||
::GetEventParameter(inEvent, kEventParamMouseLocation,
|
||||
typeQDPoint, NULL,
|
||||
sizeof(Point), NULL, &mouseLoc) == noErr &&
|
||||
::GetEventParameter(inEvent, kEventParamKeyModifiers,
|
||||
typeUInt32, NULL,
|
||||
sizeof(UInt32), NULL, &modifiers) == noErr) {
|
||||
nsMacWindow* self = NS_REINTERPRET_CAST(nsMacWindow*, userData);
|
||||
if ( self ) {
|
||||
// convert mouse to local coordinates since that's how the event handler wants them
|
||||
NS_ENSURE_TRUE(self->mMacEventHandler.get(), eventNotHandledErr);
|
||||
if (self) {
|
||||
// Convert mouse to local coordinates since that's how the event handler
|
||||
// wants them
|
||||
StPortSetter portSetter(self->mWindowPtr);
|
||||
StOriginSetter originSetter(self->mWindowPtr);
|
||||
::GlobalToLocal(&mouseLoc);
|
||||
self->mMacEventHandler->Scroll ( axis, delta, mouseLoc );
|
||||
self->mMacEventHandler->Scroll(axis, delta, mouseLoc, self, modifiers);
|
||||
retVal = noErr;
|
||||
}
|
||||
}
|
||||
return noErr;
|
||||
|
||||
return retVal;
|
||||
} // ScrollEventHandler
|
||||
|
||||
|
||||
pascal OSStatus
|
||||
nsMacWindow :: WindowEventHandler ( EventHandlerCallRef inHandlerChain, EventRef inEvent, void* userData )
|
||||
nsMacWindow::WindowEventHandler ( EventHandlerCallRef inHandlerChain, EventRef inEvent, void* userData )
|
||||
{
|
||||
OSStatus retVal = eventNotHandledErr; // Presume we won't consume the event
|
||||
|
||||
WindowRef myWind = NULL;
|
||||
::GetEventParameter ( inEvent, kEventParamDirectObject, typeWindowRef, NULL, sizeof(myWind), NULL, &myWind );
|
||||
if ( myWind ) {
|
||||
@ -658,6 +666,7 @@ nsMacWindow :: WindowEventHandler ( EventHandlerCallRef inHandlerChain, EventRef
|
||||
|
||||
// resize the window and repaint
|
||||
nsMacWindow* self = NS_REINTERPRET_CAST(nsMacWindow*, userData);
|
||||
NS_ENSURE_TRUE(self->mMacEventHandler.get(), eventNotHandledErr);
|
||||
if ( self && !self->mResizeIsFromUs ) {
|
||||
self->mMacEventHandler->ResizeEvent(myWind);
|
||||
self->mMacEventHandler->UpdateEvent();
|
||||
@ -736,7 +745,7 @@ NS_IMETHODIMP nsMacWindow::Create(nsNativeWidget aNativeParent, // this is a w
|
||||
// our fake WDEF into this window which takes care of not-drawing the borders.
|
||||
//
|
||||
void
|
||||
nsMacWindow :: InstallBorderlessDefProc ( WindowPtr inWindow )
|
||||
nsMacWindow::InstallBorderlessDefProc ( WindowPtr inWindow )
|
||||
{
|
||||
} // InstallBorderlessDefProc
|
||||
|
||||
@ -749,7 +758,7 @@ nsMacWindow :: InstallBorderlessDefProc ( WindowPtr inWindow )
|
||||
// through with it.
|
||||
//
|
||||
void
|
||||
nsMacWindow :: RemoveBorderlessDefProc ( WindowPtr inWindow )
|
||||
nsMacWindow::RemoveBorderlessDefProc ( WindowPtr inWindow )
|
||||
{
|
||||
}
|
||||
|
||||
@ -1151,7 +1160,7 @@ NS_METHOD nsMacWindow::PlaceBehind(nsTopLevelWidgetZPlacement aPlacement,
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMacWindow::SetSizeMode(PRInt32 aMode)
|
||||
{
|
||||
nsresult rv;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// resize during zoom may attempt to unzoom us. here's where we put a stop to that.
|
||||
if (mZooming)
|
||||
@ -1664,8 +1673,8 @@ NS_IMETHODIMP
|
||||
nsMacWindow::DispatchEvent ( void* anEvent, PRBool *_retval )
|
||||
{
|
||||
*_retval = PR_FALSE;
|
||||
if (mMacEventHandler.get())
|
||||
*_retval = mMacEventHandler->HandleOSEvent(*NS_REINTERPRET_CAST(EventRecord*,anEvent));
|
||||
NS_ENSURE_TRUE(mMacEventHandler.get(), NS_ERROR_FAILURE);
|
||||
*_retval = mMacEventHandler->HandleOSEvent(*NS_REINTERPRET_CAST(EventRecord*,anEvent));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1681,8 +1690,8 @@ nsMacWindow::DispatchMenuEvent ( void* anEvent, PRInt32 aNativeResult, PRBool *_
|
||||
{
|
||||
#if USE_MENUSELECT
|
||||
*_retval = PR_FALSE;
|
||||
if (mMacEventHandler.get())
|
||||
*_retval = mMacEventHandler->HandleMenuCommand(*NS_REINTERPRET_CAST(EventRecord*,anEvent), aNativeResult);
|
||||
NS_ENSURE_TRUE(mMacEventHandler.get(), NS_ERROR_FAILURE);
|
||||
*_retval = mMacEventHandler->HandleMenuCommand(*NS_REINTERPRET_CAST(EventRecord*,anEvent), aNativeResult);
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
@ -1703,9 +1712,9 @@ nsMacWindow::DragEvent(PRUint32 aMessage, PRInt16 aMouseGlobalX, PRInt16 aMouseG
|
||||
PRUint16 aKeyModifiers, PRBool *_retval)
|
||||
{
|
||||
*_retval = PR_FALSE;
|
||||
NS_ENSURE_TRUE(mMacEventHandler.get(), NS_ERROR_FAILURE);
|
||||
Point globalPoint = {aMouseGlobalY, aMouseGlobalX}; // QD Point stored as v, h
|
||||
if (mMacEventHandler.get())
|
||||
*_retval = mMacEventHandler->DragEvent(aMessage, globalPoint, aKeyModifiers);
|
||||
*_retval = mMacEventHandler->DragEvent(aMessage, globalPoint, aKeyModifiers);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1723,10 +1732,10 @@ nsMacWindow::Scroll ( PRBool aVertical, PRInt16 aNumLines, PRInt16 aMouseLocalX,
|
||||
PRInt16 aMouseLocalY, PRBool *_retval )
|
||||
{
|
||||
*_retval = PR_FALSE;
|
||||
NS_ENSURE_TRUE(mMacEventHandler.get(), NS_ERROR_FAILURE);
|
||||
Point localPoint = {aMouseLocalY, aMouseLocalX};
|
||||
if ( mMacEventHandler.get() )
|
||||
*_retval = mMacEventHandler->Scroll(aVertical ? kEventMouseWheelAxisY : kEventMouseWheelAxisX,
|
||||
aNumLines, localPoint);
|
||||
*_retval = mMacEventHandler->Scroll(aVertical ? kEventMouseWheelAxisY : kEventMouseWheelAxisX,
|
||||
aNumLines, localPoint, this, 0);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1766,6 +1775,7 @@ nsMacWindow::ComeToFront()
|
||||
|
||||
NS_IMETHODIMP nsMacWindow::ResetInputState()
|
||||
{
|
||||
NS_ENSURE_TRUE(mMacEventHandler.get(), NS_ERROR_FAILURE);
|
||||
return mMacEventHandler->ResetInputState();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user