/* ***** BEGIN LICENSE BLOCK *****
 * Source last modified: $Id: basesite.cpp,v 1.20.4.2 2004/07/09 01:59:28 hubbe Exp $
 * 
 * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
 * 
 * The contents of this file, and the files included with this file,
 * are subject to the current version of the RealNetworks Public
 * Source License (the "RPSL") available at
 * http://www.helixcommunity.org/content/rpsl unless you have licensed
 * the file under the current version of the RealNetworks Community
 * Source License (the "RCSL") available at
 * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
 * will apply. You may also obtain the license terms directly from
 * RealNetworks.  You may not use this file except in compliance with
 * the RPSL or, if you have a valid RCSL with RealNetworks applicable
 * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
 * the rights, obligations and limitations governing use of the
 * contents of the file.
 * 
 * Alternatively, the contents of this file may be used under the
 * terms of the GNU General Public License Version 2 or later (the
 * "GPL") in which case the provisions of the GPL are applicable
 * instead of those above. If you wish to allow use of your version of
 * this file only under the terms of the GPL, and not to allow others
 * to use your version of this file under the terms of either the RPSL
 * or RCSL, indicate your decision by deleting the provisions above
 * and replace them with the notice and other provisions required by
 * the GPL. If you do not delete the provisions above, a recipient may
 * use your version of this file under the terms of any one of the
 * RPSL, the RCSL or the GPL.
 * 
 * This file is part of the Helix DNA Technology. RealNetworks is the
 * developer of the Original Code and owns the copyrights in the
 * portions it created.
 * 
 * This file, and the files included with this file, is distributed
 * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
 * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
 * ENJOYMENT OR NON-INFRINGEMENT.
 * 
 * Technology Compatibility Kit Test Suite(s) Location:
 *    http://www.helixcommunity.org/content/tck
 * 
 * Contributor(s):
 * 
 * ***** END LICENSE BLOCK ***** */

#include <stdlib.h> //for atof
#include "hxcom.h"
#include "hxtypes.h"
#include "hxwintyp.h"
#include "ihxpckts.h"
#include "hxwin.h"
#include "hxengin.h"
#include "hxsite2.h"
#include "hxevent.h"
#include "hxcomm.h"
#include "hxassert.h"
#include "hxthread.h"

#include "hxvsurf.h"
#include "basesite.h"
#include "basesurf.h"
#include "baseroot.h"

#ifdef _WINDOWS
#include "winroot.h" //must be included before colormap.h
#endif

#include "colormap.h"

#if defined(_UNIX) && !defined(_MAC_UNIX)
#include "X11/Xlib.h"
#include "X11/keysym.h"
#include "unixsite.h"
#include "hxiids.h"
#include "hxcmenu.h"
#endif

#include "sitetext.h"
//#include "hxwinver.h"

#include "ihxpckts.h"
#include "hxprefs.h"
#include "hxtick.h"
#include "hxcore.h"
#include "hxupgrd.h"
#include "addupcol.h"
#include "mmx_util.h"

#ifdef _WINDOWS
#include "winsite.h"
#endif

#if defined(_MACINTOSH) || defined(_MAC_UNIX)
//#include "../dcondev/dcon.h"
#include "platform/mac/macsite.h"
#endif

#if defined(_UNIX) && !defined(_MAC_UNIX)
#include "unixsite.h"
#endif

#include "hxheap.h"

#include "colormap.h"
#include "drawline.h"
#include "hxvimlog.h"

#include "sitefact.h"

#if defined(HELIX_FEATURE_PREFERENCES)
#include "hxprefs.h"
#include "hxprefutil.h"
#endif /* HELIX_FEATURE_PREFERENCES */

#ifdef _DEBUG
#undef HX_THIS_FILE
static const char HX_THIS_FILE[] = __FILE__;
#endif

//XXXgfw just to clean up the code. We still *REALLY* need to clean
//this up.
#ifdef _WIN32
#define GETBITMAPCOLOR(x) GetBitmapColor( (LPBITMAPINFO)(x) )
#else
#define GETBITMAPCOLOR(x) GetBitmapColor( (HXBitmapInfo*)(x))
#endif
#ifdef _WIN32
#define GETBITMAPPITCH(x) GetBitmapPitch( (LPBITMAPINFO)(x) )
#else
#define GETBITMAPPITCH(x) GetBitmapPitch( (HXBitmapInfo*)(x))
#endif


/*
 *  Full Screen Preferences Information
 */
#define MODE_SEPERATOR                          "|"
#define MODE_DESRIPTION_SEPS                    "xX"
#define REGKEY_TESTED                           "Tested"
#define REGKEY_BLT_TIME                         "BltTime"
#define REGKEY_PASS                             "Passed"
#define DIRECT_DRAW_DLL                         "ddraw.dll"
#define REGKEY_FULLSCREEN_DATA                  "FullScreenData"
#define REGKEY_FULLSCREEN_AVAILIABLE_MODES      "AvailiableModes"
#define REGKEY_FULLSCREEN_TEST_MODES            "TestModes"
#define REGKEY_FULLSCREEN_PREFERED_MODE         "PreferedMode"
#define REGKEY_NEW_FULLSCREEN_CODE              "NewFullScreen"
#define REGKEY_FULLSCREEN_NEW_STRING_FORMAT     "NewStringFormat"
#define REGKEY_DO_NOT_SETUP_DD                  "DoNotSetupDD"
#define TEST_THRESHOLD                          30
#define REGKEY_FULLSCREEN_POSTAGE_STAMP         "PostageStamp"
#define TEST_LENGTH                             6000
#define NUM_OF_TEST_ITTERATIONS                 2000

#define MOVING_TIMEOUT 200 // Milliseconds

BOOL    CHXBaseSite::zm_bInFullScreenTest       = FALSE;
extern  tranType z_TransitionTable[];
extern  INT32 z_nNumberTransitionTypes;

//Out global list of YUV sites.
CHXSimpleList CHXBaseSite::zm_YUVSiteList;

//#define DEBUG_LINKING
/************************************************************************
 *  Method:
 *    Constructor
 */
CHXBaseSite::CHXBaseSite(IUnknown* pContext, IUnknown* pUnkOuter, INT32 lZorder)
    : m_lRefCount(0)
    , zm_pColorAcc(NULL)
    , m_bIsChildWindow(FALSE)
    , m_pValues(0)
    , m_pUser(0)
    , m_pParentSite(0)
    , m_pVideoSurface(0)
    , m_pCCF(0)
    , m_pWatcher(0)
    , m_pContext(pContext)
    , m_pUnkOuter(pUnkOuter)
    , m_lZOrder(lZorder)
    , m_bIsVisible(TRUE)
    , m_bInDestructor(FALSE)
    , m_pRootSurface(NULL)
    , m_CallbackHandle(0)
    , m_ScrollSiteCallbackHandle(0)
    , m_pMouseInSite(0)
    , m_pScheduler(0)
    , m_bRecomputeClipScheduled(FALSE)
    , m_bForceRedrawNeeded(FALSE)
    , m_bInFullScreen(FALSE)
    , m_bSettingDisplayMode(FALSE)
    , m_bRepaintScheduled(FALSE)
    , m_bDisableForceRedraw(FALSE)
    , m_bProcessRepaint(FALSE)
    , m_bAboutToBlt(FALSE)
    , m_fSharpness(DEF_SHARPNESS)
    , m_fHue(DEF_HUE)
    , m_fSaturation(DEF_SATURATION)
    , m_fContrast(DEF_CONTRAST)
    , m_fBrightness(DEF_BRIGHTNESS)
    , m_XSliderPos(0)
    , m_YSliderPos(0)
    , m_XSliderRange(0)
    , m_YSliderRange(0)
    , m_pTopLevelSite(0)
    , m_pFocusSite(0)
    , m_pStatusText(0)
    , m_nStatusTextExpireTime(0)
    , m_pCallback(0)
    , m_pScrollSiteCallback(0)
    , m_bWasTopMost(FALSE)
    , m_bDoNotGenerateWMPPaint(FALSE)
    , m_bSetCaptureOn(FALSE)
    , m_pCaptureUser(0)
    , m_pLastUser(0)
    , m_bModeSharpness(FALSE)
    , m_nLastMoveTime(0)
    , m_bAttachWindowPending(FALSE)
    , m_bDetachWndMsgPending(FALSE)
    , m_nOldBitsPerPixel(0)
    , m_nOldHorzRes(0)
    , m_nOldVertRes(0)
    , m_Region(NULL)
    , m_RegionForMouse(NULL)
    , m_RegionWithoutChildren(NULL)
    , m_nTransitionState(0)
    , m_lBltEntryCount(0)
    , m_bRegionIsValid(FALSE)
    , m_bTransitionReversed(FALSE)
    , m_bTransitionTranIn(TRUE)
    , m_nTransitionVertRepeat(1)
    , m_nTransitionHorzRepeat(1)
    , m_nTransitionBorderWidth(0)
    , m_ulTransitionBorderColor(0)
    , m_ulTransitionFadeColor(0)
    , m_bTransitionBlendBorder(FALSE)
    , m_bTransitionCoordinated(FALSE)
    , m_bTransitionCoordTranIsParentClip(FALSE)
    , m_bWindowCreatedByCreate(FALSE)
    , m_pWindow(NULL)
    , m_bSiteNeverBlts(FALSE)
    , m_bCalledComputeClipFromTransition(FALSE)
    , m_nEventSensitivity(SENSITIVITY_NOT_SET)
    , m_nDelayFillBorders(0)
    , m_bUsingList(FALSE)
    , m_bCompositionLocked(FALSE)
    , m_bCompositionMode(FALSE)
    , m_bScheduleUpgrade(FALSE)
    , m_bVideoUnderTransition(FALSE)
    , m_bInForceRedraw(FALSE)
    , m_bSiteRefresh(FALSE)
    , m_bMoving(FALSE)
    , m_bTestWindowing(FALSE)
    , m_nWindowColor(0)
    , m_bPostageStamp(FALSE)
    , m_bBltHasBeenCalled(FALSE)
    , m_pKeyBoardFocusUser(NULL)
    , m_nTLSMutexLockCount(0)
    , m_ulTLSMutexOwningThread(0)
    , m_pDirtyRegion(NULL)
    , m_bUserWantsSubRects(FALSE)
    , m_bSiteScalingInfo(FALSE)
    , m_bScrollingSite(FALSE)
{
    m_fpTransitionEffect = z_TransitionTable[0].m_pSubTypes[0].m_fpTranFunction;

    //If we are not being aggregated then just point the outer unkown
    //to ourselves....
    if( pUnkOuter == NULL )
    {
        m_pUnkOuter = (IUnknown*)(SiteNonDelegatingUnknown*) this;
    }

    // addref the context
    if( m_pContext )
    {
        m_pContext->AddRef();

        // get the CCF
        m_pContext->QueryInterface(IID_IHXCommonClassFactory,
                                   (void**)&m_pCCF);
    }

    HX_ASSERT( m_pCCF );
    if( m_pCCF )
    {
        m_pCCF->CreateInstance(CLSID_IHXValues, (void**)&m_pValues);
        HX_ASSERT(m_pValues);
    }

    if( m_pContext )
    {
        m_pContext->QueryInterface(IID_IHXScheduler, (void**)&m_pScheduler);
    }

    HX_ASSERT(m_pScheduler);

#if defined(THREADS_SUPPORTED) || defined(_UNIX_THREADS_SUPPORTED)
    HXMutex::MakeMutex(m_pMutex);
    HXThread::MakeThread(m_pDummyThread);
#else
    HXMutex::MakeStubMutex(m_pMutex);
    HXThread::MakeStubThread(m_pDummyThread);
#endif

    m_pVideoSurface = CBaseSurface::Create(m_pContext, this);
    m_pVideoSurface->AddRef();

    memset(&m_TopLevelWindow, 0, sizeof(HXxWindow));
    memset(&m_topleft, 0, sizeof(HXxPoint));
    memset(&m_position, 0, sizeof(HXxPoint));
    memset(&m_positionOrig, 0, sizeof(HXxPoint));
    memset(&m_CreateWindowPos, 0, sizeof(HXxPoint));
    memset(&m_size, 0, sizeof(HXxPoint));
    memset(&m_screenOffset, 0, sizeof(HXxPoint));
    m_pWindow = NULL;
    memset(&m_rectOldClientRect, 0, sizeof(HXxRect));
    memset(&m_rcFocusRect, 0, sizeof(m_rcFocusRect));

    m_pTopLevelSite  = this;
    m_bIsChildWindow = TRUE;

    CreateColorAccess(m_pContext);

    m_pCallback = new BaseSiteCallback(this);

    IHXPreferences*    pPreferences    = NULL;
    IHXBuffer*         pBuffer         = NULL;

    if (HXR_OK == m_pContext->QueryInterface(IID_IHXPreferences,(void**)&pPreferences))
    {
	ReadPrefBOOL(pPreferences, "TestWindowing", m_bTestWindowing);
    }

    HX_RELEASE(pPreferences);

    //Create our dirty rect region.
    m_pDirtyRegion = HXCreateRegion();


#ifdef _CHECK_CREATE
 {
#ifdef _WINDOWS
     FILE* f1 = fopen("c:\\create.txt", "a+"); /* Flawfinder: ignore */
#elif defined(_UNIX)
     FILE* f1 = fopen("/tmp/create.txt", "a+"); /* Flawfinder: ignore */
#endif
     if( f1 )
     {
         fprintf(f1, "%p Constructor: %p\n", GetCurrentThreadId(), this);
         fclose(f1);
     }
 }
#endif
}


/************************************************************************
 *  Method:
 *    Destructor
 */
CHXBaseSite::~CHXBaseSite()
{
    HX_DELETE(m_pMutex);
    HX_DELETE(m_pDummyThread);

    m_bInDestructor = TRUE;

    //Focus
    if(m_pTopLevelSite->GetFocusSite() == this)
    {
        m_pTopLevelSite->SetFocusSite(NULL);
    }

    //Clean up the color access functions
    HX_DELETE(zm_pColorAcc);

    //Cleanup Mouse oversupport
    if (m_pTopLevelSite->m_pMouseInSite == this)
    {
        m_pTopLevelSite->m_pMouseInSite = NULL;
    }

    //Cleanup all remaining callbacks
    if (m_CallbackHandle)
    {
        m_pScheduler->Remove(m_CallbackHandle);
        m_CallbackHandle = 0;
    }
    HX_DELETE(m_pCallback);

    if (m_ScrollSiteCallbackHandle)
    {
        m_pScheduler->Remove(m_ScrollSiteCallbackHandle);
        m_ScrollSiteCallbackHandle = 0;
    }
    HX_DELETE(m_pScrollSiteCallback);

    //Clean up all child sites
    while(m_ChildrenMap.GetCount())
    {
        IHXSite* pSite = NULL;
        pSite = (IHXSite*) (m_ChildrenMap.Begin()).get_key();
        DestroyChild(pSite);
    }
    m_ChildrenInZOrder.RemoveAll();

    //clean up passive site watchers
    while(m_PassiveSiteWatchers.GetCount())
    {
        IHXPassiveSiteWatcher* pWatcher =
            (IHXPassiveSiteWatcher*)m_PassiveSiteWatchers.GetHead();
        HX_RELEASE(pWatcher);
        m_PassiveSiteWatchers.RemoveHead();
    }

    //Check and see if we are in the YUV Site list. If so, remove ourselves.
    LISTPOSITION pPos = zm_YUVSiteList.Find(this);
    if(pPos)
    {
        zm_YUVSiteList.RemoveAt(pPos);
    }


    _EmptyBlenderList();
    _EmptyNotifierList();

    //Remove all pending tasks.
    if (m_pTopLevelSite)
        m_pTopLevelSite->RemovePendingTasks(this);

    // release intefaces
    HX_RELEASE(m_pCCF);
    HX_RELEASE(m_pScheduler);
    HX_RELEASE(m_pContext);
    HX_RELEASE(m_pValues);

    HX_RELEASE(m_pVideoSurface);
    HX_RELEASE(m_pRootSurface);

    if(m_pTopLevelSite != this)
        HX_RELEASE(m_pTopLevelSite);

    HXDestroyRegion(m_Region);
    m_Region=NULL;
    HXDestroyRegion(m_RegionForMouse);
    m_RegionForMouse=NULL;
    HXDestroyRegion(m_RegionWithoutChildren);
    m_RegionWithoutChildren = NULL;

    HXDestroyRegion(m_pDirtyRegion);
    m_pDirtyRegion = NULL;
}


/************************************************************************
 *  Method:
 *    CHXBaseSite::SetParentSite
 */
void
CHXBaseSite::SetParentSite(CHXBaseSite* pParentSite)
{
    m_pParentSite = pParentSite;
}

/************************************************************************
 *  Method:
 *    CHXBaseSite::SetTopLevelSite
 */
void
CHXBaseSite::SetTopLevelSite(CHXBaseSite* pTop)
{
    if (m_pTopLevelSite != this)
    {
        HX_RELEASE(m_pTopLevelSite);
    }

    m_pTopLevelSite = pTop;

    if (m_pTopLevelSite && m_pTopLevelSite != this)
        m_pTopLevelSite->AddRef();
}

/************************************************************************
 *  Method:
 *    IUnknown::QueryInterface
 */
STDMETHODIMP CHXBaseSite::QueryInterface(REFIID riid, void** ppvObj)
{
    return m_pUnkOuter->QueryInterface(riid,ppvObj);
}

/************************************************************************
 *  Method:
 *    IUnknown::AddRef
 */
STDMETHODIMP_(ULONG32) CHXBaseSite::AddRef()
{
    return m_pUnkOuter->AddRef();
}

/************************************************************************
 *  Method:
 *    IUnknown::Release
 */
STDMETHODIMP_(ULONG32) CHXBaseSite::Release()
{
    return m_pUnkOuter->Release();
}

/************************************************************************
 *  Method:
 *    IUnknown::QueryInterface
 */
STDMETHODIMP CHXBaseSite::SiteNonDelegatingQueryInterface(REFIID riid, void** ppvObj)
{
    if (IsEqualIID(riid, IID_IUnknown))
    {
        AddRef();
        *ppvObj = (IUnknown*)(IHXSite*)this;
        return HXR_OK;
    }
    else if (IsEqualIID(riid, IID_IHXSite))
    {
        AddRef();
        *ppvObj = (IHXSite*)this;
        return HXR_OK;
    }
    else if (IsEqualIID(riid, IID_IHXSite2))
    {
        AddRef();
        *ppvObj = (IHXSite2*)this;
        return HXR_OK;
    }
    else if (IsEqualIID(riid, IID_IHXSiteTreeNavigation))
    {
        AddRef();
        *ppvObj = (IHXSiteTreeNavigation*)this;
        return HXR_OK;
    }
    else if (IsEqualIID(riid, IID_IHXInterruptSafe))
    {
        AddRef();
        *ppvObj = (IHXInterruptSafe*)this;
        return HXR_OK;
    }
    else if (IsEqualIID(riid, IID_IHXSiteWindowless))
    {
        AddRef();
        *ppvObj = (IHXSiteWindowless*)this;
        return HXR_OK;
    }
    else if (IsEqualIID(riid, IID_IHXSiteWindowed))
    {
        AddRef();
        *ppvObj = (IHXSiteWindowed*)this;
        return HXR_OK;
    }
    else if (IsEqualIID(riid, IID_IHXStatusMessage))
    {
        AddRef();
        *ppvObj = (IHXStatusMessage*)this;
        return HXR_OK;
    }
    else if (IsEqualIID(riid, IID_IHXSiteFullScreen))
    {
        AddRef();
        *ppvObj = (IHXSiteFullScreen*)this;
        return HXR_OK;
    }
    else if (IsEqualIID(riid, IID_IHXVideoControl))
    {
        AddRef();
        *ppvObj = (IHXVideoControl*)this;
        return HXR_OK;
    }
    else if (IsEqualIID(riid, IID_IHXSiteTransition))
    {
        AddRef();
        *ppvObj = (IHXSiteTransition*)this;
        return HXR_OK;
    }
    else if (IsEqualIID(riid, IID_IHXSiteComposition))
    {
        AddRef();
        *ppvObj = (IHXSiteComposition*)this;
        return HXR_OK;
    }
    else if (m_pValues &&
             m_pValues->QueryInterface(riid, ppvObj) == HXR_OK)
    {
        return HXR_OK;
    }
    else if (IsEqualIID(riid, IID_IHXKeyBoardFocus))
    {
        AddRef();
        *ppvObj = (IHXKeyBoardFocus*)this;
        return HXR_OK;
    }
    else if (IsEqualIID(riid, IID_IHXDrawFocus))
    {
        AddRef();
        *ppvObj = (IHXDrawFocus*)this;
        return HXR_OK;
    }
    else if (IsEqualIID(riid, IID_IHXSubRectSite))
    {
        AddRef();
        *ppvObj = (IHXSubRectSite*)this;
        return HXR_OK;
    }

    *ppvObj = NULL;
    return HXR_NOINTERFACE;
}

/************************************************************************
 *  Method:
 *    IUnknown::AddRef
 */
STDMETHODIMP_(ULONG32) CHXBaseSite::SiteNonDelegatingAddRef()
{
    return InterlockedIncrement(&m_lRefCount);
}


/************************************************************************
 *  Method:
 *    IUnknown::Release
 */
STDMETHODIMP_(ULONG32) CHXBaseSite::SiteNonDelegatingRelease()
{
    if (InterlockedDecrement(&m_lRefCount) > 0)
    {
        return m_lRefCount;
    }

    delete this;
    return 0;
}

/************************************************************************
 *  Method:
 *    IHXSite::AttachUser
 */
STDMETHODIMP CHXBaseSite::AttachUser(IHXSiteUser* /*IN*/ pUser)
{
    if (m_pUser) return HXR_UNEXPECTED;

#ifndef _DEBUG_WINDOWED_SITES
    if (m_pParentSite && pUser->NeedsWindowedSites())
    {
        _NeedWindowedSite();
    }
#endif

    m_pUser = pUser;
    m_pUser->AddRef();

    //if (!m_pTopLevelSite->m_pKeyBoardFocusUser && m_pTopLevelSite->m_pUser)
    //{
    //    m_pTopLevelSite->m_pKeyBoardFocusUser = m_pTopLevelSite->m_pUser;
    //    m_pTopLevelSite->m_pKeyBoardFocusUser->AddRef();
    //}

    m_pUser->AttachSite(this);

    if (m_bAttachWindowPending)
    {
        m_bAttachWindowPending = FALSE;
        m_bDetachWndMsgPending = TRUE;
        // send HX_ATTACH_WINDOW msg to the renderers
        void *  lpParam1 = NULL;
        void *  lpParam2 = NULL;

        HXxEvent event = {HX_ATTACH_WINDOW, m_pWindow ? m_pWindow->window : NULL, lpParam1, lpParam2, 0, 0};
        m_pUser->HandleEvent(&event);
    }

    /* XXXRA
     * Mac one does scale to full screen and also forces and update message
     * should not need it!
     */

    return HXR_OK;
}

/************************************************************************
 *  Method:
 *    IHXSite::DetachUser
 */
STDMETHODIMP CHXBaseSite::DetachUser()
{
    if (!m_pUser) return HXR_UNEXPECTED;

    /*
     *  SetCapture
     */

    if (m_pTopLevelSite->m_pLastUser == m_pUser)
    {
        m_pTopLevelSite->m_pLastUser = NULL;
    }

    if (m_pTopLevelSite->m_pCaptureUser == m_pUser)
    {
        m_pTopLevelSite->m_pCaptureUser= NULL;
        m_bSetCaptureOn = FALSE;
    }

    if (m_CallbackHandle)
    {
        m_pScheduler->Remove(m_CallbackHandle);
        m_CallbackHandle = 0;
    }
    if (m_ScrollSiteCallbackHandle)
    {
        m_pScheduler->Remove(m_ScrollSiteCallbackHandle);
        m_ScrollSiteCallbackHandle = 0;
    }

    if (m_pUser && m_bDetachWndMsgPending)
    {
        // send HX_DETACH_WINDOW msg to the renderers
        void *  lpParam1 = NULL;
        void *  lpParam2 = NULL;

        HXxEvent event = {HX_DETACH_WINDOW, m_pWindow ? m_pWindow->window : NULL, lpParam1, lpParam2, 0, 0};

        m_bDetachWndMsgPending = FALSE;
        m_pUser->HandleEvent(&event);
    }

    AddRef();
    if (HXR_OK == m_pUser->DetachSite())
    {
        if (m_pTopLevelSite->m_pKeyBoardFocusUser == m_pUser)
            HX_RELEASE(m_pTopLevelSite->m_pKeyBoardFocusUser);

        HX_RELEASE(m_pUser);
    }
    Release();

    return HXR_OK;
}

/************************************************************************
 *  Method:
 *    IHXSite::GetUser
 */
STDMETHODIMP CHXBaseSite::GetUser(REF(IHXSiteUser*) /*OUT*/ pUser)
{
    if (!m_pUser) return HXR_UNEXPECTED;

    pUser = m_pUser;
    pUser->AddRef();

    return HXR_OK;
}


/************************************************************************
 *  Method:
 *    IHXSite::CreateChild
 */
STDMETHODIMP CHXBaseSite::CreateChild(REF(IHXSite*) /*OUT*/ pChildSite)
{
    _TLSLock();

    HRESULT result = HXR_OK;

    // Create an instance of CHXBaseSite, let it know it's in child
    // window mode.
    CHXBaseSite* pChildSiteWindowless = CHXBaseSite::CreateSite(m_pContext, NULL, m_ChildrenMap.GetCount());
    pChildSiteWindowless->AddRef();
    pChildSiteWindowless->SetParentSite(this);
    pChildSiteWindowless->SetTopLevelSite(m_pTopLevelSite);
    pChildSiteWindowless->SetRootSurface(m_pRootSurface);
    pChildSiteWindowless->SetParentWindow(&m_TopLevelWindow);

#ifdef _WIN32
    //this is to give the windows sites a chance to hook themselves
    //into wm_move madness.
    CHXWinSite* pSiteIt = (CHXWinSite*)pChildSiteWindowless;
    pSiteIt->HookParents();
#endif

    // Get the IHXSite interface from the child to return to the
    // outside world.
    pChildSiteWindowless->QueryInterface(IID_IHXSite, (void**)&pChildSite);

    // Store the CHXBaseSite in a list of child windows, always keep
    //a reference to it.  ExSiteInfo does an AddRef in constructor
    m_ChildrenMap.SetAt(pChildSite, pChildSiteWindowless);
    pChildSite->AddRef();

    //Now add the child into or ZOrder sorted list.
    m_ChildrenInZOrder.AddTail( (void*)pChildSiteWindowless );


    //Set the child's origin
    pChildSiteWindowless->SetOrigin(&m_topleft);

    if(m_pTopLevelSite)
        m_pTopLevelSite->ScheduleCallback(CLIP, 0);

    HXxWindow* pWindow = GetWindow();
    //XXXgfw this focus code is disabled for the beamer release.
    //SafeSetFocus(pWindow);

    _TLSUnlock();


    return HXR_OK;
}

/************************************************************************
 *  Method:
 *    IHXSite::DestroyChild
 */
STDMETHODIMP CHXBaseSite::DestroyChild(IHXSite* /*IN*/ pChildSite)
{
    // Avoid dead-lock in vidsurf2
    LockBlitters();
    FlushSurfaces();

    _TLSLock();

    //Check and see if we are in the YUV Site list. If so, remove ourselves.
    LISTPOSITION pPos = zm_YUVSiteList.Find(this);
    if(pPos)
    {
        zm_YUVSiteList.RemoveAt(pPos);
    }

    //Verify that the site is actually a child site and find its
    //position in the list in the event that it is a child.
    HX_RESULT retVal = HXR_FAIL;
    CHXBaseSite* pChildSiteWindowless=NULL;

    if (m_ChildrenMap.Lookup(pChildSite, (void*&) pChildSiteWindowless))
    {
        m_ChildrenMap.RemoveKey(pChildSite);
        pChildSiteWindowless->Destroy();
        pChildSiteWindowless->SetParentSite(NULL);
        //Remove it from our child z-order list.
        LISTPOSITION pos,posNext = m_ChildrenInZOrder.GetHeadPosition();
        while (posNext)
        {
            pos = posNext;
            CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(posNext);
            if( pSite == pChildSiteWindowless )
            {
                m_ChildrenInZOrder.RemoveAt(pos);
                while (posNext)
                {
		    pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(posNext);

		    INT32 zOrder;
		    pSite->GetZOrder(zOrder);
		    pSite->SetInternalZOrder(zOrder - 1);
                }
                break;
            }
        }
        HX_RELEASE(pChildSite);
        HX_RELEASE(pChildSiteWindowless);
        retVal = HXR_OK;
    }
    HX_ASSERT( m_ChildrenInZOrder.GetCount() == m_ChildrenMap.GetCount() );

    if (m_pTopLevelSite==this)
    {
        m_pTopLevelSite->RecomputeClip();
    }
    else
    {
        if (m_pTopLevelSite)
        {
            m_pTopLevelSite->ScheduleCallback(CLIP, 0);
        }
    }

    _TLSUnlock();
    UnlockBlitters();

    return retVal;
}

