/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Mozilla browser. * * The Initial Developer of the Original Code is Netscape * Communications, Inc. Portions created by Netscape are * Copyright (C) 1999, Mozilla. All Rights Reserved. * * Contributor(s): * Travis Bogard */ #include "nsCOMPtr.h" #include "nsCBaseLoop.h" #include "nsCEvent.h" #include "nsCEventFilter.h" //***************************************************************************** //*** nsCBaseLoop: Object Management //***************************************************************************** nsCBaseLoop::nsCBaseLoop(nsEventLoopType type) : m_Type(type) { NS_INIT_REFCNT(); } nsCBaseLoop::~nsCBaseLoop() { } //***************************************************************************** // nsCBaseLoop::nsISupports //***************************************************************************** NS_IMPL_ISUPPORTS3(nsCBaseLoop, nsIEventLoop, nsPIEventLoop, nsISupportsWeakReference) //***************************************************************************** // nsCBaseLoop::nsIEventLoop //***************************************************************************** NS_IMETHODIMP nsCBaseLoop::Run(nsIEventFilter* filter, nsITranslateListener* translateListener, nsIDispatchListener* dispatchListener, PRInt32* retCode) { nsCOMPtr event; CreateNewEvent(getter_AddRefs(event)); nsresult rv; nsCOMPtr localFilter(dont_QueryInterface(filter)); if(!localFilter) NS_ENSURE_SUCCESS(CreateNewEventFilter(getter_AddRefs(localFilter)), NS_ERROR_FAILURE); if(translateListener) { if(dispatchListener) rv = RunWithTranslateAndDispatchListener(event, localFilter, translateListener, dispatchListener); else rv = RunWithTranslateListener(event, localFilter, translateListener); } else if(dispatchListener) rv = RunWithDispatchListener(event, localFilter, dispatchListener); else rv = RunWithNoListener(event, localFilter); if(NS_FAILED(rv)) { if(retCode) *retCode = PlatformGetReturnCode(nsnull); return NS_ERROR_FAILURE; } if(retCode) *retCode = PlatformGetReturnCode(event); return NS_OK; } NS_IMETHODIMP nsCBaseLoop::Exit(PRInt32 exitCode) { return PlatformExit(exitCode); } NS_IMETHODIMP nsCBaseLoop::CloneEvent(nsIEvent* event, nsIEvent** newEvent) { NS_ENSURE_ARG(event); NS_ENSURE_ARG_POINTER(newEvent); void* platformEventData = nsnull; if(event) { platformEventData = GetPlatformEventData(event); NS_ENSURE_TRUE(platformEventData, NS_ERROR_FAILURE); } nsCEvent* cEvent = new nsCEvent(platformEventData); if(!cEvent) return NS_ERROR_OUT_OF_MEMORY; cEvent->AddRef(); nsresult rv = cEvent->QueryInterface(NS_GET_IID(nsIEvent), (void**)newEvent); cEvent->Release(); NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); return NS_OK; } NS_IMETHODIMP nsCBaseLoop::CreateNewEvent(nsIEvent** newEvent) { NS_ENSURE_ARG_POINTER(newEvent); nsCEvent* event = new nsCEvent(); NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY); event->AddRef(); nsresult rv = event->QueryInterface(NS_GET_IID(nsIEvent), (void**)newEvent); event->Release(); NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); return NS_OK; } NS_IMETHODIMP nsCBaseLoop::CreateNewEventFilter(nsIEventFilter** newFilter) { NS_ENSURE_ARG_POINTER(newFilter); nsCEventFilter* filter = new nsCEventFilter(); NS_ENSURE_TRUE(filter, NS_ERROR_OUT_OF_MEMORY); filter->AddRef(); nsresult rv = filter->QueryInterface(NS_GET_IID(nsIEventFilter), (void**)newFilter); filter->Release(); NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); return NS_OK; } NS_IMETHODIMP nsCBaseLoop::GetNextEvent(nsIEventFilter* filter, nsIEvent* event) { NS_ENSURE_ARG(event); nsCOMPtr localFilter(dont_QueryInterface(filter)); if(!localFilter) NS_ENSURE_SUCCESS(CreateNewEventFilter(getter_AddRefs(localFilter)), NS_ERROR_FAILURE); void* platformEventData = GetPlatformEventData(event); void* platformFilterData = GetPlatformFilterData(localFilter); NS_ENSURE_TRUE(platformEventData, NS_ERROR_FAILURE); return PlatformGetNextEvent(platformFilterData, platformEventData); } NS_IMETHODIMP nsCBaseLoop::PeekNextEvent(nsIEventFilter* filter, nsIEvent* event, PRBool fRemoveEvent) { NS_ENSURE_ARG(event); nsCOMPtr localFilter(dont_QueryInterface(filter)); if(!localFilter) NS_ENSURE_SUCCESS(CreateNewEventFilter(getter_AddRefs(localFilter)), NS_ERROR_FAILURE); void* platformEventData = GetPlatformEventData(event); void* platformFilterData = GetPlatformFilterData(localFilter); NS_ENSURE_TRUE(platformEventData, NS_ERROR_FAILURE); return PlatformPeekNextEvent(platformFilterData, platformEventData, fRemoveEvent); } NS_IMETHODIMP nsCBaseLoop::TranslateEvent(nsIEvent* event) { NS_ENSURE_ARG(event); void* platformEventData = GetPlatformEventData(event); NS_ENSURE_TRUE(platformEventData, NS_ERROR_FAILURE); return PlatformTranslateEvent(platformEventData); } NS_IMETHODIMP nsCBaseLoop::DispatchEvent(nsIEvent* event) { NS_ENSURE_ARG(event); void* platformEventData = GetPlatformEventData(event); NS_ENSURE_TRUE(platformEventData, NS_ERROR_FAILURE); return PlatformDispatchEvent(platformEventData); } NS_IMETHODIMP nsCBaseLoop::SendLoopEvent(nsIEvent* event, PRInt32* result) { NS_ENSURE_ARG(event); void* platformEventData = GetPlatformEventData(event); NS_ENSURE_TRUE(platformEventData, NS_ERROR_FAILURE); return PlatformSendLoopEvent(platformEventData, result); } NS_IMETHODIMP nsCBaseLoop::PostLoopEvent(nsIEvent* event) { NS_ENSURE_ARG(event); void* platformEventData = GetPlatformEventData(event); NS_ENSURE_TRUE(platformEventData, NS_ERROR_FAILURE); return PlatformPostLoopEvent(platformEventData); } NS_IMETHODIMP nsCBaseLoop::GetEventLoopType(nsEventLoopType* pType) { NS_ENSURE_ARG_POINTER(pType); *pType = m_Type; return NS_OK; } NS_IMETHODIMP nsCBaseLoop::GetEventLoopName(PRUnichar** pName) { NS_ENSURE_ARG_POINTER(pName); *pName = m_LoopName.ToNewUnicode(); return *pName ? NS_OK : NS_ERROR_OUT_OF_MEMORY; } //***************************************************************************** // nsCBaseLoop::nsPIEventLoop //***************************************************************************** NS_IMETHODIMP nsCBaseLoop::LoopInit(const PRUnichar* pLoopName) { m_LoopName.Assign(pLoopName); return NS_OK; } //***************************************************************************** // nsCBaseLoop:: Internal Helpers //***************************************************************************** void* nsCBaseLoop::GetPlatformEventData(nsIEvent* event) { void* platformEventData = nsnull; nsNativeEventDataType platformEventType = PlatformGetEventType(); event->GetNativeData(platformEventType, &platformEventData); return platformEventData; } void* nsCBaseLoop::GetPlatformFilterData(nsIEventFilter* filter) { void* platformFilterData = nsnull; nsNativeFilterDataType platformFilterType = PlatformGetFilterType(); filter->GetNativeData(platformFilterType, &platformFilterData); return platformFilterData; } nsresult nsCBaseLoop::RunWithNoListener(nsIEvent* event, nsIEventFilter* filter) { nsresult rv; void* platformEventData = GetPlatformEventData(event); void* platformFilterData = GetPlatformFilterData(filter); NS_ENSURE_TRUE(platformEventData, NS_ERROR_FAILURE); while(NS_OK == (rv = RetrieveNextEvent(platformFilterData, platformEventData))) { if(NS_FAILED(rv = PlatformTranslateEvent(platformEventData))) break; if(NS_FAILED(rv = PlatformDispatchEvent(platformEventData))) break; } return rv; } nsresult nsCBaseLoop::RunWithTranslateListener(nsIEvent* event, nsIEventFilter* filter, nsITranslateListener* translateListener) { nsresult rv; void* platformEventData = GetPlatformEventData(event); void* platformFilterData = GetPlatformFilterData(filter); NS_ENSURE_TRUE(platformEventData, NS_ERROR_FAILURE); while(NS_OK == (rv = RetrieveNextEvent(platformFilterData, platformEventData))) { if(NS_FAILED(rv = translateListener->PreTranslate(event))) break; if(NS_OK == rv) { if(NS_FAILED(rv = PlatformTranslateEvent(platformEventData))) break; if(NS_FAILED(rv = translateListener->PostTranslate(event, NS_OK == rv ? PR_TRUE : PR_FALSE))) break; } if(NS_FAILED(rv = PlatformDispatchEvent(platformEventData))) break; } return rv; } nsresult nsCBaseLoop::RunWithDispatchListener(nsIEvent* event, nsIEventFilter* filter, nsIDispatchListener* dispatchListener) { nsresult rv; void* platformEventData = GetPlatformEventData(event); void* platformFilterData = GetPlatformFilterData(filter); NS_ENSURE_TRUE(platformEventData, NS_ERROR_FAILURE); while(NS_OK == (rv = RetrieveNextEvent(platformFilterData, platformEventData))) { if(NS_FAILED(rv = PlatformTranslateEvent(platformEventData))) break; if(NS_FAILED(rv = dispatchListener->PreDispatch(event))) break; if(NS_OK == rv) { if(NS_FAILED(rv = PlatformDispatchEvent(platformEventData))) break; if(NS_FAILED(rv = dispatchListener->PostDispatch(event, NS_OK == rv ? PR_TRUE : PR_FALSE))) break; } } return rv; } nsresult nsCBaseLoop::RunWithTranslateAndDispatchListener(nsIEvent* event, nsIEventFilter* filter, nsITranslateListener* translateListener, nsIDispatchListener* dispatchListener) { nsresult rv; void* platformEventData = GetPlatformEventData(event); void* platformFilterData = GetPlatformFilterData(filter); NS_ENSURE_TRUE(platformEventData, NS_ERROR_FAILURE); while(NS_OK == (rv = RetrieveNextEvent(platformFilterData, platformEventData))) { if(NS_FAILED(rv = translateListener->PreTranslate(event))) break; if(NS_OK == rv) { if(NS_FAILED(rv = PlatformTranslateEvent(platformEventData))) break; if(NS_FAILED(rv = translateListener->PostTranslate(event, NS_OK == rv ? PR_TRUE : PR_FALSE))) break; } if(NS_FAILED(rv = dispatchListener->PreDispatch(event))) break; if(NS_OK == rv) { if(NS_FAILED(rv = PlatformDispatchEvent(platformEventData))) break; if(NS_FAILED(rv = dispatchListener->PostDispatch(event, NS_OK == rv ? PR_TRUE : PR_FALSE))) break; } } return rv; } nsresult nsCBaseLoop::RetrieveNextEvent(void* platformFilterData, void* platformEventData) { return PlatformRetrieveNextEvent(platformFilterData, platformEventData); }