From 8c4468746ee6cb28bc6419a802b85b0fb5594e1c Mon Sep 17 00:00:00 2001 From: "pierre%netscape.com" Date: Fri, 1 Oct 1999 21:40:04 +0000 Subject: [PATCH] Fixed #14775 "Crash removing delete observer when closing windows": reshuffled nsToolkit and added nsMacFocusHandler to nsMacEventHandler. r=dcone/sfraser --- widget/src/mac/nsDeleteObserver.cpp | 10 +- widget/src/mac/nsDeleteObserver.h | 5 +- widget/src/mac/nsMacEventHandler.cpp | 437 ++++++++++++++++----------- widget/src/mac/nsMacEventHandler.h | 86 ++++-- widget/src/mac/nsToolkit.cpp | 206 ++++++------- widget/src/mac/nsToolkit.h | 62 ++-- 6 files changed, 464 insertions(+), 342 deletions(-) diff --git a/widget/src/mac/nsDeleteObserver.cpp b/widget/src/mac/nsDeleteObserver.cpp index 36b2acd2863d..9a81771ad003 100644 --- a/widget/src/mac/nsDeleteObserver.cpp +++ b/widget/src/mac/nsDeleteObserver.cpp @@ -54,21 +54,23 @@ nsDeleteObserved::~nsDeleteObserved() // //------------------------------------------------------------------------- -void nsDeleteObserved::AddDeleteObserver(nsDeleteObserver* aDeleteObserver) +PRBool nsDeleteObserved::AddDeleteObserver(nsDeleteObserver* aDeleteObserver) { if (! mDeleteObserverArray) mDeleteObserverArray = new nsVoidArray(); if (mDeleteObserverArray) - mDeleteObserverArray->AppendElement(aDeleteObserver); + return mDeleteObserverArray->AppendElement(aDeleteObserver); + return PR_FALSE; } //------------------------------------------------------------------------- // //------------------------------------------------------------------------- -void nsDeleteObserved::RemoveDeleteObserver(nsDeleteObserver* aDeleteObserver) +PRBool nsDeleteObserved::RemoveDeleteObserver(nsDeleteObserver* aDeleteObserver) { if (mDeleteObserverArray) - mDeleteObserverArray->RemoveElement(aDeleteObserver); + return mDeleteObserverArray->RemoveElement(aDeleteObserver); + return PR_FALSE; } diff --git a/widget/src/mac/nsDeleteObserver.h b/widget/src/mac/nsDeleteObserver.h index a505d7e9070c..e03ae1f57c0b 100644 --- a/widget/src/mac/nsDeleteObserver.h +++ b/widget/src/mac/nsDeleteObserver.h @@ -18,6 +18,7 @@ #ifndef DeleteObserver_h__ #define DeleteObserver_h__ +#include "prtypes.h" class nsVoidArray; //------------------------------------------------------------------------- @@ -54,8 +55,8 @@ public: nsDeleteObserved(void* aObject); virtual ~nsDeleteObserved(); - void AddDeleteObserver(nsDeleteObserver* aDeleteObserver); - void RemoveDeleteObserver(nsDeleteObserver* aDeleteObserver); + PRBool AddDeleteObserver(nsDeleteObserver* aDeleteObserver); + PRBool RemoveDeleteObserver(nsDeleteObserver* aDeleteObserver); private: nsVoidArray* mDeleteObserverArray; diff --git a/widget/src/mac/nsMacEventHandler.cpp b/widget/src/mac/nsMacEventHandler.cpp index 6166b5fa7c1e..447426d7e2e3 100644 --- a/widget/src/mac/nsMacEventHandler.cpp +++ b/widget/src/mac/nsMacEventHandler.cpp @@ -20,7 +20,6 @@ #include "nsWindow.h" #include "nsMacWindow.h" -#include "nsToolkit.h" #include "prinrval.h" #include @@ -44,12 +43,143 @@ extern nsIWidget * gRollupWidget; #endif PRBool nsMacEventHandler::mInBackground = PR_FALSE; +PRBool nsMacEventHandler::mMouseInWidgetHit = PR_FALSE; -nsWindow* nsMacEventHandler::mLastWidgetHit = nsnull; -PRBool nsMacEventHandler::mMouseInWidgetHit = PR_FALSE; -nsWindow* nsMacEventHandler::mLastWidgetPointed = nsnull; +nsMacFocusHandler gFocusHandler; +//------------------------------------------------------------------------- +// +//------------------------------------------------------------------------- +nsMacFocusHandler::nsMacFocusHandler() +{ + mFocusedWidget = nsnull; + mWidgetHit = nsnull; + mWidgetPointed = nsnull; +} + + +//------------------------------------------------------------------------- +// +//------------------------------------------------------------------------- +nsMacFocusHandler::~nsMacFocusHandler() +{ + if (mFocusedWidget) + { + mFocusedWidget->RemoveDeleteObserver(this); + mFocusedWidget = nsnull; + } + + if (mWidgetHit) + { + mWidgetHit->RemoveDeleteObserver(this); + mWidgetHit = nsnull; + } + + if (mWidgetPointed) + { + mWidgetPointed->RemoveDeleteObserver(this); + mWidgetPointed = nsnull; + } +} + +//------------------------------------------------------------------------- +// +//------------------------------------------------------------------------- +void nsMacFocusHandler::SetFocus(nsWindow *aFocusedWidget) +{ + if (aFocusedWidget == mFocusedWidget) + return; + + nsGUIEvent guiEvent; + guiEvent.eventStructType = NS_GUI_EVENT; + guiEvent.point.x = 0; + guiEvent.point.y = 0; + guiEvent.time = PR_IntervalNow(); + guiEvent.widget = nsnull; + guiEvent.nativeMsg = nsnull; + + // tell the old widget it is not focused + if (mFocusedWidget) + { + mFocusedWidget->RemoveDeleteObserver(this); + + guiEvent.message = NS_LOSTFOCUS; + guiEvent.widget = mFocusedWidget; + mFocusedWidget->DispatchWindowEvent(guiEvent); + } + + mFocusedWidget = aFocusedWidget; + + // let the new one know it got the focus + if (mFocusedWidget) + { + mFocusedWidget->AddDeleteObserver(this); + + guiEvent.message = NS_GOTFOCUS; + guiEvent.widget = mFocusedWidget; + mFocusedWidget->DispatchWindowEvent(guiEvent); + } +} + + +//------------------------------------------------------------------------- +// +//------------------------------------------------------------------------- +void nsMacFocusHandler::SetWidgetHit(nsWindow *aWidgetHit) +{ + if (aWidgetHit == mWidgetHit) + return; + + if (mWidgetHit) + if (! mWidgetHit->RemoveDeleteObserver(this)) + NS_WARNING("nsMacFocusHandler wasn't in the WidgetHit observer list"); + + mWidgetHit = aWidgetHit; + + if (mWidgetHit) + mWidgetHit->AddDeleteObserver(this); +} + + +//------------------------------------------------------------------------- +// +//------------------------------------------------------------------------- +void nsMacFocusHandler::SetWidgetPointed(nsWindow *aWidgetPointed) +{ + if (aWidgetPointed == mWidgetPointed) + return; + + if (mWidgetPointed) + if (! mWidgetPointed->RemoveDeleteObserver(this)) + NS_WARNING("nsMacFocusHandler wasn't in the WidgetPointed observer list"); + + mWidgetPointed = aWidgetPointed; + + if (mWidgetPointed) + mWidgetPointed->AddDeleteObserver(this); +} + + +//------------------------------------------------------------------------- +// +//------------------------------------------------------------------------- +void nsMacFocusHandler::NotifyDelete(void* aDeletedObject) +{ + if (mFocusedWidget == aDeletedObject) + mFocusedWidget = nsnull; + else + if (mWidgetHit == aDeletedObject) + mWidgetHit = nsnull; + else + if (mWidgetPointed == aDeletedObject) + mWidgetPointed = nsnull; + else + NS_WARNING("NotifyDelete: unknown widget"); +} + + +#pragma mark - //------------------------------------------------------------------------- // // nsMacEventHandler constructor/destructor @@ -60,13 +190,13 @@ nsMacEventHandler::nsMacEventHandler(nsMacWindow* aTopLevelWidget) OSErr err; InterfaceTypeList supportedServices; - mTopLevelWidget = aTopLevelWidget; - mTSMDocument = nsnull; + mTopLevelWidget = aTopLevelWidget; // // create a TSMDocument for this window. We are allocating a TSM document for // each Mac window // + mTSMDocument = nsnull; supportedServices[0] = kTextService; err = ::NewTSMDocument(1,supportedServices,&mTSMDocument,(long)this); NS_ASSERTION(err==noErr,"nsMacEventHandler::nsMacEventHandler: NewTSMDocument failed."); @@ -85,26 +215,11 @@ nsMacEventHandler::nsMacEventHandler(nsMacWindow* aTopLevelWidget) nsMacEventHandler::~nsMacEventHandler() { - if (mLastWidgetPointed) - mLastWidgetPointed->RemoveDeleteObserver(this); - - if (mLastWidgetHit) - mLastWidgetHit->RemoveDeleteObserver(this); - if (mTSMDocument) (void)::DeleteTSMDocument(mTSMDocument); } -void nsMacEventHandler::NotifyDelete(void* aDeletedObject) -{ - if (mLastWidgetPointed == aDeletedObject) - mLastWidgetPointed = nsnull; - - if (mLastWidgetHit == aDeletedObject) - mLastWidgetHit = nsnull; -} - #pragma mark - //------------------------------------------------------------------------- @@ -179,17 +294,10 @@ PRBool nsMacEventHandler::HandleMenuCommand( long aMenuResult) { // get the focused widget - nsWindow* focusedWidget = mTopLevelWidget; - nsCOMPtr toolkit ( dont_AddRef((nsToolkit*)mTopLevelWidget->GetToolkit()) ); - if (toolkit) - focusedWidget = toolkit->GetFocus(); - + nsWindow* focusedWidget = gFocusHandler.GetFocus(); if (!focusedWidget) - { - NS_WARNING("Throwing away menu event because there is no focused widget"); - return PR_FALSE; - } - + focusedWidget = mTopLevelWidget; + // nsEvent nsMenuEvent menuEvent; menuEvent.eventStructType = NS_MENU_EVENT; @@ -206,26 +314,33 @@ PRBool nsMacEventHandler::HandleMenuCommand( menuEvent.mMenuItem = nsnull; //ĄTODO: initialize mMenuItem menuEvent.mCommand = aMenuResult; - // dispatch the menu event: if it is not processed by the focused widget, - // propagate the event through the different parents all the way up to the window + // dispatch the menu event PRBool eventHandled = focusedWidget->DispatchWindowEvent(menuEvent); + // if the menu event is not processed by the focused widget, propagate it + // through the different parents all the way up to the top-level window if (! eventHandled) { - nsCOMPtr grandParent; - nsCOMPtr parent ( dont_AddRef((nsWindow*)focusedWidget->GetParent()) ); - while (parent) + // make sure the focusedWidget wasn't changed or deleted + // when we dispatched the event (even though if we get here, + // the event is supposed to not have been handled) + if (focusedWidget == gFocusHandler.GetFocus()) { - menuEvent.widget = parent; - eventHandled = parent->DispatchWindowEvent(menuEvent); - if (eventHandled) + nsCOMPtr grandParent; + nsCOMPtr parent ( dont_AddRef((nsWindow*)focusedWidget->GetParent()) ); + while (parent) { - break; - } - else - { - grandParent = dont_AddRef((nsWindow*)parent->GetParent()); - parent = grandParent; + menuEvent.widget = parent; + eventHandled = parent->DispatchWindowEvent(menuEvent); + if (eventHandled) + { + break; + } + else + { + grandParent = dont_AddRef((nsWindow*)parent->GetParent()); + parent = grandParent; + } } } } @@ -676,16 +791,9 @@ PRBool nsMacEventHandler::HandleKeyEvent(EventRecord& aOSEvent) nsresult result; // get the focused widget - nsWindow* focusedWidget = mTopLevelWidget; - nsCOMPtr toolkit ( dont_AddRef((nsToolkit*)mTopLevelWidget->GetToolkit()) ); - if (toolkit) - focusedWidget = toolkit->GetFocus(); - + nsWindow* focusedWidget = gFocusHandler.GetFocus(); if (!focusedWidget) - { - NS_WARNING("Throwing away key event because there is no focused widget"); - return PR_FALSE; - } + focusedWidget = mTopLevelWidget; // nsEvent nsKeyEvent keyEvent; @@ -724,71 +832,68 @@ PRBool nsMacEventHandler::HandleKeyEvent(EventRecord& aOSEvent) PRBool nsMacEventHandler::HandleActivateEvent(EventRecord& aOSEvent) { OSErr err; - nsCOMPtr toolkit ( dont_AddRef((nsToolkit*)mTopLevelWidget->GetToolkit()) ); - if (toolkit) + + Boolean isActive = ((aOSEvent.modifiers & activeFlag) != 0); + if (isActive) { - Boolean isActive = ((aOSEvent.modifiers & activeFlag) != 0); - if (isActive) - { - // - // Activate The TSMDocument associated with this handler - // - if (mTSMDocument) - err = ::ActivateTSMDocument(mTSMDocument); + // + // Activate The TSMDocument associated with this handler + // + if (mTSMDocument) + err = ::ActivateTSMDocument(mTSMDocument); #if 0 - NS_ASSERTION(err==noErr,"nsMacEventHandler::HandleActivateEvent: ActivateTSMDocument failed"); - printf("nsEventHandler::HandleActivateEvent: ActivateTSMDocument[%p]\n",mTSMDocument); + NS_ASSERTION(err==noErr,"nsMacEventHandler::HandleActivateEvent: ActivateTSMDocument failed"); + printf("nsEventHandler::HandleActivateEvent: ActivateTSMDocument[%p]\n",mTSMDocument); #endif - - //ĄTODO: retrieve the focused widget for that window - - nsWindow* focusedWidget = mTopLevelWidget; - toolkit->SetFocus(focusedWidget); - nsIMenuBar* menuBar = focusedWidget->GetMenuBar(); - if (menuBar) - { - MenuHandle menuHandle = nsnull; + + //ĄTODO: we should restore the focus to the the widget + // that had it when the window was deactivated + nsWindow* focusedWidget = mTopLevelWidget; + gFocusHandler.SetFocus(focusedWidget); + nsIMenuBar* menuBar = focusedWidget->GetMenuBar(); + if (menuBar) + { + MenuHandle menuHandle = nsnull; - //menuBar->GetNativeData((void *)menuHandle); - //::SetMenuBar((Handle)menuHandle); - menuBar->Paint(); - } - else - { - //ĄTODO: if the focusedWidget doesn't have a menubar, - // look all the way up to the window - // until one of the parents has a menubar - } - - //ĄTODO: set the menu bar here + //menuBar->GetNativeData((void *)menuHandle); + //::SetMenuBar((Handle)menuHandle); + menuBar->Paint(); } else { - - if (nsnull != gRollupListener && (nsnull != gRollupWidget) ) { - if( mTopLevelWidget == gRollupWidget) - gRollupListener->Rollup(); - } - // - // Deactivate the TSMDocument assoicated with this EventHandler - // - if (mTSMDocument) - err = ::DeactivateTSMDocument(mTSMDocument); -#if 0 - NS_ASSERTION(err==noErr,"nsMacEventHandler::HandleActivateEvent: DeactivateTSMDocument failed"); - printf("nsEventHandler::HandleActivateEvent: DeactivateTSMDocument[%p]\n",mTSMDocument); -#endif - - //ĄTODO: save the focused widget for that window - toolkit->SetFocus(nsnull); - - //nsIMenuBar* menuBarInterface = mTopLevelWidget->GetMenuBar(); - //if (menuBarInterface) - //{ - //Handle menuBar = ::GetMenuBar(); // Get a copy of the menu list - //menuBarInterface->SetNativeData((void*)menuBar); - //} + //ĄTODO: if the focusedWidget doesn't have a menubar, + // look all the way up to the window + // until one of the parents has a menubar } + + //ĄTODO: set the menu bar here + } + else + { + + if (nsnull != gRollupListener && (nsnull != gRollupWidget) ) { + if( mTopLevelWidget == gRollupWidget) + gRollupListener->Rollup(); + } + // + // Deactivate the TSMDocument assoicated with this EventHandler + // + if (mTSMDocument) + err = ::DeactivateTSMDocument(mTSMDocument); +#if 0 + NS_ASSERTION(err==noErr,"nsMacEventHandler::HandleActivateEvent: DeactivateTSMDocument failed"); + printf("nsEventHandler::HandleActivateEvent: DeactivateTSMDocument[%p]\n",mTSMDocument); +#endif + + //ĄTODO: save the focused widget for that window + gFocusHandler.SetFocus(nsnull); + + //nsIMenuBar* menuBarInterface = mTopLevelWidget->GetMenuBar(); + //if (menuBarInterface) + //{ + //Handle menuBar = ::GetMenuBar(); // Get a copy of the menu list + //menuBarInterface->SetNativeData((void*)menuBar); + //} } return PR_TRUE; } @@ -871,7 +976,8 @@ PRBool nsMacEventHandler::HandleMouseDownEvent( nsMouseEvent mouseEvent; ConvertOSEventToMouseEvent(aOSEvent, mouseEvent, NS_MOUSE_LEFT_BUTTON_DOWN); nsWindow* widgetHit = (nsWindow*)mouseEvent.widget; - if (widgetHit){ + if (widgetHit) + { #ifdef NOTNOW if (nsnull != gRollupListener && (nsnull != gRollupWidget) ) { @@ -888,24 +994,14 @@ PRBool nsMacEventHandler::HandleMouseDownEvent( #endif // set the focus on the widget hit, if it accepts it if (widgetHit->AcceptFocusOnClick()) - { - nsCOMPtr toolkit ( dont_AddRef((nsToolkit*)widgetHit->GetToolkit()) ); - if (toolkit) - toolkit->SetFocus(widgetHit); - } + gFocusHandler.SetFocus(widgetHit); // dispatch the event retVal = widgetHit->DispatchMouseEvent(mouseEvent); } - if (mLastWidgetHit) - mLastWidgetHit->RemoveDeleteObserver(this); - - mLastWidgetHit = widgetHit; + gFocusHandler.SetWidgetHit(widgetHit); mMouseInWidgetHit = PR_TRUE; - - if (mLastWidgetHit) - mLastWidgetHit->AddDeleteObserver(this); break; } @@ -946,17 +1042,17 @@ PRBool nsMacEventHandler::HandleMouseUpEvent( ConvertOSEventToMouseEvent(aOSEvent, mouseEvent, NS_MOUSE_LEFT_BUTTON_UP); nsWindow* widgetReleased = (nsWindow*)mouseEvent.widget; - if ((widgetReleased != nsnull) && (widgetReleased != mLastWidgetHit)) + nsWindow* widgetHit = gFocusHandler.GetWidgetHit(); + + if ((widgetReleased != nsnull) && (widgetReleased != widgetHit)) retVal |= widgetReleased->DispatchMouseEvent(mouseEvent); - if (mLastWidgetHit) + if (widgetHit) { - mLastWidgetHit->RemoveDeleteObserver(this); + gFocusHandler.SetWidgetHit(nsnull); - mouseEvent.widget = mLastWidgetHit; - retVal |= mLastWidgetHit->DispatchMouseEvent(mouseEvent); - - mLastWidgetHit = nsnull; + mouseEvent.widget = widgetHit; + retVal |= widgetHit->DispatchMouseEvent(mouseEvent); } return retVal; @@ -971,44 +1067,43 @@ PRBool nsMacEventHandler::HandleMouseUpEvent( PRBool nsMacEventHandler::HandleMouseMoveEvent( EventRecord& aOSEvent) { + nsWindow* lastWidgetHit = gFocusHandler.GetWidgetHit(); + nsWindow* lastWidgetPointed = gFocusHandler.GetWidgetPointed(); + PRBool retVal = PR_FALSE; nsMouseEvent mouseEvent; ConvertOSEventToMouseEvent(aOSEvent, mouseEvent, NS_MOUSE_MOVE); - if (mLastWidgetHit) + if (lastWidgetHit) { Point macPoint = aOSEvent.where; ::GlobalToLocal(&macPoint); - PRBool inWidgetHit = mLastWidgetHit->PointInWidget(macPoint); - if (inWidgetHit != mMouseInWidgetHit) + PRBool inWidgetHit = lastWidgetHit->PointInWidget(macPoint); + if (mMouseInWidgetHit != inWidgetHit) { - mouseEvent.message = (inWidgetHit ? NS_MOUSE_ENTER : NS_MOUSE_EXIT); mMouseInWidgetHit = inWidgetHit; + mouseEvent.message = (inWidgetHit ? NS_MOUSE_ENTER : NS_MOUSE_EXIT); } - retVal |= mLastWidgetHit->DispatchMouseEvent(mouseEvent); + retVal |= lastWidgetHit->DispatchMouseEvent(mouseEvent); } else { nsWindow* widgetPointed = (nsWindow*)mouseEvent.widget; - if (widgetPointed != mLastWidgetPointed) + if (widgetPointed != lastWidgetPointed) { - if (mLastWidgetPointed) + if (lastWidgetPointed) { - mLastWidgetPointed->RemoveDeleteObserver(this); - - mouseEvent.widget = mLastWidgetPointed; - mouseEvent.message = NS_MOUSE_EXIT; - retVal |= mLastWidgetPointed->DispatchMouseEvent(mouseEvent); - mLastWidgetPointed = nsnull; - mouseEvent.widget = widgetPointed; + mouseEvent.widget = lastWidgetPointed; + mouseEvent.message = NS_MOUSE_EXIT; + retVal |= lastWidgetPointed->DispatchMouseEvent(mouseEvent); } + gFocusHandler.SetWidgetPointed(widgetPointed); + if (widgetPointed) { - widgetPointed->AddDeleteObserver(this); - - mLastWidgetPointed = widgetPointed; + mouseEvent.widget = widgetPointed; mouseEvent.message = NS_MOUSE_ENTER; retVal |= widgetPointed->DispatchMouseEvent(mouseEvent); } @@ -1085,17 +1180,18 @@ void nsMacEventHandler::ConvertOSEventToMouseEvent( nsPoint widgetHitPoint(hitPoint.h, hitPoint.v); // if the mouse button is still down, send events to the last widget hit + nsWindow* lastWidgetHit = gFocusHandler.GetWidgetHit(); nsWindow* widgetHit = nsnull; - if (mLastWidgetHit) + + if (lastWidgetHit) { if (::StillDown() || aMessage == NS_MOUSE_LEFT_BUTTON_UP) - widgetHit = mLastWidgetHit; + widgetHit = lastWidgetHit; else { - // Patch: some widgets can eat mouseUp events (text widgets in TEClick, sbars in TrackControl). - // In that case, fall back to the normal case. - mLastWidgetHit->RemoveDeleteObserver(this); - mLastWidgetHit = nsnull; + // Some widgets can eat mouseUp events (text widgets in TEClick, sbars in TrackControl). + // In that case, stop considering this widget as being still hit. + gFocusHandler.SetWidgetHit(nsnull); } } @@ -1282,16 +1378,9 @@ PRBool nsMacEventHandler::HandleStartComposition(void) // // get the focused widget [tague: may need to rethink this later] // - nsWindow* focusedWidget = mTopLevelWidget; - nsCOMPtr toolkit ( dont_AddRef((nsToolkit*)mTopLevelWidget->GetToolkit()) ); - if (toolkit) - focusedWidget = toolkit->GetFocus(); - + nsWindow* focusedWidget = gFocusHandler.GetFocus(); if (!focusedWidget) - { - NS_WARNING("Throwing away start composition event because there is no focused widget"); - return PR_FALSE; - } + focusedWidget = mTopLevelWidget; // // create the nsCompositionEvent @@ -1323,16 +1412,9 @@ PRBool nsMacEventHandler::HandleEndComposition(void) // // get the focused widget [tague: may need to rethink this later] // - nsWindow* focusedWidget = mTopLevelWidget; - nsCOMPtr toolkit ( dont_AddRef((nsToolkit*)mTopLevelWidget->GetToolkit()) ); - if (toolkit) - focusedWidget = toolkit->GetFocus(); - + nsWindow* focusedWidget = gFocusHandler.GetFocus(); if (!focusedWidget) - { - NS_WARNING("Throwing away end composition event because there is no focused widget"); - return PR_FALSE; - } + focusedWidget = mTopLevelWidget; // // create the nsCompositionEvent @@ -1364,16 +1446,9 @@ PRBool nsMacEventHandler::HandleTextEvent(PRUint32 textRangeCount, nsTextRangeAr // // get the focused widget [tague: may need to rethink this later] // - nsWindow* focusedWidget = mTopLevelWidget; - nsCOMPtr toolkit ( dont_AddRef((nsToolkit*)mTopLevelWidget->GetToolkit()) ); - if (toolkit) - focusedWidget = toolkit->GetFocus(); - + nsWindow* focusedWidget = gFocusHandler.GetFocus(); if (!focusedWidget) - { - NS_WARNING("Throwing away text event because there is no focused widget"); - return PR_FALSE; - } + focusedWidget = mTopLevelWidget; // // create the nsCompositionEvent diff --git a/widget/src/mac/nsMacEventHandler.h b/widget/src/mac/nsMacEventHandler.h index 49946c0e80a3..67f28e6e1643 100644 --- a/widget/src/mac/nsMacEventHandler.h +++ b/widget/src/mac/nsMacEventHandler.h @@ -21,16 +21,56 @@ #include #include #include -#include "nsDeleteObserver.h" +#include "prtypes.h" #include "nsCOMPtr.h" #include "nsGUIEvent.h" -#include "prtypes.h" - +#include "nsDeleteObserver.h" class nsWindow; class nsMacWindow; -class nsMacEventHandler : public nsDeleteObserver + +//------------------------------------------------------------------------- +// +//------------------------------------------------------------------------- + +class nsMacFocusHandler : public nsDeleteObserver +{ +public: + nsMacFocusHandler(); + virtual ~nsMacFocusHandler(); + + void SetFocus(nsWindow *aFocusedWidget); + nsWindow* GetFocus() {return(mFocusedWidget);} + + void SetWidgetHit(nsWindow *aWidgetHit); + void SetWidgetPointed(nsWindow *aWidgetPointed); + + nsWindow* GetWidgetHit() {return(mWidgetHit);} + nsWindow* GetWidgetPointed() {return(mWidgetPointed);} + + // DeleteObserver + virtual void NotifyDelete(void* aDeletedObject); + +private: + nsWindow* mFocusedWidget; + nsWindow* mWidgetHit; + nsWindow* mWidgetPointed; +}; + + +//------------------------------------------------------------------------- +// +//------------------------------------------------------------------------- + +extern nsMacFocusHandler gFocusHandler; + + +//------------------------------------------------------------------------- +// +//------------------------------------------------------------------------- + +class nsMacEventHandler { public: nsMacEventHandler(nsMacWindow* aTopLevelWidget); @@ -46,16 +86,15 @@ public: // // TSM Event Handlers // - virtual long HandlePositionToOffset(Point aPoint,short* regionClass); + virtual long HandlePositionToOffset(Point aPoint,short* regionClass); virtual PRBool HandleOffsetToPosition(long offset,Point* position); virtual PRBool HandleUpdateInputArea(char* text,Size text_size, ScriptCode textScript,long fixedLength,TextRangeArray* textRangeArray); protected: #if 1 - virtual void InitializeKeyEvent(nsKeyEvent& aKeyEvent, EventRecord& aOSEvent, nsWindow* focusedWidget, PRUint32 message); - virtual PRBool IsSpecialRaptorKey(UInt32 macKeyCode); - virtual PRUint32 ConvertKeyEventToUnicode(EventRecord& aOSEvent); - + virtual void InitializeKeyEvent(nsKeyEvent& aKeyEvent, EventRecord& aOSEvent, nsWindow* focusedWidget, PRUint32 message); + virtual PRBool IsSpecialRaptorKey(UInt32 macKeyCode); + virtual PRUint32 ConvertKeyEventToUnicode(EventRecord& aOSEvent); #endif virtual PRBool HandleKeyEvent(EventRecord& aOSEvent); virtual PRBool HandleActivateEvent(EventRecord& aOSEvent); @@ -64,30 +103,25 @@ protected: virtual PRBool HandleMouseUpEvent(EventRecord& aOSEvent); virtual PRBool HandleMouseMoveEvent(EventRecord& aOSEvent); - virtual void ConvertOSEventToMouseEvent( - EventRecord& aOSEvent, - nsMouseEvent& aMouseEvent, - PRUint32 aMessage); + virtual void ConvertOSEventToMouseEvent( + EventRecord& aOSEvent, + nsMouseEvent& aMouseEvent, + PRUint32 aMessage); virtual PRBool HandleStartComposition(void); virtual PRBool HandleEndComposition(void); virtual PRBool HandleTextEvent(PRUint32 textRangeCount, nsTextRangeArray textRangeArray); -public: - virtual void NotifyDelete(void* aDeletedObject); - protected: - nsMacWindow* mTopLevelWidget; - static nsWindow* mLastWidgetHit; // These items have been made static to fix #9456 - static PRBool mMouseInWidgetHit; - static nsWindow* mLastWidgetPointed; - RgnHandle mUpdateRgn; - TSMDocumentID mTSMDocument; - PRBool mIMEIsComposing; - PRUnichar *mIMECompositionString; - size_t mIMECompositionStringSize; - size_t mIMECompositionStringLength; + static PRBool mMouseInWidgetHit; static PRBool mInBackground; + nsMacWindow* mTopLevelWidget; + RgnHandle mUpdateRgn; + TSMDocumentID mTSMDocument; + PRBool mIMEIsComposing; + PRUnichar* mIMECompositionString; + size_t mIMECompositionStringSize; + size_t mIMECompositionStringLength; }; #endif // MacMacEventHandler_h__ diff --git a/widget/src/mac/nsToolkit.cpp b/widget/src/mac/nsToolkit.cpp index da9d01f865a4..06d5f5021bc7 100644 --- a/widget/src/mac/nsToolkit.cpp +++ b/widget/src/mac/nsToolkit.cpp @@ -31,135 +31,125 @@ static NS_DEFINE_IID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); // Interface IDs... static NS_DEFINE_IID(kIEventQueueServiceIID, NS_IEVENTQUEUESERVICE_IID); -nsWindow* nsToolkit::mFocusedWidget = nsnull; -//================================================================= -/* Constructor - * @update dc 08/31/98 - * @param NONE - * @return NONE - */ -nsToolkit::nsToolkit(): Repeater() +static nsMacNSPREventQueueHandler* gEventQueueHandler = nsnull; + +//------------------------------------------------------------------------- +// +//------------------------------------------------------------------------- +nsMacNSPREventQueueHandler::nsMacNSPREventQueueHandler(): Repeater() { - NS_INIT_REFCNT(); + mRefCnt = 0; + mEventQService = nsnull; } - -//================================================================= -/* Destructor. - * @update dc 08/31/98 - * @param NONE - * @return NONE - */ -nsToolkit::~nsToolkit() +//------------------------------------------------------------------------- +// +//------------------------------------------------------------------------- +nsMacNSPREventQueueHandler::~nsMacNSPREventQueueHandler() { - if (mFocusedWidget) - { - mFocusedWidget->RemoveDeleteObserver(this); - mFocusedWidget = nsnull; - } + if (mEventQService == nsnull) + return; StopRepeating(); + nsServiceManager::ReleaseService(kEventQueueServiceCID, mEventQService); + mEventQService = nsnull; } -//================================================================= -/* Set the focus to a widget, send out the appropriate focus/defocus events - * @update dc 08/31/98 - * @param aMouseInside -- A boolean indicating if the mouse is inside the control - * @return NONE - */ -void nsToolkit::SetFocus(nsWindow *aFocusWidget) -{ - if (aFocusWidget == mFocusedWidget) - return; - - nsGUIEvent guiEvent; - guiEvent.eventStructType = NS_GUI_EVENT; - guiEvent.point.x = 0, guiEvent.point.y = 0; - guiEvent.time = PR_IntervalNow(); - guiEvent.widget = nsnull; - guiEvent.nativeMsg = nsnull; - - // tell the old widget, it is not focused - if (mFocusedWidget) +//------------------------------------------------------------------------- +// +//------------------------------------------------------------------------- +void nsMacNSPREventQueueHandler::StartPumping() +{ + if (mRefCnt == 0) { - mFocusedWidget->RemoveDeleteObserver(this); - - guiEvent.message = NS_LOSTFOCUS; - guiEvent.widget = mFocusedWidget; - mFocusedWidget->DispatchWindowEvent(guiEvent); - mFocusedWidget = nsnull; + nsServiceManager::GetService(kEventQueueServiceCID, + kIEventQueueServiceIID, + (nsISupports **)&mEventQService); + if (mEventQService == nsnull) + { + NS_WARNING("GetService(kEventQueueServiceCID) failed"); + return; + } } - - // let the new one know - if (aFocusWidget) - { - mFocusedWidget = aFocusWidget; - mFocusedWidget->AddDeleteObserver(this); - guiEvent.message = NS_GOTFOCUS; - guiEvent.widget = mFocusedWidget; - mFocusedWidget->DispatchWindowEvent(guiEvent); - } + ++mRefCnt; + StartRepeating(); } -//================================================================= -/* nsISupports implementation macro's - * @update dc 08/31/98 - * @param NONE - * @return NONE - */ +//------------------------------------------------------------------------- +// +//------------------------------------------------------------------------- +PRBool nsMacNSPREventQueueHandler::StopPumping() +{ + if (mEventQService == nsnull) + return PR_TRUE; + + if (mRefCnt > 0) { + if (--mRefCnt == 0) { + StopRepeating(); + nsServiceManager::ReleaseService(kEventQueueServiceCID, mEventQService); + mEventQService = nsnull; + return PR_TRUE; + } + } + + return PR_FALSE; +} + +//------------------------------------------------------------------------- +// +//------------------------------------------------------------------------- +void nsMacNSPREventQueueHandler::RepeatAction(const EventRecord& inMacEvent) +{ + // Handle pending NSPR events + if (mEventQService) + mEventQService->ProcessEvents(); +} + + +#pragma mark - + NS_DEFINE_IID(kIToolkitIID, NS_ITOOLKIT_IID); NS_IMPL_ISUPPORTS(nsToolkit,kIToolkitIID); -//================================================================= -/* Initialize the Toolbox - * @update dc 08/31/98 - * @param aThread -- A pointer to a PRThread, not really sure of its use for the Mac yet - * @return NONE - */ -NS_IMETHODIMP nsToolkit::Init(PRThread *aThread) +//------------------------------------------------------------------------- +// +//------------------------------------------------------------------------- +nsToolkit::nsToolkit() { - StartRepeating(); - + NS_INIT_REFCNT(); + if (gEventQueueHandler == nsnull) + gEventQueueHandler = new nsMacNSPREventQueueHandler; +} + +//------------------------------------------------------------------------- +// +//------------------------------------------------------------------------- +nsToolkit::~nsToolkit() +{ + if (gEventQueueHandler) { + if (gEventQueueHandler->StopPumping()) { + delete gEventQueueHandler; + gEventQueueHandler = nsnull; + } + } +} + + +//------------------------------------------------------------------------- +// +//------------------------------------------------------------------------- +NS_IMETHODIMP nsToolkit::Init(PRThread */*aThread*/) +{ + if (gEventQueueHandler) + gEventQueueHandler->StartPumping(); return NS_OK; } - - -//================================================================= -/* Process the NSPR event queue. - * @update dc 08/31/98 - * @param inMacEvent -- A mac os event, Not used - * @return NONE - */ -void nsToolkit::RepeatAction(const EventRecord& /*inMacEvent*/) -{ - // Handle pending NSPR events - nsIEventQueueService* eventQService = NULL; - if ( NS_SUCCEEDED( nsServiceManager::GetService(kEventQueueServiceCID, - kIEventQueueServiceIID, - (nsISupports **)&eventQService) ) ) - { - eventQService->ProcessEvents(); - nsServiceManager::ReleaseService(kEventQueueServiceCID, eventQService); - } -} - - -//================================================================= -/* - */ -void nsToolkit::NotifyDelete(void* aDeletedObject) -{ - if (mFocusedWidget == aDeletedObject) - mFocusedWidget = nsnull; -} - - -//================================================================= -/* - */ +//------------------------------------------------------------------------- +// +//------------------------------------------------------------------------- bool nsToolkit::HasAppearanceManager() { diff --git a/widget/src/mac/nsToolkit.h b/widget/src/mac/nsToolkit.h index 53b8d2d19e13..ca89ca1079de 100644 --- a/widget/src/mac/nsToolkit.h +++ b/widget/src/mac/nsToolkit.h @@ -21,45 +21,65 @@ #include "nsIToolkit.h" #include "nsRepeater.h" -#include "nsDeleteObserver.h" -struct PLEventQueue; -struct MethodInfo; -class nsWindow; +class nsIEventQueueService; + /** - * Wrapper around the thread running the message pump. * The toolkit abstraction is necessary because the message pump must * execute within the same thread that created the widget under Win32. - */ + * We don't care about that on Mac: we have only one thread for the UI + * and maybe even for the whole application. + * + * So on the Mac, the nsToolkit used to be a unique object, created once + * at startup along with nsAppShell and passed to all the top-level + * windows and it became a convenient place to throw in everything we + * didn't know where else to put, like the NSPR event queue and + * the handling of global pointers on some special widgets (focused + * widget, widget hit, widget pointed). + * + * All this has changed: the application now usually creates one copy of + * the nsToolkit per window and the special widgets had to be moved + * to the nsMacEventHandler. Also, to avoid creating several repeaters, + * the NSPR event queue has been moved to a global object of its own: + * the nsMacNSPREventQueueHandler declared below. + * + * If by any chance we support one day several threads for the UI + * on the Mac, will have to create one instance of the NSPR + * event queue per nsToolkit. + */ -class nsToolkit : public nsIToolkit, public Repeater, public nsDeleteObserver +class nsToolkit : public nsIToolkit { public: nsToolkit(); - virtual ~nsToolkit(); + virtual ~nsToolkit(); NS_DECL_ISUPPORTS - NS_IMETHOD Init(PRThread *aThread); + NS_IMETHOD Init(PRThread *aThread); -public: - void SetFocus(nsWindow *aFocusWidget); - nsWindow* GetFocus() {return(mFocusedWidget);} - - // Appearance Mgr - static bool HasAppearanceManager(); + static bool HasAppearanceManager(); +}; + + +class nsMacNSPREventQueueHandler : public Repeater +{ +public: + nsMacNSPREventQueueHandler(); + virtual ~nsMacNSPREventQueueHandler(); + + virtual void StartPumping(); + virtual PRBool StopPumping(); // Repeater interface virtual void RepeatAction(const EventRecord& inMacEvent); - - // DeleteObserver - virtual void NotifyDelete(void* aDeletedObject); - -private: - static nsWindow* mFocusedWidget; + +protected: + nsrefcnt mRefCnt; + nsIEventQueueService* mEventQService; };