/************************************************************************
 *  Method:
 *    IHXSite::AttachWatcher
 */
STDMETHODIMP CHXBaseSite::AttachWatcher(IHXSiteWatcher* /*IN*/ pWatcher)
{
    if (m_pWatcher) return HXR_UNEXPECTED;

    m_pWatcher = pWatcher;

    if (m_pWatcher)
    {
        m_pWatcher->AddRef();
        m_pWatcher->AttachSite(this);
    }

    return HXR_OK;
}

/************************************************************************
 *  Method:
 *    IHXSite::DetachWatcher
 */
STDMETHODIMP CHXBaseSite::DetachWatcher()
{
    if (!m_pWatcher) return HXR_UNEXPECTED;

    m_pWatcher->DetachSite();
    HX_RELEASE(m_pWatcher);

    return HXR_OK;
}

/************************************************************************
 *  Method:
 *    IHXSite::SetSize
 */

STDMETHODIMP CHXBaseSite::SetSize(HXxSize size)
{
    HX_RESULT ret = HXR_OK;

    _TLSLock();

    if (_AtSystemTime())
    {
        m_pTopLevelSite->ExecutePendingTasks();
        ret = _SafeSetSize(size);
        _TLSUnlock();
        return ret;
    }

    PendingTask* pPendingTask = new PendingTask( ONSETSIZE,
                                                 this,
                                                 (void*)size.cx,
                                                 (void*)size.cy,
                                                 (void*)NULL,
                                                 (void*)NULL,
                                                 (void*)NULL,
                                                 (void*)NULL
                                                 );
    m_pTopLevelSite->m_PendingTaskList.AddTail((void*) pPendingTask);
    m_pTopLevelSite->ScheduleCallback(MOUSE, 0);
    _TLSUnlock();

    return TRUE;
}

/************************************************************************
 *  Method:
 *    IHXSite::SetSize
 */
HX_RESULT CHXBaseSite::_SafeSetSize(HXxSize size)
{
    _TLSLock();

    HRESULT hres = HXR_OK;
    CHXSimpleList::Iterator i;

    size.cx = size.cx<0?0:size.cx;
    size.cy = size.cy<0?0:size.cy;

    //Fix up sizes for full screen. Some renderes, MPEG, will get very
    //late setsize calls. If we get a setsize call after we have gone
    //to fullscreen, we need to readjust our full screen window.
    if( IsFullScreen() && this==m_pTopLevelSite )
    {
        double stretchRatio = 0;
        double xRatio       = 0;
        double yRatio       = 0;
        UINT16 newBitsPerPixel = 0;
        UINT16 nHozRes      = 0;
        UINT16 nVertRes     = 0;

        _GetDeviceCaps(NULL, newBitsPerPixel, nHozRes, nVertRes);

        if(m_bPostageStamp)
        {
            if( m_windowSize.cx*2 <= nHozRes &&
                m_windowSize.cy*2 <= nVertRes)
            {
                xRatio  = yRatio = 2.0;
            }
            else
            {
                xRatio  = yRatio = 1.0;
            }

        }
        else
        {
            xRatio = (double)nHozRes  / (double)size.cx ;
            yRatio = (double)nVertRes / (double)size.cy ;
        }

        if (xRatio<yRatio)
            stretchRatio = xRatio;
        else
            stretchRatio = yRatio;

        if( m_bPostageStamp )
        {
            size.cx = (int) ((double) m_windowSize.cx * stretchRatio + 0.5);
            size.cy = (int) ((double) m_windowSize.cy * stretchRatio + 0.5);
        }
        else
        {
            size.cx = (int) ((double) size.cx * stretchRatio + 0.5);
            size.cy = (int) ((double) size.cy * stretchRatio + 0.5);
        }

#if !defined(_UNIX) || defined(_MAC_UNIX)
        m_screenOffset.x = (nHozRes  - size.cx)/2;
        m_screenOffset.y = (nVertRes - size.cy)/2;
#endif

    }

    //before we do anything, we give the SiteWatcher a chance to
    //influence this operation.
    if (m_pWatcher)
    {
        hres = m_pWatcher->ChangingSize(m_size, size);
    }

    //Get rid of our last alpha blend region as it is the wrong size
    //now....
    HX_FREE( m_pVideoSurface->m_pucLastImage );

    if (HXR_OK == hres )
    {
        //We must invalidate our rect.....
        HXxRect pTmp = { m_topleft.x,
                         m_topleft.y,
                         m_topleft.x+m_size.cx,
                         m_topleft.y+m_size.cy};
        m_pTopLevelSite->_RecursiveDamageRect( &pTmp, TRUE );

        m_size = size;

        // iterate child site list
        for(i=m_PassiveSiteWatchers.Begin(); i!= m_PassiveSiteWatchers.End(); ++i)
        {
            ((IHXPassiveSiteWatcher*) *i)->SizeChanged(&m_size);
        }

        if( m_pWindow && m_pWindow->window &&
            (m_pTopLevelSite!=this || m_bWindowCreatedByCreate ) )
        {
            _SetSize(size);
        }

        //Handle scrolling..
        if( m_pValues )
        {
            ULONG32 bScroll = FALSE;
            m_pValues->GetPropertyULONG32("ScrollingSite", bScroll);
            if (bScroll)
            {
                SetXSliderRange(size.cx);
                SetYSliderRange(size.cy);
                m_bScrollingSite = TRUE;
            }
        }
        //We must invalidate our rect after the resize also..
        HXxRect pTmp2 = { m_topleft.x,
                          m_topleft.y,
                          m_topleft.x+m_size.cx,
                          m_topleft.y+m_size.cy};
        m_pTopLevelSite->_RecursiveDamageRect( &pTmp2, TRUE );
    }
    if (this == m_pTopLevelSite && m_pStatusText)
    {
        m_pStatusText->ParentChangedSize();
    }

    if (m_pTopLevelSite==this)
    {
        m_pTopLevelSite->RecomputeClip();
    }
    else
    {
        if(m_pTopLevelSite)
            m_pTopLevelSite->ScheduleCallback(CLIP, 0);
    }


    if( this == m_pTopLevelSite && m_pStatusText )
    {
        m_pStatusText->ParentChangedSize();
    }

    //XXXgfw Don't know where to really do this work. It must be after
    //the site is created and smil can set these values but before we
    //handle events.

    //Get sensitivity setting for mouse clicks.  Only do this
    //once per site on the first event.  If 'sensitivity'
    //isn't set by then too bad.
    if( m_nEventSensitivity==SENSITIVITY_NOT_SET )
    {
        //opaque is the default set by the W3C working group.
        m_nEventSensitivity = SENSITIVITY_OPAQUE;
        if( m_pValues )
        {
            IHXBuffer* pBuf = NULL;
            m_pValues->GetPropertyCString( "sensitivity", pBuf );
            if( pBuf )
            {
                const char* pszBuff = (const char*)pBuf->GetBuffer();
                if( pszBuff)
                {
                    //m_nEventSensitivity is in alpha values [0,255]
                    if( strcmp( pszBuff, "transparent" )==0 )
                    {
                        m_nEventSensitivity = SENSITIVITY_TRANSPARENT;
                    }
                    else if( strcmp( pszBuff, "opaque" )==0 )
                    {
                        m_nEventSensitivity = SENSITIVITY_OPAQUE;
                    }
                    else
                    {

                        double sen = ::atof( pszBuff );
                        if( sen < 0 )
                            sen = 0;
                        if( sen > 100 )
                            sen = 100;
                        //Scale percentages to [0,255]
                        m_nEventSensitivity = 255-(int)(sen*255.0/100.0+0.5);
                    }
                }
                HX_RELEASE(pBuf);
            }
        }
    }


    _TLSUnlock();
    return hres;
}

/************************************************************************
 *  Method:
 *    IHXSite::SetPosition
 */

STDMETHODIMP CHXBaseSite::SetPosition(HXxPoint position)
{
    HX_RESULT ret = HXR_OK;

    _TLSLock();

    if (_AtSystemTime())
    {
        m_pTopLevelSite->ExecutePendingTasks();
        ret = _SafeSetPosition(position);
        _TLSUnlock();
        return ret;
    }

    PendingTask* pPendingTask = new PendingTask(ONSETPOSITION,
                                                this, (void*) position.x,
                                                (void*) position.y,
                                                (void*) NULL,
                                                (void*) NULL,
                                                (void*) NULL,
                                                (void*) NULL);
    m_pTopLevelSite->m_PendingTaskList.AddTail((void*) pPendingTask);
    m_pTopLevelSite->ScheduleCallback(MOUSE, 0);
    _TLSUnlock();
    return TRUE;
}

HX_RESULT CHXBaseSite::_SafeSetPosition(HXxPoint position)
{
    _TLSLock();
    HRESULT hres = HXR_OK;
    CHXSimpleList::Iterator i;
    CHXMapPtrToPtr::Iterator j;

    //Before we do anything, we give the SiteWatcher a chance to
    //influence this operation.
    if (m_pWatcher)
    {
        hres = m_pWatcher->ChangingPosition(m_position, position);
    }

#if defined(_MACINTOSH) || defined(_MAC_UNIX)
    if (this == m_pTopLevelSite)
    {
        // xxxbobclark
        // For the Mac, the top-level site is moved by adjusting
        // its HXxWindow's x and y values. If we go ahead and
        // change m_position, it can screw up situations like the
        // embedded player where it DOES call SetPosition on the
        // top-level site to move it in its window.
        _TLSUnlock();
        return HXR_OK;
    }
#endif

    if (HXR_OK == hres)
    {
        //Damage The old position....
        HXxRect pTmp = { m_topleft.x,
                         m_topleft.y,
                         m_topleft.x+m_size.cx,
                         m_topleft.y+m_size.cy};
        m_pTopLevelSite->_RecursiveDamageRect( &pTmp, TRUE );

        if(!m_bWindowCreatedByCreate )
        {
            // if we've created the window we don't want to move the site
            // just the window
            m_position     = position;
            m_positionOrig = m_position;
        }

        //fixup our top left
        ResetOrigin();

        //iterate passive site watcher list
        for(i=m_PassiveSiteWatchers.Begin(); i!= m_PassiveSiteWatchers.End(); ++i)
        {
            ((IHXPassiveSiteWatcher*) *i)->PositionChanged(&m_position);
        }

        if( m_pWindow &&
            m_pWindow->window &&
            (m_pTopLevelSite!=this || m_bWindowCreatedByCreate )
            )
        {
            m_CreateWindowPos = position;
            _SetPosition(position);
        }
    }

    //We must first remove our old dirty region because we moved and
    //we could get negative offsets...
    HXxRect pTmp2 = { m_topleft.x,
                      m_topleft.y,
                      m_topleft.x+m_size.cx,
                      m_topleft.y+m_size.cy};
    m_pTopLevelSite->_RecursiveDamageRect( &pTmp2, TRUE );

    if (m_pTopLevelSite==this)
    {
        m_pTopLevelSite->RecomputeClip();
    }
    else
    {
        if (m_pTopLevelSite)
        {
            m_pTopLevelSite->ScheduleCallback(CLIP, 0);
        }
    }

    m_pVideoSurface->UpdateDestRect();

    _TLSUnlock();
    return hres;
}


/************************************************************************
 *  Method:
 *    IHXSite::GetSize
 */
STDMETHODIMP CHXBaseSite::GetSize(REF(HXxSize) size)
{
    size = m_size;

    //XXXgfw what???????? why change it after assignment???
//     m_pValues->GetPropertyULONG32("MediaSizeX", (ULONG32&) ttt.cx);
//     m_pValues->GetPropertyULONG32("MediaSizeY", (ULONG32&) ttt.cy);

    return HXR_OK;
}


/************************************************************************
 *  Method:
 *    IHXSite::GetPosition
 */
STDMETHODIMP CHXBaseSite::GetPosition(REF(HXxPoint) position)
{
    position = m_position;
    return HXR_OK;
}

//
// CHXBaseSite::DamageRect()
//
// All incoming coordinates are SITE relative...
//
STDMETHODIMP CHXBaseSite::DamageRect(HXxRect rect)
{
#if defined(_MACINTOSH) || defined(_MAC_UNIX)
    _TLSLock();
#endif
    HXRECTANGLE rectTmp;
    HXxPoint* pOrigin = GetOrigin();

    //Crop
    if( rect.left < 0 )
        rect.left = 0;
    if( rect.top < 0 )
        rect.top = 0;
    if( rect.right > m_size.cx )
        rect.right = m_size.cx;
    if( rect.bottom > m_size.cy )
        rect.bottom = m_size.cy;

    //Translate rect to window coordinates.
    rect.left   += pOrigin->x;
    rect.right  += pOrigin->x;
    rect.top    += pOrigin->y;
    rect.bottom += pOrigin->y;

    rectTmp.x      = (short)rect.left;
    rectTmp.y      = (short)rect.top;
    rectTmp.width  = (short)(rect.right-rect.left);
    rectTmp.height = (short)(rect.bottom-rect.top);

    HXUnionRectWithRegion( &rectTmp, m_pDirtyRegion, m_pDirtyRegion);

    //Do OS specific stuff here.
    _DamageRect(rect);
#if defined(_MACINTOSH) || defined(_MAC_UNIX)
    _TLSUnlock();
#endif
    return HXR_OK;
}

//This is the same as DamageRect except that the coordinates are in
//Window relative coords and we don't do the OS specific stuff (like
//no invalidateRect.
void CHXBaseSite::DamageRectWindowRel(HXxRect rect)
{
    HXxPoint* pPosition = GetOrigin();

    //Crop
    HXREGION* pReg = HXCreateRectRegion( rect.left,
                                         rect.top,
                                         rect.right-rect.left,
                                         rect.bottom-rect.top
                                         );

    //Find out what part intersects us.
    HXREGION*   pTemp = Transition( pPosition->x, pPosition->y,
                                    pPosition->x + m_size.cx,
                                    pPosition->y + m_size.cy
                                    );
    HXIntersectRegion( pTemp, pReg, pReg );
    if( !HXEmptyRegion(pReg) )
    {
        HXUnionRegion( pReg, m_pDirtyRegion, m_pDirtyRegion);
        // We must call _DamageRect to give windows a chance to see if
        // we are occluded by a drop down menu. If we are, then we
        // have to invalidate the OS rect so Windows does not do a
        // save under.
        HXxRect rectTmp =
            {pTemp->extents.x1, pTemp->extents.y1, pTemp->extents.x2, pTemp->extents.y2};
        _DamageRect(rectTmp);
    }


    HXDestroyRegion( pReg );
    HXDestroyRegion( pTemp );
}


/************************************************************************
 *  Method:
 *    IHXSite::DamageRegion
 */
STDMETHODIMP CHXBaseSite::DamageRegion(HXxRegion region)

{
    HX_ASSERT( "Depricated method, do not use. Use the new damage region." == NULL );

    //This was never used and it was not defined what a HXxRegion was.
    //So, we just have to invalidate the whole site.
    //Users should use the new damage region that takes the cross platform
    //region that actually works.
    HXxRect rect;
    HXREGION* reg = (HXREGION*)region;
    rect.left   = 0;
    rect.top    = 0;
    rect.right  = m_size.cx;
    rect.bottom = m_size.cy;
    return DamageRect( rect );
}

// Method:
//    IHXSite::ForceRedraw
STDMETHODIMP CHXBaseSite::ForceRedraw()
{
    HXxEvent event;
    HXxWindow* hxxWin = GetWindow();

    if( IsCompositionLocked() && m_pVideoSurface->m_nBltMode!=HX_OVERLAY_BLT )
    {
        return HXR_OK;
    }

    // make sure we have a visible window event though this should be
    // computed from the list of rects.
    if (!_ShouldEnterForceRedraw())
    {
        return HXR_OK;
    }

    _TLSLock();

    AddRef();
    memset(&m_UpdateBltStatsRect, 0, sizeof(m_UpdateBltStatsRect));

    if(m_pTopLevelSite->m_bDisableForceRedraw)
    {
        m_pTopLevelSite->m_bDisableForceRedraw = TRUE;
    }
    else
    {
        BOOL bDoIt =
            ((m_bIsVisible && m_pUser && m_Region && !HXEmptyRegion(m_Region)) ||
             (m_AlphaBlendNotifiers.GetCount()!=0 || m_AlphaBlendSites.GetCount()!=0));

        if( bDoIt )
        {
            AboutToBlt();
            event.handled = 0;
            if( m_bUserWantsSubRects )
            {
                if( !HXEmptyRegion(m_pDirtyRegion) )
                {
                    HXxExposeInfo exposeInfo;
                    HXxBoxRegion    dirtRegion;

                    //Construct a dirty rect that is relative to the
                    //site's topleft corner.
                    HXREGION* pTmpReg = HXCreateRegion();
                    HXUnionRegion( pTmpReg, m_pDirtyRegion, pTmpReg );
                    HXOffsetRegion( pTmpReg, -m_topleft.x, -m_topleft.y );

                    // adjust for scrolling; essentially turning off
                    // subrect blitting while scrolling

                    if (GetXSliderPos() || GetYSliderPos())
                    {
			HXREGION* pMe = HXCreateRectRegion( 0,
						0,
						m_size.cx,
						m_size.cy
						);
			HXUnionRegion(pMe, pTmpReg, pTmpReg);
			HXDestroyRegion(pMe);
                    }

                    //Set up the cross platform region.
                    dirtRegion.numRects = pTmpReg->numRects;
                    dirtRegion.rects    = pTmpReg->rects;

                    exposeInfo.extents.left    = pTmpReg->extents.x1;
                    exposeInfo.extents.right   = pTmpReg->extents.x2;
                    exposeInfo.extents.top     = pTmpReg->extents.y1;
                    exposeInfo.extents.bottom  = pTmpReg->extents.y2;
                    exposeInfo.pRegion         = & dirtRegion;
                    exposeInfo.pWindow         = GetWindow();
                    exposeInfo.pParam1         = NULL;
                    exposeInfo.pParam2         = NULL;

                    event.event   = HX_SURFACE_UPDATE2;
                    event.window  = hxxWin?hxxWin->window : NULL;
                    event.param1  = m_pVideoSurface;
                    event.param2  = &exposeInfo;
                    event.result  = 0;
                    event.handled = 0;

                    // Clear the dirty region
                    HXZeroOutRegion( m_pDirtyRegion );

                    if( m_pUser )
                    {
                        if (!m_bDoNotGenerateWMPPaint)
                        {
                            m_bInForceRedraw = m_bSiteRefresh;
                            m_pUser->HandleEvent(&event);
                            m_bInForceRedraw = FALSE;
                        }
                    }
                    HXDestroyRegion( pTmpReg );
                }
            }
            else
            {
//XXXgfw OK, this is screwed up. Windows renders want a rectangle in
//XXXgfw param2 while the unix renderers want a Window there. To clean this
//XXXgfw up we need to clean up and unify the renderers.....
#if defined(_UNIX) && !defined(_MAC_UNIX)
                event.event   = HX_SURFACE_UPDATE;
                event.window  = hxxWin?hxxWin->window : NULL;
                event.param1  = m_pVideoSurface;
                event.param2  = GetWindow();
                event.result  = 0;
                event.handled = 0;
#else
                event.event   = HX_SURFACE_UPDATE;
                event.window  = m_pWindow? m_pWindow->window : NULL;
                event.param1  = m_pVideoSurface;
                event.param2  = NULL;
                event.result  = 0;
                event.handled = 0;
#endif
                // Clear the dirty region
                HXZeroOutRegion( m_pDirtyRegion );

                if( m_pUser )
                {
                    if (!m_bDoNotGenerateWMPPaint)
                    {
                        // Distinguishes between a new frame and a repaint of a prior frame
                        m_bInForceRedraw = m_bSiteRefresh;
                        m_pUser->HandleEvent(&event);
                        m_bInForceRedraw = FALSE;
                    }
                }
            }

            // If blt has never been called, then blt black to the
            // background.  Do not do this if we are a windowed
            // renderer.
            if (!event.handled && !m_bBltHasBeenCalled
                && !m_pWindow && m_pVideoSurface->m_nBltMode!=HX_OVERLAY_BLT )
            {
                // Get the current size of the site The source rect is
                // just a 1 by 1 black pixel that gets stretched to
                // fit the destination
                HXxRect rDestRect   = { 0, 0, m_size.cx, m_size.cy};
                HXxRect rSrcRect    = { 0, 0, 1, 1};

                HXBitmapInfoHeader bih;
                memset(&bih, 0, sizeof(HXBitmapInfoHeader));

                bih.biSize          = sizeof(HXBitmapInfoHeader);
                bih.biWidth         = 1;
                bih.biHeight        = 1;
                bih.biPlanes        = 1;
                bih.biBitCount      = 32;
                bih.biCompression   = HX_RGB;

                UCHAR pBuffer[4] = { 0,0,0,0 };
                m_pVideoSurface->Blt(pBuffer,
                                     &bih,
                                     rDestRect,
                                     rSrcRect);
                m_bBltHasBeenCalled = FALSE;
            }

            //Stupid Windowed renderers!
            if(!m_bDoNotGenerateWMPPaint &&
               !event.handled            &&
               m_pWindow                 &&
               m_pWindow->window )
            {
                _SendOSUpdateMessage();
            }
        }

        m_pVideoSurface->UpdateBltStats(&m_UpdateBltStatsRect);
    }

    _TLSUnlock();
    _ExitForceRedraw();

    Release();
    return HXR_OK;
}



/************************************************************************
 *  Method:
 *    IHXSite2::UpdateSiteWindow
 *
 *      Not used on Windows platform
 */
STDMETHODIMP CHXBaseSite::UpdateSiteWindow
(
    HXxWindow* /*IN*/ pWindow
    )
{
    return HXR_NOTIMPL;
}


/************************************************************************
 *  Method:
 *    IHXSite2::ShowSite
 */
STDMETHODIMP CHXBaseSite::ShowSite(BOOL bShow)
{
    _TLSLock();

    if(m_bIsVisible != bShow)
    {
        m_bIsVisible = bShow;

        //Invalidate the rect....
        HXxRect pTmp = { m_topleft.x,
                         m_topleft.y,
                         m_topleft.x+m_size.cx,
                         m_topleft.y+m_size.cy};
        m_pTopLevelSite->_RecursiveDamageRect( &pTmp, TRUE );

        if( this == m_pTopLevelSite )
        {
            RecomputeClip();
        }
        else
        {
            if(m_pTopLevelSite)
                m_pTopLevelSite->ScheduleCallback(CLIP, 0);
        }
    }

    _ShowSite(bShow);

    SizeSliders();

    _TLSUnlock();

    return HXR_OK;
}

void CHXBaseSite::_ForceRedrawAll()
{
    if( (IsSiteVisible() && m_Region && !HXEmptyRegion(m_Region)) ||
        (m_AlphaBlendSites.GetCount()||m_AlphaBlendNotifiers.GetCount() )
        )
    {

//         HXREGION* pReg = NULL;

//         if( pDirtyRect)
//         {
//             pReg = HXCreateRectRegion( pDirtyRect->left,
//                                         pDirtyRect->top,
//                                         pDirtyRect->right-pDirtyRect->left,
//                                         pDirtyRect->bottom-pDirtyRect->top );
//             HXIntersectRegion( m_Region, pReg, pReg );
//             HXUnionRegion( m_pDirtyRegion, pReg, m_pDirtyRegion );
//             HXDestroyRegion( pReg );
//         }
//         else
//         {
//            HXUnionRegion( m_pDirtyRegion, m_Region, m_pDirtyRegion );
//        }
        InternalForceRedraw();
    }

    //Now do all the children in z-order
    LISTPOSITION pos = m_ChildrenInZOrder.GetHeadPosition();
    while(pos)
    {
        CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
        pSite->_ForceRedrawAll();
    }
}

BOOL CHXBaseSite::_CheckForVisibleChild()
{
    BOOL retVal = FALSE;
    if( m_bIsVisible && !m_bSiteNeverBlts )
    {
        retVal = TRUE;
    }
    else
    {
        LISTPOSITION pos = m_ChildrenInZOrder.GetHeadPosition();
        while(pos)
        {
            CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
            if( pSite->_CheckForVisibleChild() )
            {
                retVal = TRUE;
                break;
            }
        }
    }
    return retVal;
}

/************************************************************************
 *  Method:
 *    IHXSite2::IsSiteVisible
 */
STDMETHODIMP_(BOOL) CHXBaseSite::IsSiteVisible()
{
    BOOL bIsVisible = m_bIsVisible;
    if(m_pParentSite)
    {
        bIsVisible &= m_pParentSite->IsSiteVisible();
    }

    if( bIsVisible )
    {
        //If we are a m_bSiteNeverBlts then it doesn't matter if we are
        //visible or not, we must have at least one child that is
        //visible and not m_bSiteNeverBlts. Otherwise we really aren't
        //visible at all. This distinction is needed because of our
        //favorite logic in computesubrecs not that we have transparent
        //regions.
        if(!_CheckForVisibleChild())
        {
            bIsVisible = FALSE;
        }
    }

    return bIsVisible;
}

/************************************************************************
 *  Method:
 *    IHXSite2::UpdateZOrder
 *    This method updates the Z order of its child sites since one of its
 *    child sites' Z order is being updated.
 */

void
CHXBaseSite::UpdateZOrder( CHXBaseSite* pUpdatedChildSite, INT32 lOldZOrder, INT32 lNewZOrder)
{
    HX_ASSERT(pUpdatedChildSite);
    LISTPOSITION pos = m_ChildrenInZOrder.Find((void*)pUpdatedChildSite);
    if (!pos)
    {
	return;
    }

    m_ChildrenInZOrder.RemoveAt(pos);

    BOOL bHasReinsertedChild = FALSE;
    INT32 zOrder = 0;
    INT32 newZOrder = 0;
    LISTPOSITION posNext = m_ChildrenInZOrder.GetHeadPosition();
    while (posNext)
    {
	pos = posNext;
	CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(posNext);
	if (!bHasReinsertedChild)
	{
	    pSite->GetZOrder(zOrder);

	    if (zOrder > lNewZOrder)
	    {
		m_ChildrenInZOrder.InsertBefore(pos, (void*)pUpdatedChildSite);
		bHasReinsertedChild = TRUE;
		pUpdatedChildSite->SetInternalZOrder(newZOrder++);
	    }
	}
	pSite->SetInternalZOrder(newZOrder++);
    }

    if (!bHasReinsertedChild)
    {
	m_ChildrenInZOrder.AddTail((void*)pUpdatedChildSite);
	pUpdatedChildSite->SetInternalZOrder(newZOrder++);
    }

    HX_ASSERT((newZOrder == m_ChildrenInZOrder.GetCount()) &&
		(m_ChildrenInZOrder.GetCount() == m_ChildrenMap.GetCount()));
}

/************************************************************************
 *  Method:
 *    IHXSite2::SetZOrder
 */
STDMETHODIMP CHXBaseSite::SetZOrder(INT32 lZOrder)
{
    if(!m_pParentSite)
    {
        return HXR_UNEXPECTED;
    }

    _TLSLock();

    if (lZOrder == -1)
    {
        lZOrder = m_pParentSite->GetNumberOfChildSites() - 1;
    }

    if (lZOrder >= (INT32) m_pParentSite->GetNumberOfChildSites())
    {
        lZOrder = m_pParentSite->GetNumberOfChildSites() - 1;
    }

    if (m_lZOrder != lZOrder)
    {
        m_pParentSite->UpdateZOrder(this, m_lZOrder, lZOrder);
        //Invalidate the rect....
        if( m_pTopLevelSite )
        {
            HXxRect pTmp = { m_topleft.x,
                             m_topleft.y,
                             m_topleft.x+m_size.cx,
                             m_topleft.y+m_size.cy};
            m_pTopLevelSite->_RecursiveDamageRect( &pTmp, TRUE );
        }
    }

    if( this == m_pTopLevelSite)
    {
        RecomputeClip();
    }
    else
    {
        if (m_pTopLevelSite)
            m_pTopLevelSite->ScheduleCallback(CLIP, 0);
    }

    _TLSUnlock();
    return HXR_OK;
}

