diff --git a/mozilla/widget/src/mac/nsMacEventHandler.cpp b/mozilla/widget/src/mac/nsMacEventHandler.cpp index dba7e9a873a..30f4730b304 100644 --- a/mozilla/widget/src/mac/nsMacEventHandler.cpp +++ b/mozilla/widget/src/mac/nsMacEventHandler.cpp @@ -58,8 +58,6 @@ PRBool nsMacEventHandler::sMouseInWidgetHit = PR_FALSE; nsMacEventDispatchHandler gEventDispatchHandler; -static pascal void ScrollActionProc (ControlHandle ctrl, ControlPartCode part) ; - // // ScrollActionProc // @@ -75,7 +73,8 @@ static pascal void ScrollActionProc(ControlHandle ctrl, ControlPartCode partCode case kControlDownButtonPart: case kControlPageUpPart: case kControlPageDownPart: - if ( gEventDispatchHandler.GetActive() ) { + PhantomScrollbarData* data = NS_REINTERPRET_CAST(PhantomScrollbarData*, ::GetControlReference(ctrl)); + if ( data && (data->mWidgetToGetEvent || gEventDispatchHandler.GetActive()) ) { nsMouseScrollEvent scrollEvent; scrollEvent.scrollFlags = nsMouseScrollEvent::kIsVertical; if ( partCode == kControlPageUpPart || partCode == kControlPageDownPart ) @@ -93,7 +92,8 @@ static pascal void ScrollActionProc(ControlHandle ctrl, ControlPartCode partCode scrollEvent.point.x = 100; scrollEvent.point.y = 100; scrollEvent.time = PR_IntervalNow(); - scrollEvent.widget = gEventDispatchHandler.GetActive(); + scrollEvent.widget = data->mWidgetToGetEvent ? + data->mWidgetToGetEvent : gEventDispatchHandler.GetActive(); scrollEvent.nativeMsg = nsnull; // dispatch scroll event @@ -1255,6 +1255,12 @@ PRBool nsMacEventHandler::HandleMouseDownEvent(EventRecord& aOSEvent) // don't allow clicks that rolled up a popup through to the content area. if ( ignoreClickInContent ) break; + + nsMouseEvent mouseEvent; + PRUint32 mouseButton = NS_MOUSE_LEFT_BUTTON_DOWN; + if ( aOSEvent.modifiers & controlKey ) + mouseButton = NS_MOUSE_RIGHT_BUTTON_DOWN; + ConvertOSEventToMouseEvent(aOSEvent, mouseEvent, mouseButton); // Check if the mousedown is in our window's phantom scrollbar. If so, track // the movement of the mouse. The scrolling code is in the action proc. @@ -1262,18 +1268,25 @@ PRBool nsMacEventHandler::HandleMouseDownEvent(EventRecord& aOSEvent) ::GlobalToLocal ( &local ); ControlHandle scrollbar; ControlPartCode partCode = ::FindControl(local, whichWindow, &scrollbar); - if ( partCode >= kControlUpButtonPart && partCode <= kControlPageDownPart && - scrollbar && - GetControlReference(scrollbar) == 'mozz' ) { - ::TrackControl(scrollbar, local, mControlActionProc); - break; + if ( partCode >= kControlUpButtonPart && partCode <= kControlPageDownPart && scrollbar ) { + PhantomScrollbarData* data = NS_REINTERPRET_CAST(PhantomScrollbarData*, ::GetControlReference(scrollbar)); + if ( data && data->mTag == PhantomScrollbarData::kUniqueTag ) { + +#if USEMOUSEPOSITIONFORSCROLLWHEEL +// Uncomment this in order to set the widget to scroll the widget the mouse is over. However, +// we end up getting an idle event while scrolling quickly with the wheel, and the end result +// is that our idle-time mouseMove event kicks in a moves where we think the mouse is to where +// the scrollwheel driver has convinced the OS the mouse really is. Net result: we lose track +// of the widget and scrolling stops until you stop the wheel and move it again :( + data->mWidgetToGetEvent = gEventDispatchHandler.GetWidgetPointed(); // tell action proc which widget to use +#endif + + ::TrackControl(scrollbar, local, mControlActionProc); + data->mWidgetToGetEvent = nsnull; + break; + } } - nsMouseEvent mouseEvent; - PRUint32 mouseButton = NS_MOUSE_LEFT_BUTTON_DOWN; - if ( aOSEvent.modifiers & controlKey ) - mouseButton = NS_MOUSE_RIGHT_BUTTON_DOWN; - ConvertOSEventToMouseEvent(aOSEvent, mouseEvent, mouseButton); nsCOMPtr kungFuDeathGrip ( mouseEvent.widget ); // ensure widget doesn't go away nsWindow* widgetHit = NS_STATIC_CAST(nsWindow*, mouseEvent.widget); // while we're processing event if (widgetHit) @@ -1357,7 +1370,7 @@ PRBool nsMacEventHandler::HandleMouseMoveEvent( EventRecord& aOSEvent ) { nsWindow* lastWidgetHit = gEventDispatchHandler.GetWidgetHit(); nsWindow* lastWidgetPointed = gEventDispatchHandler.GetWidgetPointed(); - + PRBool retVal = PR_FALSE; nsMouseEvent mouseEvent; diff --git a/mozilla/widget/src/mac/nsMacEventHandler.h b/mozilla/widget/src/mac/nsMacEventHandler.h index 4ba349a6678..60d28d7d647 100644 --- a/mozilla/widget/src/mac/nsMacEventHandler.h +++ b/mozilla/widget/src/mac/nsMacEventHandler.h @@ -37,6 +37,27 @@ class nsWindow; class nsMacWindow; +// +// struct PhantomScrollbarData +// +// When creating the phantom scrollbar for a Gecko instance, create +// one of these structures and stick it in the control's refCon. It +// is used not only to identify our scrollbar from any others, but +// also to pass data to the scrollbar's action proc about which +// widget is the one the mouse is over. +// +struct PhantomScrollbarData +{ + PhantomScrollbarData ( ) + : mTag(kUniqueTag), mWidgetToGetEvent(nsnull) { } + + enum ResType { kUniqueTag = 'mozz' }; + + ResType mTag; // should always be kUniqueTag + nsIWidget* mWidgetToGetEvent; // for the action proc, the widget to get the event +}; + + //------------------------------------------------------------------------- // //------------------------------------------------------------------------- @@ -131,7 +152,7 @@ protected: static PRBool sInBackground; ControlActionUPP mControlActionProc; - + nsMacWindow* mTopLevelWidget; RgnHandle mUpdateRgn; TSMDocumentID mTSMDocument; diff --git a/mozilla/widget/src/mac/nsMacWindow.cpp b/mozilla/widget/src/mac/nsMacWindow.cpp index 0c7e79b4035..1c36ee654d2 100644 --- a/mozilla/widget/src/mac/nsMacWindow.cpp +++ b/mozilla/widget/src/mac/nsMacWindow.cpp @@ -272,11 +272,11 @@ nsMacWindow::nsMacWindow() : Inherited() , mAcceptsActivation(PR_TRUE) , mIsActive(PR_FALSE) , mZoomOnShow(PR_FALSE) - , mPhantomScrollbar(nil) + , mPhantomScrollbar(nsnull) { //mMacEventHandler.reset(new nsMacEventHandler(this)); mMacEventHandler = (auto_ptr) new nsMacEventHandler(this); - WIDGET_SET_CLASSNAME("nsMacWindow"); + WIDGET_SET_CLASSNAME("nsMacWindow"); } @@ -289,6 +289,14 @@ nsMacWindow::~nsMacWindow() { if (mWindowPtr) { + // cleanup the struct we hang off the scrollbar's refcon + if ( mPhantomScrollbar ) { + PhantomScrollbarData* data = + NS_REINTERPRET_CAST(PhantomScrollbarData*, ::GetControlReference(mPhantomScrollbar)); + delete data; + ::SetControlReference(mPhantomScrollbar, (long)nsnull); + } + if (mWindowMadeHere) ::DisposeWindow(mWindowPtr); @@ -300,6 +308,7 @@ nsMacWindow::~nsMacWindow() nsMacMessageSink::RemoveRaptorWindowFromList(mWindowPtr); mWindowPtr = nsnull; } + } @@ -508,13 +517,21 @@ nsresult nsMacWindow::StandardCreate(nsIWidget *aParent, // create a phantom scrollbar to catch the attention of mousewheel // drivers. We'll catch events sent to this scrollbar in the eventhandler - // and dispatch them into gecko as NS_SCROLL_EVENTs at that point. Stash - // an identifier in the refcon so we can check it before calling TrackControl(). - Rect sbRect = { 32000, 32000, 32100, 32016 }; + // and dispatch them into gecko as NS_SCROLL_EVENTs at that point. We need + // to hang a struct off the refCon in order to provide some data + // to the action proc. + // + // For Logitech, the scrollbar has to be in the content area but can have + // zero width. For USBOverdrive (used also my MSFT), the scrollbar can be + // anywhere, but must have a valid width (one pixel wide works). The + // current location (one pixel wide, and flush along the left side of the + // window) is a reasonable comprimise in the short term. It is not intended + // to fix all cases. + Rect sbRect = { 100, 0, 200, 1 }; mPhantomScrollbar = ::NewControl ( mWindowPtr, &sbRect, nil, true, 50, 0, 100, - kControlScrollBarLiveProc, (long)'mozz' ); + kControlScrollBarLiveProc, (long)new PhantomScrollbarData ); ::EmbedControl ( rootControl, mPhantomScrollbar ); - + // register tracking and receive handlers with the native Drag Manager #if !TARGET_CARBON if ( sDragTrackingHandlerUPP ) {