From 43615396008d37e79fbc6f42176ffe7b7d00b74c Mon Sep 17 00:00:00 2001 From: "smfr%smfr.org" Date: Fri, 30 Sep 2005 00:59:29 +0000 Subject: [PATCH] Widget part of fix for bug 297343: avoid re-entrant -[NSWindow makeKeyAndOrderFront:] calls by postponing the focus and activate calls into Gecko so that they get called the next time through the event loop, when window visibility and key status are correct. This allows embedder code that implements to nsIEmbeddingWindow::SetFocus() to check those and avoid re-entrant/redundant makeKeyAndOrderFront: calls. r=mento. Only affects Camino. --- widget/src/cocoa/mozView.h | 12 +- widget/src/cocoa/nsChildView.h | 73 +++++------- widget/src/cocoa/nsChildView.mm | 158 +++++++++++++++++--------- widget/src/cocoa/nsCocoaWindow.mm | 1 - widget/src/cocoa/nsNativeScrollbar.h | 11 +- widget/src/cocoa/nsNativeScrollbar.mm | 49 ++++---- 6 files changed, 177 insertions(+), 127 deletions(-) diff --git a/widget/src/cocoa/mozView.h b/widget/src/cocoa/mozView.h index 6fb66544d372..afd520711b10 100644 --- a/widget/src/cocoa/mozView.h +++ b/widget/src/cocoa/mozView.h @@ -52,20 +52,26 @@ class nsIWidget; @protocol mozView // access the nsIWidget associated with this view. DOES NOT ADDREF. -- (nsIWidget*) widget; +- (nsIWidget*)widget; // access the native cocoa window (NSWindow) that this view // is in. It's necessary for a gecko NSView to keep track of the // window because |-window| returns nil when the view has been // removed from the view hierarchy (as is the case when it's hidden, // since you can't just hide a view, that would make too much sense). -- (NSWindow*) getNativeWindow; -- (void) setNativeWindow: (NSWindow*)aWindow; +- (NSWindow*)getNativeWindow; +- (void)setNativeWindow:(NSWindow*)aWindow; + + // return a context menu for this view +- (NSMenu*)getContextMenu; // calls setNeedsDisplay, with the rect in inRectValue if supplied. // Allows callers to do a delayed invalidate using // -performSelector:withObject:afterDelay: - (void)setNeedsDisplayWithValue:(NSValue*)inRectValue; + // called when our corresponding Gecko view goes away +- (void)widgetDestroyed; + @end diff --git a/widget/src/cocoa/nsChildView.h b/widget/src/cocoa/nsChildView.h index 1438d33a4d4e..24be7b41d77e 100644 --- a/widget/src/cocoa/nsChildView.h +++ b/widget/src/cocoa/nsChildView.h @@ -34,8 +34,9 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -#ifndef Window_h__ -#define Window_h__ + +#ifndef nsChildView_h__ +#define nsChildView_h__ #import "mozView.h" @@ -71,6 +72,7 @@ class nsChildView; @interface ChildView : NSQuickDrawView { +@private NSWindow* mWindow; // shortcut to the top window, [WEAK] // the nsChildView that created the view. It retains this NSView, so @@ -131,6 +133,14 @@ public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIEVENTSINK + + // nsIKBStateControl interface + NS_IMETHOD ResetInputState(); + NS_IMETHOD SetIMEOpenState(PRBool aState); + NS_IMETHOD GetIMEOpenState(PRBool* aState); + NS_IMETHOD SetIMEEnabled(PRBool aState); + NS_IMETHOD GetIMEEnabled(PRBool* aState); + NS_IMETHOD CancelIMEComposition(); // nsIWidget interface NS_IMETHOD Create(nsIWidget *aParent, @@ -202,10 +212,10 @@ public: NS_IMETHOD DispatchEvent(nsGUIEvent* event, nsEventStatus & aStatus); virtual PRBool DispatchMouseEvent(nsMouseEvent &aEvent); - virtual void StartDraw(nsIRenderingContext* aRenderingContext = nsnull); - virtual void EndDraw(); - NS_IMETHOD Update(); - virtual void UpdateWidget(nsRect& aRect, nsIRenderingContext* aContext); + virtual void StartDraw(nsIRenderingContext* aRenderingContext = nsnull); + virtual void EndDraw(); + NS_IMETHOD Update(); + virtual void UpdateWidget(nsRect& aRect, nsIRenderingContext* aContext); virtual void ConvertToDeviceCoordinates(nscoord &aX, nscoord &aY); void LocalToWindowCoordinate(nsPoint& aPoint) { ConvertToDeviceCoordinates(aPoint.x, aPoint.y); } @@ -219,6 +229,7 @@ public: NS_IMETHOD SetPreferredSize(PRInt32 aWidth, PRInt32 aHeight); NS_IMETHOD SetCursor(nsCursor aCursor); + NS_IMETHOD SetCursor(imgIContainer* aCursor, PRUint32 aHotspotX, PRUint32 aHotspotY); NS_IMETHOD CaptureRollupEvents(nsIRollupListener * aListener, PRBool aDoCapture, PRBool aConsumeRollupEvent); NS_IMETHOD SetTitle(const nsAString& title); @@ -247,48 +258,34 @@ public: void LiveResizeStarted(); void LiveResizeEnded(); -public: - // nsIKBStateControl interface - NS_IMETHOD ResetInputState(); - NS_IMETHOD SetIMEOpenState(PRBool aState); - NS_IMETHOD GetIMEOpenState(PRBool* aState); - NS_IMETHOD SetIMEEnabled(PRBool aState); - NS_IMETHOD GetIMEEnabled(PRBool* aState); - NS_IMETHOD CancelIMEComposition(); - protected: - PRBool ReportDestroyEvent(); - PRBool ReportMoveEvent(); - PRBool ReportSizeEvent(); + PRBool ReportDestroyEvent(); + PRBool ReportMoveEvent(); + PRBool ReportSizeEvent(); NS_IMETHOD CalcOffset(PRInt32 &aX,PRInt32 &aY); - virtual PRBool OnPaint(nsPaintEvent & aEvent); - - // our own impl of ::ScrollRect() that uses CopyBits so that it looks good. On - // Carbon, this just calls ::ScrollWindowRect() - void ScrollBits ( Rect & foo, PRInt32 inLeftDelta, PRInt32 inTopDelta ) ; + virtual PRBool OnPaint(nsPaintEvent & aEvent); // override to create different kinds of child views. Autoreleases, so // caller must retain. - virtual NSView* CreateCocoaView(NSRect inFrame); - void TearDownView(); + virtual NSView* CreateCocoaView(NSRect inFrame); + void TearDownView(); // Find a quickdraw port in which to draw (needed by GFX until it // is converted to Cocoa). This MUST be overridden if CreateCocoaView() // does not create something that inherits from NSQuickDrawView! - virtual GrafPtr GetQuickDrawPort() ; + virtual GrafPtr GetQuickDrawPort(); // gets plugin port or view's port -/* protected: */ -public: -#if DEBUG - const char* gInstanceClassName; -#endif + // return qdPort for a focussed ChildView, and null otherwise + GrafPtr GetChildViewQuickDrawPort(); - id mView; // my parallel cocoa view, [STRONG] +protected: - NSView* mParentView; + NSView* mView; // my parallel cocoa view (ChildView or NativeScrollbarView), [STRONG] + + NSView* mParentView; nsIWidget* mParentWidget; nsIFontMetrics* mFontMetrics; @@ -312,12 +309,4 @@ public: }; -#if DEBUG -#define WIDGET_SET_CLASSNAME(n) gInstanceClassName = (n) -#else -#define WIDGET_SET_CLASSNAME(n) -#endif - - - -#endif // Window_h__ +#endif // nsChildView_h__ diff --git a/widget/src/cocoa/nsChildView.mm b/widget/src/cocoa/nsChildView.mm index 92b15d13236d..9549e10c63c7 100644 --- a/widget/src/cocoa/nsChildView.mm +++ b/widget/src/cocoa/nsChildView.mm @@ -78,6 +78,9 @@ @interface ChildView(Private) + // sets up our view, attaching it to its owning gecko view +- (id)initWithFrame:(NSRect)inFrame geckoChild:(nsChildView*)inChild eventSink:(nsIEventSink*)inSink; + // sends gecko an ime composition event - (nsRect) sendCompositionEvent:(PRInt32)aEventType; @@ -88,9 +91,6 @@ markedRange:(NSRange)markRange doCommit:(BOOL)doCommit; - // sets up our view, attaching it to its owning gecko view -- (id)initWithFrame:(NSRect)inFrame geckoChild:(nsChildView*)inChild eventSink:(nsIEventSink*)inSink; - // convert from one event system to the other for event dispatching - (void) convertEvent:(NSEvent*)inEvent message:(PRInt32)inMsg toGeckoEvent:(nsInputEvent*)outGeckoEvent; @@ -111,6 +111,9 @@ - (void)flushRect:(NSRect)inRect; - (BOOL)isRectObscuredBySubview:(NSRect)inRect; +- (void)sendActivateEvent; +- (void)sendDeactivateEvent; + #if USE_CLICK_HOLD_CONTEXTMENU // called on a timer two seconds after a mouse down to see if we should display // a context menu (click-hold) @@ -300,8 +303,6 @@ nsChildView::nsChildView() : nsBaseWidget() , mPluginPort(nsnull) , mVisRgn(nsnull) { - WIDGET_SET_CLASSNAME("nsChildView"); - SetBackgroundColor(NS_RGB(255, 255, 255)); SetForegroundColor(NS_RGB(0, 0, 0)); } @@ -432,7 +433,7 @@ nsresult nsChildView::StandardCreate(nsIWidget *aParent, // if this is a ChildView, make sure that our per-window data // is set up if ([mView isKindOfClass:[ChildView class]]) - [mView ensureWindowData]; + [(ChildView*)mView ensureWindowData]; return NS_OK; } @@ -520,6 +521,8 @@ NS_IMETHODIMP nsChildView::Destroy() return NS_OK; mDestroyCalled = PR_TRUE; + [mView widgetDestroyed]; + nsBaseWidget::OnDestroy(); nsBaseWidget::Destroy(); @@ -573,18 +576,19 @@ void* nsChildView::GetNativeData(PRUint32 aDataType) break; case NS_NATIVE_GRAPHIC: // quickdraw port - // XXX this can return NULL if we are not the focused view - retVal = [mView qdPort]; + // XXX qdPort is invalid if we have not locked focus + retVal = GetChildViewQuickDrawPort(); break; case NS_NATIVE_REGION: { if (!mVisRgn) mVisRgn = ::NewRgn(); - GrafPtr port = (GrafPtr)[mView qdPort]; - if (port && mVisRgn) - ::GetPortVisibleRegion(port, mVisRgn); + // XXX qdPort is invalid if we have not locked focus + GrafPtr grafPort = GetChildViewQuickDrawPort(); + if (grafPort && mVisRgn) + ::GetPortVisibleRegion(grafPort, mVisRgn); retVal = (void*)mVisRgn; break; } @@ -608,7 +612,8 @@ void* nsChildView::GetNativeData(PRUint32 aDataType) if (mPluginPort == nsnull) { mPluginPort = new nsPluginPort; - [mView setIsPluginView: YES]; + if ([mView isKindOfClass:[ChildView class]]) + [(ChildView*)mView setIsPluginView: YES]; } NSWindow* window = [mView getNativeWindow]; @@ -717,21 +722,6 @@ NS_IMETHODIMP nsChildView::IsEnabled(PRBool *aState) return NS_OK; } - -static Boolean WeAreFrontProcess() -{ - ProcessSerialNumber thisPSN; - ProcessSerialNumber frontPSN; - (void)::GetCurrentProcess(&thisPSN); - if (::GetFrontProcess(&frontPSN) == noErr) - { - if ((frontPSN.highLongOfPSN == thisPSN.highLongOfPSN) && - (frontPSN.lowLongOfPSN == thisPSN.lowLongOfPSN)) - return true; - } - return false; -} - //------------------------------------------------------------------------- // // Set the focus on this component @@ -810,12 +800,20 @@ nsIMenuBar* nsChildView::GetMenuBar() // // Override to set the cursor on the mac // -NS_METHOD nsChildView::SetCursor(nsCursor aCursor) +NS_IMETHODIMP nsChildView::SetCursor(nsCursor aCursor) { nsBaseWidget::SetCursor(aCursor); [[nsCursorManager sharedInstance] setCursor: aCursor]; return NS_OK; -} // nsChildView::SetCursor +} + +// implement to fix "hidden virtual function" warning +NS_IMETHODIMP nsChildView::SetCursor(imgIContainer* aCursor, + PRUint32 aHotspotX, PRUint32 aHotspotY) +{ + return nsBaseWidget::SetCursor(aCursor, aHotspotX, aHotspotY); +} + #pragma mark - //------------------------------------------------------------------------- @@ -1418,7 +1416,9 @@ nsChildView::UpdateWidget(nsRect& aRect, nsIRenderingContext* aContext) // For updating widgets, we _always_ want to use the NSQuickDrawView's port, // since that's the correct port for gecko to use to make rendering contexts. // The plugin is the only thing that uses the plugin port. - GrafPtr curPort = (GrafPtr)[mView qdPort]; + GrafPtr curPort = GetChildViewQuickDrawPort(); + if (!curPort) return; + StPortSetter port(curPort); // initialize the paint event @@ -1880,7 +1880,7 @@ NS_IMETHODIMP nsChildView::ScreenToWidget(const nsRect& aGlobalRect, nsRect& aLo * @param nscoord -- Y coordinate to convert * @return NONE */ -void nsChildView::ConvertToDeviceCoordinates(nscoord &aX, nscoord &aY) +void nsChildView::ConvertToDeviceCoordinates(nscoord &aX, nscoord &aY) { PRInt32 offX = 0, offY = 0; this->CalcOffset(offX,offY); @@ -2001,8 +2001,17 @@ nsChildView::GetQuickDrawPort() { if (mPluginPort) return mPluginPort->port; - else - return (GrafPtr) [mView qdPort]; + + return GetChildViewQuickDrawPort(); +} + +GrafPtr +nsChildView::GetChildViewQuickDrawPort() +{ + if ([mView isKindOfClass:[ChildView class]]) + return (GrafPtr)[(ChildView*)mView qdPort]; + + return nsnull; } #pragma mark - @@ -2036,7 +2045,7 @@ nsChildView::DragEvent(PRUint32 aMessage, PRInt16 aMouseGlobalX, PRInt16 aMouseG // ensure that this is going to a ChildView (not something else like a // scrollbar). I think it's safe to just bail at this point if it's not // what we expect it to be - if ( ![mView isKindOfClass:[ChildView class]] ) { + if (![mView isKindOfClass:[ChildView class]]) { *_retval = PR_FALSE; return NS_OK; } @@ -2060,13 +2069,12 @@ nsChildView::DragEvent(PRUint32 aMessage, PRInt16 aMouseGlobalX, PRInt16 aMouseG // convert to window coords dragLoc = [[mView window] convertScreenToBase:dragLoc]; // and fill in the event - [mView convertLocation:dragLoc message:aMessage modifiers:0 toGeckoEvent:&geckoEvent]; + [(ChildView*)mView convertLocation:dragLoc message:aMessage modifiers:0 toGeckoEvent:&geckoEvent]; DispatchWindowEvent(geckoEvent); // we handled the event *_retval = PR_TRUE; - return NS_OK; } @@ -2136,6 +2144,12 @@ nsChildView::Idle() SetPort(NULL); // Bullet-proof against future changes in NSQDView } +- (void)widgetDestroyed +{ + mGeckoChild = nsnull; + mEventSink = nsnull; +} + // // -widget // mozView method @@ -2428,10 +2442,8 @@ nsChildView::Idle() - (void)drawRect:(NSRect)aRect { PRBool isVisible; - mGeckoChild->IsVisible(isVisible); - if (!isVisible) { + if (!mGeckoChild || NS_FAILED(mGeckoChild->IsVisible(isVisible)) || !isVisible) return; - } // Workaround for the fact that NSQuickDrawViews can't be opaque; see if the rect // being drawn is covered by a subview, and, if so, just bail. @@ -2851,9 +2863,13 @@ nsChildView::Idle() return [self getContextMenu]; } --(NSMenu*)getContextMenu +- (NSMenu*)getContextMenu { - return [[self superview] getContextMenu]; + NSView* superView = [self superview]; + if ([superView respondsToSelector:@selector(getContextMenu)]) + return [(NSView*)superView getContextMenu]; + + return nil; } - (TopLevelWindowData*)ensureWindowData @@ -2989,7 +3005,7 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac doCommit:(BOOL) doCommit { #ifdef DEBUG_IME - NSLog(@"****in sendTextEvent; string = %@", aString); + NSLog(@"****in sendTextEvent; string = '%@'", aString); NSLog(@" markRange = %d, %d; selRange = %d, %d", markRange.location, markRange.length, selRange.location, selRange.length); #endif @@ -3011,7 +3027,7 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac - (void)insertText:(id)insertString { #if DEBUG_IME - NSLog(@"****in insertText: %@", insertString); + NSLog(@"****in insertText: '%@'", insertString); NSLog(@" markRange = %d, %d; selRange = %d, %d", mMarkedRange.location, mMarkedRange.length, mSelectedRange.location, mSelectedRange.length); #endif @@ -3078,7 +3094,10 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac } - (void) doCommandBySelector:(SEL)aSelector -{ +{ +#if DEBUG_IME + NSLog(@"**** in doCommandBySelector %s", aSelector); +#endif [super doCommandBySelector:aSelector]; } @@ -3087,7 +3106,7 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac #if DEBUG_IME NSLog(@"****in setMarkedText location: %d, length: %d", selRange.location, selRange.length); NSLog(@" markRange = %d, %d; selRange = %d, %d", mMarkedRange.location, mMarkedRange.length, mSelectedRange.location, mSelectedRange.length); - NSLog(@" aString = %@", aString); + NSLog(@" aString = '%@'", aString); #endif if ( ![aString isKindOfClass:[NSAttributedString class]] ) @@ -3251,6 +3270,11 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac return 0; } + +// need to declare this because AppKit does not make it available as API or SPI +//static NSString* const NSMarkedClauseSegmentAttributeName = @"NSMarkedClauseSegment"; +//static NSString* const NSTextInputReplacementRangeAttributeName = @"NSTextInputReplacementRangeAttributeName"; + - (NSArray*) validAttributesForMarkedText { #if DEBUG_IME @@ -3258,6 +3282,7 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac NSLog(@" markRange = %d, %d; selectRange = %d, %d", mMarkedRange.location, mMarkedRange.length, mSelectedRange.location, mSelectedRange.length); #endif + //return [NSArray arrayWithObjects:NSUnderlineStyleAttributeName, NSMarkedClauseSegmentAttributeName, NSTextInputReplacementRangeAttributeName, nil]; return [NSArray array]; // empty array; we don't support any attributes right now } // end NSTextInput @@ -3268,8 +3293,6 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac // Handle matching cocoa IME with gecko key events. Sends a key down and key press // event to gecko. // -// NOTE: diacriticals (opt-e, e) aren't fully handled. -// - (void)keyDown:(NSEvent*)theEvent { PRBool isKeyDownEventHandled = PR_TRUE; @@ -3416,6 +3439,8 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac // This method is called when we are about to be focused. - (BOOL)becomeFirstResponder { + if (!mGeckoChild) return NO; // we've been destroyed + nsFocusEvent event(PR_TRUE, NS_GOTFOCUS, mGeckoChild); mGeckoChild->DispatchWindowEvent(event); @@ -3425,6 +3450,8 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac // This method is called when are are about to lose focus. - (BOOL)resignFirstResponder { + if (!mGeckoChild) return NO; // we've been destroyed + nsFocusEvent event(PR_TRUE, NS_LOSTFOCUS, mGeckoChild); mGeckoChild->DispatchWindowEvent(event); @@ -3433,20 +3460,47 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac - (void)viewsWindowDidBecomeKey { + // When unhiding the app, -windowBecameKey: gets called when two bits of window + // state are incorrect (on Tiger): + // + // 1. [window isVisible] returns YES even though it's not on the screen + // 2. [NSApp keyWindow] is not the right window yet + // + // Because this state is not correct at this time, we postpone sending + // the events into gecko (which in turn propagate into the host app) + // until the next time through the event loop, when we're off this stack + // and Cocoa has got its story straight. + [self performSelector:@selector(sendActivateEvent) withObject:nil afterDelay:0]; +} + +- (void)viewsWindowDidResignKey +{ + [self performSelector:@selector(sendDeactivateEvent) withObject:nil afterDelay:0]; +} + +- (void)sendActivateEvent +{ + if (!mGeckoChild) + return; // we've been destroyed + nsFocusEvent focusEvent(PR_TRUE, NS_GOTFOCUS, mGeckoChild); mGeckoChild->DispatchWindowEvent(focusEvent); nsFocusEvent activateEvent(PR_TRUE, NS_ACTIVATE, mGeckoChild); mGeckoChild->DispatchWindowEvent(activateEvent); - } -- (void)viewsWindowDidResignKey +- (void)sendDeactivateEvent { - nsFocusEvent event(PR_TRUE, NS_LOSTFOCUS, mGeckoChild); - mGeckoChild->DispatchWindowEvent(event); -} + if (!mGeckoChild) + return; // we've been destroyed + + nsFocusEvent deactivateEvent(PR_TRUE, NS_DEACTIVATE, mGeckoChild); + mGeckoChild->DispatchWindowEvent(deactivateEvent); + nsFocusEvent unfocusEvent(PR_TRUE, NS_LOSTFOCUS, mGeckoChild); + mGeckoChild->DispatchWindowEvent(unfocusEvent); +} //------------------------------------------------------------------------- // diff --git a/widget/src/cocoa/nsCocoaWindow.mm b/widget/src/cocoa/nsCocoaWindow.mm index a48def919bc3..a909dc9ce2d1 100644 --- a/widget/src/cocoa/nsCocoaWindow.mm +++ b/widget/src/cocoa/nsCocoaWindow.mm @@ -290,7 +290,6 @@ nsCocoaWindow::nsCocoaWindow() { #if 0 mMacEventHandler.reset(new nsMacEventHandler(this)); - WIDGET_SET_CLASSNAME("nsCocoaWindow"); // create handlers for drag&drop mDragTrackingHandlerUPP = NewDragTrackingHandlerUPP(DragTrackingHandler); diff --git a/widget/src/cocoa/nsNativeScrollbar.h b/widget/src/cocoa/nsNativeScrollbar.h index 506ee6a2885f..6c85ea25de8f 100644 --- a/widget/src/cocoa/nsNativeScrollbar.h +++ b/widget/src/cocoa/nsNativeScrollbar.h @@ -39,15 +39,16 @@ #ifndef nsNativeScrollbar_h__ #define nsNativeScrollbar_h__ -#include "nsINativeScrollbar.h" #include "nsChildView.h" -#include + +#include "nsINativeScrollbar.h" #include "nsIContent.h" #import "mozView.h" class nsIScrollbarMediator; +@class NativeScrollbarView; // // nsNativeScrollbar @@ -65,8 +66,6 @@ public: nsNativeScrollbar(); virtual ~nsNativeScrollbar(); - NS_IMETHOD Destroy(); - NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSINATIVESCROLLBAR @@ -93,6 +92,8 @@ protected: void UpdateScroller(); + NativeScrollbarView* ScrollbarView() const { return (NativeScrollbarView*)mView; } + // DATA private: @@ -126,8 +127,6 @@ private: // overridden parent class initializer - (id)initWithFrame:(NSRect)frameRect; -- (void)scrollbarDestroyed; - - (IBAction)scroll:(NSScroller*)sender; @end diff --git a/widget/src/cocoa/nsNativeScrollbar.mm b/widget/src/cocoa/nsNativeScrollbar.mm index 64c716483dbe..25dd01ec084f 100644 --- a/widget/src/cocoa/nsNativeScrollbar.mm +++ b/widget/src/cocoa/nsNativeScrollbar.mm @@ -35,9 +35,6 @@ * * ***** END LICENSE BLOCK ***** */ - -#include - #include "nsNativeScrollbar.h" #include "nsIDeviceContext.h" @@ -69,7 +66,6 @@ nsNativeScrollbar::nsNativeScrollbar() , mLineIncrement(0) , mIsEnabled(PR_TRUE) { - WIDGET_SET_CLASSNAME("nsNativeScrollbar"); } @@ -77,13 +73,6 @@ nsNativeScrollbar::~nsNativeScrollbar() { } -NS_IMETHODIMP -nsNativeScrollbar::Destroy() -{ - [mView scrollbarDestroyed]; - return NS_OK; -} - // // CreateCocoaView // @@ -198,7 +187,7 @@ nsNativeScrollbar::DoScroll(NSScrollerPart inPart) // case NSScrollerKnob: case NSScrollerKnobSlot: - newPos = (int) ([mView floatValue] * mMaxValue); + newPos = (int) ([ScrollbarView() floatValue] * mMaxValue); UpdateContentPosition(newPos); if ( mMediator ) { PRInt32 op = oldPos, np = mValue; @@ -293,6 +282,8 @@ nsNativeScrollbar::GetMaxRange(PRUint32* aMaxRange) NS_IMETHODIMP nsNativeScrollbar::SetPosition(PRUint32 aPos) { + NativeScrollbarView* scrollbarView = ScrollbarView(); + if ((PRInt32)aPos < 0) aPos = 0; @@ -305,9 +296,9 @@ nsNativeScrollbar::SetPosition(PRUint32 aPos) // mValue = ((PRInt32)aPos) > mMaxValue ? mMaxValue : ((int)aPos); mValue = aPos; if ( mMaxValue ) - [mView setFloatValue:(mValue / (float)mMaxValue)]; + [scrollbarView setFloatValue:(mValue / (float)mMaxValue)]; else - [mView setFloatValue:0.0]; + [scrollbarView setFloatValue:0.0]; return NS_OK; } @@ -448,13 +439,16 @@ nsNativeScrollbar::RecreateHorizontalScrollbar() orientation.size.width = 100; orientation.size.height = 16; + NativeScrollbarView* scrollbarView = ScrollbarView(); + // save off the old values and get rid of the previous view. Hiding // it removes it from the parent hierarchy. - NSRect oldBounds = [mView bounds]; - float oldValue = [mView floatValue]; - float oldProportion = [mView knobProportion]; + NSRect oldBounds = [scrollbarView bounds]; + float oldValue = [scrollbarView floatValue]; + float oldProportion = [scrollbarView knobProportion]; mVisible = PR_TRUE; // ensure that hide does the work Show(PR_FALSE); + scrollbarView = nil; [mView release]; // create the new horizontal scroller, init it, hook it up to the @@ -462,7 +456,9 @@ nsNativeScrollbar::RecreateHorizontalScrollbar() mView = [[NativeScrollbarView alloc] initWithFrame:orientation geckoChild:this]; [mView setNativeWindow: [mParentView getNativeWindow]]; [mView setFrame:oldBounds]; - [mView setFloatValue:oldValue knobProportion:oldProportion]; + + scrollbarView = ScrollbarView(); + [scrollbarView setFloatValue:oldValue knobProportion:oldProportion]; Show(PR_TRUE); Enable(PR_TRUE); } @@ -519,18 +515,20 @@ nsNativeScrollbar::IsEnabled(PRBool *aState) void nsNativeScrollbar::UpdateScroller() { + NativeScrollbarView* scrollbarView = ScrollbarView(); + // Update the current value based on the new range. We need to recompute the // float value in case we had to set the value to 0 because gecko cheated // and set the position before it set the max value. float knobProp = 1.0f; if ((mVisibleImageSize + mMaxValue) > 0) knobProp = (float)mVisibleImageSize / (float)(mVisibleImageSize + mMaxValue); - [mView setFloatValue:(mValue / (float)mMaxValue) knobProportion:knobProp]; + [scrollbarView setFloatValue:(mValue / (float)mMaxValue) knobProportion:knobProp]; BOOL enableScrollbar = (mIsEnabled && (mMaxValue > 0)); - [mView setEnabled:enableScrollbar]; + [scrollbarView setEnabled:enableScrollbar]; - [mView setNeedsDisplay:YES]; + [scrollbarView setNeedsDisplay:YES]; } @@ -639,11 +637,11 @@ nsNativeScrollbar::UpdateScroller() } // -// -scrollbarDestroyed +// -widgetDestroyed // // the gecko nsNativeScrollbar is being destroyed. // -- (void)scrollbarDestroyed +- (void)widgetDestroyed { mGeckoChild = nsnull; @@ -666,6 +664,11 @@ nsNativeScrollbar::UpdateScroller() } } +// getContextMenu, from mozView protocol +- (NSMenu*)getContextMenu +{ + return nil; +} // // -scroll