/************************************************************************
 *  Method:
 *    IHXSite2::GetZOrder
 */
STDMETHODIMP CHXBaseSite::GetZOrder(REF(INT32) lZOrder)
{
    lZOrder = m_lZOrder;
    HX_ASSERT(m_lZOrder> -1 && m_lZOrder< 2000);
    return HXR_OK;
}

/************************************************************************
 *  Method:
 *    IHXSite2::MoveSiteToTop
 */
STDMETHODIMP CHXBaseSite::MoveSiteToTop()
{
    SetZOrder(-1); //-1 means the top.
    return HXR_OK;
}

//IHXSubRectSite::GetSubRectVideoSurface()
STDMETHODIMP CHXBaseSite::GetSubRectVideoSurface( REF(IHXSubRectVideoSurface*) pSurface )
{
    HX_RESULT res = HXR_FAIL;

    if (m_pVideoSurface)
    {
        res = m_pVideoSurface->QueryInterface(IID_IHXSubRectVideoSurface,
                                              (void**)&pSurface);
    }
    return res;
}

/************************************************************************
 *  Method:
 *    IHXSite2::GetVideoSurface
 */
STDMETHODIMP CHXBaseSite::GetVideoSurface(REF(IHXVideoSurface*) pSurface)
{
    HX_RESULT res = HXR_FAIL;

    if (m_pVideoSurface)
    {
        res = m_pVideoSurface->QueryInterface(IID_IHXVideoSurface,
                                              (void**)&pSurface);
    }

    return res;
}

/************************************************************************
 *  Method:
 *    IHXSite2::GetNumberOfChildSites
 *            and
 *    IHXSiteTreeNavigation::GetNumberOfChildSites
 */
STDMETHODIMP_(UINT32) CHXBaseSite::GetNumberOfChildSites()
{
    HX_ASSERT( m_ChildrenInZOrder.GetCount() == m_ChildrenMap.GetCount() );
    return (UINT32)m_ChildrenMap.GetCount();
}

/************************************************************************
 *  Method:
 *    IHXSite2::AddPassiveSiteWatcher
 */
STDMETHODIMP CHXBaseSite::AddPassiveSiteWatcher(IHXPassiveSiteWatcher* pWatcher)
{
    pWatcher->AddRef();
    m_PassiveSiteWatchers.AddTail(pWatcher);
    return HXR_OK;
}

/************************************************************************
 *  Method:
 *    IHXSite2::RemovePassiveSiteWatcher
 */
STDMETHODIMP CHXBaseSite::RemovePassiveSiteWatcher(IHXPassiveSiteWatcher* pWatcher)
{
    // iterate child site list
    IHXPassiveSiteWatcher* pThisWatcher = NULL;
    LISTPOSITION pPos = m_PassiveSiteWatchers.Find(pWatcher);
    HX_RESULT retVal = HXR_FAIL;

    if (pPos)
    {
        m_PassiveSiteWatchers.RemoveAt(pPos);
        HX_RELEASE(pWatcher);
        retVal = HXR_OK;
    }

    return retVal;
}

#if defined(_DEBUG) && !defined(_MACINTOSH) && !defined(_MAC_UNIX)
void _PrintKeyboardEventInfo(HXxEvent* pEvent )
{
    char szBuff[256]; /* Flawfinder: ignore */

    if( pEvent->event == HX_CHAR )
        _DumpString( "HX_CHAR     " );
    if( pEvent->event == HX_KEY_DOWN )
        _DumpString( "HX_KEY_DOWN " );
    if( pEvent->event == HX_KEY_UP )
        _DumpString( "HX_KEY_UP   " );

    if( ((UINT32)pEvent->param2)&HX_VIRTUAL_KEY_MASK )
    {
        _DumpString( " key: " );

        switch((UINT32)pEvent->param1 )
        {
           case HX_VK_LBUTTON       :
               _DumpString( "HX_VK_LBUTTON   ");
               break;
           case HX_VK_RBUTTON       :
               _DumpString( "HX_VK_RBUTTON   ");
               break;
           case HX_VK_CANCEL        :
               _DumpString( "HX_VK_CANCEL    ");
               break;
           case HX_VK_MBUTTON       :
               _DumpString( "HX_VK_MBUTTON   ");
               break;
           case HX_VK_BACK          :
               _DumpString( "HX_VK_BACK      ");
               break;
           case HX_VK_TAB           :
               _DumpString( "HX_VK_TAB       ");
               break;
           case HX_VK_CLEAR         :
               _DumpString( "HX_VK_CLEAR     ");
               break;
           case HX_VK_RETURN        :
               _DumpString( "HX_VK_RETURN    ");
               break;
           case HX_VK_SHIFT         :
               _DumpString( "HX_VK_SHIFT     ");
               break;
           case HX_VK_CONTROL       :
               _DumpString( "HX_VK_CONTROL   ");
               break;
           case HX_VK_MENU          :
               _DumpString( "HX_VK_MENU      ");
               break;
           case HX_VK_PAUSE         :
               _DumpString( "HX_VK_PAUSE     ");
               break;
           case HX_VK_CAPITAL       :
               _DumpString( "HX_VK_CAPITAL   ");
               break;
           case HX_VK_ESCAPE        :
               _DumpString( "HX_VK_ESCAPE    ");
               break;
           case HX_VK_SPACE         :
               _DumpString( "HX_VK_SPACE     ");
               break;
           case HX_VK_PRIOR         :
               _DumpString( "HX_VK_PRIOR     ");
               break;
           case HX_VK_NEXT          :
               _DumpString( "HX_VK_NEXT      ");
               break;
           case HX_VK_END           :
               _DumpString( "HX_VK_END       ");
               break;
           case HX_VK_HOME          :
               _DumpString( "HX_VK_HOME      ");
               break;
           case HX_VK_LEFT          :
               _DumpString( "HX_VK_LEFT      ");
               break;
           case HX_VK_UP            :
               _DumpString( "HX_VK_UP        ");
               break;
           case HX_VK_RIGHT         :
               _DumpString( "HX_VK_RIGHT     ");
               break;
           case HX_VK_DOWN          :
               _DumpString( "HX_VK_DOWN      ");
               break;
           case HX_VK_SELECT        :
               _DumpString( "HX_VK_SELECT    ");
               break;
           case HX_VK_EXECUTE       :
               _DumpString( "HX_VK_EXECUTE   ");
               break;
           case HX_VK_SNAPSHOT      :
               _DumpString( "HX_VK_SNAPSHOT  ");
               break;
           case HX_VK_INSERT        :
               _DumpString( "HX_VK_INSERT    ");
               break;
           case HX_VK_DELETE        :
               _DumpString( "HX_VK_DELETE    ");
               break;
           case HX_VK_HELP          :
               _DumpString( "HX_VK_HELP      ");
               break;
           case HX_VK_LWIN          :
               _DumpString( "HX_VK_LWIN      ");
               break;
           case HX_VK_RWIN          :
               _DumpString( "HX_VK_RWIN      ");
               break;
           case HX_VK_APPS          :
               _DumpString( "HX_VK_APPS      ");
               break;
           case HX_VK_NUMPAD0       :
               _DumpString( "HX_VK_NUMPAD0   ");
               break;
           case HX_VK_NUMPAD1       :
               _DumpString( "HX_VK_NUMPAD1   ");
               break;
           case HX_VK_NUMPAD2       :
               _DumpString( "HX_VK_NUMPAD2   ");
               break;
           case HX_VK_NUMPAD3       :
               _DumpString( "HX_VK_NUMPAD3   ");
               break;
           case HX_VK_NUMPAD4       :
               _DumpString( "HX_VK_NUMPAD4   ");
               break;
           case HX_VK_NUMPAD5       :
               _DumpString( "HX_VK_NUMPAD5   ");
               break;
           case HX_VK_NUMPAD6       :
               _DumpString( "HX_VK_NUMPAD6   ");
               break;
           case HX_VK_NUMPAD7       :
               _DumpString( "HX_VK_NUMPAD7   ");
               break;
           case HX_VK_NUMPAD8       :
               _DumpString( "HX_VK_NUMPAD8   ");
               break;
           case HX_VK_NUMPAD9       :
               _DumpString( "HX_VK_NUMPAD9   ");
               break;
           case HX_VK_MULTIPLY      :
               _DumpString( "HX_VK_MULTIPLY  ");
               break;
           case HX_VK_ADD           :
               _DumpString( "HX_VK_ADD       ");
               break;
           case HX_VK_SEPARATOR     :
               _DumpString( "HX_VK_SEPARATOR ");
               break;
           case HX_VK_SUBTRACT      :
               _DumpString( "HX_VK_SUBTRACT  ");
               break;
           case HX_VK_DECIMAL       :
               _DumpString( "HX_VK_DECIMAL   ");
               break;
           case HX_VK_DIVIDE        :
               _DumpString( "HX_VK_DIVIDE    ");
               break;
           case HX_VK_F1            :
               _DumpString( "HX_VK_F1        ");
               break;
           case HX_VK_F2            :
               _DumpString( "HX_VK_F2        ");
               break;
           case HX_VK_F3            :
               _DumpString( "HX_VK_F3        ");
               break;
           case HX_VK_F4            :
               _DumpString( "HX_VK_F4        ");
               break;
           case HX_VK_F5            :
               _DumpString( "HX_VK_F5        ");
               break;
           case HX_VK_F6            :
               _DumpString( "HX_VK_F6        ");
               break;
           case HX_VK_F7            :
               _DumpString( "HX_VK_F7        ");
               break;
           case HX_VK_F8            :
               _DumpString( "HX_VK_F8        ");
               break;
           case HX_VK_F9            :
               _DumpString( "HX_VK_F9        ");
               break;
           case HX_VK_F10           :
               _DumpString( "HX_VK_F10       ");
               break;
           case HX_VK_F11           :
               _DumpString( "HX_VK_F11       ");
               break;
           case HX_VK_F12           :
               _DumpString( "HX_VK_F12       ");
               break;
           case HX_VK_F13           :
               _DumpString( "HX_VK_F13       ");
               break;
           case HX_VK_F14           :
               _DumpString( "HX_VK_F14       ");
               break;
           case HX_VK_F15           :
               _DumpString( "HX_VK_F15       ");
               break;
           case HX_VK_F16           :
               _DumpString( "HX_VK_F16       ");
               break;
           case HX_VK_F17           :
               _DumpString( "HX_VK_F17       ");
               break;
           case HX_VK_F18           :
               _DumpString( "HX_VK_F18       ");
               break;
           case HX_VK_F19           :
               _DumpString( "HX_VK_F19       ");
               break;
           case HX_VK_F20           :
               _DumpString( "HX_VK_F20       ");
               break;
           case HX_VK_F21           :
               _DumpString( "HX_VK_F21       ");
               break;
           case HX_VK_F22           :
               _DumpString( "HX_VK_F22       ");
               break;
           case HX_VK_F23           :
               _DumpString( "HX_VK_F23       ");
               break;
           case HX_VK_F24           :
               _DumpString( "HX_VK_F24       ");
               break;
           case HX_VK_NUMLOCK       :
               _DumpString( "HX_VK_NUMLOCK   ");
               break;
           case HX_VK_SCROLL        :
               _DumpString( "HX_VK_SCROLL    ");
               break;
           default:
               _DumpString( " !! UNKOWN VIRTUAL !! " );
        }
    }
    else
    {
        sprintf( szBuff, " key: \"%c\" (%d) ", pEvent->param1, pEvent->param1 ); /* Flawfinder: ignore */
        _DumpString( szBuff );
    }
    sprintf( szBuff, "scancode: %d flags: ", ((UINT32)pEvent->param2)&0x000000ff ); /* Flawfinder: ignore */
    _DumpString( szBuff );

    if( (UINT32)pEvent->param2 & HX_VIRTUAL_KEY_MASK )
        _DumpString( "VirtualKey " );
    if( (UINT32)pEvent->param2 & HX_EXTENDED_KEY_MASK )
        _DumpString( "ExtendedKey " );
    if( (UINT32)pEvent->param2 & HX_SHIFT_MASK )
        _DumpString( "ShiftKey " );
    if( (UINT32)pEvent->param2 & HX_CTRL_MASK )
        _DumpString( "ControlKey " );
    if( (UINT32)pEvent->param2 & HX_ALT_MASK )
        _DumpString( "AltKey " );
    if( (UINT32)pEvent->param2 & HX_CAPS_LOCK_MASK )
        _DumpString( "CapsLock " );
    if( (UINT32)pEvent->param2 & HX_NUM_LOCK_MASK )
        _DumpString( "NumLock " );
    if( (UINT32)pEvent->param2 & HX_SCROLL_LOCK_MASK )
        _DumpString( "ScrollLock " );
    _DumpString( "\n" );
}
#endif


CHXBaseSite* CHXBaseSite::_GetSiteFromPixel(HXxPoint& point)
{
    CHXBaseSite* pRet = this;

    if( (  m_bSiteNeverBlts ||
           m_nEventSensitivity == SENSITIVITY_TRANSPARENT ||
           ( m_pVideoSurface &&
             m_pVideoSurface->IsPixelTransparent(point, m_nEventSensitivity)
             )
           ) &&
        !(m_nEventSensitivity == SENSITIVITY_OPAQUE )
        )
    {
        //Now go through all the alphablend regions and see who this
        //pixel belongs to.
        CHXMapPtrToPtr::Iterator i = m_AlphaBlendSites.Begin();
        for( ; i!=m_AlphaBlendSites.End() ; ++i)
        {
            CHXBaseSite* pSite    = (CHXBaseSite*) i.get_key();
            HXREGION*      pRegion = (HXREGION*)*i;
            if( HXPointInRegion( pRegion, point.x, point.y ) )
            {
                pRet=pSite->_GetSiteFromPixel(point);
                break;
            }
        }
        //If we are transparent here we MUST be blending with someone.
        HX_ASSERT( this!=pRet);
    }
    return pRet;
}




/************************************************************************
 *  Method:
 *    IHXSiteWindowless::EventOccurred
 */
STDMETHODIMP CHXBaseSite::EventOccurred(HXxEvent* /*IN*/ pEvent)
{

    HX_RESULT hr = HXR_OK;
    CHXMapPtrToPtr::Iterator i;
    HXxEvent event;

    if( NULL == pEvent )
    {
        return HXR_OK;
    }
    memcpy(&event, pEvent, sizeof(HXxEvent)); /* Flawfinder: ignore */

    AddRef();

    if(!_HandleOSEvents(pEvent) && !_ConvertToHXEvent(pEvent) )
    {
        if( _ConvertToHXEvent(pEvent))
        {
            Release();
            return hr;
        }
        switch((ULONG32)pEvent->event)
        {
           case HX_KEY_UP:
           case HX_KEY_DOWN:
#if defined(_DEBUG) && 0
               _PrintKeyboardEventInfo(pEvent);
#endif
               // Always send <CR> and <TAB> to the top level site for smil
#if !defined(_MACINTOSH) && !defined(_MAC_UNIX) // XXXSEH: Is this the correct solution?
               if (HX_VK_TAB == (int)pEvent->param1 || HX_VK_RETURN == (int)pEvent->param1)
#else
                   if (0)
#endif
                       m_pTopLevelSite->m_pUser->HandleEvent(pEvent);
               // Send keyboard messages to the user that has focus
                   else if (m_pTopLevelSite->m_pKeyBoardFocusUser)
                       m_pTopLevelSite->m_pKeyBoardFocusUser->HandleEvent(pEvent);
                   else if (m_pUser)
                       m_pUser->HandleEvent(pEvent);

               break;

           case HX_CHAR:
#if defined(_DEBUG) && 0
               _PrintKeyboardEventInfo(pEvent);
#endif
               // Always send <CR> and <TAB> to the top level site for smil
#if !defined(_MACINTOSH) && !defined(_MAC_UNIX) // XXXSEH: Is this the correct solution?
               if (HX_VK_TAB == (int)pEvent->param1 || HX_VK_RETURN == (int)pEvent->param1)
#else
                   if (0)
#endif
                       m_pTopLevelSite->m_pUser->HandleEvent(pEvent);
               // Send keyboard messages to the user that has focus
                   else if (m_pTopLevelSite->m_pKeyBoardFocusUser)
                       m_pTopLevelSite->m_pKeyBoardFocusUser->HandleEvent(pEvent);
                   else if (m_pUser)
                       m_pUser->HandleEvent(pEvent);

               break;

           case HX_SET_FOCUS:
           case HX_LOSE_FOCUS:
               if (m_pUser)
                   m_pUser->HandleEvent(pEvent);
               break;

           case HX_SET_STATUS:
           case HX_SET_CURSOR:
               if (m_pUser)
                   m_pUser->HandleEvent(pEvent);
               break;

           case HX_MOUSE_LEAVE:
           case HX_MOUSE_ENTER:
           {
               HXxEvent tempEvent;
               memcpy( &tempEvent, pEvent, sizeof( HXxEvent ) ); /* Flawfinder: ignore */

               if (m_pUser)
                   m_pUser->HandleEvent(pEvent);

               //Also send a set status and set cursor to the user.
               tempEvent.event = HX_SET_CURSOR;
               if (m_pUser)
                   m_pUser->HandleEvent(&tempEvent);
               tempEvent.event   = HX_SET_STATUS;
               tempEvent.handled = FALSE;
               if (m_pUser)
                   m_pUser->HandleEvent(&tempEvent);
           }
           break;

           case HX_PRIMARY_BUTTON_UP:
           case HX_PRIMARY_BUTTON_DOWN:
           case HX_CONTEXT_BUTTON_UP:
           case HX_CONTEXT_BUTTON_DOWN:
           case HX_MOUSE_MOVE:
           case HX_PRIMARY_DBLCLK:
           case HX_CONTEXT_DBLCLK:
           case HX_THIRD_DBLCLK:
           {

               HXxPoint point = *((HXxPoint*)pEvent->param1);

               HX_ASSERT( m_nEventSensitivity != SENSITIVITY_NOT_SET || m_pWindow);

#if defined(_DEBUG) && 0
               //XXXgfw just so I can set break points.
               if( pEvent->event == HX_PRIMARY_BUTTON_DOWN )
               {
                   int MasterSlaveFlipFlop=1;
               }
#endif

               // check to see if this message is within my bounding box.
               if( m_RegionWithoutChildren &&
                   ::HXPointInRegion( m_RegionWithoutChildren, point.x, point.y))
               {
                   // ok check to see it is within our clipping area
                   if (::HXPointInRegion(m_RegionForMouse, point.x, point.y) )
                   {
                       //Get the site under the point that isn't transparent.
                       CHXBaseSite* pRealSite = this;
                       pRealSite = _GetSiteFromPixel(point);
                       pRealSite->_HandleMouseEvent(pEvent);

#if defined(_UNIX) && !defined(_MAC_UNIX)
                       // for unix only, post context menu if the event is unhandled
                       if (!pEvent->handled && pEvent->event == HX_CONTEXT_BUTTON_DOWN)
                       {
                           IHXClientEngineMapper* pCleng = NULL;

                           if (m_pContext)
                           {
                               m_pContext->QueryInterface(IID_IHXClientEngineMapper,
                                                          (void**)&pCleng);
                               if (pCleng)
                               {
                                   IUnknown* pUnknown = NULL;
                                   if (HXR_OK != pCleng->GetPlayerBySite(this, pUnknown))
                                   {
                                       // check our children
                                       CHXMapPtrToPtr::Iterator i = m_ChildrenMap.Begin();
                                       for ( ; i != m_ChildrenMap.End(); ++i)
                                       {
                                           CHXBaseSite* pSite = (CHXBaseSite*) *i;
                                           if (HXR_OK == pCleng->GetPlayerBySite(pSite, pUnknown))
                                               break;
                                       }
                                   }
                                   if (pUnknown)
                                   {
                                       IHXContextMenu *pContextMenu = NULL;
                                       pUnknown->QueryInterface(IID_IHXContextMenu, (void**)&pContextMenu);
                                       HX_RELEASE(pUnknown);
                                       if (pContextMenu)
                                       {
                                           pContextMenu->InitContextMenu("Contextual Menu");
                                           pContextMenu->ShowMenu(NULL, point);
                                           HX_RELEASE(pContextMenu);
                                       }
                                   }
                                   HX_RELEASE(pCleng);
                               }
                           }
                       }
#endif
                   }
                   else
                   {
                       INT32 handledCount = 0;
                       INT32 mapCount     = 0;
                       LISTPOSITION pos   = NULL;

                       // try send this to all of our children
                     mapchanged2:
                       mapCount = m_ChildrenInZOrder.GetCount();
                       pos = m_ChildrenInZOrder.GetHeadPosition();
                       while(pos)
                       {
                           CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
                           pSite->EventOccurred(pEvent);
                           if (pEvent->handled)
                           {
                               break;
                           }
                           handledCount+=pEvent->handled;
                           pEvent->handled=0;

                           if (m_ChildrenInZOrder.GetCount() != mapCount)
                           {
                               goto mapchanged2;
                           }
                       }
                       if (handledCount)
                       {
                           pEvent->handled = 1;
                       }
                       HX_ASSERT(handledCount<2);
                   }
               }
               break;
           }
           default:
#if defined(_DEBUG) && 0
               _DumpString("CHXBaseSite::EventOccurred Unkown event type........\n");
#endif
               break;
        }
    }

    event.handled = pEvent->handled;
    event.result  = pEvent->result;
    memcpy( pEvent, &event, sizeof( event ) ); /* Flawfinder: ignore */
    Release();

    return hr;
}



void CHXBaseSite::_HandleMouseEvent(HXxEvent* pEvent)
{
    HXxEvent event;
    memcpy( &event, pEvent, sizeof(event) ); /* Flawfinder: ignore */
    HXxPoint point = *((HXxPoint*)pEvent->param1);

    m_pTopLevelSite->m_pLastUser = m_pUser;

    //If this is a click then this is the site with "focus"
    if (pEvent->event == HX_PRIMARY_BUTTON_DOWN)
    {
        m_pTopLevelSite->SetFocusSite(this);
        HXxWindow* pTempwindow = GetWindow();
        if(pTempwindow && pTempwindow->window)
        {
            SafeSetFocus(pTempwindow);
        }

        // Keyboard focus must change to match the site focus
        if (m_pTopLevelSite->m_pKeyBoardFocusUser &&
            m_pTopLevelSite->m_pKeyBoardFocusUser != m_pUser)
        {
            HXxEvent focusEvent;
            memcpy(&focusEvent, pEvent, sizeof(focusEvent)); /* Flawfinder: ignore */
            focusEvent.handled = FALSE;

            focusEvent.event = HX_SET_FOCUS;
            EventOccurred(&focusEvent);

            if (focusEvent.handled)
                SetKeyboardFocus(m_pUser);
            else
                SetKeyboardFocus(m_pTopLevelSite->m_pUser);
        }
    }

    // translate point and send it off to our user
    float xf = 0.0;
    float yf = 0.0;
    if( m_pParentSite )
    {
        int dX = (m_size.cx-m_pParentSite->m_size.cx);
        int dY = (m_size.cy-m_pParentSite->m_size.cy);
        if( dX && dY )
        {
            xf = (float)GetXSliderPos()/(float)(dX);
            yf = (float)GetYSliderPos()/(float)(dY);
        }
    }

    point.x = point.x - (short)((m_topleft.x - GetXSliderPos()) + GetSliderWidth()*xf);
    point.y = point.y - (short)((m_topleft.y - GetYSliderPos()) + GetSliderHeight()*yf);
    memcpy(&event, pEvent, sizeof(HXxEvent)); /* Flawfinder: ignore */
    event.param1 = &point;

    // hey do we think that we are the window with the mouse?
    CHXBaseSite* pTopLevelSite = m_pTopLevelSite;
    if (pTopLevelSite->m_pMouseInSite != this)
    {

        if (pTopLevelSite->m_pMouseInSite)
        {
            HXxPoint oobPoint;
            oobPoint.x = -1;
            oobPoint.y = -1;
            HXxEvent Outevent = { HX_MOUSE_LEAVE,
                                  m_pWindow ? m_pWindow->window : NULL,
                                  (void*)&oobPoint,
                                  0, 0,
                                  FALSE };
            pTopLevelSite->m_pMouseInSite->EventOccurred(&Outevent);
        }
        //Generate a mouse enter message
        pTopLevelSite->m_pMouseInSite = this;

        HXxEvent tempevent = {HX_MOUSE_ENTER,
                              m_pWindow ? m_pWindow->window : NULL,
                              (void*)&point,
                              0, 0,
                              FALSE};
        if (m_pUser)
        {
            m_pUser->HandleEvent(&tempevent);
        }

        // hey, have we started the mouseleave generator?
        pTopLevelSite->ScheduleCallback(MOUSE, 100);
    }


    // we have already called HandleEvent on the
    // original user in HandleWndProc
    if(pEvent->window != (m_pWindow ? m_pWindow->window : NULL))
    {
        _GenerateOSEvent(&event, pEvent);
    }

    //Send out the HX_SET_CURSOR and HX_SET_STATUS *after*
    //the mouse leave/enter messages. These are sent out for
    //all mouse move messages.
    if( pEvent->event==HX_MOUSE_MOVE && m_pUser )
    {
        HXxEvent stTmpEvent;
        memcpy( &stTmpEvent, pEvent, sizeof( HXxEvent ) ); /* Flawfinder: ignore */

        //Set Cursor....
        stTmpEvent.event   = HX_SET_CURSOR;
        stTmpEvent.handled = FALSE;
        m_pUser->HandleEvent(&stTmpEvent);

        //Set Status....
        stTmpEvent.event   = HX_SET_STATUS;
        stTmpEvent.handled = FALSE;
        m_pUser->HandleEvent(&stTmpEvent);
    }

    //ALWAYS send the RMA MOUSE messages...  Needed for
    //hyperlinks to work in SMIL since the native
    //message is handled by...say...the Flash
    //renderer... and SMIL only understands the RMA
    //mouse messages.
    if(m_pUser)
    {
        m_pUser->HandleEvent(&event);
        pEvent->handled |= event.handled;
    }

#if !defined(_UNIX) || defined(_MAC_UNIX)
//XXXgfw We should change the realtext renderer to use
//HX_SET_CURSOR and HX_SET_STATUS instead and then
//just get rid of this....
    // and now for the real text renderer we will
    // check to see if this was a mouse move
    // message. If so we will give the user a
    // WM_SETCURSOR
    if (m_pUser && pEvent->event == HX_MOUSE_MOVE)
    {
        _GenerateSetCursorEvent();
    }
#endif
}

/************************************************************************
 *  Method:
 *    IHXSiteWindowless::GetParentWindow
 */
STDMETHODIMP_(HXxWindow*) CHXBaseSite::GetParentWindow()
{
    if (m_pWindow && m_pWindow->window)
    {
        return m_pWindow;
    }
    else
    {
        if(m_pParentSite)
        {
            return m_pParentSite->GetParentWindow();
        }
        else
        {
            return NULL;
        }
    }
}

/************************************************************************
 *  Method:
 *    CHXBaseSite::GetTopLevelSite
 */
CHXBaseSite*
CHXBaseSite::GetTopLevelSite()
{
    if (!m_pParentSite)
    {
        return this;
    }
    else
    {
        return m_pParentSite->GetTopLevelSite();
    }
}

CHXBaseSite*
CHXBaseSite::GetContainingCHXBaseSite()
{
    if (m_pWindow && m_pWindow->window)
    {
        return this;
    }
    else
    {
        if (m_pParentSite)
        {
            return m_pParentSite->GetContainingCHXBaseSite();
        }
    }
    return NULL;
}


/************************************************************************
 *  Method:
 *    CHXBaseSite::AttachWindow
 */
