From 818da747fa89cbbbb61e7a4bf65500fd8eb1767a Mon Sep 17 00:00:00 2001 From: "smfr%smfr.org" Date: Thu, 7 Jul 2005 15:47:49 +0000 Subject: [PATCH] Fix the drawing part of bug 298677: scrollbars draw in the wrong place. Fixed by registering a Carbon Event handler on the native control that ensures that the port origin is set correctly before control draws. r=josh, jhpedemonte. sr=me. a=shaver. git-svn-id: svn://10.0.0.236/trunk@175750 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/widget/src/mac/nsMacControl.cpp | 129 ++++++++++++++++++- mozilla/widget/src/mac/nsMacControl.h | 9 +- mozilla/widget/src/mac/nsNativeScrollbar.cpp | 6 +- mozilla/widget/src/mac/nsWindow.h | 2 + 4 files changed, 136 insertions(+), 10 deletions(-) diff --git a/mozilla/widget/src/mac/nsMacControl.cpp b/mozilla/widget/src/mac/nsMacControl.cpp index dd5f6e771af..4af492a0bf5 100644 --- a/mozilla/widget/src/mac/nsMacControl.cpp +++ b/mozilla/widget/src/mac/nsMacControl.cpp @@ -40,6 +40,7 @@ #include "nsFont.h" #include "nsFontUtils.h" #include "nsToolkit.h" +#include "nsGfxUtils.h" #include "nsMacControl.h" #include "nsColor.h" @@ -55,11 +56,83 @@ #include #include +#if 0 +void DumpControlState(ControlHandle inControl, const char* message) +{ + if (!message) message = "gdb called"; + + CGrafPtr curPort; + ::GetPort((GrafPtr*)&curPort); + Rect portBounds; + ::GetPortBounds(curPort, &portBounds); + + Rect controlBounds = {0, 0, 0, 0}; + if (inControl) + ::GetControlBounds(inControl, &controlBounds); + + printf("%20s -- port %p bounds %d, %d, %d, %d, control bounds %d, %d, %d, %d\n", message, curPort, + portBounds.left, portBounds.top, portBounds.right, portBounds.bottom, + controlBounds.left, controlBounds.top, controlBounds.right, controlBounds.bottom); +} +#endif + + static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID); // TODO: leaks, need to release when unloading the dll nsIUnicodeEncoder * nsMacControl::mUnicodeEncoder = nsnull; nsIUnicodeDecoder * nsMacControl::mUnicodeDecoder = nsnull; +static const EventTypeSpec kControlEventList[] = +{ + { kEventClassControl, kEventControlDraw } +}; + + +static pascal OSStatus MacControlDrawHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) +{ + nsMacControl* macControl = NS_REINTERPRET_CAST(nsMacControl*, inUserData); + + ControlRef theControl; + ::GetEventParameter(inEvent, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &theControl); + + CGrafPtr controlPort; // port we're drawing into (usually the control's port) + if (::GetEventParameter(inEvent, kEventParamGrafPort, typeGrafPtr, NULL, sizeof(CGrafPtr), NULL, &controlPort) != noErr) + controlPort = ::GetWindowPort(::GetControlOwner(theControl)); + + OSStatus err = eventNotHandledErr; + + // see if we're already inside a StartDraw/EndDraw (e.g. OnPaint()) + if (macControl->IsDrawing()) + { + // we need to make sure that the port origin is set correctly for the control's + // widget, because other handlers before us may have messed with it. + nsRect controlBounds; + macControl->GetBounds(controlBounds); + + nsPoint origin(controlBounds.x, controlBounds.y); + macControl->LocalToWindowCoordinate(origin); + + Point newOrigin; + newOrigin.h = -origin.x; + newOrigin.v = -origin.y; + + StOriginSetter setter(controlPort, &newOrigin); + + err = ::CallNextEventHandler(inHandlerCallRef, inEvent); + } + else + { + // make sure we leave the origin set for other controls + StOriginSetter originSetter(controlPort); + macControl->StartDraw(); + err = ::CallNextEventHandler(inHandlerCallRef, inEvent); + macControl->EndDraw(); + } + + return err; +} + +#pragma mark - //------------------------------------------------------------------------- // @@ -74,6 +147,7 @@ nsMacControl::nsMacControl() mMouseInButton = PR_FALSE; mControl = nsnull; + mControlEventHandler = nsnull; mControlType = pushButProc; mLastBounds.SetRect(0,0,0,0); @@ -115,7 +189,7 @@ nsMacControl::~nsMacControl() if (mControl) { Show(PR_FALSE); - ::DisposeControl(mControl); + ClearControl(); mControl = nsnull; } } @@ -339,21 +413,23 @@ ControlPartCode nsMacControl::GetControlHiliteState() // //------------------------------------------------------------------------- -NS_METHOD nsMacControl::CreateOrReplaceMacControl(short inControlType) +nsresult nsMacControl::CreateOrReplaceMacControl(short inControlType) { nsRect controlRect; GetRectForMacControl(controlRect); Rect macRect; nsRectToMacRect(controlRect, macRect); - if(nsnull != mWindowPtr) + if (nsnull != mWindowPtr) { - if (mControl) - ::DisposeControl(mControl); + ClearControl(); StartDraw(); mControl = ::NewControl(mWindowPtr, &macRect, "\p", mVisible, mValue, mMin, mMax, inControlType, nil); - EndDraw(); + EndDraw(); + + if (mControl) + InstallEventHandlerOnControl(); // need to reset the font now // XXX to do: transfer the text in the old control over too @@ -366,6 +442,47 @@ NS_METHOD nsMacControl::CreateOrReplaceMacControl(short inControlType) return (mControl) ? NS_OK : NS_ERROR_NULL_POINTER; } +//------------------------------------------------------------------------- +// +// +//------------------------------------------------------------------------- +void nsMacControl::ClearControl() +{ + RemoveEventHandlerFromControl(); + if (mControl) + { + ::DisposeControl(mControl); + mControl = nsnull; + } +} + +//------------------------------------------------------------------------- +// +// +//------------------------------------------------------------------------- +DEFINE_ONE_SHOT_HANDLER_GETTER(MacControlDrawHandler) + +OSStatus nsMacControl::InstallEventHandlerOnControl() +{ + return ::InstallControlEventHandler(mControl, + GetMacControlDrawHandlerUPP(), + GetEventTypeCount(kControlEventList), kControlEventList, + (void*)this, &mControlEventHandler); +} + + +//------------------------------------------------------------------------- +// +// +//------------------------------------------------------------------------- +void nsMacControl::RemoveEventHandlerFromControl() +{ + if (mControlEventHandler) + { + ::RemoveEventHandler(mControlEventHandler); + mControlEventHandler = nsnull; + } +} //------------------------------------------------------------------------- // diff --git a/mozilla/widget/src/mac/nsMacControl.h b/mozilla/widget/src/mac/nsMacControl.h index c7f4054b35f..0a168fe7832 100644 --- a/mozilla/widget/src/mac/nsMacControl.h +++ b/mozilla/widget/src/mac/nsMacControl.h @@ -79,7 +79,13 @@ public: protected: - NS_METHOD CreateOrReplaceMacControl(short inControlType); + nsresult CreateOrReplaceMacControl(short inControlType); + + OSStatus InstallEventHandlerOnControl(); + void RemoveEventHandlerFromControl(); + + void ClearControl(); + virtual void GetRectForMacControl(nsRect &outRect); virtual ControlPartCode GetControlHiliteState(); @@ -97,6 +103,7 @@ protected: PRInt32 mMin; PRInt32 mMax; ControlHandle mControl; + EventHandlerRef mControlEventHandler; short mControlType; nsString mLastLabel; diff --git a/mozilla/widget/src/mac/nsNativeScrollbar.cpp b/mozilla/widget/src/mac/nsNativeScrollbar.cpp index e5bed31b5b3..c1cb2f96f40 100644 --- a/mozilla/widget/src/mac/nsNativeScrollbar.cpp +++ b/mozilla/widget/src/mac/nsNativeScrollbar.cpp @@ -47,7 +47,6 @@ #include "nsIDOMElement.h" #include "nsIScrollbarMediator.h" -#include "Sound.h" inline void BoundsCheck(PRInt32 low, PRUint32& value, PRUint32 high) { @@ -178,7 +177,8 @@ nsNativeScrollbar::DoScrollAction(ControlPartCode part) GetPosition(&oldPos); GetLineIncrement(&incr); GetViewSize(&visibleImageSize); - switch(part) + + switch (part) { // // For the up/down buttons, scroll up or down by the line height and @@ -485,7 +485,7 @@ nsNativeScrollbar::SetViewSize(PRUint32 aSize) if ( GetControl() ) { StartDraw(); - SetControlViewSize(GetControl(), mVisibleImageSize); + ::SetControlViewSize(GetControl(), mVisibleImageSize); EndDraw(); } return NS_OK; diff --git a/mozilla/widget/src/mac/nsWindow.h b/mozilla/widget/src/mac/nsWindow.h index 26864cd996b..e25f3d81a3f 100644 --- a/mozilla/widget/src/mac/nsWindow.h +++ b/mozilla/widget/src/mac/nsWindow.h @@ -180,6 +180,8 @@ public: virtual void StartDraw(nsIRenderingContext* aRenderingContext = nsnull); virtual void EndDraw(); + PRBool IsDrawing() const { return mDrawing; } + NS_IMETHOD Update(); virtual void UpdateWidget(nsRect& aRect, nsIRenderingContext* aContext);