Fixed #14775 "Crash removing delete observer when closing windows": reshuffled nsToolkit and added nsMacFocusHandler to nsMacEventHandler. r=dcone/sfraser

This commit is contained in:
pierre%netscape.com 1999-10-01 21:40:04 +00:00
Родитель 4bb28b8cda
Коммит 8c4468746e
6 изменённых файлов: 464 добавлений и 342 удалений

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -20,7 +20,6 @@
#include "nsWindow.h"
#include "nsMacWindow.h"
#include "nsToolkit.h"
#include "prinrval.h"
#include <ToolUtils.h>
@ -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<nsToolkit> 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<nsWindow> grandParent;
nsCOMPtr<nsWindow> 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<nsWindow> grandParent;
nsCOMPtr<nsWindow> 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<nsToolkit> 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<nsToolkit> 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<nsToolkit> 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<nsToolkit> 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<nsToolkit> 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<nsToolkit> 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

Просмотреть файл

@ -21,16 +21,56 @@
#include <Events.h>
#include <MacWindows.h>
#include <TextServices.h>
#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__

Просмотреть файл

@ -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()
{

Просмотреть файл

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