STDMETHODIMP CHXBaseSite::AttachWindow(HXxWindow* pWindow)
{
    if (m_pWindow && m_pWindow->window) return HXR_UNEXPECTED;

    _TLSLock();

    if (!m_pParentSite)
    {
        memcpy(&m_TopLevelWindow, pWindow, sizeof(HXxWindow)); /* Flawfinder: ignore */
    }

    m_pWindow = pWindow;

    if (!m_pRootSurface && !m_pParentSite)
    {
        m_pRootSurface = CBaseRootSurface::Create(m_pContext, this);
        m_pRootSurface->AddRef();
    }

    _AttachWindow();

    if (!m_pParentSite)
    {
        _GetDeviceCaps(NULL, m_nOldBitsPerPixel, m_nOldHorzRes, m_nOldVertRes);
        m_pRootSurface->AddRef();
        SetRootSurface(m_pRootSurface);
        m_pRootSurface->Release();
        SetParentWindow(&m_TopLevelWindow);
    }

    if (m_pUser)
    {
        m_bAttachWindowPending = FALSE;
        m_bDetachWndMsgPending = TRUE;
        // send HX_ATTACH_WINDOW msg to the renderers
        void *  lpParam1 = NULL;
        void *  lpParam2 = NULL;

        HXxEvent event = {HX_ATTACH_WINDOW, m_pWindow ? m_pWindow->window : NULL, lpParam1, lpParam2, 0, 0};

        m_pUser->HandleEvent(&event);
    }
    else
    {
        m_bAttachWindowPending = TRUE;
    }

    //XXXgfw This focus code is disabled for the Beamer release.
//     if (!m_pParentSite)
//     {
//         SafeSetFocus(m_pWindow);
//     }

    _TLSUnlock();

    return HXR_OK;
}


/************************************************************************
 *  Method:
 *    IHXSiteWindowed::DetachWindow
 */
STDMETHODIMP CHXBaseSite::DetachWindow()
{
    if (!m_pWindow || !m_pWindow->window) return HXR_UNEXPECTED;

    if (m_pVideoSurface)
    {
	m_pVideoSurface->EndOptimizedBlt();
    }
						  
    // Avoid dead-lock in vidsurf2
    LockBlitters();
    FlushSurfaces();

    _TLSLock();

    if (m_pUser && m_bDetachWndMsgPending)
    {
        // send HX_DETACH_WINDOW msg to the renderers
        void *  lpParam1 = NULL;
        void *  lpParam2 = NULL;
        HXxEvent event = {HX_DETACH_WINDOW, m_pWindow ? m_pWindow->window : NULL, lpParam1, lpParam2, 0, 0};

        m_bDetachWndMsgPending = FALSE;
        m_pUser->HandleEvent(&event);
    }

    //Status text
    if (m_pStatusText)
    {
        m_pStatusText->Destroy();
#ifdef _WINDOWS
        HX_DELETE(m_pStatusText);
#else
        HX_RELEASE(m_pStatusText);
#endif
        HX_DELETE(m_pStatusText);
    }

    _DestroySliders();
    // let the OS specific site do its cleanup.
    _DetachWindow();

    m_pWindow = NULL;

    DestroySurfaces();
    HX_RELEASE(m_pRootSurface);

    if (m_pTopLevelSite)
        m_pTopLevelSite->RemovePendingTasks(this);
    SetRootSurface(NULL);
    SetParentWindow(NULL);

    if (m_pTopLevelSite == this)
    {
        if (m_CallbackHandle)
        {
            m_pScheduler->Remove(m_CallbackHandle);
            m_CallbackHandle = 0;
        }
        if (m_ScrollSiteCallbackHandle)
        {
            m_pScheduler->Remove(m_ScrollSiteCallbackHandle);
            m_ScrollSiteCallbackHandle = 0;
        }
    }

    _TLSUnlock();
    UnlockBlitters();

    return HXR_OK;
}

/************************************************************************
 *  Method:
 *    IHXSiteWindowed::Create
 */
STDMETHODIMP CHXBaseSite::Create(void* ParentWindow, UINT32 style)
{
    HRESULT retVal = HXR_OK;
    if( m_pWindow && m_pWindow->window )
    {
        //We already have one.
        return HXR_FAIL;
    }

    _TLSLock();

    void* hWnd = _Create(ParentWindow, style);

    if (!hWnd)
    {
        retVal = HXR_FAIL;
    }
    else
    {
        HXxWindow* pWindow = new HXxWindow;
        memset(pWindow,0,sizeof(HXxWindow));
        pWindow->window = hWnd;

        if( this == m_pTopLevelSite )
        {
            //This flags tells us if Create was used to make the window
            //or not. We use this in SetSize and SetPosition so that we
            //never resize or move the TLCs window. But, in TLC that call
            //create, like testplay, we need to do the move and resize
            //for them.
            m_bWindowCreatedByCreate = TRUE;
        }

        //This way we always pass through attach window.
        AttachWindow(pWindow);

    }

    _TLSUnlock();
    return retVal;
}

/************************************************************************
 *  Method:
 *    IHXSiteWindowed::Destroy
 */
STDMETHODIMP CHXBaseSite::Destroy()
{
    //This could be the site that owns the overlay even though
    //it doesn't have a window. Give it a chance to clean up
    //here...
    if( m_pVideoSurface )
    {
        m_pVideoSurface->EndOptimizedBlt();
    }

    _DestroySliders();

    if(!m_pWindow || !m_pWindow->window)
    {
        return HXR_UNEXPECTED;
    }

    _TLSLock();
    HXxWindow tempWindow;
    memcpy( &tempWindow, m_pWindow, sizeof( HXxWindow ) ); /* Flawfinder: ignore */
    DetachWindow();
    _Destroy(&tempWindow);
    m_pWindow = NULL;

    if (m_pTopLevelSite && m_pTopLevelSite != this)
        m_pTopLevelSite->ScheduleCallback(CLIP, 0);

    _TLSUnlock();
    return HXR_OK;
}

STDMETHODIMP_(HXxWindow*) CHXBaseSite::GetWindow()
{
    return GetParentWindow();
}

/************************************************************************
 *  Method:
 *    IHXSite2::SetCursor
 */
STDMETHODIMP CHXBaseSite::SetCursor(HXxCursor cursor, REF(HXxCursor) oldCursor)
{
    return HXR_NOTIMPL;
}


/************************************************************************
 *  Method:
 *    IHXSiteTreeNavigation::GetParentSite
 */
STDMETHODIMP
CHXBaseSite::GetParentSite(REF(IHXSite*)pParentSite)
{
    pParentSite = m_pParentSite;
    if (pParentSite)
    {
        pParentSite->AddRef();
        return HXR_OK;
    }
    
    return HXR_FAIL;
}

/************************************************************************
 *  Method:
 *    IHXSiteTreeNavigation::GetNthChildSite
 */
STDMETHODIMP
CHXBaseSite::GetNthChildSite(ULONG32 ulIndex,
                                REF(IHXSite*) pSite)
{
    ULONG32 ulCurrentZOrder = 0;
    //Now do all the children in z-order
    LISTPOSITION pos = m_ChildrenInZOrder.GetHeadPosition();
    while(pos)
    {
        CHXBaseSite* pChildSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
        
        if (ulCurrentZOrder == ulIndex)
        {
            HX_ASSERT(pChildSite);
            return pChildSite->QueryInterface(IID_IHXSite, (void**)&pSite);
        }
        
        ulCurrentZOrder++;
    }
    
    return HXR_FAIL;
}

/************************************************************************
 *  Method:
 *    IHXCallback::Func
 */

STDMETHODIMP CHXBaseSite::Func(void)
{
    _TLSLock();

    m_CallbackHandle = 0;

    AddRef();

    ExecutePendingTasks();

    if (m_bRecomputeClipScheduled)
    {
        m_bDisableForceRedraw = TRUE;
        m_bRecomputeClipScheduled = FALSE;
        RecomputeClip();
        m_bDisableForceRedraw = FALSE;
        _ForceRedrawAll();
        m_bForceRedrawNeeded = FALSE;
        m_bCalledComputeClipFromTransition = FALSE;
        FillColorKey();
    }

    if (m_bProcessRepaint)
    {
        _ForceRedrawAll();
        m_bProcessRepaint = FALSE;
    }

    if( m_bForceRedrawNeeded )
    {
        _ForceRedrawAll();
        m_bForceRedrawNeeded = FALSE;
        FillColorKey();
    }

    //The preferable fix is during WM_PAINT, if in full screen, to call
    //FillBorders.  However, we are currently generating quite a number
    //of spurious WM_PAINT callbacks and this would further degrade
    //performance. If some day we reduce the number of spurious
    //WM_PAINT callbacks then this code (which is hookey) should be
    //placed in * the WM_PAINT handler (too many handlers in that
    //sentence).
    if (m_nDelayFillBorders)
    {
        m_nDelayFillBorders--;
        m_pRootSurface->FillBorders();
    }

    if (m_nStatusTextExpireTime)
    {
        if (m_pStatusText && (HX_GET_TICKCOUNT() - m_nStatusTextExpireTime > 100))
        {
            if (m_pStatusText)
            {
                m_pStatusText->SetStatusText(NULL);
                if (IsFullScreen())
                {
                    m_pRootSurface->FillBorders();
                }
            }
            m_nStatusTextExpireTime = 0;
        }
    }

    if (m_nLastMoveTime)
    {
        if (HX_GET_TICKCOUNT() - m_nLastMoveTime > MOVING_TIMEOUT)
        {
            SiteNotMoving();
            m_nLastMoveTime = 0;
        }
    }

    if (m_bScheduleUpgrade)
    {
        ScheduleUpgrade();
    }

#ifdef _DEBUG_WINDOWED_SITES
    DrawAllSites();
#endif

    //TEST TEST TEST TEST XXXgfw
//     SetCompositionMode(1);
//     UnlockComposition();
//     BltComposition();
//     LockComposition();
//     ScheduleCallback(MOUSE, 45);
    //TEST TEST TEST TEST XXXgfw

    ScheduleCallback(MOUSE, 100);

#if !defined(_UNIX) && !defined(_MACINTOSH)
    //XXXgfw this whole section of code should go away when we add
    //       HX_SET_CURSOR and HX_SET_STATUS messages....
    //We don't need this in UNIX because we have EnterNotify and
    //LeaveNotify events that the OS supplies. This will be
    //handled in the OS specific class.

    // xxxbobclark The mac site call generate mouse leave message.

    if (_AtSystemTime())
    {
        GenerateMouseLeaveMessage();
    }
#endif
    Release();

    _TLSUnlock();
    return HXR_OK;
}

/************************************************************************
 *  Method:
 *    SetStatus
 */

STDMETHODIMP CHXBaseSite::SetStatus(const char* pText)
{
    if (this != m_pTopLevelSite)
    {
        m_pTopLevelSite->SetStatus(pText);
    }

    /*
     * if we get a zero length string we will remove the Status Text
     * in 100 milliseconds.
     */

    _TLSLock();
    if (!pText || !*pText)
    {
        m_nStatusTextExpireTime = HX_GET_TICKCOUNT();
        ScheduleCallback(MOUSE, 100);
        _TLSUnlock();
        return HXR_OK;
    }

    m_nStatusTextExpireTime = 0;

    if (!m_pStatusText)
    {
        m_pStatusText = new CHXSiteStatusText();
        //XXXgfw We need to make this interface cross platform.
#ifdef _WINDOWS
        m_pStatusText->Create( GetWindow()->window );
#else
        m_pStatusText->AddRef();
        m_pStatusText->Create( this );
#endif
        m_pStatusText->ParentChangedSize();
    }

    m_pStatusText->SetStatusText(pText);

    _TLSUnlock();
    return HXR_OK;
}

HXxPoint
CHXBaseSite::GetScreenOffset()
{
    if (m_pParentSite)
    {
        return m_pParentSite->GetScreenOffset();
    }

    return m_screenOffset;
}

STDMETHODIMP CHXBaseSite::EnterFullScreen()
{
    IHXPreferences* pPreferences = NULL;
    HX_RESULT        ret = HXR_OK;

    //Check to see if we are in postage stamp mode.
    m_bPostageStamp = FALSE;
    if (HXR_OK == m_pContext->QueryInterface(IID_IHXPreferences,(void**)&pPreferences))
    {
        IHXBuffer* pBuffer = NULL;
        char        szBuffer[255]; /* Flawfinder: ignore */

        strcpy(szBuffer, REGKEY_FULLSCREEN_DATA); /* Flawfinder: ignore */
        strcat(szBuffer, "\\"); /* Flawfinder: ignore */
        strcat(szBuffer, REGKEY_FULLSCREEN_POSTAGE_STAMP); /* Flawfinder: ignore */
	ReadPrefBOOL(pPreferences, szBuffer, m_bPostageStamp);
    }

    if (m_pParentSite)
    {
        return m_pParentSite->EnterFullScreen();
    }

    if (IsFullScreen())
    {
        return HXR_OK;
    }
    _TLSLock();
    ret = _EnterFullScreen();
    _TLSUnlock();
    return ret;
}

STDMETHODIMP CHXBaseSite::ExitFullScreen()
{
    HX_RESULT ret = HXR_OK;
    if (m_pParentSite)
    {
        return m_pParentSite->ExitFullScreen();
    }

    if( !m_bInFullScreen )
    {
        return HXR_OK;
    }

    // Avoid dead-lock in vidsurf2
    LockBlitters();
    FlushSurfaces();

    _TLSLock();
    ret = _ExitFullScreen();
    _TLSUnlock();

    UnlockBlitters();

    return ret;
}

STDMETHODIMP CHXBaseSite::TestFullScreen(void* hTestBitmap,const char* pszStatusText)
{
    return _TestFullScreen(hTestBitmap, pszStatusText);
}

STDMETHODIMP_(BOOL) CHXBaseSite::IsFullScreen()
{
    if (m_pParentSite)
    {
        return m_pParentSite->IsFullScreen();
    }

    return m_bInFullScreen;
}

STDMETHODIMP CHXBaseSite::Initialize (IHXValues* pParams)
{
    INT32 transitionType    = 0;
    INT32 transitionSubType = 0;
    BOOL  bFoundType        = FALSE;
    BOOL  bFoundSubType     = FALSE;

    IHXBuffer* pPropertyValue = NULL;
    pParams->GetPropertyCString("type", (IHXBuffer*&)pPropertyValue);

    if (pPropertyValue)
    {
        char* pString;
        pString = (char*)pPropertyValue->GetBuffer();

        if (pString)
        {
            for(int i = 0; i < z_nNumberTransitionTypes; ++i)
            {
                tranType* pStruct;
                pStruct = &z_TransitionTable[i];

                if (pStruct->m_pName)
                {
                    if (!strcmp(pStruct->m_pName, pString))
                    {
                        bFoundType = TRUE;
                        transitionType = i;
                        break;
                    }
                }
            }
        }
    }
    HX_RELEASE(pPropertyValue);

    pParams->GetPropertyCString("subType", (IHXBuffer*&)pPropertyValue);

    if (bFoundType && pPropertyValue)
    {
        char* pString;
        pString = (char*)pPropertyValue->GetBuffer();

        if (pString)
        {
            for(int i = 0; i < z_TransitionTable[transitionType].m_nNum; ++i)
            {
                tranStruct* pStruct;
                pStruct = &z_TransitionTable[transitionType].m_pSubTypes[i];

                if (pStruct->m_pTranName)
                {
                    if (!strcmp(pStruct->m_pTranName, pString))
                    {
                        bFoundSubType = TRUE;
                        transitionSubType = i;
                        break;
                    }
                }
            }
        }
    }
    HX_RELEASE(pPropertyValue);


    pParams->GetPropertyCString("reverse", (IHXBuffer*&)pPropertyValue);
    if (pPropertyValue)
    {
        m_bTransitionReversed = (::atoi((const char *)pPropertyValue->GetBuffer())==1);
        HX_RELEASE(pPropertyValue);
    }

    pParams->GetPropertyCString("TranIn", (IHXBuffer*&)pPropertyValue);
    if (pPropertyValue)
    {
        m_bTransitionTranIn = (::atoi((const char *)pPropertyValue->GetBuffer())==1);
        HX_RELEASE(pPropertyValue);
    }

    pParams->GetPropertyCString("VerticalRepeat", (IHXBuffer*&)pPropertyValue);
    if (pPropertyValue)
    {
        m_nTransitionVertRepeat = ::atoi((const char *)pPropertyValue->GetBuffer());
        HX_RELEASE(pPropertyValue);
    }

    pParams->GetPropertyCString("HorizontalRepeat", (IHXBuffer*&)pPropertyValue);
    if (pPropertyValue)
    {
        m_nTransitionHorzRepeat = ::atoi((const char *)pPropertyValue->GetBuffer());
        HX_RELEASE(pPropertyValue);
    }

    pParams->GetPropertyCString("BorderWidth", (IHXBuffer*&)pPropertyValue);
    if (pPropertyValue)
    {
        m_nTransitionBorderWidth = ::atoi((const char *)pPropertyValue->GetBuffer());
        HX_RELEASE(pPropertyValue);
    }

    pParams->GetPropertyCString("BorderColor", (IHXBuffer*&)pPropertyValue);
    if (pPropertyValue)
    {
        m_ulTransitionBorderColor = ::atoi((const char *)pPropertyValue->GetBuffer());
        HX_RELEASE(pPropertyValue);
    }

    pParams->GetPropertyCString("FadeColor", (IHXBuffer*&)pPropertyValue);
    if (pPropertyValue)
    {
        m_ulTransitionFadeColor = ::atoi((const char *)pPropertyValue->GetBuffer());
        HX_RELEASE(pPropertyValue);
    }

    pParams->GetPropertyCString("BlendBorder", (IHXBuffer*&)pPropertyValue);
    if (pPropertyValue)
    {
        m_bTransitionBlendBorder = (::atoi((const char *)pPropertyValue->GetBuffer())==1);
        HX_RELEASE(pPropertyValue);
    }

    pParams->GetPropertyCString("Coordinated", (IHXBuffer*&)pPropertyValue);
    if (pPropertyValue)
    {
        m_bTransitionCoordinated = (::atoi((const char *)pPropertyValue->GetBuffer())==1);
        HX_RELEASE(pPropertyValue);
    }

    pParams->GetPropertyCString("ClipBoundary", (IHXBuffer*&)pPropertyValue);
    if (pPropertyValue)
    {
        const char* pszType = (const char*)pPropertyValue->GetBuffer();
        BOOL        bIsParent = TRUE;
        if( pszType && strlen( pszType ) )
        {
            bIsParent = pszType[0]=='p' || pszType[0]=='P';
        }
        m_bTransitionCoordTranIsParentClip = bIsParent;
        HX_RELEASE(pPropertyValue);
    }

    if (bFoundSubType && bFoundType)
    {
        m_fpTransitionEffect        =
            z_TransitionTable[transitionType].m_pSubTypes[transitionSubType].m_fpTranFunction;
        m_nTransitionState = 0;
        return HXR_OK;
    }
    else
    {
        return HXR_FAIL;
    }
}

STDMETHODIMP CHXBaseSite::SetPercentage (UINT32 nThousandnthsComplete)
{
    _TLSLock();
    if( nThousandnthsComplete != (UINT32)m_nTransitionState )
    {
        m_nTransitionState = nThousandnthsComplete;

        // We need to invalidate the rect first before we may
        // update m_topleft and m_postion. This would happen
        // if we are doing some sort of slideWipe transition.
        // The first rect will be the "old" position of a
        // slideWipe. If we are not using some sort of
        // slideWipe, then the rect won't change and we
        // won't damage again.
        HXxRect cTmp = { m_topleft.x,
                         m_topleft.y,
                         m_topleft.x+m_size.cx,
                         m_topleft.y+m_size.cy};
        m_pTopLevelSite->_RecursiveDamageRect( &cTmp, TRUE );

        int completeness = m_nTransitionState;

        if(m_bTransitionReversed)
            completeness = 1000 - completeness;

        if( m_fpTransitionEffect == SlideFromLeft )
        {
            m_position.x = m_positionOrig.x -
                ((INT32)(m_size.cx - (double(m_size.cx)/1000.0)*(double)completeness));
            ResetOrigin();
        }
        else if( m_fpTransitionEffect == SlideFromTop )
        {
            m_position.y = m_positionOrig.y -
                ((INT32)(m_size.cy - (double(m_size.cy)/1000.0)*(double)completeness));
            ResetOrigin();
        }
        else if( m_fpTransitionEffect == SlideFromRight )
        {
            m_position.x = m_positionOrig.x +
                ((INT32)(m_size.cx - (double(m_size.cx)/1000.0)*(double)completeness));
            ResetOrigin();
        }
        else if( m_fpTransitionEffect == SlideFromBottom )
        {
            m_position.y = m_positionOrig.y +
                ((INT32)(m_size.cy - (double(m_size.cy)/1000.0)*(double)completeness));
            ResetOrigin();
        }

        // Did we change the rect? If so, then damage with
        // the new rect
        if (cTmp.left   != m_topleft.x             ||
            cTmp.top    != m_topleft.y             ||
            cTmp.right  != m_topleft.x + m_size.cx ||
            cTmp.bottom != m_topleft.y + m_size.cy)
        {
            // Invalidate the changed rect
            cTmp.left   = m_topleft.x;
            cTmp.top    = m_topleft.y;
            cTmp.right  = m_topleft.x + m_size.cx;
            cTmp.bottom = m_topleft.y + m_size.cy;
            m_pTopLevelSite->_RecursiveDamageRect(&cTmp, TRUE);
        }

        if( this==m_pTopLevelSite)
        {
            m_pTopLevelSite->RecomputeClip();
        }
        else
        {
            if(m_pTopLevelSite)
                m_pTopLevelSite->ScheduleCallback(CLIP, 0);
            m_pTopLevelSite->m_bCalledComputeClipFromTransition = TRUE;
        }
    }

    _TLSUnlock();
    return HXR_OK;
}

/*
 * IHXVideoControls methods
 */
STDMETHODIMP_(float) CHXBaseSite::GetBrightness(void)
{
    if (m_pParentSite)
    {
        return m_pParentSite->GetBrightness();
    }

    return m_fBrightness;
}

STDMETHODIMP CHXBaseSite::SetBrightness(float brightness)
{
    if (m_pParentSite)
    {
        return m_pParentSite->SetBrightness(brightness);
    }

    m_fBrightness = brightness;
    ScheduleCallback(REPAINT, 0);
    return HXR_OK;
}

STDMETHODIMP_(float) CHXBaseSite::GetContrast(void)
{
    if (m_pParentSite)
    {
        return m_pParentSite->GetContrast();
    }

    return m_fContrast;
}

STDMETHODIMP CHXBaseSite::SetContrast(float contrast)
{
    if (m_pParentSite)
    {
        return m_pParentSite->SetContrast(contrast);
    }

    m_fContrast = contrast;
    ScheduleCallback(REPAINT, 0);
    return HXR_OK;
}

STDMETHODIMP_(float) CHXBaseSite::GetSaturation(void)
{
    if (m_pParentSite)
    {
        return m_pParentSite->GetSaturation();
    }

    return m_fSaturation;
}

STDMETHODIMP CHXBaseSite::SetSaturation(float saturation)
{
    if (m_pParentSite)
    {
        return m_pParentSite->SetSaturation(saturation);
    }

    m_fSaturation = saturation;
    ScheduleCallback(REPAINT, 0);
    return HXR_OK;
}

STDMETHODIMP_(float) CHXBaseSite::GetHue(void)
{
    if (m_pParentSite)
    {
        return m_pParentSite->GetHue();
    }

    return m_fHue;
}

STDMETHODIMP CHXBaseSite::SetHue(float hue)
{
    if (m_pParentSite)
    {
        return m_pParentSite->SetHue(hue);
    }

    m_fHue = hue;
    ScheduleCallback(REPAINT, 0);
    return HXR_OK;
}

STDMETHODIMP_(float) CHXBaseSite::GetSharpness(void)
{
    if (m_pParentSite)
    {
        return m_pParentSite->GetSharpness();
    }

    return m_fSharpness;
}

STDMETHODIMP CHXBaseSite::SetSharpness(float sharpness)
{
    if (m_pParentSite)
    {
        return m_pParentSite->SetSharpness(sharpness);
    }

    m_fSharpness = sharpness;
    ScheduleCallback(REPAINT, 0);
    return HXR_OK;
}

STDMETHODIMP CHXBaseSite::SetModeSharpness(UINT16 dFlag)
{
    m_bModeSharpness = dFlag;
    return HXR_OK;
}

STDMETHODIMP_(BOOL) CHXBaseSite::IsInterruptSafe()
{
    return TRUE;
}

STDMETHODIMP CHXBaseSite::SetKeyboardFocus(IHXSiteUser* pSiteUser)
{
#ifdef FUTURE_WORKING_FOCUS
    if (m_pTopLevelSite->m_pKeyBoardFocusUser)
    {
        HXxEvent event = {HX_LOSE_FOCUS, m_pWindow ? m_pWindow->window : NULL, NULL, NULL, 0, 0};
        m_pTopLevelSite->m_pKeyBoardFocusUser->HandleEvent(&event);
        m_pTopLevelSite->m_pKeyBoardFocusUser->Release();
        m_pTopLevelSite->m_pKeyBoardFocusUser = NULL;
    }

    if (pSiteUser)
    {
        m_pTopLevelSite->m_pKeyBoardFocusUser = pSiteUser;
        m_pTopLevelSite->m_pKeyBoardFocusUser->AddRef();
        HXxEvent event = {HX_SET_FOCUS, m_pWindow ? m_pWindow->window : NULL, NULL, NULL, 0, 0};
        m_pTopLevelSite->m_pKeyBoardFocusUser->HandleEvent(&event);
    }
#else
    HXxWindow* pFocusWindow = GetWindow();

    if(pFocusWindow && pFocusWindow->window)
    {
        SafeSetFocus(pFocusWindow);
    }
#endif // FUTURE_WORKING_FOCUS

    return HXR_OK;
}

STDMETHODIMP CHXBaseSite::GetKeyboardFocus(IHXSiteUser* &pSiteUser)
{
    pSiteUser = m_pTopLevelSite->m_pKeyBoardFocusUser;

    if (pSiteUser)
    {
        pSiteUser->AddRef();
        return HXR_OK;
    }
    else
        return HXR_FAILED;
}

STDMETHODIMP CHXBaseSite::SetStyle(IHXValues* pProperties)
{
    // Map IHXValues to drawing properties
    ULONG32 ulTemp = HX_SOLID_LINE;
    pProperties->GetPropertyULONG32("LINE_STYLE", ulTemp);
    m_rcFocusRect.ulLineStyle = ulTemp;

    // Store custom line pattern
    HX_RELEASE(m_rcFocusRect.pCustomPattern);
    m_rcFocusRect.ulCustomEntries = 0;

    if (ulTemp == HX_CUSTOM_LINE)
    {
        pProperties->GetPropertyBuffer("CUSTOM_LINE_PATTERN", m_rcFocusRect.pCustomPattern);
        if (m_rcFocusRect.pCustomPattern)
        {
            m_rcFocusRect.pCustomPattern->AddRef();

            ulTemp = 0;
            pProperties->GetPropertyULONG32("CUSTOM_LINE_ENTRIES", ulTemp);
            m_rcFocusRect.ulCustomEntries = ulTemp;
        }
    }

    // Store line width
    ulTemp = 1;
    pProperties->GetPropertyULONG32("LINE_WIDTH", ulTemp);
    m_rcFocusRect.ulLineWidth = ulTemp;

    // Store primary color
    ulTemp = 0;
    pProperties->GetPropertyULONG32("RED", ulTemp);
    m_rcFocusRect.red = (UINT8)ulTemp;

    ulTemp = 0;
    pProperties->GetPropertyULONG32("GREEN", ulTemp);
    m_rcFocusRect.green = (UINT8)ulTemp;

    ulTemp = 0;
    pProperties->GetPropertyULONG32("BLUE", ulTemp);
    m_rcFocusRect.blue = (UINT8)ulTemp;

    m_rcFocusRect.bSecondaryColors = FALSE;

    // Store secondary color
    ulTemp = 0;
    if (HXR_OK == pProperties->GetPropertyULONG32("RED2", ulTemp))
        m_rcFocusRect.bSecondaryColors = TRUE;

    m_rcFocusRect.red2 = (UINT8)ulTemp;

    ulTemp = 0;
    if (HXR_OK == pProperties->GetPropertyULONG32("GREEN2", ulTemp))
        m_rcFocusRect.bSecondaryColors = TRUE;

    m_rcFocusRect.green2 = (UINT8)ulTemp;

    ulTemp = 0;
    if (HXR_OK == pProperties->GetPropertyULONG32("BLUE2", ulTemp))
        m_rcFocusRect.bSecondaryColors = TRUE;

    m_rcFocusRect.blue2 = (UINT8)ulTemp;

    return HXR_OK;
}

