396 lines
11 KiB
C++
396 lines
11 KiB
C++
/* -*- 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 <travis@netscape.com>
|
|
*/
|
|
|
|
#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<nsIEvent> event;
|
|
CreateNewEvent(getter_AddRefs(event));
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIEventFilter> 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<nsIEventFilter> 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<nsIEventFilter> 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);
|
|
}
|