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:
mark%moxienet.com 2005-09-21 04:10:59 +00:00
parent 2a2163f012
commit 793f191702
4 changed files with 103 additions and 97 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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();
}