STDMETHODIMP CHXBaseSite::ClearFocus()
{
    m_rcFocusRect.bRectActive = FALSE;

    // Clear the focus rect but preserve the properties
    if (m_rcFocusRect.ulShape & DRAW_POLYGON)
    {
        m_rcFocusRect.ulShape &= ~DRAW_POLYGON;

        if (m_rcFocusRect.polygon.pFocusPoints)
        {
            delete [] m_rcFocusRect.polygon.pFocusPoints;
            m_rcFocusRect.polygon.pFocusPoints = NULL;
            m_rcFocusRect.polygon.ulFocusPoints = 0;
        }
    }
    else
    {
        m_rcFocusRect.ulShape &= ~DRAW_RECT;
        m_rcFocusRect.ulShape &= ~DRAW_ELLIPSE;

        memset(&m_rcFocusRect.rcFocus, 0, sizeof(m_rcFocusRect.rcFocus));
    }


    return HXR_OK;
}

STDMETHODIMP CHXBaseSite::SetFocusPolygon(HXxPoint* pPoints, ULONG32 numPoints)
{
    if (!m_rcFocusRect.ulLineWidth)
        return HXR_FAIL;

    if (m_rcFocusRect.bRectActive)
        ClearFocus();

    m_rcFocusRect.polygon.ulFocusPoints = numPoints;
    m_rcFocusRect.polygon.pFocusPoints = new HXxPoint[numPoints];
    m_rcFocusRect.ulShape |= DRAW_POLYGON;

    for (ULONG32 i=0; i<numPoints; i++)
        m_rcFocusRect.polygon.pFocusPoints[i] = pPoints[i];

    m_rcFocusRect.bRectActive = TRUE;

    return HXR_OK;
}

STDMETHODIMP CHXBaseSite::SetFocusRect(HXxRect* pRect)
{
    if (!m_rcFocusRect.ulLineWidth)
        return HXR_FAIL;

    if (m_rcFocusRect.bRectActive)
        ClearFocus();

    m_rcFocusRect.rcFocus = *pRect;
    m_rcFocusRect.ulShape |= DRAW_RECT;
    m_rcFocusRect.bRectActive = TRUE;

    return HXR_OK;
}

STDMETHODIMP CHXBaseSite::SetFocusEllipse(HXxRect* pRect)
{
    if (!m_rcFocusRect.ulLineWidth)
        return HXR_FAIL;

    if (m_rcFocusRect.bRectActive)
        ClearFocus();

    m_rcFocusRect.rcFocus = *pRect;
    m_rcFocusRect.ulShape |= DRAW_ELLIPSE;
    m_rcFocusRect.bRectActive = TRUE;

    return HXR_OK;
}

void CHXBaseSite::_DrawFocusRect(UCHAR* pImage,
                                 HXBitmapInfoHeader* pImageInfo,
                                 HXxRect* pImageRect,
                                 void* pOsSpecificData)
{
    // Do we have an active rect
    if (!m_rcFocusRect.bRectActive)
        return;

    // Only support rgb for now
    if (IsYUV(GETBITMAPCOLOR(pImageInfo)))
        return;

    int *pUpperLeft = (int*)pImage + (pImageRect->left + pImageRect->top) * pImageInfo->biBitCount/8;

    INT32 nStyle = SOLID_LINE;

    if (m_rcFocusRect.ulLineStyle == HX_DASHED_LINE)
        nStyle = DASHED_LINE;
    else if (m_rcFocusRect.ulLineStyle == HX_DOTTED_LINE)
        nStyle = DOTTED_LINE;
    else if (m_rcFocusRect.ulLineStyle == HX_CUSTOM_LINE)
        nStyle = CUSTOM_LINE;

    INT32 *pCustomPattern = NULL;
    if (m_rcFocusRect.pCustomPattern)
        pCustomPattern = (INT32*)(m_rcFocusRect.pCustomPattern->GetBuffer());

    PixelProps primary = {m_rcFocusRect.red,
                          m_rcFocusRect.green,
                          m_rcFocusRect.blue,
                          TRUE};

    PixelProps secondary = {m_rcFocusRect.red2,
                            m_rcFocusRect.green2,
                            m_rcFocusRect.blue2,
                            m_rcFocusRect.bSecondaryColors};


    // Draw the rect into the pImage
    if (m_rcFocusRect.ulShape & DRAW_RECT)
    {
        StraightLine((void*)pImage,
                     GETBITMAPPITCH(pImageInfo),
                     pImageInfo->biBitCount,
                     pImageRect->right-pImageRect->left,
                     pImageRect->bottom-pImageRect->top,
                     m_rcFocusRect.rcFocus.left, m_rcFocusRect.rcFocus.top,
                     m_rcFocusRect.rcFocus.right, m_rcFocusRect.rcFocus.top,
                     (UINT8)m_rcFocusRect.ulLineWidth,
                     &primary, &secondary,
                     nStyle,
                     pCustomPattern, m_rcFocusRect.ulCustomEntries);

        StraightLine((void*)pImage,
                     GETBITMAPPITCH(pImageInfo),
                     pImageInfo->biBitCount,
                     pImageRect->right-pImageRect->left,
                     pImageRect->bottom-pImageRect->top,
                     m_rcFocusRect.rcFocus.right, m_rcFocusRect.rcFocus.top,
                     m_rcFocusRect.rcFocus.right, m_rcFocusRect.rcFocus.bottom,
                     (UINT8)m_rcFocusRect.ulLineWidth,
                     &primary, &secondary,
                     nStyle,
                     pCustomPattern, m_rcFocusRect.ulCustomEntries);

        StraightLine((void*)pImage,
                     GETBITMAPPITCH(pImageInfo),
                     pImageInfo->biBitCount,
                     pImageRect->right-pImageRect->left,
                     pImageRect->bottom-pImageRect->top,
                     m_rcFocusRect.rcFocus.right, m_rcFocusRect.rcFocus.bottom,
                     m_rcFocusRect.rcFocus.left, m_rcFocusRect.rcFocus.bottom,
                     (UINT8)m_rcFocusRect.ulLineWidth,
                     &primary, &secondary,
                     nStyle,
                     pCustomPattern, m_rcFocusRect.ulCustomEntries);

        StraightLine((void*)pImage,
                     GETBITMAPPITCH(pImageInfo),
                     pImageInfo->biBitCount,
                     pImageRect->right-pImageRect->left,
                     pImageRect->bottom-pImageRect->top,
                     m_rcFocusRect.rcFocus.left, m_rcFocusRect.rcFocus.bottom,
                     m_rcFocusRect.rcFocus.left, m_rcFocusRect.rcFocus.top,
                     (UINT8)m_rcFocusRect.ulLineWidth,
                     &primary, &secondary,
                     nStyle,
                     pCustomPattern, m_rcFocusRect.ulCustomEntries);

    }
    else if (m_rcFocusRect.ulShape & DRAW_ELLIPSE)
    {
    }
    else if (m_rcFocusRect.ulShape & DRAW_POLYGON)
    {
        UINT32 i=0;
        for (i=0; i<m_rcFocusRect.polygon.ulFocusPoints-1; i++)
        {
            StraightLine((void*)pImage,
                         GETBITMAPPITCH(pImageInfo),
                         pImageInfo->biBitCount,
                         pImageRect->right-pImageRect->left,
                         pImageRect->bottom-pImageRect->top,
                         m_rcFocusRect.polygon.pFocusPoints[i].x, m_rcFocusRect.polygon.pFocusPoints[i].y,
                         m_rcFocusRect.polygon.pFocusPoints[i+1].x, m_rcFocusRect.polygon.pFocusPoints[i+1].y,
                         (UINT8)m_rcFocusRect.ulLineWidth,
                         &primary, &secondary,
                         nStyle,
                         pCustomPattern, m_rcFocusRect.ulCustomEntries);
        }

        StraightLine((void*)pImage,
                     GETBITMAPPITCH(pImageInfo),
                     pImageInfo->biBitCount,
                     pImageRect->right-pImageRect->left,
                     pImageRect->bottom-pImageRect->top,
                     m_rcFocusRect.polygon.pFocusPoints[i].x, m_rcFocusRect.polygon.pFocusPoints[i].y,
                     m_rcFocusRect.polygon.pFocusPoints[0].x, m_rcFocusRect.polygon.pFocusPoints[0].y,
                     (UINT8)m_rcFocusRect.ulLineWidth,
                     &primary, &secondary,
                     nStyle,
                     pCustomPattern, m_rcFocusRect.ulCustomEntries);
    }
}

/************************************************************************
 ************************************************************************
 *                      INTERNAL HELPER FUNCTIONS
 ************************************************************************
 ************************************************************************/



void CHXBaseSite::SetXSliderRange(INT32 range)
{
    _TryCreateXSlider();

    if (m_XSliderRange != range)
    {
        if (m_XSliderRange)
        {
            m_XSliderPos = m_XSliderPos * range / m_XSliderRange;
        }

        HXxSize parentSize;
        memset(&parentSize, 0, sizeof(HXxSize));
        if (m_pParentSite)
        {
            m_pParentSite->GetSize(parentSize);
        }

        m_XSliderRange = range;

        _SetXSliderValues(m_XSliderRange, parentSize.cx);
    }
}

INT32 CHXBaseSite::GetXSliderRange()
{
    return m_XSliderRange;
}

INT32 CHXBaseSite::GetYSliderRange()
{
    return m_YSliderRange;
}

void CHXBaseSite::SetYSliderRange(INT32 range)
{
    _TryCreateYSlider();

    if (m_YSliderRange != range)
    {
        if (m_YSliderRange)
        {
            m_YSliderPos = m_YSliderPos * range / m_YSliderRange;
        }

        HXxSize parentSize;
        memset(&parentSize, 0, sizeof(HXxSize));
        if (m_pParentSite)
        {
            m_pParentSite->GetSize(parentSize);
        }

        m_YSliderRange = range;
        _SetYSliderValues(m_YSliderRange, parentSize.cy);
    }
}

INT32 CHXBaseSite::GetXSliderPos()
{
    return m_XSliderPos;
}

INT32 CHXBaseSite::GetYSliderPos()
{
    return m_YSliderPos;
}

INT32 CHXBaseSite::GetSliderWidth()
{
    INT32 Width, Height;

    _GetSystemSizeOfSliders(&Width, &Height);
    return Width;
}

INT32 CHXBaseSite::GetSliderHeight()
{
    INT32 Width, Height;

    _GetSystemSizeOfSliders(&Width, &Height);
    return Height;
}

// XXXAH this function is pretty poorly named and I want to change it.
// however in keeping with the idea behind this conversion (namely CHANGE
// NOTHING on windows), I will leave it in here for the moment.
void CHXBaseSite::GetWindowRect(HXxRect* pRect)
{
    if (m_RegionForMouse)
    {
        pRect->left   = m_Region->extents.x1;
        pRect->top    = m_Region->extents.y1;
        pRect->right  = m_Region->extents.x2;
        pRect->bottom = m_Region->extents.y2;
    }
}

void CHXBaseSite::GetExtentsWithoutChildren(HXxRect* pRect)
{
    if (m_RegionWithoutChildren)
    {
        pRect->left   = m_RegionWithoutChildren->extents.x1;
        pRect->top    = m_RegionWithoutChildren->extents.y1;
        pRect->right  = m_RegionWithoutChildren->extents.x2;
        pRect->bottom = m_RegionWithoutChildren->extents.y2;
    }
}

void CHXBaseSite::RecursiveSizeSliders()
{
    SizeSliders();
    LISTPOSITION pos = m_ChildrenInZOrder.GetHeadPosition();
    while(pos)
    {
        CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
        pSite->RecursiveSizeSliders();
    }
}

void CHXBaseSite::SizeSliders()
{
    //Size the X slider 1st.
    INT32 width;
    INT32 height;
    _GetSystemSizeOfSliders(&width, &height);

    // The size of the SITE is the size of the bounding rect of the
    // region.
    HXxRect boundRect;
    memset( &boundRect, 0, sizeof( HXxRect ) );
    if (m_pParentSite)
    {
        m_pParentSite->GetExtentsWithoutChildren(&boundRect);
    }
    else
    {
        GetWindowRect(&boundRect);
    }

    // XXXAH why am I using this function? Will Have to check later to
    // see why IHXSite2::IsSiteVisible is insufficient.  AHH I now
    // remember this is due to a bug with the sliders appearing on TOP
    // of the buffering animation.
    BOOL siteVisible = _IsWindowVisible();

    /*
     *  Modify boundRect by the screen offset.
     */

    HXxPoint screenOffset;
    if (m_pParentSite)
    {
        screenOffset = m_pParentSite->GetScreenOffset();
    }
    else
    {
        screenOffset = GetScreenOffset();
    }

    boundRect.left       += screenOffset.x;
    boundRect.right      += screenOffset.x;
    boundRect.top        += screenOffset.y;
    boundRect.bottom     += screenOffset.y;

    _ShowXSlider((siteVisible && m_bIsVisible) ? TRUE : FALSE);
    _MoveXSlider(boundRect.left, boundRect.bottom - height, boundRect.right - boundRect.left, height, TRUE);
    _ShowYSlider((siteVisible && m_bIsVisible) ? TRUE : FALSE);
    _MoveYSlider(boundRect.right - width, boundRect.top, width, boundRect.bottom - boundRect.top - (_DoesXSliderExist() ? height : 0), TRUE);

    // XXXMEH - checking siteVisible above prevents scroll bars
    // from appearing above the buffering animation logo. For datatypes
    // which ForceRedraw over and over, this is no problem. The scroll bars
    // just show up one blt late. However, most still image datatypes
    // just ForceRedraw once at the first timesync. So for those
    // datatypes, that fix is preventing the scroll bars from showing up.
    // So if m_bIsVisible is TRUE and siteVisible is FALSE (where we
    // *would* have turned the scrollbars on but were prevented by the
    // fact that the site was not yet visible), then we will set up
    // a callback to check again.
    if (m_bIsVisible && !siteVisible && m_bScrollingSite)
    {
        // Have we already scheduled a callback?
        if (!m_ScrollSiteCallbackHandle)
        {
            // Have we already created a ScrollSiteCallback
            if (!m_pScrollSiteCallback)
            {
                m_pScrollSiteCallback = new ScrollSiteCallback(this);
            }
            if (m_pScrollSiteCallback && m_pScheduler)
            {
                m_ScrollSiteCallbackHandle = m_pScheduler->RelativeEnter(m_pScrollSiteCallback, 20);
            }
        }
    }
}

void CHXBaseSite::FuncSizeSliders()
{
    m_ScrollSiteCallbackHandle = 0;
    SizeSliders();
}

HX_RESULT CHXBaseSite::ConvertStringToXYDepth(const char* pszModeString, REF(INT32) x, REF(INT32) y, REF(INT32) depth)
{
    HX_RESULT    retVal          = HXR_FAIL;
    int          stringLength    = strlen(pszModeString);
    char*        pszTempString   = new char[stringLength+1];

    memcpy(pszTempString, pszModeString, stringLength+1); /* Flawfinder: ignore */

    char*   token = strtok( pszTempString, MODE_DESRIPTION_SEPS);

    if (!token)
    {
        goto cleanup;
    }
    x     = atoi(token);

    token  = strtok( NULL, MODE_DESRIPTION_SEPS);
    if (!token)
    {
        goto cleanup;
    }
    y = atoi(token);

    token  = strtok( NULL, MODE_DESRIPTION_SEPS);
    if (!token)
    {
        goto cleanup;
    }
    depth   = atoi(token);
    retVal  = HXR_OK;

  cleanup:
    HX_VECTOR_DELETE(pszTempString);
    return retVal;
}

void CHXBaseSite::SetDisplayMode()
{
    m_bSettingDisplayMode = TRUE;

    _TLSLock();

    // check to see if the top level client has set the resolution of
    // full screen. If not then we will stay in the same resolution.
    // if they did then we will will call DD and set the mode.

    IHXPreferences* pPreferences    = NULL;
    IHXBuffer*      pBuffer         = NULL;
    char*            pszModesToTest  = NULL;
    char             szBuffer[255]; /* Flawfinder: ignore */


    if (HXR_OK == m_pContext->QueryInterface(IID_IHXPreferences,(void**)&pPreferences))
    {
        strcpy(szBuffer, REGKEY_FULLSCREEN_DATA); /* Flawfinder: ignore */
        strcat(szBuffer, "\\"); /* Flawfinder: ignore */
        strcat(szBuffer, REGKEY_FULLSCREEN_PREFERED_MODE); /* Flawfinder: ignore */

        pPreferences->ReadPref(szBuffer, pBuffer);

        INT32 x       = 0;
        INT32 y       = 0;
        INT32 depth   = 0;

        if (pBuffer)
        {
            if (HXR_OK ==ConvertStringToXYDepth((char*)pBuffer->GetBuffer(), x, y, depth))
            {
                DestroySurfaces();
                if (zm_bInFullScreenTest)
                {
                    m_pRootSurface->SetResolution(x, y, depth, m_pWindow ? m_pWindow->window : NULL);
                }
                else
                {
                    void* pWindow = _GetContainingWindow();
                    m_pRootSurface->SetResolution(x, y, depth, pWindow);
                }
                ReInitSurfaces();
            }
            HX_RELEASE(pBuffer);
        }
        HX_RELEASE(pPreferences);
    }

    m_bSettingDisplayMode = FALSE;

    _TLSUnlock();
}

//Not used in unix land.......
BOOL CHXBaseSite::GenerateMouseLeaveMessage()
{
    if (m_pMouseInSite)
    {
        void* pWindowHandle = _GetWindowWithCursor();
        // XXXAH this is different than the current implemenation!! XXXAH
        // But the current impementation has a bug in it!!
        //XXXgfw why do we test for GetWindow() and then use m_pWindow??
        HXxWindow* pWindow = GetWindow();
        if(pWindow && (pWindowHandle != pWindow->window))
        {
            HXxPoint oobPoint;
            oobPoint.x = -1;
            oobPoint.y = -1;
            HXxEvent event = {HX_MOUSE_LEAVE, m_pWindow ? m_pWindow->window : NULL, (void*)&oobPoint, 0, 0, FALSE};
            m_pMouseInSite->EventOccurred(&event);
            m_pMouseInSite = NULL;
            return TRUE;
        }
    }
    return FALSE;
}

void CHXBaseSite::CheckExposeEvents()
{
    if (!m_pRootSurface)
    {
        m_bRepaintScheduled = FALSE;
        return;
    }

    if (!m_pParentSite)
    {
        m_pRootSurface->SetBltLock(TRUE);
    }

    if (m_bRepaintScheduled)
    {
        InternalForceRedraw();
        m_bRepaintScheduled = FALSE;
    }

    LISTPOSITION pos = m_ChildrenInZOrder.GetHeadPosition();
    while(pos)
    {
        CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
        pSite->CheckExposeEvents();
    }

    m_pVideoSurface->FillColorKey();
    m_pVideoSurface->UpdateDestRect();

    if (!m_pParentSite)
    {
        m_pRootSurface->SetBltLock(FALSE);
    }
}

BOOL CHXBaseSite::_TakesPartInAlphaChain()
{
    BOOL retVal=FALSE;
    int nCID=-1;

    if( !IsSiteVisible() )
        return FALSE;

    if( m_pVideoSurface )
        nCID = GETBITMAPCOLOR(&(m_pVideoSurface->m_bmiLastBlt));

    //Current conditions to force conversion to ARGB and inclusion in
    //the alpha blending chain.
    //
    // 1) Native format is ARGB
    // 2) Has not blt'ed at least once (CID_UNKNOWN)
    // 3) m_bSiteNeverBlts type of regions (see through).
    // 4) _BlendedBordersActive() type. We must have ARGB to blend the borders.
    // 5) m_nEventSensitivity==SENSITIVITY_TRANSPARENT we need these to be part
    //    of the alpha chain so that we can find the site that click belongs to.
    // 6) any site with a fade transition in effect.
    if(CID_ARGB32==nCID || CID_UNKNOWN==nCID || m_bSiteNeverBlts )
//   if(CID_ARGB32==nCID || m_bSiteNeverBlts )
        retVal = TRUE;
    else if( m_nEventSensitivity==SENSITIVITY_TRANSPARENT )
        retVal = TRUE;
    else if( _BlendedBordersActive() )
        retVal = TRUE;
    else if( m_fpTransitionEffect == Crossfade )
        retVal = TRUE;
    else if( m_fpTransitionEffect == FadeToColor )
        retVal = TRUE;
    else if( m_fpTransitionEffect == FadeFromColor )
        retVal = TRUE;

    return retVal;
}

BOOL CHXBaseSite::ComputeSubRects()
{
    _TLSLock();

    BOOL         retVal          = TRUE;
    HXREGION*      hTemp           = NULL;
    HXREGION*      hTemp2          = NULL;
    BOOL         bRepaintMessage = TRUE;
    HXxSize      size;
    HXxPoint*    pPosition       = NULL;
    HXxRect      rectClientRect;
    LISTPOSITION pos             = NULL;


    m_pVideoSurface->_RemoveYUVImageLists();

    if( m_pValues )
    {
        IHXBuffer* pBuf=NULL;
        m_bSiteNeverBlts=FALSE;
        m_pValues->GetPropertyCString( "SiteNeverBlts", pBuf );
        if( pBuf )
        {
            m_bSiteNeverBlts = atoi( (const char*)pBuf->GetBuffer() )==1;
            if( m_bSiteNeverBlts )
            {
                //Make these sites naturally transparent to events.
                m_nEventSensitivity = SENSITIVITY_TRANSPARENT;
            }

            HX_RELEASE(pBuf);
        }
    }

    if (m_Region)
    {
        hTemp2 = HXCreateRectRegion(0,0,0,0);
        HXUnionRegion(hTemp2, m_Region, hTemp2);
        HXDestroyRegion(m_Region);
        m_Region = NULL;
        HXDestroyRegion(m_RegionForMouse);
        m_RegionForMouse = NULL;
    }

    if (m_RegionWithoutChildren)
    {
        HXDestroyRegion(m_RegionWithoutChildren);
        m_RegionWithoutChildren = NULL;
    }

    rectClientRect.left     = m_topleft.x;
    rectClientRect.right    = m_topleft.x + m_size.cx;
    rectClientRect.top      = m_topleft.y;
    rectClientRect.bottom   = m_topleft.y + m_size.cy;

    if (IsSiteVisible())
    {
        m_RegionWithoutChildren = Transition(m_topleft.x, m_topleft.y,
                                             m_topleft.x + m_size.cx,
                                             m_topleft.y + m_size.cy,
                                             &m_TransitionBorderLines);


        if (m_pParentSite)
            m_pParentSite->BuildParnetClipping(m_RegionWithoutChildren,this);

        // subtract all of my children from my clipping region
        m_Region = HXCreateRectRegion(0,0,0,0);

        HXUnionRegion(m_Region, m_RegionWithoutChildren, m_Region);
        if (m_Region->numRects == 0)
        {
            retVal = FALSE;
        }
        else
        {
            pos = m_ChildrenInZOrder.GetHeadPosition();
            while(pos)
            {
                CHXBaseSite* pSite = (CHXBaseSite*) m_ChildrenInZOrder.GetNext(pos);
                if (pSite->IsSiteVisible())
                {
                    pPosition = pSite->GetOrigin();
                    memcpy(&size, &pSite->m_size, sizeof(size)); /* Flawfinder: ignore */

                    hTemp = pSite->Transition(pPosition->x, pPosition->y,
                                              pPosition->x + size.cx,
                                              pPosition->y + size.cy);

                    HXSubtractRegion(m_Region, hTemp, m_Region);
                    HXDestroyRegion(hTemp);
                    hTemp = NULL;
                }
            }
        }
    }
    else
    {
        m_RegionWithoutChildren = HXCreateRectRegion(0,0,0,0);
        m_Region                = HXCreateRectRegion(0,0,0,0);
    }

    // check to see if every destination new region and the
    // old region are the same.
    if (hTemp2)
    {
        if (HXEqualRegion( m_Region, hTemp2)  &&
            m_rectOldClientRect.left    == rectClientRect.left  &&
            m_rectOldClientRect.right   == rectClientRect.right &&
            m_rectOldClientRect.top     == rectClientRect.top   &&
            m_rectOldClientRect.bottom  == rectClientRect.bottom)
        {
            bRepaintMessage = FALSE;
        }
        else
        {
            //We want to damage the old and new rects.
//             HXxRect pTmp = { m_topleft.x,
//                              m_topleft.y,
//                              m_topleft.x+m_size.cx,
//                              m_topleft.y+m_size.cy};
            //XOR the old and new and damage it.
//            HXXorRegion( hTemp2, m_Region, hTemp2 );
//            m_pTopLevelSite->_RecursiveDamageRect( &pTmp );
        }
    }

    memcpy(&m_rectOldClientRect, &rectClientRect, sizeof(m_rectOldClientRect)); /* Flawfinder: ignore */
    HXDestroyRegion(hTemp2);
    hTemp2 = NULL;
    m_bRegionIsValid = TRUE;

    ////////////////////////////////////////////////////////
    //            BEGIN ALPHA BLENDING WORK               //
    ////////////////////////////////////////////////////////

    //for each sibling lowing in the Zorder than us, compute a
    //alpha region for it to blend with.

    //First, clean up the old.....
    _EmptyBlenderList();
    //Now make the new.......
    //First, the parent is a special case....
    if( m_pParentSite && IsSiteVisible() && _TakesPartInAlphaChain())
    {
        INT32 nZOrder   = 0;
        INT32 nMyZOrder = m_lZOrder;

        CHXBaseSite* pParent   = m_pParentSite;
        HXxPoint*    pPosition = m_pParentSite->GetOrigin();
        HXREGION*      pRegion   =
            pParent->Transition( pPosition->x, pPosition->y,
                                 pPosition->x + pParent->m_size.cx,
                                 pPosition->y + pParent->m_size.cy);

        if(pRegion->numRects != 0)
        {
            pos = m_pParentSite->m_ChildrenInZOrder.GetHeadPosition();
            while(pos)
            {
                CHXBaseSite* pSite = (CHXBaseSite*)m_pParentSite->m_ChildrenInZOrder.GetNext(pos);
                //All site before me in my parents list are of lower zorder by
                //default. We don't want to subtract ourselves.
                if( this == pSite )
                {
                    break;
                }
                if(pSite->IsSiteVisible())
                {
                    pPosition = pSite->GetOrigin();
                    HXREGION* hTemp = pSite->Transition(pPosition->x, pPosition->y,
                                                        pPosition->x + pSite->m_size.cx,
                                                        pPosition->y + pSite->m_size.cy);
                    HXSubtractRegion(pRegion, hTemp, pRegion);
                    HXDestroyRegion(hTemp);
                    hTemp = NULL;
                }
            }
        }

        //pRegion now has the region we need to intersect with.

        //XXXgfw, if you are seeing weird alpha problems try
        //using this region instead of the transition one below.
//          HXREGION* pMe = HXCreateRectRegion( m_topleft.x,
//                                             m_topleft.y,
//                                             m_size.cx, // !!! should be +m_topleft
//                                             m_size.cy // !!! should be +m_topleft
//                                             );
        HXREGION* pMe = Transition(m_topleft.x, m_topleft.y,
                                   m_topleft.x + m_size.cx,
                                   m_topleft.y + m_size.cy);

        HXIntersectRegion( pRegion, pMe, pRegion );
        HXDestroyRegion( pMe );

        //Don't delete the region if we save it in the map!
        BOOL bRegionNeedsDeleting = TRUE;
        if( !HXEmptyRegion(pRegion)  )
        {
            //Add it to our region list that we alpha blend with only
            //if we are alpha blendable.
            if( _TakesPartInAlphaChain() )
            {
                // pRegion now contains our alpha blend region on our parent.
                // If our parent is a m_bSiteNeverBlts kind, then we will
                // can't alphablend with it, we need to see what alphablend
                // regions our parent has that intersect with us. Then, for
                // each one that does intersect us, we add it, and add
                // ourselves to that sites notifier list. We should NOT have
                // added our parent to that sites notifier list because it is
                // a m_bSiteNeverBlts.
                //
                // Terribly confusing what.
                // If you don't get it, listen to this:
                //   http://www.dangermouse.org/sounds/what.wav
                if( !pParent->m_bSiteNeverBlts)
                {
#if defined(_DEBUG) && 0
                    VerifyNoDups( m_AlphaBlendSites, pRegion );
#endif
                    m_AlphaBlendSites.SetAt( pParent, pRegion );
                    int nCID = GETBITMAPCOLOR(&(pParent->m_pVideoSurface->m_bmiLastBlt));

                    bRegionNeedsDeleting = FALSE;
                    //Add ourselves to that site's notifier list if only if we
                    //are not a m_bSiteNeverBlts.
                    if( !m_bSiteNeverBlts)
                        pParent->_AlphaBlendAddNotifier(this);
                }
                else
                {
                    //OK, go through the parents alpha regions and intersect..
                    CHXMapPtrToPtr::Iterator ii = pParent->m_AlphaBlendSites.Begin();
                    for ( ; ii != pParent->m_AlphaBlendSites.End(); ++ii)
                    {
                        HXREGION* pTmpReg = HXCreateRegion();
                        HXIntersectRegion( pRegion, (HXREGION*)*ii, pTmpReg );
                        if( !HXEmptyRegion(pTmpReg) )
                        {
                            //Add this region and a notifier if we need it.
                            CHXBaseSite* pTmpSite = (CHXBaseSite*) ii.get_key();

                            // See we already have a alphablend region with that
                            // site. If so, union the two.
                            void* pOrig = NULL;
                            if(m_AlphaBlendSites.Lookup((void*)pTmpSite, pOrig ) )
                            {
                                //Must union it.
                                HXUnionRegion( pTmpReg, (HXREGION*)pOrig, pTmpReg );
                                HXDestroyRegion( (HXREGION*)pOrig );
                            }
#if defined(_DEBUG) && 0
                            VerifyNoDups( m_AlphaBlendSites, pTmpReg );
#endif
                            m_AlphaBlendSites.SetAt( pTmpSite, pTmpReg );
                            int nCID = GETBITMAPCOLOR(&(pTmpSite->m_pVideoSurface->m_bmiLastBlt));
                            if( !m_bSiteNeverBlts )
                                pTmpSite->_AlphaBlendAddNotifier(this);
                        }
                        else
                        {
                            //just clean up an empty region that isn't added to our map.
                            HXDestroyRegion( pTmpReg );
                            pTmpReg=NULL;
                        }
                    }
                }
            }
            //XXXgfw maybe do an AddRef on the site????
        }

        if( bRegionNeedsDeleting )
        {
            //just clean up an empty region that isn't added to our map.
            HXDestroyRegion(pRegion);
            pRegion=NULL;
        }

        //Now do all the children.....
        pos = m_pParentSite->m_ChildrenInZOrder.GetHeadPosition();
        while(pos)
        {
            CHXBaseSite* pSite = (CHXBaseSite*)m_pParentSite->m_ChildrenInZOrder.GetNext(pos);
            if( this == pSite )
            {
                break;
            }
            pSite->AlphaBlendComputeSubRects(this);
        }
    }

    // OK, here is some real fun. If, we are a m_bSiteNeverBlts type of
    // site, then we must take our m_Region, intersect it with all of
    // our alphablend sites, and then add that result back into the
    // m_Region of the alphablend sibling. Because, since we aren't
    // drawing, someone needs to draw that part of the screen.
    if( m_bSiteNeverBlts )
    {
        CHXMapPtrToPtr::Iterator iter = m_AlphaBlendSites.Begin();
        for ( ; iter != m_AlphaBlendSites.End(); ++iter)
        {
            HXREGION*   pTmpReg = HXCreateRegion();
            HXREGION*   hTemp   = NULL;
            HXxPoint* pPosition;
            HXxSize   size;

            HXREGION* pAlphaReg = (HXREGION*)*iter;
            CHXBaseSite* pTmpSite = (CHXBaseSite*) iter.get_key();

            //Now remove all higher order siblings from this alpha region.
            HXUnionRegion( pTmpReg, pAlphaReg, pTmpReg );
            if( m_pParentSite )
                m_pParentSite->_RemoveHigherOrderSiblings(pTmpReg, this );

            // Get rid of all children of mine..
            pos = m_ChildrenInZOrder.GetHeadPosition();
            while(pos)
            {
                CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
                if(pSite->IsSiteVisible() )
                {
                    memcpy(&size, &pSite->m_size, sizeof(HXxSize)); /* Flawfinder: ignore */
                    pPosition = pSite->GetOrigin();
                    hTemp = pSite->Transition(pPosition->x, pPosition->y,
                                              pPosition->x + size.cx,
                                              pPosition->y + size.cy);

                    HXSubtractRegion(pTmpReg, hTemp, pTmpReg);
                    HXDestroyRegion(hTemp);
                    hTemp=NULL;
                }
            }

            if( !HXEmptyRegion(pTmpReg) )
            {
                //Add this back into the sites m_Region.
                HXUnionRegion(pTmpSite->m_Region, pTmpReg, pTmpSite->m_Region);
            }
            HXDestroyRegion(pTmpReg);
        }
    }

    ////////////////////////////////////////////////////////
    //              END ALPHA BLENDING WORK               //
    ////////////////////////////////////////////////////////


    // Now copy our visual region into a mouse/event region.
    m_RegionForMouse = HXCreateRegion();
    HXUnionRegion( m_RegionForMouse, m_Region, m_RegionForMouse);

    //If we have a parent site and a window then we must set our window
    //rgn to that specified in m_hClip

    m_topleft.x =0;
    m_topleft.y =0;
    GetAbsoluteCords(m_topleft);


    if(bRepaintMessage )
    {
        InternalForceRedraw();

        if (m_pVideoSurface)
        {
            m_pVideoSurface->FillColorKey();
        }
    }

    SizeSliders();

    _TLSUnlock();
    return TRUE;
}

void CHXBaseSite::BuildParnetClipping( HXREGION* hClip, CHXBaseSite* pChild)
{
    HXREGION*      hTemp     = NULL;
    HXxPoint*    pPosition = NULL;
    HXxSize      size;
    BOOL         bFound    = FALSE;

    // subtract all of my children from my clipping region
    LISTPOSITION pos = m_ChildrenInZOrder.GetHeadPosition();
    while(pos)
    {
        CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
        //Keep in mind that all site before pChild have zorder less than
        //pChild and all sites after have a higher zorder.
        if( pChild == pSite )
        {
            bFound = TRUE;
        }
        if(bFound && pChild!=pSite && pSite->IsSiteVisible())
        {
            memcpy(&size, &pSite->m_size, sizeof(HXxSize)); /* Flawfinder: ignore */
            pPosition = pSite->GetOrigin();

            hTemp = pSite->Transition(pPosition->x, pPosition->y,
                                      pPosition->x + size.cx,
                                      pPosition->y + size.cy);

            HXSubtractRegion(hClip, hTemp, hClip);
            HXDestroyRegion(hTemp);
            hTemp=NULL;
        }
    }

    // now handle my clipping region
    // if my region is valid use that ...
    if (m_bRegionIsValid )
    {
        HXIntersectRegion(hClip, m_RegionWithoutChildren, hClip);
    }
    else
    {
        hTemp = Transition(m_topleft.x, m_topleft.y,
                           m_topleft.x + m_size.cx,
                           m_topleft.y + m_size.cy,
                           &m_TransitionBorderLines);

        HXIntersectRegion(hClip, hTemp, hClip);
        HXDestroyRegion(hTemp);
        hTemp=NULL;

        if (m_pParentSite)
            m_pParentSite->BuildParnetClipping(hClip,this);
    }
}


BOOL CHXBaseSite::AreVideoControlsActive()
{
    if (m_pParentSite)
    {
        return m_pParentSite->AreVideoControlsActive();
    }

    return m_fBrightness    != DEF_BRIGHTNESS ||
        m_fContrast      != DEF_CONTRAST   ||
        m_fSharpness     != DEF_SHARPNESS  ||
        m_fHue           != DEF_HUE        ||
        m_fSaturation    != DEF_SATURATION;
}

BOOL CHXBaseSite::_BordersActive()
{
    return (m_TransitionBorderLines.m_nLines && m_nTransitionBorderWidth);
}

BOOL CHXBaseSite::_BlendedBordersActive()
{
    return (m_TransitionBorderLines.m_nLines &&
            m_nTransitionBorderWidth &&
            m_bTransitionBlendBorder &&
            m_nTransitionState < 1000);
}

BOOL CHXBaseSite::_FadeTransitionActive()
{
    return ( (m_fpTransitionEffect == Crossfade ||
              m_fpTransitionEffect == FadeToColor ||
              m_fpTransitionEffect == FadeFromColor)
             && m_nTransitionState<1000
             );
}

BOOL CHXBaseSite::_IsAlphaBlending()
{
    return _BordersActive() ||
        _FadeTransitionActive() ||
        _TakesPartInAlphaChain() ||
        m_AlphaBlendNotifiers.GetCount() != 0 ||
        m_AlphaBlendSites.GetCount() != 0;

}

BOOL CHXBaseSite::IsHigherZOrderTranstitionActive()
{
    BOOL bRet = FALSE;

    CHXMapPtrToPtr::Iterator iter = m_AlphaBlendNotifiers.Begin();
    for ( ; iter != m_AlphaBlendNotifiers.End(); ++iter)
    {
        CHXBaseSite* pSite = (CHXBaseSite*)*iter;

        if (pSite->m_fpTransitionEffect != DefaultTransition &&
            pSite->m_nTransitionState > 0 &&
            pSite->m_nTransitionState < 1000 &&
            GETBITMAPCOLOR(&pSite->m_pVideoSurface->m_bmiLastBlt) == CID_ARGB32)
        {
            bRet = TRUE;
            break;
        }
    }

    return bRet;
}

////////////////////////////////////////////////////////
//            BEGIN ALPHA BLENDING WORK               //
////////////////////////////////////////////////////////
void CHXBaseSite::_RemoveHigherOrderSiblings( HXREGION* hClip, CHXBaseSite* pChild)
{
    HXREGION*      hTemp     = NULL;
    HXxPoint*    pPosition = NULL;
    HXxSize      size;
    BOOL         bFound    = FALSE;

    // Get rid of all higher zorder siblings from this region.
    LISTPOSITION pos = m_ChildrenInZOrder.GetHeadPosition();
    while(pos)
    {
        CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
        //Keep in mind that all site before pChild in this list are lower
        //zorder and all sites afer have higher zorders.
        if( pChild == pSite )
        {
            bFound = TRUE;
        }

        if(bFound && pChild!=pSite && pSite->IsSiteVisible() )
        {
            memcpy(&size, &pSite->m_size, sizeof(HXxSize)); /* Flawfinder: ignore */
            pPosition = pSite->GetOrigin();

            hTemp = pSite->Transition(pPosition->x, pPosition->y,
                                      pPosition->x + size.cx,
                                      pPosition->y + size.cy);

            HXSubtractRegion(hClip, hTemp, hClip);
            HXDestroyRegion(hTemp);
            hTemp=NULL;
        }
    }
    if( m_pParentSite )
        m_pParentSite->_RemoveHigherOrderSiblings( hClip, this );
}

void CHXBaseSite::AlphaBlendComputeSubRects(CHXBaseSite* pIgnoredSite)
{
    HXREGION*      hTemp     = NULL;
    HXxSize      size;
    HXxPoint*    pPosition = NULL;
    HXREGION*      pReturn   = NULL;
    LISTPOSITION pos       = NULL;

    HX_ASSERT( pIgnoredSite != this );

    if( pIgnoredSite == this )
        return;

    if( pIgnoredSite && !pIgnoredSite->_TakesPartInAlphaChain() )
        return;

    if(IsSiteVisible())
    {
        pReturn = Transition(m_topleft.x, m_topleft.y,
                             m_topleft.x + m_size.cx,
                             m_topleft.y + m_size.cy,
                             &m_TransitionBorderLines);


        if(m_pParentSite)
        {
            m_pParentSite->AlphaBlendBuildParnetClipping( pReturn, this, pIgnoredSite );
        }

        // subtract all of my children from my clipping region
        if( pReturn->numRects != 0 )
        {
            pos = m_ChildrenInZOrder.GetHeadPosition();
            while(pos)
            {
                CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
                if(pSite->IsSiteVisible())
                {
                    pPosition = pSite->GetOrigin();
                    memcpy(&size, &pSite->m_size, sizeof(size)); /* Flawfinder: ignore */

                    hTemp = pSite->Transition(pPosition->x, pPosition->y,
                                              pPosition->x + size.cx,
                                              pPosition->y + size.cy);

                    HXSubtractRegion(pReturn, hTemp, pReturn);
                    HXDestroyRegion(hTemp);
                    hTemp = NULL;
                }
            }
        }
    }

    //Now we have an alpha blend region. Add it to the master sites
    //map if we overlap it at all.
    BOOL regionNeedsDeleting = TRUE;
    if( pReturn && !HXEmptyRegion( pReturn ) )
    {
        HXxPoint* pPosition = pIgnoredSite->GetOrigin();
        HXxSize*  pSize     = &(pIgnoredSite->m_size);

        HXREGION*   pTmp = pIgnoredSite->Transition(pPosition->x,
                                                    pPosition->y,
                                                    pPosition->x+pSize->cx,
                                                    pPosition->y+pSize->cy);

        //We must remove any overlapping NON-ARGB regions. Higher order
        //siblings and chilren....
        pos = pIgnoredSite->m_ChildrenInZOrder.GetHeadPosition();
        while(pos)
        {
            CHXBaseSite* pSite2 =
                (CHXBaseSite*)(pIgnoredSite->m_ChildrenInZOrder.GetNext(pos));
            if(pSite2->IsSiteVisible() && !pSite2->_IsAlphaBlending())
            {
                pPosition = pSite2->GetOrigin();
                memcpy(&size, &pSite2->m_size, sizeof(size)); /* Flawfinder: ignore */

                hTemp = pSite2->Transition(pPosition->x, pPosition->y,
                                           pPosition->x + size.cx,
                                           pPosition->y + size.cy);

                HXSubtractRegion(pReturn, hTemp, pReturn);
                HXDestroyRegion(hTemp);
                hTemp = NULL;
            }
        }










        HXIntersectRegion( pReturn, pTmp, pReturn );
        HXDestroyRegion( pTmp );
        if ( !HXEmptyRegion( pReturn ) )
        {
            //Add it to our region list that we alpha blend with only
            //if we are alpha blendable.
            if( pIgnoredSite && pIgnoredSite->_TakesPartInAlphaChain() )
            {
                // pRetrun now contains our alpha blend region on
                // ourselves.  If we are a m_bSiteNeverBlts kind, then we
                // don't want the ignored site to alphablend with us, we
                // need to see what alphablend regions we have that
                // intersect with the ignored site. Then, for each one
                // that does intersect, we add it, and add the ignored
                // site to our notifier list. We should NOT have added
                // ourselves to that sites notifier list because it is a
                // m_bSiteNeverBlts.
                //
                // Terribly confusing what.
                // If you don't get it, listen to this:
                //   http://www.dangermouse.org/sounds/what.wav
                if( !m_bSiteNeverBlts)
                {
                    //Add this to our list of regions we alpha blend with.
                    //XXXgfw addref the site???
#if defined(_DEBUG) && 0
                    VerifyNoDups( pIgnoredSite->m_AlphaBlendSites, pReturn );
#endif

                    pIgnoredSite->m_AlphaBlendSites.SetAt( this, pReturn );
                    int nCID = GETBITMAPCOLOR(&(m_pVideoSurface->m_bmiLastBlt));

                    regionNeedsDeleting = FALSE;

                    //Add the ignored site to our site's notifier list. Do this
                    //only if the ignored site isn't m_bSiteNeverBlts type.
                    if( !(pIgnoredSite->m_bSiteNeverBlts) )
                        _AlphaBlendAddNotifier(pIgnoredSite);
                }
                else
                {
                    //OK, go through the alpha regions and intersect..
                    CHXMapPtrToPtr::Iterator ii = m_AlphaBlendSites.Begin();
                    for ( ; ii != m_AlphaBlendSites.End(); ++ii)
                    {
                        HXREGION* pTmpReg = HXCreateRegion();
                        HXIntersectRegion( pReturn, (HXREGION*)*ii, pTmpReg );
                        if( !HXEmptyRegion(pTmpReg) )
                        {
                            //Add this region and a notifier if we need it.
                            CHXBaseSite* pTmpSite = (CHXBaseSite*) ii.get_key();

                            // See we already have a alphablend region with that
                            // site. If so, union the two.
                            void* pOrig = NULL;
                            if(pIgnoredSite->m_AlphaBlendSites.Lookup((void*)pTmpSite, pOrig ) )
                            {
                                //Must union it.
                                HXUnionRegion( pTmpReg, (HXREGION*)pOrig, pTmpReg );
                                HXDestroyRegion( (HXREGION*)pOrig );
                            }
#if defined(_DEBUG) && 0
                            VerifyNoDups( pIgnoredSite->m_AlphaBlendSites, pTmpReg );
#endif

                            pIgnoredSite->m_AlphaBlendSites.SetAt( pTmpSite, pTmpReg );
                            int nCID = GETBITMAPCOLOR(&(pTmpSite->m_pVideoSurface->m_bmiLastBlt));
                            if( !pIgnoredSite->m_bSiteNeverBlts )
                                _AlphaBlendAddNotifier(pIgnoredSite);
                        }
                        else
                        {
                            //just clean up an empty region that isn't added to our map.
                            HXDestroyRegion( pTmpReg );
                            pTmpReg=NULL;
                        }
                    }
                }
            }
        }
    }

    if( pReturn && regionNeedsDeleting )
    {
        HXDestroyRegion(pReturn);
        pReturn=NULL;
    }

    //Now do all of our children too......
    pos = m_ChildrenInZOrder.GetHeadPosition();
    while(pos)
    {
        CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
        pSite->AlphaBlendComputeSubRects( pIgnoredSite );
    }
}

void CHXBaseSite::AlphaBlendBuildParnetClipping( HXREGION* hClip,
                                                 CHXBaseSite* pChild,
                                                 CHXBaseSite* pIgnoredSite
                                                 )
{
    HXREGION*      hTemp         = NULL;
    HXxPoint*    pPosition;
    HXxSize      size;
    BOOL         bIgnoreSiteIsSibling = FALSE;
    LISTPOSITION pos           = NULL;
    BOOL         bFoundChild   = FALSE;
    BOOL         bFoundIgnored = FALSE;


    //Is the ignored site a sibling of ours? If not, ignore its z
    //order.
    if( pIgnoredSite->m_pParentSite == this )
    {
        bIgnoreSiteIsSibling = TRUE;
    }

    // subtract all of my children from my clipping region
    pos = m_ChildrenInZOrder.GetHeadPosition();
    while(pos)
    {
        CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
        if( pSite == pChild )
        {
            //Now all sites in this list will be of higher Zorder
            bFoundChild = TRUE;
        }
        else if( pSite == pIgnoredSite )
        {
            //Now, all sites in this list will be higher than the
            //ignored.
            bFoundIgnored = TRUE;
        }

        if( bFoundChild && pSite!=pChild &&
            ((!bFoundIgnored ) || !bIgnoreSiteIsSibling) &&
            (pSite->IsSiteVisible())
            )
        {
            memcpy(&size, &pSite->m_size, sizeof(HXxSize)); /* Flawfinder: ignore */
            pPosition = pSite->GetOrigin();

            hTemp = pSite->Transition(pPosition->x, pPosition->y,
                                      pPosition->x + size.cx,
                                      pPosition->y + size.cy);

            HXSubtractRegion(hClip, hTemp, hClip);
            HXDestroyRegion(hTemp);
            hTemp=NULL;
        }
    }

    hTemp = Transition(m_topleft.x, m_topleft.y,
                       m_topleft.x + m_size.cx,
                       m_topleft.y + m_size.cy);

    HXIntersectRegion(hClip, hTemp, hClip);
    HXDestroyRegion(hTemp);
    hTemp=NULL;

    if (m_pParentSite)
        m_pParentSite->AlphaBlendBuildParnetClipping( (HXREGION*)hClip,
                                                      (CHXBaseSite*)this,
                                                      (CHXBaseSite*)pIgnoredSite);
}

////////////////////////////////////////////////////////
//              END ALPHA BLENDING WORK               //
////////////////////////////////////////////////////////





void CHXBaseSite::UpdateModes()
{
    INT32 nNumModes = 0;
    CModesDesc* pModesDesc = 0;
    m_pRootSurface->GetDisplayModes(pModesDesc, &nNumModes);
    pModesDesc = new CModesDesc[nNumModes ];
    m_pRootSurface->GetDisplayModes(pModesDesc, &nNumModes);

    for(INT32 i=0; i<nNumModes; i++)
    {
        if (pModesDesc[i].m_nWidth>= 320 && pModesDesc[i].m_nHeight>=200 && pModesDesc[i].m_nBitCount>=8)
        {
            if (!DoesPrefExist(pModesDesc[i].m_nWidth, pModesDesc[i].m_nHeight, pModesDesc[i].m_nBitCount))
            {
                UpdatePrefs(pModesDesc[i].m_nWidth, pModesDesc[i].m_nHeight, pModesDesc[i].m_nBitCount, 0, FALSE, FALSE);
            }
        }
    }

    HX_VECTOR_DELETE(pModesDesc);
}

BOOL CHXBaseSite::DoesPrefExist(INT32 resolutionX, INT32 resolutionY, INT32 colorDepth)
{
    char         szNameBuffer[255]; /* Flawfinder: ignore */
    IHXBuffer*          pBuffer         = NULL;
    IHXPreferences*     pPreferences    = NULL;
    BOOL         bFound          = FALSE;

    if (HXR_OK == m_pContext->QueryInterface(IID_IHXPreferences, (void**)&pPreferences))
    {
        sprintf(szNameBuffer, "%s\\%s\\%dx%dx%d", /* Flawfinder: ignore */
                REGKEY_FULLSCREEN_DATA,
                REGKEY_FULLSCREEN_AVAILIABLE_MODES,
                resolutionX,
                resolutionY,
                colorDepth);
        if (HXR_OK == pPreferences->ReadPref(szNameBuffer, pBuffer))
        {
            bFound = TRUE;
            HX_RELEASE(pBuffer);
        }
    }
    HX_RELEASE(pPreferences);
    return bFound;
}

void CHXBaseSite::UpdatePrefs(INT32 resolutionX, INT32 resolutionY, INT32 colorDepth, ULONG32 ulBltTime, BOOL bPassed, BOOL bTested)
{
    char szNameBuffer[255]; /* Flawfinder: ignore */
    IHXBuffer* pBuffer = NULL;
    IHXPreferences*     pPreferences        = NULL;

    if (HXR_OK == m_pContext->QueryInterface(IID_IHXPreferences, (void**)&pPreferences))
    {
        sprintf(szNameBuffer, "%s\\%s\\%dx%dx%d", /* Flawfinder: ignore */
                REGKEY_FULLSCREEN_DATA,
                REGKEY_FULLSCREEN_AVAILIABLE_MODES,
                resolutionX,
                resolutionY,
                colorDepth);

        pBuffer = new CHXBuffer();
        pBuffer->AddRef();
        char szTempBuffer[255]; /* Flawfinder: ignore */
        strcpy(szTempBuffer, szNameBuffer); /* Flawfinder: ignore */
        strcat(szTempBuffer, "\\"); /* Flawfinder: ignore */
        strcat(szTempBuffer, REGKEY_TESTED); /* Flawfinder: ignore */
        if (bTested)
        {
            pBuffer->Set((const unsigned char*) "1", 2);
        }
        else
        {
            pBuffer->Set((const unsigned char*) "0", 2);
        }
        pPreferences->WritePref(szTempBuffer, pBuffer);
        strcpy(szTempBuffer, szNameBuffer); /* Flawfinder: ignore */
        strcat(szTempBuffer, "\\"); /* Flawfinder: ignore */
        strcat(szTempBuffer, REGKEY_BLT_TIME); /* Flawfinder: ignore */
        char szNumberBuffer[20]; /* Flawfinder: ignore */
        sprintf( szNumberBuffer, "%d", ulBltTime ); /* Flawfinder: ignore */
        //itoa(ulBltTime, szNumberBuffer, 10);
        pBuffer->Set((const unsigned char*) szNumberBuffer, strlen(szNumberBuffer)+1);
        pPreferences->WritePref(szTempBuffer, pBuffer);
        strcpy(szTempBuffer, szNameBuffer); /* Flawfinder: ignore */
        strcat(szTempBuffer, "\\"); /* Flawfinder: ignore */
        strcat(szTempBuffer, REGKEY_PASS); /* Flawfinder: ignore */
        if (bPassed)
        {
            pBuffer->Set((const unsigned char*) "1", 2);
        }
        else
        {
            pBuffer->Set((const unsigned char*) "0", 2);
        }
        pPreferences->WritePref(szTempBuffer, pBuffer);
        HX_RELEASE(pBuffer);
    }
    HX_RELEASE(pPreferences);
}

void CHXBaseSite::ScheduleCallback(INT32 nWhichCallback,
                                   INT32 nMilliseconds,
                                   BOOL  bOverrideCompositionMode)
{
    HX_ASSERT(m_pTopLevelSite == this);

    if( IsCompositionMode() && nWhichCallback!=MOUSE && !bOverrideCompositionMode )
    {
        return;
    }

    switch (nWhichCallback)
    {
       case REPAINT:
           if (m_bProcessRepaint)
               return;
           m_bProcessRepaint = TRUE;
           break;
       case CLIP:
           if (m_bRecomputeClipScheduled)
               return;
           m_bRecomputeClipScheduled = TRUE;
           break;
       case REDRAW_ALL:
           if (m_bForceRedrawNeeded)
               return;
           m_bForceRedrawNeeded = TRUE;
           break;
       case MOUSE:
           if (m_CallbackHandle)
               return;
           break;
       case MOVE:
           _TLSLock();

           /*
            * Site moving used to take an X, Y parameter, but since we changed it to
            * go to GDI mode, that is no longer relevant.
            */
           SiteMoving(0, 0);
           m_nLastMoveTime = HX_GET_TICKCOUNT();
           ScheduleCallback(MOUSE, 100);

           _TLSUnlock();

           return;

       default:
           HX_ASSERT(0);
           break;
    }

    if (m_pScheduler)
    {
        if (m_CallbackHandle)
        {
            m_pScheduler->Remove(m_CallbackHandle);
            m_CallbackHandle = 0;
        }
        m_CallbackHandle = m_pScheduler->RelativeEnter(m_pCallback, nMilliseconds);
    }
    return;
}

CBaseRootSurface* CHXBaseSite::GetRootSurface()
{
    return m_pRootSurface;
}

BOOL CHXBaseSite::IsPointInClippingRegion(HXxPoint* pPoint)
{
    return ::HXPointInRegion( m_RegionForMouse, pPoint->x, pPoint->y );
}

void
CHXBaseSite::SiteNotMoving()
{
#if 1
    m_bMoving = FALSE;
#else
    m_pVideoSurface->ForceGDIMode(FALSE);
#endif

    LISTPOSITION pos = m_ChildrenInZOrder.GetHeadPosition();
    while(pos)
    {
        CHXBaseSite* pChildSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
        pChildSite->SiteNotMoving();
    }
}

void CHXBaseSite::ColorConverterRequest(int CIDIn, int CIDOut, BOOL bFoundConverter)
{
    if (m_pTopLevelSite)
        m_pTopLevelSite->InternalColorConverterRequest(CIDIn, CIDOut, bFoundConverter, this);
}

void CHXBaseSite::InternalColorConverterRequest(int CIDIn, int CIDOut, BOOL bFoundConverter, CHXBaseSite* pSite)
{
    int* pCIDs;
    BOOL bSchedule = FALSE;
    IHXSite *pISite = (IHXSite*)pSite;

    if (!bFoundConverter)
    {
        /*
         *  1st wins. If there is already an upgrade request for this
         *  site, then add no more.
         */
        if (!m_upgradeMap.Lookup((void*) pISite, (void*&) pCIDs))
        {
            pCIDs = new int[2];
            pCIDs[0] = CIDIn;
            pCIDs[1] = CIDOut;
            m_upgradeMap.SetAt((void*)pISite, (void*)pCIDs);

            if (m_pScheduler)
            {
                if (m_CallbackHandle)
                {
                    m_pScheduler->Remove(m_CallbackHandle);
                    m_CallbackHandle = 0;
                }
                m_CallbackHandle = m_pScheduler->RelativeEnter(m_pCallback, 0);
            }

            m_bScheduleUpgrade = TRUE;
        }
    }
    else
    {
        if (m_upgradeMap.Lookup((void*) pISite, (void*&) pCIDs))
        {
            HX_DELETE(pCIDs);
            m_upgradeMap.Remove((void*) pISite);

            if (!m_upgradeMap.GetCount())
            {
                m_bScheduleUpgrade = FALSE;
            }
        }
    }
}

void CHXBaseSite::ScheduleUpgrade()
{
    /*
     *  We currently take the head of the list and upgrade that request
     *  and forget about all of the rest within the list.
     */

    IHXSite* pSite = NULL;
    int* pCIDs;

    if (m_upgradeMap.GetCount())
    {
        POSITION pos = m_upgradeMap.GetStartPosition();
        m_upgradeMap.GetNextAssoc(pos, (void*&)pSite, (void*&) pCIDs);
        InternalScheduleUpgrade(pCIDs[0], pCIDs[1], pSite);
        HX_VECTOR_DELETE(pCIDs);
        while(pos)
        {
            m_upgradeMap.GetNextAssoc(pos, (void*&)pSite, (void*&) pCIDs);
            HX_VECTOR_DELETE(pCIDs);
        }
        m_upgradeMap.RemoveAll();
    }

    m_bScheduleUpgrade = FALSE;

}

void CHXBaseSite::InternalScheduleUpgrade(UINT32 CIDIn, UINT32 CIDOut, IHXSite* pSite)
{
    /*
     *  1st we have to find the player to which we are attached.
     *
     *  We will use two methods to find out who we are attached to.
     *  1.  We will QI for SiteManager2 and iterate over the sites to see
     *      if we are in the list.
     *  2.  If we have only one player we will use that one!
     *  3.  And we'll use the 1st player if we can't find anything.
     */

    IHXClientEngine*       pEngine         = NULL;
    IHXSite*               pIterationSite  = NULL;
    IHXBuffer*             pBuffer         = NULL;
    IUnknown*               pUnknown        = NULL;
    IHXSiteManager2*       pSiteManager2   = NULL;
    UINT16 nPlayerCount;
    UINT32 index;
    UINT32 index2;
    UINT32 nNumSites;

    m_pContext->QueryInterface(IID_IHXClientEngine, (void**)&pEngine);

    if (!pEngine)
        goto cleanup;

    nPlayerCount = pEngine->GetPlayerCount();

    /*
     *  Do we only have one player? If so, case solved!
     */

    if (nPlayerCount == 1)
    {
        pEngine->GetPlayer(0, pUnknown);
        goto playerFound;
    }
    else
    {
        for(index = 0; index< nPlayerCount; index++)
        {
            pEngine->GetPlayer((UINT16) index, pUnknown);
            pUnknown->QueryInterface(IID_IHXSiteManager2, (void**) &pSiteManager2);
            if (pSiteManager2)
            {
                pSiteManager2->GetNumberOfSites(nNumSites);
                for(index2 = 0; index2< nNumSites; index2++)
                {
                    pSiteManager2->GetSiteAt(index2, pIterationSite);
                    if (pSite == pIterationSite)
                    {
                        /*
                         *  We have a winner
                         */
                        HX_RELEASE(pSiteManager2);
                        goto playerFound;
                    }
                }
            }
            HX_RELEASE(pSiteManager2);
            HX_RELEASE(pUnknown);
        }
    }

    pEngine->GetPlayer(0, pUnknown);


  playerFound:
    // Auto download of color converter
    AddToAutoUpgradeCollection("colo", pUnknown);

  cleanup:
    HX_RELEASE(pUnknown);
    HX_RELEASE(pBuffer);
    HX_RELEASE(pEngine);
}

void CHXBaseSite::SetEvent(REF(HXxEvent) theEvent, ULONG32 event, void* window, void*   param1, void*   param2)
{
    theEvent.event       = event;
    theEvent.window = window;
    theEvent.param1 = param1;
    theEvent.param2 = param2;
    theEvent.result = 0;
    theEvent.handled = FALSE;
}

void CHXBaseSite::CheckDisplayMode(void* hdc)
{
    BOOL bCreatedDC = FALSE;

    if (m_pTopLevelSite == this && !zm_bInFullScreenTest)
    {
        if (!m_bSettingDisplayMode)
        {
            UINT16 newBitsPerPixel, newHozRes, newVertRes;
            _GetDeviceCaps(hdc, newBitsPerPixel, newHozRes, newVertRes);

            if (m_nOldBitsPerPixel != newBitsPerPixel || newHozRes != m_nOldHorzRes || newVertRes != m_nOldVertRes)
            {
                m_nOldBitsPerPixel  = newBitsPerPixel;
                m_nOldHorzRes           = newHozRes;
                m_nOldVertRes           = newVertRes;
                ChangeResolution();
            }
        }
    }
}

void CHXBaseSite::ChangeResolution()
{
    if( this==m_pTopLevelSite &&
        m_pRootSurface &&
        m_pRootSurface->_OptimizedSurfaceOpened())
    {
        DestroySurfaces();
        /// XXXAH Uhm, I think I should be chaning the resolution here ....
        _ReInitPrimarySurface();
        ReInitSurfaces();
    }
}

void
CHXBaseSite::DestroySurfaces()
{
    if (m_pVideoSurface)
    {
        m_pVideoSurface->DestroySurfaces();
    }

    if (m_pRootSurface)
    {
        m_pRootSurface->DestroySurfaces();
    }

    LISTPOSITION pos = m_ChildrenInZOrder.GetHeadPosition();
    while(pos)
    {
        CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
        pSite->DestroySurfaces();
    }
}


void CHXBaseSite::LockBlitters()
{
    if (m_pVideoSurface)
    {
        m_pVideoSurface->_LockBlitter();
    }

    LISTPOSITION pos = m_ChildrenInZOrder.GetHeadPosition();
    while(pos)
    {
        CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
        pSite->LockBlitters();
    }
}

void CHXBaseSite::UnlockBlitters()
{
    if (m_pVideoSurface)
    {
        m_pVideoSurface->_UnlockBlitter();
    }

    LISTPOSITION pos = m_ChildrenInZOrder.GetHeadPosition();
    while(pos)
    {
        CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
        pSite->UnlockBlitters();
    }
}

void CHXBaseSite::FlushSurfaces()
{
    if (m_pVideoSurface)
    {
        m_pVideoSurface->_FlushSurfaces();
    }

    LISTPOSITION pos = m_ChildrenInZOrder.GetHeadPosition();
    while(pos)
    {
        CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
        pSite->FlushSurfaces();
    }

}

void CHXBaseSite::DisableColorControls(float &fBrightness,
                                       float &fContrast,
                                       float &fSaturation,
                                       float &fHue)
{
    if (m_pParentSite)
    {
        m_pParentSite->DisableColorControls(fBrightness,
                                            fContrast,
                                            fSaturation,
                                            fHue);
        return;
    }

    m_fHue = 0;
    m_fSaturation = 0;
    m_fContrast = 0;
    m_fBrightness = 0;
}

void CHXBaseSite::EnableColorControls(float fBrightness,
                                      float fContrast,
                                      float fSaturation,
                                      float fHue)
{
    if (m_pParentSite)
    {
        m_pParentSite->EnableColorControls(fBrightness,
                                           fContrast,
                                           fSaturation,
                                           fHue);
        return;
    }

    m_fHue = fHue;
    m_fSaturation = fSaturation;
    m_fContrast = fContrast;
    m_fBrightness = fBrightness;
}

void CHXBaseSite::ReInitSurfaces()
{
    if (m_pVideoSurface)
    {
        m_pVideoSurface->ReInitSurfaces();
    }

    if (m_pRootSurface)
    {
        m_pRootSurface->ReInitSurfaces();
    }

    LISTPOSITION pos = m_ChildrenInZOrder.GetHeadPosition();
    while(pos)
    {
        CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
        pSite->ReInitSurfaces();
    }
}
void CHXBaseSite::_EmptyBlenderList()
{
    if( m_pTopLevelSite && m_pTopLevelSite->m_pMutex  )
        _TLSLock();
    CHXMapPtrToPtr::Iterator iter = m_AlphaBlendSites.Begin();
    for ( ; iter != m_AlphaBlendSites.End(); ++iter)
    {
        HXREGION* pTmp = (HXREGION*)*iter;
        HXDestroyRegion( pTmp );
        pTmp = NULL;
    }
    m_AlphaBlendSites.RemoveAll();
    if( m_pTopLevelSite && m_pTopLevelSite->m_pMutex  )
        _TLSUnlock();
}

void CHXBaseSite::_EmptyNotifierList()
{
    if( m_pTopLevelSite && m_pTopLevelSite->m_pMutex )
        _TLSLock();

    m_bUsingList = FALSE;
    CHXMapPtrToPtr::Iterator iter = m_AlphaBlendNotifiers.Begin();
    for ( ; iter != m_AlphaBlendNotifiers.End(); ++iter)
    {
        CHXBaseSite* pSite = (CHXBaseSite*)*iter;
        HX_RELEASE( pSite );
    }
    m_AlphaBlendNotifiers.RemoveAll();
    m_bUsingList = FALSE;

    if( m_pTopLevelSite && m_pTopLevelSite->m_pMutex )
        _TLSUnlock();
}

void CHXBaseSite::_AlphaBlendAddNotifier(CHXBaseSite* it)
{
    if( m_pTopLevelSite && m_pTopLevelSite->m_pMutex )
        _TLSLock();

    m_bUsingList = FALSE;

    CHXBaseSite* pNotUsed = NULL;
    if( NULL==m_AlphaBlendNotifiers.Lookup( (void*)it) )
    {
        //Does not exist yet.
        it->AddRef();
        m_AlphaBlendNotifiers.SetAt( it, it );
    }
    m_bUsingList = FALSE;

    if( m_pTopLevelSite && m_pTopLevelSite->m_pMutex )
        _TLSUnlock();
}

void CHXBaseSite::_RemoveAllNotifiers()
{
    _EmptyNotifierList();
    LISTPOSITION pos = m_ChildrenInZOrder.GetHeadPosition();
    while(pos)
    {
        CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
        pSite->_RemoveAllNotifiers();
    }
}
void CHXBaseSite::_RemoveAllYUVImageLists()
{
    m_pVideoSurface->_RemoveYUVImageLists();
    LISTPOSITION pos = m_ChildrenInZOrder.GetHeadPosition();
    while(pos)
    {
        CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
        pSite->_RemoveAllYUVImageLists();
    }
}

//  #if defined(_CHECK_PERFORMANCE)
//  LONG32 g_nNumTimes = 0;
//  double g_fTotalTime = 0;
//  double g_fAverageTime = 0;
//  #endif

void CHXBaseSite::RecomputeClip()
{
//  #if defined(_CHECK_PERFORMANCE)
//     double frequency, startTime;
//     static LARGE_INTEGER QueryPerformanceCounterResult = {0,0};
//     static LARGE_INTEGER QueryPerformanceFrequencyResult = {0,0};
//     if (this == m_pTopLevelSite)
//     {

//        QueryPerformanceFrequency(&QueryPerformanceFrequencyResult);

//        frequency = ((double)QueryPerformanceFrequencyResult.LowPart + 4294967296.0*QueryPerformanceFrequencyResult.HighPart);
//        QueryPerformanceCounter(&QueryPerformanceCounterResult);

//        startTime = ((double)QueryPerformanceCounterResult.LowPart + 4294967296.0*QueryPerformanceCounterResult.HighPart)/frequency;
//     }
//  #endif

    if( IsCompositionLocked() )
    {
        return;
    }

    m_bRegionIsValid = FALSE;

    //Need to clean up the notifier list here....
    if( this==m_pTopLevelSite )
    {
        _RemoveAllNotifiers();
    }

    //If we are a YUV site, add ourselves to the list.
    int nCID = GETBITMAPCOLOR(&(m_pVideoSurface->m_bmiLastBlt));
    if( IsYUV(nCID) )
    {
        if( !zm_YUVSiteList.Find(this) )
        {
            zm_YUVSiteList.AddTail(this);
        }
    }

    // this recomputes our clipping rect.
    if( ComputeSubRects() )
    {
        //We need to do this in Z-Order. So, create a temp map
        //and use the zorder as key and the pSite pointer as value.
        LISTPOSITION pos = m_ChildrenInZOrder.GetHeadPosition();
        while(pos)
        {
            CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
            pSite->RecomputeClip();
        }
    }


    // do we have video under transition?
    if( this==m_pTopLevelSite)
    {
        FindLinkedSites();
    }

    SetClipping();
//  #if defined(_CHECK_PERFORMANCE)
//     if (this == m_pTopLevelSite)
//     {
//        QueryPerformanceCounter(&QueryPerformanceCounterResult);
//        double endTime = ((double)QueryPerformanceCounterResult.LowPart + 4294967296.0*QueryPerformanceCounterResult.HighPart)/frequency;

//        if (endTime > startTime)
//        {
//           g_nNumTimes++;
//           g_fTotalTime += endTime - startTime;
//           g_fAverageTime = g_fTotalTime / (double) g_nNumTimes;
//        }
//        if( g_nNumTimes%50==0 )
//        {
//           FILE* pFP=fopen("c:\\file.txt", "a+");
//           if( pFP )
//           {
//              fprintf( pFP, "ave: %f  num: %ld  tot: %f\n",
//                       g_fAverageTime, g_nNumTimes, g_fTotalTime);
//              fclose( pFP );
//           }
//        }
//     }
//  #endif
}

void CHXBaseSite::FindLinkedSites()
{
    m_ListOfRealVideoSites.RemoveAll();
    m_bVideoUnderTransition = FALSE;
    FindVideoSites();

    if (m_bVideoUnderTransition && m_ListOfRealVideoSites.GetCount() > 1)
    {
        // find out which one (if any) has overlay.
        // note: we should make this work with more than one overlay in the future.
        CHXSimpleList::Iterator i = m_ListOfRealVideoSites.Begin();
        CHXBaseSite* pSite = NULL;
        CHXBaseSite* pLinkedSite = NULL;
        for(;i!=m_ListOfRealVideoSites.End(); ++i)
        {
            pSite = (CHXBaseSite*) *i;
            if (pSite->m_pVideoSurface->m_surfaceSize.cx != 0 && pSite->m_pVideoSurface->m_nBltMode == HX_OVERLAY_BLT)
            {
                break;
            }
            pSite = NULL;
        }

#ifdef DEBUG_LINKING
    {
        char szbuff[255]; /* Flawfinder: ignore */
        sprintf(szbuff, "Under Transition Master Site = %p\n", pSite); /* Flawfinder: ignore */
        OutputDebugString(szbuff);
    }
#endif

        // yup it looks like one of the sites has overlay.
        if (pSite)
        {
            i = m_ListOfRealVideoSites.Begin();
            for(;i!=m_ListOfRealVideoSites.End(); ++i)
            {
                pLinkedSite = (CHXBaseSite*) *i;
                if (pLinkedSite != pSite &&
                    pLinkedSite->m_topleft.x == pSite->m_topleft.x  &&
                    pLinkedSite->m_topleft.y == pSite->m_topleft.y  &&
                    pLinkedSite->m_size.cx   == pSite->m_size.cx    &&
                    pLinkedSite->m_size.cy   == pSite->m_size.cy
                    )
                {
                    // we have a site on top of us. And it is at least partially visible.
                    pLinkedSite->m_pVideoSurface->LinkOverlay(pSite);
                    pSite->m_pVideoSurface->AddLinkedSite(pLinkedSite);
                    // of course we have to come up with some mechanisim to unlink the overlay.
#ifdef DEBUG_LINKING
                {
                    char szbuff[255]; /* Flawfinder: ignore */
                    sprintf(szbuff, "Linking Site %p  Surface %p to Site %p \n", pLinkedSite, pLinkedSite->m_pVideoSurface, pSite); /* Flawfinder: ignore */
                    OutputDebugString(szbuff);
                }
#endif
                }
                else
                {
#ifdef DEBUG_LINKING
                    if (pLinkedSite != pSite)
                    {
                        char szbuff[255]; /* Flawfinder: ignore */
                        sprintf(szbuff, "NO link (%d, %d, %d, %d) != (%d, %d, %d, %d)\n", /* Flawfinder: ignore */
                                pLinkedSite->m_topleft.x, pLinkedSite->m_topleft.y,
                                pLinkedSite->m_size.cx, pLinkedSite->m_size.cy,
                                pSite->m_topleft.x, pSite->m_topleft.y,
                                pSite->m_size.cx, pSite->m_size.cy);
                        OutputDebugString(szbuff);
                    }
#endif
                }
            }
        }
    }
}

void CHXBaseSite::SetClipping()
{
    if (m_pParentSite && m_pWindow && m_pWindow->window)
    {
        static CHXMapPtrToPtr z_map;

        int i;
        if (!z_map.Lookup(this, (void*&)i))
        {
            i= z_map.GetCount();
            z_map.SetAt(this, (void*&)i);
        }
#ifdef _DEBUG
        if (m_Region->numRects)
        {
            FILE* f = fopen("c:\\blt.txt", "a+"); /* Flawfinder: ignore */
            fprintf(f, "index: %d this - %d  hwnd %d VISIBLE: %s (%d, %d, %d, %d)  NumBoxes: %d \n", i, this,
                    m_pWindow->window, m_bIsVisible ? "TRUE" : "FALSE",
                    (INT32)m_topleft.x,
                    (INT32)m_topleft.y,
                    (INT32)m_size.cx,
                    (INT32)m_size.cy, m_Region->numRects);
            fclose(f);
        }
#endif

        //      *** HMW - Fix a windowed renderer window (HWND) positioning bug.
        //      The x and y positions was previously picked up from m_position, causing the child window to always be positioned at 0,0
        SafeMoveWindow((void*) m_pWindow->window,
                       (int)m_topleft.x,
                       (int)m_topleft.y,
                       (int)m_size.cx ,
                       (int)m_size.cy ,
                       m_bIsVisible);

        SafeSetWindowRgn(m_pWindow->window, m_Region, TRUE);
        // XXXAH This is all buggered up. Have to fix
    }

    LISTPOSITION pos = m_ChildrenInZOrder.GetHeadPosition();
    while(pos)
    {
        CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
        pSite->SetClipping();
    }
}


void CHXBaseSite::FindVideoSites()
{
#ifdef DEBUG_LINKING
    {
        char szbuff[255]; /* Flawfinder: ignore */
        sprintf(szbuff, "FindVideoSites this = %p\tRects: %d\tCID=%d\tblts= %s\n", /* Flawfinder: ignore */
                this,
                m_Region->numRects,
                m_pVideoSurface->m_nSrcCID,
                !m_bSiteNeverBlts ? "TRUE":"FALSE");
        OutputDebugString(szbuff);
    }
#endif

    if( IsYUV(GETBITMAPCOLOR(&m_pVideoSurface->m_bmiLastBlt)))
    {
        if (! m_Region->numRects && !m_AlphaBlendNotifiers.GetCount())
        {
//            m_pVideoSurface->RelinquishOverlay();
        }
        else
        {
            if  ( !m_bSiteNeverBlts &&  !_BlendedBordersActive() && !_BordersActive())
            {
                m_pTopLevelSite->m_ListOfRealVideoSites.AddTail(this);
                if (m_fpTransitionEffect != DefaultTransition)
                {
                    m_pTopLevelSite->m_bVideoUnderTransition = TRUE;
                }
            }
        }

    }

    LISTPOSITION pos = m_ChildrenInZOrder.GetHeadPosition();
    while(pos)
    {
        CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
        pSite->FindVideoSites();
    }
}


INT32 CHXBaseSite::GetTopMostSiteZOrder()
{
    INT32 nZorder = 0;
    CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetTail();
    if( pSite )
        pSite->GetZOrder(nZorder);
    return nZorder;
}

void CHXBaseSite::SetParentWindow(HXxWindow* pWindow)
{
    if (pWindow)
    {
        memcpy(&m_TopLevelWindow, pWindow, sizeof(HXxWindow)); /* Flawfinder: ignore */
    }
    else
    {
        memset(&m_TopLevelWindow, 0 , sizeof(HXxWindow));
    }

    LISTPOSITION pos = m_ChildrenInZOrder.GetHeadPosition();
    while(pos)
    {
        CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
        pSite->SetParentWindow(pWindow);
    }
}

void CHXBaseSite::SetRootSurface(CBaseRootSurface* pSurface)
{
    HX_RELEASE(m_pRootSurface);

    m_pRootSurface = pSurface;
    if (m_pRootSurface)
    {
        m_pRootSurface->AddRef();

        // Enable/Disable optimized video
        IHXPreferences*    pPreferences    = NULL;
        IHXBuffer*         pBuffer         = NULL;

        if (HXR_OK == m_pContext->QueryInterface(IID_IHXPreferences,(void**)&pPreferences))
        {
            if (pPreferences->ReadPref("UseWinDraw", pBuffer) == HXR_OK)
            {
                BOOL bUseWindraw = ::atoi((char*) pBuffer->GetBuffer()) == 1;

                if (bUseWindraw)
                    m_pRootSurface->_EnableHardwareAcceleration();
                else
                    m_pRootSurface->_DisableHardwareAcceleration();

                HX_RELEASE(pBuffer);
            }

            HX_RELEASE(pPreferences);
        }
    }

    LISTPOSITION pos = m_ChildrenInZOrder.GetHeadPosition();
    while(pos)
    {
        CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
        pSite->SetRootSurface(pSurface);
    }
}

void CHXBaseSite::CheckColorSettings()
{
// NOTE 40 steps of granularity for color control parameters (based on
// below float to int precision; proper rounding is not essential)

    if (m_pParentSite)
    {
        m_pParentSite->CheckColorSettings();
        return;
    }

    float fCurrentBrightness;
    float fCurrentContrast;
    float fCurrentSaturation;
    float fCurrentHue;

    zm_pColorAcc->GetColorAdjustments(&fCurrentBrightness, &fCurrentContrast, &fCurrentSaturation, &fCurrentHue);

    if( (int)(fCurrentBrightness * 20.f) != (int)(m_fBrightness * 20.f) ||
        (int)(fCurrentContrast * 20.f) != (int)(m_fContrast * 20.f) ||
        (int)(fCurrentSaturation * 20.f) != (int)(m_fSaturation * 20.f) ||
        (int)(fCurrentHue * 20.f) != (int)(m_fHue * 20.f) )
    {
        // Adjust colors according to video control settings
        zm_pColorAcc->SetColorAdjustments(m_fBrightness,
                                          m_fContrast, m_fSaturation, m_fHue);
    }


    float   fCurrentSharpness;
    INT16   bInterpolate;

    zm_pColorAcc->GetSharpnessAdjustments(&fCurrentSharpness, &bInterpolate);

    if (fCurrentSharpness != m_fSharpness)
    {
        zm_pColorAcc->SetSharpnessAdjustments(m_fSharpness, FALSE);
    }
}

BOOL CHXBaseSite::SharpenImage(HXBitmapInfoHeader* pOptimizedFormat, UCHAR* pImageBits, REF(HXxRect) rSrcRect)
{
    if (m_pParentSite)
    {
        return m_pParentSite->SharpenImage(pOptimizedFormat, pImageBits, rSrcRect);
    }

    BOOL bDidSharpen = FALSE;

    if( zm_pColorAcc &&
        (m_fSharpness+1.0)>0.1 &&
        IsYUVPlanar(GETBITMAPCOLOR(pOptimizedFormat)) )
    {
        INT32 nSrcWidth = rSrcRect.right - rSrcRect.left;
        INT32 nSrcHeight = rSrcRect.bottom - rSrcRect.top;

        bDidSharpen = TRUE;

        INT32   ulSrcPitch = GETBITMAPPITCH(pOptimizedFormat);
        INT32   ulYOffset  = rSrcRect.top * ulSrcPitch + rSrcRect.left;
        UCHAR*  ySrc       = pImageBits + ulYOffset;

        //do edge enhancement if it is not already done once
        if(ySrc[0] != 1)
        {
            if(m_bModeSharpness)
            {
                //Deblocking filter is ON
                zm_pColorAcc->EnhanceUniform(ySrc,nSrcHeight,
                                             nSrcWidth,ulSrcPitch,m_fSharpness);
            }
            else
            {
                //Deblocking filter is OFF
                zm_pColorAcc->Enhance(ySrc,nSrcHeight,
                                      nSrcWidth,ulSrcPitch,m_fSharpness);
            }
        }
        else
        {
            //replicate pixel
            ySrc[0]=ySrc[1];
        }
    }

    return bDidSharpen;
}

void CHXBaseSite::SiteMoving(INT32 x, INT32 y)
{
#if 1
    m_bMoving = TRUE;
    m_pVideoSurface->UpdateDestRect(x,y);
#else

    //GDI mode is *way* too expensive if we have alphablended ARGB
    //content ontop of it. It just kills the whole system.  So, we
    //will stay in overlay mode in those cases.
    if( !m_pVideoSurface->m_bYUVBlending )
    {
        if( !m_pVideoSurface->ForceGDIMode(TRUE))
            m_pVideoSurface->UpdateDestRect(x,y);
    }
    else
    {
        m_pVideoSurface->UpdateDestRect(x,y);
    }
#endif


    LISTPOSITION pos = m_ChildrenInZOrder.GetHeadPosition();
    while(pos)
    {
        CHXBaseSite* pChildSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
        pChildSite->SiteMoving(x,y);
    }
    if( this == m_pTopLevelSite )
    {
        FillColorKey();
        ScheduleCallback( REDRAW_ALL, 0 );
    }
}

void
CHXBaseSite::ResetOrigin()
{
    m_topleft.x =0;
    m_topleft.y =0;
    GetAbsoluteCords(m_topleft);


    LISTPOSITION pos = m_ChildrenInZOrder.GetHeadPosition();
    while(pos)
    {
        CHXBaseSite* pChildSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
        pChildSite->ResetOrigin();
    }
}

void
CHXBaseSite::GetAbsoluteCords(REF(HXxPoint) point)
{
    point.x += m_position.x;
    point.y += m_position.y;

    if (m_pParentSite)
    {
        m_pParentSite->GetAbsoluteCords(point);
    }
    return;
}

void
CHXBaseSite::AboutToBlt()
{
    if (m_pTopLevelSite != this)
    {
        m_pTopLevelSite->AboutToBlt();
        return;
    }

    if (m_bAboutToBlt)
    {
        return;
    }

    m_bAboutToBlt = TRUE;

    if (m_bRecomputeClipScheduled)
    {
        if (m_CallbackHandle)
        {
            m_pScheduler->Remove(m_CallbackHandle);
            m_CallbackHandle = 0;
        }
        Func();
    }
    m_bAboutToBlt = FALSE;
}

void
CHXBaseSite::FillColorKey()
{
    m_pVideoSurface->FillColorKey();

    LISTPOSITION pos = m_ChildrenInZOrder.GetHeadPosition();
    while(pos)
    {
        CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
        pSite->FillColorKey();
    }
}

BOOL
CHXBaseSite::SafeMoveWindow(void* hWnd, INT32 X, INT32 Y, INT32 nWidth, INT32 nHeight, BOOL bRepaint)
{
    if (_AtSystemTime())
    {
        m_pTopLevelSite->ExecutePendingTasks();
        return _MoveWindow(hWnd, X, Y, nWidth, nHeight, bRepaint);
    }

    PendingTask* pPendingTask = new PendingTask(ONMOVEWINDOW, this, (void*) hWnd, (void*) X, (void*) Y, (void*) nWidth, (void*) nHeight, (void*) bRepaint);
    m_pTopLevelSite->m_PendingTaskList.AddTail((void*) pPendingTask);
    m_pTopLevelSite->ScheduleCallback(MOUSE, 0);

    return TRUE;
}

BOOL
CHXBaseSite::SafeUpdateWindow(void* hWnd)
{
    if (_AtSystemTime())
    {
        m_pTopLevelSite->ExecutePendingTasks();
        return _UpdateWindow(hWnd);
    }

    PendingTask* pPendingTask = new PendingTask(ONUPDATEWINDOW, this, (void*) hWnd);
    m_pTopLevelSite->m_PendingTaskList.AddTail((void*) pPendingTask);
    m_pTopLevelSite->ScheduleCallback(MOUSE, 0);

    return TRUE;
}

BOOL CHXBaseSite::SafeShowWindow(void* hWnd, INT32 nCmdShow)
{
    if (_AtSystemTime())
    {
        m_pTopLevelSite->ExecutePendingTasks();
        return _ShowWindow(hWnd, nCmdShow);
    }

    PendingTask* pPendingTask = new PendingTask(ONSHOWWINDOW, this, (void*) hWnd, (void*) nCmdShow);
    m_pTopLevelSite->m_PendingTaskList.AddTail((void*) pPendingTask);
    m_pTopLevelSite->ScheduleCallback(MOUSE, 0);

    return TRUE;
}

BOOL CHXBaseSite::SafeSetWindowPos(void* hWnd, void* hWndInsertAfter, INT32 X, INT32 Y, INT32 cx, INT32 cy, UINT uFlags)
{
    if (_AtSystemTime())
    {
        m_pTopLevelSite->ExecutePendingTasks();

        BOOL ret = _SetWindowPos(hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
        return    ret;
    }

    PendingTask* pPendingTask = new PendingTask(ONSETWINDOWPOS, this, (void*) hWnd, (void*) hWndInsertAfter, (void*) X, (void*) Y, (void*) cx, (void*) cy, (void*) uFlags);
    m_pTopLevelSite->m_PendingTaskList.AddTail((void*) pPendingTask);
    m_pTopLevelSite->ScheduleCallback(MOUSE, 0);

    return TRUE;
}

INT32 CHXBaseSite::SafeSetWindowRgn(void* hWnd, HXREGION* hRgn, BOOL bRedraw)
{
    if (_AtSystemTime())
    {
        m_pTopLevelSite->ExecutePendingTasks();
        return _SetWindowRgn(hWnd, hRgn, bRedraw);
    }

    // create a temp region
    HXREGION*      hTemp           = NULL;

    hTemp = HXCreateRectRegion(0,0,0,0);
    HXUnionRegion(hTemp, hRgn, hTemp);

    PendingTask* pPendingTask = new PendingTask(ONSETWINDOWREGION, this, (void*) hWnd, (void*) hTemp, (void*) bRedraw);
    m_pTopLevelSite->m_PendingTaskList.AddTail((void*) pPendingTask);
    m_pTopLevelSite->ScheduleCallback(MOUSE, 0);

    return 1;
}

void CHXBaseSite::SafeSetXSliderRange(INT32 range)
{
    if (_AtSystemTime())
    {
        m_pTopLevelSite->ExecutePendingTasks();
        SetXSliderRange(range);
        return;
    }

    PendingTask* pPendingTask = new PendingTask(ONSETXSLIDER, this, (void*) range);
    m_pTopLevelSite->m_PendingTaskList.AddTail((void*) pPendingTask);
    m_pTopLevelSite->ScheduleCallback(MOUSE, 0);
}

void CHXBaseSite::SafeSetYSliderRange(INT32 range)
{
    if (_AtSystemTime())
    {
        m_pTopLevelSite->ExecutePendingTasks();
        SetYSliderRange(range);
        return;
    }

    PendingTask* pPendingTask = new PendingTask(ONSETYSLIDER, this, (void*) range);
    m_pTopLevelSite->m_PendingTaskList.AddTail((void*) pPendingTask);
    m_pTopLevelSite->ScheduleCallback(MOUSE, 0);
}

void CHXBaseSite::SafeSetFocus(HXxWindow* pWindow)
{
    if (_AtSystemTime())
    {
        m_pTopLevelSite->ExecutePendingTasks();
        _SetFocus(pWindow->window);
        return;
    }

    PendingTask* pPendingTask = new PendingTask(ONSETFOCUS, this, (void*) pWindow);
    m_pTopLevelSite->m_PendingTaskList.AddTail((void*) pPendingTask);
    m_pTopLevelSite->ScheduleCallback(MOUSE, 0);
}

void
CHXBaseSite::ExecutePendingTasks()
{
    if (_AtSystemTime())
    {
        while(m_PendingTaskList.GetCount())
        {
            PendingTask* pPendingTask = (PendingTask*) m_PendingTaskList.RemoveHead();
            switch(pPendingTask->m_TaskType)
            {
               case ONMOVEWINDOW:
                   _MoveWindow(pPendingTask->m_ulArg1, (int) pPendingTask->m_ulArg2, (int) pPendingTask->m_ulArg3, (int) pPendingTask->m_ulArg4, (int) pPendingTask->m_ulArg5, (BOOL) (int) pPendingTask->m_ulArg6);
                   break;
               case ONUPDATEWINDOW:
                   _UpdateWindow(pPendingTask->m_ulArg1);
                   break;
               case ONSHOWWINDOW:
                   _ShowWindow(pPendingTask->m_ulArg1, (int) pPendingTask->m_ulArg2);
                   break;
               case ONSETWINDOWPOS:
                   _SetWindowPos(pPendingTask->m_ulArg1, pPendingTask->m_ulArg2, (int) pPendingTask->m_ulArg3, (int) pPendingTask->m_ulArg4, (int) pPendingTask->m_ulArg5, (int) pPendingTask->m_ulArg6, (UINT) pPendingTask->m_ulArg7);
                   break;
               case ONSETWINDOWREGION:
                   _SetWindowRgn( pPendingTask->m_ulArg1, (HXREGION*)pPendingTask->m_ulArg2, (BOOL) pPendingTask->m_ulArg3);
                   HXDestroyRegion((HXREGION*)pPendingTask->m_ulArg2);
                   break;
               case ONSETXSLIDER:
                   pPendingTask->m_pThis->SetXSliderRange((int)pPendingTask->m_ulArg1);
                   break;
               case ONSETYSLIDER:
                   pPendingTask->m_pThis->SetYSliderRange((int)pPendingTask->m_ulArg1);
                   break;
               case ONSETFOCUS:
                   pPendingTask->m_pThis->_SetFocus( pPendingTask->m_ulArg1);
                   break;
               case ONSETSIZE:
                   HXxSize size;
                   size.cx = (long)pPendingTask->m_ulArg1;
                   size.cy = (long)pPendingTask->m_ulArg2;
                   pPendingTask->m_pThis->_SafeSetSize(size);
                   break;
               case ONSETPOSITION:
                   HXxPoint position;
                   position.x = (long)pPendingTask->m_ulArg1;
                   position.y = (long)pPendingTask->m_ulArg2;
                   pPendingTask->m_pThis->_SafeSetPosition(position);
                   break;
               default:
                   HX_ASSERT(FALSE);
                   break;
            }

            HX_DELETE(pPendingTask);
        }
    }
}

void
CHXBaseSite::RemovePendingTasks(CHXBaseSite* pThis)
{
    LISTPOSITION pPos;

    pPos = m_PendingTaskList.GetHeadPosition();

    while(pPos)
    {

        PendingTask* pPendingTask = (PendingTask*) m_PendingTaskList.GetAt(pPos);
        if (pPendingTask->m_pThis == pThis)
        {
            pPos = m_PendingTaskList.RemoveAt(pPos);
            HX_DELETE(pPendingTask);
        }
        else
        {
            m_PendingTaskList.GetNext(pPos);
        }
    }
}

void CHXBaseSite::ResetUpdateOverlay()
{
    if (m_pVideoSurface)
    {
        m_pVideoSurface->ResetUpdateOverlay();
    }

    LISTPOSITION pos = m_ChildrenInZOrder.GetHeadPosition();
    while(pos)
    {
        CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
        pSite->ResetUpdateOverlay();
    }
}

HXREGION* CHXBaseSite::Transition(INT32 left, INT32 top, INT32 right, INT32 bottom, tranLines* lines)
{
    INT32   completeness = m_nTransitionState;

    if (lines)
        lines->Destroy();

    // if this is a default transition we don't ever want to invert it!
    if (m_fpTransitionEffect == DefaultTransition ||
        m_fpTransitionEffect == SlideFromLeft ||
        m_fpTransitionEffect == SlideFromBottom ||
        m_fpTransitionEffect == SlideFromRight ||
        m_fpTransitionEffect == SlideFromTop ||
        m_fpTransitionEffect == Crossfade ||
        m_fpTransitionEffect == FadeFromColor ||
        m_fpTransitionEffect == FadeToColor
        )
    {
        return m_fpTransitionEffect(left, top, right, bottom, completeness, NULL);
    }

    tranLines* tmpLines = (completeness > 0 && completeness < 1000) ? lines : NULL;

    HXREGION* retRGN = HXCreateRegion();
    double vSize = double(bottom - top) / double(m_nTransitionVertRepeat);
    double hSize = double(right - left) / double(m_nTransitionHorzRepeat);

    if (m_bTransitionReversed)
        completeness = 1000 - m_nTransitionState;

    for (int h = 0; h < m_nTransitionHorzRepeat; ++h)
    {
        for (int v = 0; v < m_nTransitionVertRepeat; ++v)
        {
            INT32 l = left + int(hSize * h);
            INT32 t = top + int(vSize * v);
            HXREGION* tmpRgn = m_fpTransitionEffect(l, t, int(l + hSize), int(t + vSize), completeness, tmpLines);
            HXCombineRgn( retRGN, retRGN, tmpRgn, HX_RGN_OR);
            HXDestroyRegion(tmpRgn);
        }
    }

    if (tmpLines)
        tmpLines->Clip(left, top, right - 1, bottom - 1);

    if (!(m_bTransitionTranIn ^ m_bTransitionReversed))
        retRGN = InvertRGN(retRGN, left, top, right, bottom);

    //Intersect with our rect.
    HXREGION* pMe = HXCreateRectRegion( m_topleft.x,
                                        m_topleft.y,
                                        m_size.cx,
                                        m_size.cy
                                        );
    HXIntersectRegion( retRGN, pMe, retRGN );
    HXDestroyRegion( pMe );


    return retRGN;
}

//Incoming coords are OS Winow relative....
void CHXBaseSite::_RecursiveDamageRect( HXxRect* dirtyRect, BOOL bForce )
{
    HXxRect rect = {0, 0, 0, 0};
    HXREGION* pReg = HXCreateRectRegion( dirtyRect->left,
                                         dirtyRect->top,
                                         dirtyRect->right-dirtyRect->left,
                                         dirtyRect->bottom-dirtyRect->top
                                         );

    //Find out what part intersects us.
    HXREGION* pTemp     = HXCreateRegion();
    HXxPoint*  pPosition = GetOrigin();
    if( m_Region && !bForce )
    {
        HXIntersectRegion( m_Region, pReg, pTemp );
    }
    else
    {
        HXZeroOutRegion( pTemp );
        HXUnionRegion( pTemp, pReg, pTemp );
    }

    if( !HXEmptyRegion(pTemp) )
    {
        HXUnionRegion(m_pDirtyRegion, pTemp, m_pDirtyRegion );

        //We must now verify our dirty region does not fall outside of our
        //real boundries. If the site is animated it can move in such a
        //way that we will get negative offsets once we turn the region to
        //site relative coordinates in the HX_SURFACE_UPDATE2 message.
        HXDestroyRegion( pTemp );
        pTemp  = Transition( pPosition->x, pPosition->y,
                             pPosition->x + m_size.cx,
                             pPosition->y + m_size.cy
                             );
        HXIntersectRegion( pTemp, m_pDirtyRegion, m_pDirtyRegion );
    }


    HXDestroyRegion( pTemp );
    HXDestroyRegion( pReg );

    CHXSimpleList::Iterator it = m_ChildrenInZOrder.Begin();
    while( it != m_ChildrenInZOrder.End() )
    {
        CHXBaseSite* pSite = (CHXBaseSite*)*it;
        if( pSite )
            pSite->_RecursiveDamageRect(dirtyRect, bForce);
        ++it;
    }
}
//Incoming coords are OS Winow relative....
void CHXBaseSite::ManageExposeEvents( HXxRect* dirtyRect )
{
    //We may not be the toplevel site if there is a windowed renderer
    //being used.

    _RecursiveDamageRect(dirtyRect);
    ResetUpdateOverlay();
    FillColorKey();
    m_pTopLevelSite->_ForceRedrawAll();
}

void CHXBaseSite::InternalForceRedraw()
{
    m_bSiteRefresh = TRUE;
    ForceRedraw();
    m_bSiteRefresh = FALSE;
}

////////////////////////////////////////////////
//
//    basesite callback
//
////////////////////////////////////////////////
BaseSiteCallback::BaseSiteCallback(CHXBaseSite* pSite) :
    m_lRefCount (0)
                                                       ,m_pSite(pSite)
{
}

BaseSiteCallback::~BaseSiteCallback()
{
}

STDMETHODIMP BaseSiteCallback::QueryInterface(REFIID riid, void** ppvObj)
{
    if (IsEqualIID(riid, IID_IHXCallback))
    {
        AddRef();
        *ppvObj = (IHXCallback*)this;
        return HXR_OK;
    }
    else if (IsEqualIID(riid, IID_IUnknown))
    {
        AddRef();
        *ppvObj = this;
        return HXR_OK;
    }

    *ppvObj = NULL;
    return HXR_NOINTERFACE;
}

STDMETHODIMP_(ULONG32) BaseSiteCallback::AddRef()
{
    return m_pSite->AddRef();
}

STDMETHODIMP_(ULONG32) BaseSiteCallback::Release()
{
    return m_pSite->Release();
}


STDMETHODIMP BaseSiteCallback::Func(void)
{
    if(m_pSite)
    {
        m_pSite->Func();
    }
    return HXR_OK;
}

ScrollSiteCallback::ScrollSiteCallback(CHXBaseSite* pSite) :
    m_lRefCount (0)
    ,m_pSite(pSite)
{
}

ScrollSiteCallback::~ScrollSiteCallback()
{
}

STDMETHODIMP ScrollSiteCallback::QueryInterface(REFIID riid, void** ppvObj)
{
    if (IsEqualIID(riid, IID_IHXCallback))
    {
        AddRef();
        *ppvObj = (IHXCallback*)this;
        return HXR_OK;
    }
    else if (IsEqualIID(riid, IID_IUnknown))
    {
        AddRef();
        *ppvObj = this;
        return HXR_OK;
    }

    *ppvObj = NULL;
    return HXR_NOINTERFACE;
}

STDMETHODIMP_(ULONG32) ScrollSiteCallback::AddRef()
{
    return m_pSite->AddRef();
}

STDMETHODIMP_(ULONG32) ScrollSiteCallback::Release()
{
    return m_pSite->Release();
}

STDMETHODIMP ScrollSiteCallback::Func(void)
{
    if(m_pSite)
    {
        m_pSite->FuncSizeSliders();
    }
    return HXR_OK;
}

STDMETHODIMP CHXBaseSite::LockComposition()
{
    if(m_pParentSite)
    {
        return m_pParentSite->LockComposition();
    }

    if( !m_bCompositionMode )
        return HXR_FAIL;

    m_bCompositionLocked = TRUE;
    return HXR_OK;
}

STDMETHODIMP CHXBaseSite::SetCompositionMode(BOOL OnOrOff )
{
    if(m_pParentSite)
    {
        return m_pParentSite->SetCompositionMode(OnOrOff);
    }

    m_bCompositionMode = OnOrOff;
    return HXR_OK;
}


STDMETHODIMP CHXBaseSite::UnlockComposition()
{
    HX_RESULT ret = HXR_OK;
    _TLSLock();

    if( m_pParentSite)
    {
        ret = m_pParentSite->UnlockComposition();
        _TLSUnlock();
        return ret;
    }

    if( !m_bCompositionMode )
    {
        _TLSUnlock();
        return HXR_FAIL;
    }

    m_bCompositionLocked = FALSE;

    //Do a recompute clip and redraw all.
    HX_ASSERT( m_pParentSite==NULL);
    HX_ASSERT( this == m_pTopLevelSite );
    m_bDisableForceRedraw = TRUE;
    RecomputeClip();
    m_bDisableForceRedraw = FALSE;
    _ForceRedrawAll();
    m_bCalledComputeClipFromTransition = FALSE;
    FillColorKey();

    _TLSUnlock();
    return HXR_OK;
}

STDMETHODIMP CHXBaseSite::BltComposition()
{
    HX_RESULT ret = HXR_OK;
    _TLSLock();

    if( m_pParentSite)
    {
        ret = m_pParentSite->BltComposition();
        _TLSUnlock();
        return ret;
    }

    //Tell the root surface to blt itself.
#if defined(_TEST_COMPOSITION)
 {
     char szBuff[256]; /* Flawfinder: ignore */
     sprintf( szBuff,"tick count: %lu\n", HX_GET_TICKCOUNT()); /* Flawfinder: ignore */
     _DumpString(szBuff);
 }
#endif
    if( m_pRootSurface )
        m_pRootSurface->BltComposition();

    _TLSUnlock();
    return HXR_OK;
}

STDMETHODIMP_(BOOL) CHXBaseSite::IsCompositionLocked()
{
    if( m_pParentSite)
    {
        return m_pParentSite->IsCompositionLocked();
    }

    return m_bCompositionLocked && m_bCompositionMode;
}

STDMETHODIMP_(BOOL) CHXBaseSite::IsCompositionMode()
{
    if( m_pParentSite)
    {
        return m_pParentSite->IsCompositionMode();
    }

    return m_bCompositionMode;
}


void CHXBaseSite::_TLSLock()
{
    if( m_pTopLevelSite)
    {
        if( this != m_pTopLevelSite )
            m_pTopLevelSite->_TLSLock();
        else
        {
            m_pMutex->Lock();

            InterlockedIncrement(&m_nTLSMutexLockCount);
            m_ulTLSMutexOwningThread = m_pDummyThread->GetCurrentThreadID();
        }
    }
}

void CHXBaseSite::_TLSUnlock()
{
    if( m_pTopLevelSite)
    {
        if( this != m_pTopLevelSite )
            m_pTopLevelSite->_TLSUnlock();
        else
        {
            HX_ASSERT(m_nTLSMutexLockCount>0);

            m_pMutex->Unlock();
            InterlockedDecrement(&m_nTLSMutexLockCount);
        }
    }
}


BOOL CHXBaseSite::_TLSIsLocked()
{
    if( m_pTopLevelSite)
    {
        if( this != m_pTopLevelSite )
            return m_pTopLevelSite->_TLSIsLocked();
        else
        {
            HX_ASSERT( m_nTLSMutexLockCount >=0 );

            return (m_ulTLSMutexOwningThread!=m_pDummyThread->GetCurrentThreadID() &&
                    m_nTLSMutexLockCount>0);
        }
    }
    HX_ASSERT("oops"==NULL);
    return FALSE;
}

HX_RESULT CHXBaseSite::SendSubRectMessages(BOOL bRet)
{
    if( m_pVideoSurface && IsYUV(GETBITMAPCOLOR( &m_pVideoSurface->m_bmiLastBlt)) )
    {
        m_bUserWantsSubRects = FALSE;
        return HXR_FAIL;
    }

    m_bUserWantsSubRects = bRet;
    m_bSiteScalingInfo   = TRUE;

    return HXR_OK;
}

//These are in SITE relative coords.
HX_RESULT CHXBaseSite::SubRectDamageRegion( HXxBoxRegion* pRegion )
{
    HXxRect rectTmp;

    if( !pRegion )
        return HXR_OK;

    HX_ASSERT( pRegion->rects );

    //Add each rect to our damage region.
    for( int i=0 ; i<pRegion->numRects ; i++ )
    {
        rectTmp.left   = pRegion->rects[i].x1;
        rectTmp.top    = pRegion->rects[i].y1;
        rectTmp.right  = pRegion->rects[i].x2;
        rectTmp.bottom = pRegion->rects[i].y2;
        DamageRect( rectTmp );
    }
    return HXR_OK;
}



///////////////////////
// DEBUG METHODS
///////////////////////
void CHXBaseSite::DisplaySiteData(const char *pszLeadIn)
{
#ifdef _DEBUG
    IHXBuffer* pBuf= NULL;
    char szBuff[256]; /* Flawfinder: ignore */
    if( m_pValues )
    {
        m_pValues->GetPropertyCString( "channel", pBuf );
        if( pBuf )
        {
            sprintf( szBuff, "%s -------------Site %p (%s)--------------\n", pszLeadIn, this, (const char*)(pBuf->GetBuffer())); /* Flawfinder: ignore */
            _DumpString(szBuff);
            HX_RELEASE(pBuf);
        }
        else
        {
            sprintf( szBuff, "%s -------------Site %p --------------\n", pszLeadIn, this); /* Flawfinder: ignore */
            _DumpString(szBuff);
        }
    }
    else
    {
        sprintf( szBuff, "%s -------------Site %p --------------\n", pszLeadIn, this); /* Flawfinder: ignore */
        _DumpString(szBuff);
    }

    INT32 nCID = GETBITMAPCOLOR( &(m_pVideoSurface->m_bmiLastBlt) );

    sprintf( szBuff, "%s Size (%d, %d) zorder: %d  visible: %d BltCID:%d SurfaceCID:%d AlphaChain: %d\n", /* Flawfinder: ignore */
             pszLeadIn, m_size.cx, m_size.cy, m_lZOrder, IsSiteVisible(),
             nCID, m_pVideoSurface->m_nSurfaceCID, _TakesPartInAlphaChain() );
    _DumpString(szBuff);
    sprintf( szBuff, "%s Bounding Rect (parent rel): (%d, %d) - (%d, %d)\n", /* Flawfinder: ignore */
             pszLeadIn, m_position.x, m_position.y,
             m_position.x + m_size.cx, m_position.y+m_size.cy );
    _DumpString(szBuff);
    sprintf( szBuff, "%s Bounding Rect (absolulte ): (%d, %d) - (%d, %d)\n", /* Flawfinder: ignore */
             pszLeadIn, m_topleft.x, m_topleft.y,
             m_topleft.x+m_size.cx, m_topleft.y+m_size.cy);
    _DumpString(szBuff);
    sprintf( szBuff, "%s Window: %p m_pUser: %p EventSensitivity: ", /* Flawfinder: ignore */
             pszLeadIn,
             m_pWindow?m_pWindow->window:0, m_pUser
             );
    _DumpString(szBuff);
    if( m_nEventSensitivity==SENSITIVITY_TRANSPARENT)
        sprintf(szBuff, "TRANSPARENT\n"); /* Flawfinder: ignore */
    else if( m_nEventSensitivity==SENSITIVITY_OPAQUE)
        sprintf(szBuff, "OPAQUE\n"); /* Flawfinder: ignore */
    else if( m_nEventSensitivity==SENSITIVITY_NOT_SET)
        sprintf(szBuff, "NOT_SET\n"); /* Flawfinder: ignore */
    else
        sprintf(szBuff, "%d\n", m_nEventSensitivity); /* Flawfinder: ignore */
    _DumpString(szBuff);

    sprintf( szBuff, "%s Alpha(blend:%d noti: %d) m_bSiteNeverBlts: %d YUVAImageList: %d ImageBlocks: %d\n", /* Flawfinder: ignore */
             pszLeadIn,
             m_AlphaBlendSites.GetCount(),
             m_AlphaBlendNotifiers.GetCount(),
             m_bSiteNeverBlts,
             m_pVideoSurface->m_YUVAImageList.GetCount(),
             m_pVideoSurface->m_imageBlocks.GetCount()
             );
    _DumpString(szBuff);
    CHXMapPtrToPtr::Iterator iter = m_AlphaBlendSites.Begin();
    for ( ; iter != m_AlphaBlendSites.End(); ++iter)
    {
        HXREGION* pTmp = (HXREGION*)*iter;
        CHXBaseSite* pSite = (CHXBaseSite*) iter.get_key();
        sprintf( szBuff, "%s   %p  num rects: %d\n", /* Flawfinder: ignore */
                 pszLeadIn,
                 pSite,
                 pTmp->numRects
                 );
        _DumpString(szBuff);
#if defined(_DUMP_REGION_RECTS) || 1
        for( int i=0 ; i<pTmp->numRects ; i++ )
        {
            sprintf( szBuff, "%s      %d (%d, %d)-(%d, %d)\n", pszLeadIn, i, /* Flawfinder: ignore */
                     pTmp->rects[i].x1,
                     pTmp->rects[i].y1,
                     pTmp->rects[i].x2,
                     pTmp->rects[i].y2
                     );
            _DumpString( szBuff );
        }
#endif
    }



    if( m_fpTransitionEffect != DefaultTransition )
    {
        sprintf( szBuff, "%s Num Sub Rects: Region:%d  RegWC: %d  RegForMouse: %d m_fpTransitionEffect: %p(%d)\n", /* Flawfinder: ignore */
                 pszLeadIn,
                 !m_Region?0:m_Region->numRects,
                 !m_RegionWithoutChildren?0:m_RegionWithoutChildren->numRects,
                 !m_RegionForMouse?0:m_RegionForMouse->numRects,
                 m_fpTransitionEffect,
                 m_nTransitionState
                 );
    }
    else
    {
        sprintf( szBuff, "%s Num Sub Rects: Region:%d  RegWC: %d  RegForMouse: %d m_fpTransitionEffect: DEFAULT\n", /* Flawfinder: ignore */
                 pszLeadIn,
                 !m_Region?0:m_Region->numRects,
                 !m_RegionWithoutChildren?0:m_RegionWithoutChildren->numRects,
                 !m_RegionForMouse?0:m_RegionForMouse->numRects
                 );
    }

    _DumpString(szBuff);

#if defined(_DUMP_REGION_RECTS) || 1
    if( m_Region )
    {

        for( int i=0 ; i<m_Region->numRects ; i++ )
        {
            sprintf( szBuff, "%s   %d (%d, %d)-(%d, %d)\n", pszLeadIn, i, /* Flawfinder: ignore */
                     m_Region->rects[i].x1,
                     m_Region->rects[i].y1,
                     m_Region->rects[i].x2,
                     m_Region->rects[i].y2
                     );
            _DumpString( szBuff );
        }
    }
#endif
#endif /* _DEBUG */
}

void CHXBaseSite::DisplayAllSiteData()
{
#ifdef _DEBUG
    CHXBaseSite* pTopSite = GetTopLevelSite();
    char szBuff[256]; /* Flawfinder: ignore */
    sprintf( szBuff, "************************************************\n" ); /* Flawfinder: ignore */
    _DumpString(szBuff);
    sprintf( szBuff, "TOPLEVEL: Composition Mode: %s  Composition Locked: %s \n", /* Flawfinder: ignore */
             pTopSite->IsCompositionMode()?"TRUE":"FALSE",
             pTopSite->IsCompositionLocked()?"TRUE":"FALSE"
             );
    _DumpString(szBuff);
    sprintf( szBuff, "************************************************\n" ); /* Flawfinder: ignore */
    _DumpString(szBuff);
    pTopSite->DisplayChildSiteData("");
    sprintf( szBuff, "************************************************\n" ); /* Flawfinder: ignore */
    _DumpString(szBuff);
    sprintf( szBuff, "************************************************\n" ); /* Flawfinder: ignore */
    _DumpString(szBuff);

    sprintf( szBuff, "List of YUV Sites\n" ); /* Flawfinder: ignore */
    _DumpString(szBuff);
    CHXSimpleList::Iterator i = zm_YUVSiteList.Begin();
    while( i != zm_YUVSiteList.End() )
    {
        sprintf( szBuff, "%p\n", *i ); /* Flawfinder: ignore */
        _DumpString(szBuff);
        ++i;
    }
#endif /* _DEBUG */
}

void CHXBaseSite::DisplayChildSiteData(const char *pszLeadIn)
{
#ifdef _DEBUG
    DisplaySiteData(pszLeadIn);
    LISTPOSITION pos = m_ChildrenInZOrder.GetHeadPosition();
    int nn=strlen(pszLeadIn)+10;
    char *pszTmp= new char[nn];
    memset(pszTmp, ' ', nn );
    pszTmp[nn-1]='\0';
    while(pos)
    {
        CHXBaseSite* pSite = (CHXBaseSite*)m_ChildrenInZOrder.GetNext(pos);
        pSite->DisplayChildSiteData(pszTmp);
    }
    delete [] pszTmp;
#endif /* _DEBUG */
}

//Verify that we don't add any overlapping alphablend regions...
void CHXBaseSite::VerifyNoDups( CHXMapPtrToPtr& map, HXREGION* reg )
{
#ifdef _DEBUG
    //Loop through and see if reg is already in the map.
    CHXMapPtrToPtr::Iterator iter = map.Begin();
    for ( ; iter != map.End(); ++iter)
    {
        HXREGION* pSiteReg = (HXREGION*)*iter;
        HXREGION* pTmp = HXCreateRegion();
        HXIntersectRegion( pSiteReg, reg, pTmp );
        if( !HXEmptyRegion(pTmp) )
        {
            DisplayAllSiteData();
            HX_ASSERT( "Adding a duplicate region!" );
        }
        HXDestroyRegion(pTmp);
    }
#endif /* _DEBUG */
}

///////////////////////
// DEBUG METHODS END END END
///////////////////////
