/* ***** BEGIN LICENSE BLOCK *****
 * Source last modified: $Id: macsite.cpp,v 1.9.20.3 2004/07/09 01:59:02 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 ***** */

#ifndef _MACINTOSH
#ifndef _MAC_UNIX
#error This is the Macintosh platform specific implementation.
#endif
#endif

#include "hxcom.h"

#include "hxtypes.h"
#include "hxwintyp.h"
#include "hxmap.h"
#include "hxslist.h"
#include "ihxpckts.h"
#include "hxwin.h"
#include "hxengin.h"
#include "hxsite2.h"
#include "chxxtype.h"
#include "hxvctrl.h"
#include "hxvsurf.h"
#include "hxcodec.h"
#include "surface.h"
#include "vidosurf.h"
#include "sitetext.h"
#include "chxpckts.h"
#include "hxevent.h"
#include "bltpatch.h"
#include "hxprefs.h"

#include "hxevent.h"
#include "hxcore.h"

#include "platform/mac/macsite.h"
#include "platform/mac/macsurf.h"
#include "platform/mac/macroot.h"

#ifdef _CARBON
#ifndef _MAC_MACHO
#include <ControlDefinitions.h>
#endif
#endif

#include "platform/mac/hx_moreprocesses.h"

//#include "../dcondev/dcon.h"

#include "basesurf.h"

#include "hxtick.h"
#include "hxvimlog.h"
#include "hxheap.h"
#ifdef _DEBUG
#undef HX_THIS_FILE		
static const char HX_THIS_FILE[] = __FILE__;
#endif

#define SCROLL_BAR_WIDTH 16

CHXSimpleList CHXMacSite::zm_ListOfMacSites;
BOOL CHXMacSite::zm_bFullScreenActive = FALSE;
Ptr CHXMacSite::zm_pRememberFullScreenInformation = nil;

extern "C" void MacSiteHandleAllEvents(HXxEvent* pEvent);



/*
 *
 *	SetOriginAndMaintainClipRgn is designed to replace
 *	SetOrigin(). It will internally call SetOrigin
 *	if necessary, and it will also adjust the clip
 *	region in order to maintain the parts of the
 *	screen that the clip region refers to. This
 *	is necessary because, sadly, SetOrigin() in
 *	the Mac Toolbox does NOT change the values in
 *	the clipRgn so it suddenly refers to a different
 *	part of the screen!
 *
 */
void SetOriginAndMaintainClipRgn(short horizOffset, short vertOffset)
{
    // SetOriginMaintainClip, like SetOrigin(), assumes
    // that the port is set correctly.
    GrafPtr curPort;
    ::GetPort( &curPort );

    Rect portBounds;
    
#if defined(_CARBON) || defined(_MAC_UNIX)
    ::GetPortBounds( curPort, &portBounds );
#else
    portBounds = curPort->portRect;
#endif

    if ( ( horizOffset == portBounds.left ) && ( vertOffset == portBounds.top ) )
    {
	return; // everything is already (presumably) set up correctly.
    }
    
    RgnHandle clipRgn = ::NewRgn();
    
    ::GetClip( clipRgn );
    
    Rect clipRgnBounds;
#if defined(_CARBON) || defined(_MAC_UNIX)
    ::GetRegionBounds(clipRgn, &clipRgnBounds);
#else
    clipRgnBounds = (**clipRgn).rgnBBox;
#endif
    
    // if the clip region goes too close to -32768 or 32767, we run the
    // risk of rolling over those values when we do an OffsetRgn(). Sadly,
    // OffsetRgn does NOT internally check for rollovers, but blithely
    // slams those rolled-over values into the region, resulting in a
    // meaningless region. To avoid that we're trimming the region to
    // noticeable values. (i.e. if we see regions with a width or height
    // of 44444, we can use that as a magic cookie type signature.)
    if (clipRgnBounds.left < -25252
	|| clipRgnBounds.top < -25252
	|| clipRgnBounds.right > 25252
	|| clipRgnBounds.bottom > 25252
	)
    {
	RgnHandle soonToBeSectedRgnCopy = ::NewRgn();
	::SetRectRgn( soonToBeSectedRgnCopy, -22222, -22222, 22222, 22222 );

	::SectRgn( clipRgn, soonToBeSectedRgnCopy, clipRgn );

	::DisposeRgn( soonToBeSectedRgnCopy );
    }
    ::OffsetRgn( clipRgn, horizOffset - portBounds.left, vertOffset - portBounds.top );
    
    ::SetOrigin( horizOffset, vertOffset );
    ::SetClip( clipRgn );
    ::DisposeRgn( clipRgn );
}



/************************************************************************
 *  Method:
 *    CHXMacSite constructor
 */
CHXMacSite::CHXMacSite(IUnknown* pContext, IUnknown* pUnkOuter, INT32 lZOrder)
  : CHXBaseSite(pContext, pUnkOuter, lZOrder)
  , m_hHScrollBar(NULL)
  , m_hVScrollBar(NULL)
  , m_ScrollBarActionProc(NULL)
  , m_nHorizPageSize(1)
  , m_nVertPageSize(1)
  , m_bCreatedOSWindow(FALSE)
  , m_pHXxFullScreenWindow(NULL)
  , m_fStretchMultiple(0.0)
  , m_RememberMacPort(nil)
  , m_bInternalResizeOnFullscreen(TRUE)
  , m_pMacSiteRedrawCallback(NULL)
#ifdef THREADS_SUPPORTED

#ifdef USE_CARBON_TIMER
#ifdef _MAC_MACHO
  , m_RedrawCFTimerRef(NULL)
#else
  , m_RedrawCarbonTimerRef(NULL)
  , m_RedrawCarbonTimerUPP(NULL)
#endif
#endif

  , m_pIHXCoreMutex(NULL)
  , m_pClientEngine(NULL)
#endif
{
    m_MostRecentConvertedMouseLoc.x = 0;
    m_MostRecentConvertedMouseLoc.y = 0;
    
    m_RememberNonFullscreenSize.cx = 0;
    m_RememberNonFullscreenSize.cy = 0;
    m_RememberNonFullscreenPosition.x = 0;
    m_RememberNonFullscreenPosition.y = 0;
    
    IHXPreferences* pPreferences = NULL;
    IHXBuffer* pBuffer = NULL;
    
    if (HXR_OK == m_pContext->QueryInterface(IID_IHXPreferences, (void**)&pPreferences))
    {
	if (pPreferences->ReadPref("MacFullscreenInternalResize", pBuffer) == HXR_OK)
	{
	    m_bInternalResizeOnFullscreen = ::atoi((char*)pBuffer->GetBuffer()) == 1;
	    HX_RELEASE(pBuffer);
	}
	HX_RELEASE(pPreferences);
    }
    
    zm_ListOfMacSites.AddTail(this);
    
    m_pMacSiteRedrawCallback = new MacSiteRedrawCallback(this);
    m_pMacSiteRedrawCallback->AddRef();

#ifdef THREADS_SUPPORTED
    // xxxzach - TEMP - installing the event loop timer when running in the embedded player
    //			results in a crash when loading a 2nd page. 
    //		  	appears to call the timer proc after ~CHXMacSite has been called
    //			so don't install timer if running as embedded player
    const OSType kPlayerSignature = 'PNst';
#ifdef USE_CARBON_TIMER
#ifdef _MAC_MACHO
    memset(&m_RedrawCFTimerContext, 0, sizeof(CFRunLoopTimerContext));
    
    m_RedrawCFTimerContext.info = (void*)this; // info is what's passed into the timer function
    
    m_RedrawCFTimerRef = ::CFRunLoopTimerCreate(
                kCFAllocatorDefault,
                ::CFAbsoluteTimeGetCurrent() + 31536000.0, // a year from now
                31536000.0, // every year
                0, //CFOptionFlags
                0, //CFIndexOrder
                CHXMacSite::RedrawCFTimer,
                &m_RedrawCFTimerContext);
    
    ::CFRunLoopAddTimer(
                ::CFRunLoopGetCurrent(),
                m_RedrawCFTimerRef,
                kCFRunLoopCommonModes
                );
#else
    m_RedrawCarbonTimerUPP = ::NewEventLoopTimerUPP(
		(EventLoopTimerProcPtr)CHXMacSite::RedrawCarbonTimer);

    OSStatus osStatus = ::InstallEventLoopTimer(
		GetMainEventLoop(), kEventDurationForever, kEventDurationForever,
		m_RedrawCarbonTimerUPP, this, &m_RedrawCarbonTimerRef);
    HX_ASSERT(osStatus == noErr);
#endif
#endif
	    
    m_pContext->QueryInterface(IID_IHXCoreMutex, (void**)&m_pIHXCoreMutex);
    HX_ASSERT(m_pIHXCoreMutex);
    
    m_pContext->QueryInterface(IID_IHXClientEngine, (void**)&m_pClientEngine);
#endif
}

/************************************************************************
 *  Method:
 *    CHXMacSite destructor
 */
CHXMacSite::~CHXMacSite()
{
#ifdef THREADS_SUPPORTED
    HX_RELEASE(m_pIHXCoreMutex);
    HX_RELEASE(m_pClientEngine);
    
#ifdef USE_CARBON_TIMER
#ifdef _MAC_MACHO
    ::CFRunLoopRemoveTimer(
                ::CFRunLoopGetCurrent(),
                m_RedrawCFTimerRef,
                kCFRunLoopCommonModes
                );
    
    m_RedrawCFTimerRef = NULL;
    memset(&m_RedrawCFTimerContext, 0, sizeof(CFRunLoopTimerContext));
#else
    ::RemoveEventLoopTimer(m_RedrawCarbonTimerRef);
    m_RedrawCarbonTimerRef = NULL;

    ::DisposeEventLoopTimerUPP(m_RedrawCarbonTimerUPP);
    m_RedrawCarbonTimerUPP = NULL;
#endif
#endif

#endif
    _DestroySliders();
    
    if (m_pMacSiteRedrawCallback &&
	m_pMacSiteRedrawCallback->m_ulMacSiteRedrawCallbackPendingID &&
	m_pScheduler)
    {
	m_pScheduler->Remove(m_pMacSiteRedrawCallback->m_ulMacSiteRedrawCallbackPendingID);
	m_pMacSiteRedrawCallback->m_ulMacSiteRedrawCallbackPendingID = 0;
    }
    HX_RELEASE(m_pMacSiteRedrawCallback);
    
    LISTPOSITION pos = zm_ListOfMacSites.Find(this);
    zm_ListOfMacSites.RemoveAt(pos);
}

/************************************************************************
 *  Method:
 *    CHXMacSite::GetWindow
 */
STDMETHODIMP_(HXxWindow*) CHXMacSite::GetWindow() 
{
    if (zm_bFullScreenActive)
    {
	if (m_pHXxFullScreenWindow) return m_pHXxFullScreenWindow;
	if (m_pParentSite) return m_pParentSite->GetWindow();
	
	HX_ASSERT(!"shouldn't get here");
    }
    return CHXBaseSite::GetWindow();


    if (zm_bFullScreenActive && m_pHXxFullScreenWindow) return m_pHXxFullScreenWindow;
    
return m_pWindow;
    return CHXBaseSite::GetWindow();
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_NeedWindowedSite
 */
void
CHXMacSite::_NeedWindowedSite()
{
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_AttachWindow
 */
void
CHXMacSite::_AttachWindow()
{
    m_pHXxFullScreenWindow = new HXxWindow;
    if (m_pTopLevelSite == this)
    {
	Rect r = {0,0,0,0};
	m_pHXxFullScreenWindow->window = ::NewCWindow(nil, &r, "\p", false, plainDBox, nil, false, 0);
	
	// if we created the mac window we need to update the HXxWindow parameters
	// so we're not clipped out later
	if (m_bCreatedOSWindow)
	{
	    HX_ASSERT(m_pWindow);
	    
	    WindowPtr w = (WindowPtr)m_pWindow->window;
	    
	    HX_ASSERT(w);
	    
	    m_pWindow->x = 0;
	    m_pWindow->y = 0;
	    
	    Rect bounds;
	    ::GetPortBounds(::GetWindowPort(w), &bounds);
	    
	    m_pWindow->width = bounds.right-bounds.left;
	    m_pWindow->height = bounds.bottom-bounds.top;
	    
	    m_pWindow->clipRect.left = 0;
	    m_pWindow->clipRect.top = 0;
	    m_pWindow->clipRect.right = m_pWindow->width;
	    m_pWindow->clipRect.bottom = m_pWindow->height;
	}
    }
    else
    {
	CHXMacSite* pMacParentSite = (CHXMacSite*)m_pParentSite; // XXXbobclark Ewwww! (Can we use RTTI ya think?)
	m_pHXxFullScreenWindow->window = pMacParentSite->m_pHXxFullScreenWindow->window;
    }
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_DetachWindow
 */
void
CHXMacSite::_DetachWindow()
{
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_Create
 */
void*
CHXMacSite::_Create(void* ParentWindow, UINT32 style)
{
    if (!ParentWindow)
    {
	Rect r = {200,400,40,40};
	WindowPtr w = ::NewCWindow(nil, &r, "\p", true, documentProc, (WindowPtr)-1L, false, 0);
	
	if (w)
	{
	    m_bCreatedOSWindow = TRUE;
	    return w;
	}
    }
    
    m_bCreatedOSWindow = FALSE;
    return ParentWindow;
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_Destroy
 */
void
CHXMacSite::_Destroy(HXxWindow* pWindow)
{
    if (CMacSurface::zm_pOverlaySurface == (CMacSurface*)m_pVideoSurface)
    {
	CMacSurface::CleanUpOverlay();
	CMacSurface::zm_pOverlaySurface = nil;
    }
    
    if (pWindow && m_bCreatedOSWindow)
    {
	WindowPtr w = (WindowPtr)pWindow->window;
	if (w)
	{
	    ::DisposeWindow(w);
	}
	m_bCreatedOSWindow = FALSE;
    }
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_SetSize
 */
void
CHXMacSite::_SetSize(HXxSize size)
{
    if (m_bCreatedOSWindow && m_pWindow && m_pWindow->window)
    {
	WindowPtr w = (WindowPtr)m_pWindow->window;
	::SizeWindow(w, size.cx, size.cy, true);
	
	m_pWindow->x = 0;
	m_pWindow->y = 0;

	Rect bounds;
	::GetPortBounds(::GetWindowPort(w), &bounds);

	m_pWindow->width = bounds.right-bounds.left;
	m_pWindow->height = bounds.bottom-bounds.top;

	m_pWindow->clipRect.left = 0;
	m_pWindow->clipRect.top = 0;
	m_pWindow->clipRect.right = m_pWindow->width;
	m_pWindow->clipRect.bottom = m_pWindow->height;
    }
    // delete the scroll bars so it recreates them in the right spot
    _DestroySliders();
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_SetPosition
 */
void
CHXMacSite::_SetPosition(HXxPoint position)
{
    if (m_bCreatedOSWindow && m_pWindow && m_pWindow->window)
    {
	WindowPtr w = (WindowPtr)m_pWindow->window;
	::MoveWindow(w, position.x, position.y, false);
    }
    else
    {
	m_screenOffset = position;
    }
    // delete the scroll bars so it recreates them in the right spot.
    _DestroySliders();
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_DamageRect
 */
void
CHXMacSite::_DamageRect(HXxRect rect)
{
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_DamageRect
 */
void
CHXMacSite::_DamageRegion(HXxRegion rgn)
{
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_ShouldEnterForceRedraw
 */
BOOL
CHXMacSite::_ShouldEnterForceRedraw()
{
    if (InterlockedIncrement(&m_lBltEntryCount) > 1)
    {
        InterlockedDecrement(&m_lBltEntryCount);
        return FALSE; 
    }

#ifdef THREADS_SUPPORTED
#ifdef USE_CARBON_TIMER
    if (!IsMacInCooperativeThread())
    {
	// we need to schedule a Carbon Timer callback
	// to access ourselves at system time.
	
	// XXXMEH 06/17/2002 - we moved this InterlockDecrement()
	// to BEFORE the SetEventLoopTimerNextFireTime(). The reason
	// is that sometimes, you actually get an IMMEDIATE callback
	// on the main thread before you have decremented m_lBltEntryCount.
	// When this happened while the decrement was AFTER SetEventLoopTimerNextFireTime(),
	// then the ForceRedraw() would bail out early at the
	// if(InterlockedIncrement(&m_lBltEntryCount) > 1) at the
	// top of this method and the blt would never happen.
        InterlockedDecrement(&m_lBltEntryCount);
#ifdef _MAC_MACHO
	HX_ASSERT(m_RedrawCFTimerRef);
        ::CFRunLoopTimerSetNextFireDate(
                        m_RedrawCFTimerRef,
                        ::CFAbsoluteTimeGetCurrent() // immediately!
                        );
#else
	HX_ASSERT(m_RedrawCarbonTimerRef);
	::SetEventLoopTimerNextFireTime(m_RedrawCarbonTimerRef, kEventDurationNoWait);
#endif
        // XXXMEH 06/17/2002 - We USED to decrement m_lBltEntryCount here - 
        // now we have moved it before SetEventLoopTimerNextFireTime()
	return FALSE;
    }
#endif
#endif

    HXxWindow* topWindow = GetWindow();
    if (_AtSystemTime() && topWindow && topWindow->window)
    {
	::GetPort(&m_RememberMacPort);
	WindowPtr w = (WindowPtr)topWindow->window;
#if defined(_CARBON) || defined(_MAC_UNIX)
	::SetPort( GetWindowPort( w ) );
#else
	::SetPort(w);
#endif
	
	// get new origin

	HXxPoint offset;
	offset.x = 0;
	offset.y = 0;
	GetMacContentAreaOffset(offset);

	// see if the clip region overlaps where we know we're supposed to be.
	
	Rect siteRect = { 0, 0, topWindow->height, topWindow->width };
	OffsetRect( &siteRect, topWindow->x, topWindow->y );
	
	BOOL bSiteClippedOutSoRedrawNecessary = FALSE;
	
	RgnHandle clippedSiteRgn = ::NewRgn();
	RgnHandle siteRgn = ::NewRgn();
	
	::RectRgn(siteRgn, &siteRect);
	
#if defined(_CARBON) || defined(_MAC_UNIX)
	RgnHandle clipRgn = ::NewRgn();
	::GetPortClipRegion( GetWindowPort( w ), clipRgn );
	::SectRgn( siteRgn, clipRgn, clippedSiteRgn );
	::DisposeRgn( clipRgn );
#else
	::SectRgn(siteRgn, w->clipRgn, clippedSiteRgn);
#endif
	
	if (::EmptyRgn(clippedSiteRgn))
	{
	    bSiteClippedOutSoRedrawNecessary = TRUE;
	}
	
	DisposeRgn(siteRgn);
	DisposeRgn(clippedSiteRgn);
	
	if (bSiteClippedOutSoRedrawNecessary)
	{
	    // D'oh, doesn't intersect! So let's just draw next time around.

	    // we need to schedule a redraw if one ain't there already.
	    if (!m_pMacSiteRedrawCallback->m_ulMacSiteRedrawCallbackPendingID
		&& m_pScheduler)
	    {
		m_pMacSiteRedrawCallback->m_ulMacSiteRedrawCallbackPendingID =
			m_pScheduler->RelativeEnter(m_pMacSiteRedrawCallback, 1);
	    }

	    goto returnfalse;
	}
    }
    
    return TRUE;

returnfalse:
    // xxxbobclark I needed to move this code around because CWPro 7's compiler
    // was running out of local variable space. Odd.
    
    ::SetPort(m_RememberMacPort);
    // decrement count since it won't execute ForceRedraw.
    InterlockedDecrement(&m_lBltEntryCount);
    return FALSE;

}

/************************************************************************
 *  Method:
 *    CHXMacSite::_ExitForceRedraw
 */
void
CHXMacSite::_ExitForceRedraw()
{
    HXxWindow* topWindow = GetParentWindow();
    if (_AtSystemTime() && topWindow && topWindow->window)
    {
	::SetPort(m_RememberMacPort);
	m_RememberMacPort = nil;
    }
    
    InterlockedDecrement(&m_lBltEntryCount);
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_SendOSUpdateMessage
 */
void
CHXMacSite::_SendOSUpdateMessage()
{
#if 0
    ASSERT(GetOSWindow());
    
    if (GetOSWindow())
    {
	GrafPtr savePort;
	::GetPort(&savePort);
	
	WindowPtr w = (WindowPtr)GetOSWindow();
	::SetPort(w);
	// XXXbobclark
	// I still haven't fully grokked how to avoid loops: _HandleOSEvent on an
	// update event can call _ForceRedraw(), which in turn calls _SendOSUpdateMessage,
	// where InvalRect() can generate an update event.... And we need this to function
	// properly, so things like paused movies will redraw if they're obscured then shown.

//	::InvalRect(&w->portRect);
	::SetPort(savePort);
    }
#endif
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_ShowSite
 */
void
CHXMacSite::_ShowSite(BOOL bShow)
{
    if (m_pWindow && m_pWindow->window)
    {
	// XXXbobclark I think that the cross-platform stuff should take care of this...
    }
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_AtSystemTime
 */
BOOL
CHXMacSite::_AtSystemTime()
{
    return IsMacInCooperativeThread();
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_EventOccurred
 */
HX_RESULT
CHXMacSite::_EventOccurred(HXxEvent* pEvent)
{
    return HXR_OK;
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_GetDeviceCaps
 */
void
CHXMacSite::_GetDeviceCaps(void* hdc, UINT16& uBytesPerPixel, UINT16& uHorizRes,
	UINT16& uVertRes)
{
    static UINT16 sBytesPerPixel = 4;
    static UINT16 sHorizRes = 640;
    static UINT16 sVertRes = 480;
    static BOOL sInited = FALSE;
    
    if (!sInited && _AtSystemTime())
    {
	GDHandle mainGD = ::GetMainDevice();
	sHorizRes = (**mainGD).gdRect.right - (**mainGD).gdRect.left;
	sVertRes = (**mainGD).gdRect.bottom - (**mainGD).gdRect.top;
	PixMapHandle pmh = (**mainGD).gdPMap;
	if (pmh)
	{
	    sBytesPerPixel = (**pmh).pixelSize;
	}
    }
    
    uBytesPerPixel = sBytesPerPixel;
    uHorizRes = sHorizRes;
    uVertRes = sVertRes;
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_GetWindowRect
 */
void
CHXMacSite::_GetWindowRect(HXxRect* destRect)
{
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_DestroySliders
 */
void
CHXMacSite::_DestroySliders()
{
    if (m_hHScrollBar)
    {
	::DisposeControl(m_hHScrollBar);
	m_hHScrollBar = NULL;
    }
    if (m_hVScrollBar)
    {
	::DisposeControl(m_hVScrollBar);
	m_hVScrollBar = NULL;
    }
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_HandleOSEvents
 */
BOOL
CHXMacSite::_HandleOSEvents(HXxEvent* pEvent)
{
    BOOL handled = FALSE;
    {
	EventRecord* macEvent = (EventRecord*) pEvent->param1;

	// if we switch out while in full-screen, unfortunately we need
	// to turn off full-screen.
	
	if (zm_bFullScreenActive && macEvent->what == nullEvent)
	{
	    ProcessSerialNumber currentPSN;
	    ProcessSerialNumber frontPSN;
	    
	    ::GetCurrentProcess(&currentPSN);
	    ::GetFrontProcess(&frontPSN);
	    
	    Boolean bCurrentIsFront = TRUE;
	    ::SameProcess(&currentPSN, &frontPSN, &bCurrentIsFront);
	    
	    if (!bCurrentIsFront)
	    {

		ExitFullScreen();
		
		HXxWindow* pWindow = GetWindow();
		if (pWindow && pWindow->window)
		{
		    GrafPtr savePort;
		    ::GetPort(&savePort);
		    WindowPtr w = (WindowPtr)pWindow->window;
		    ::SetPort(::GetWindowPort(w));
		    Rect windowBounds;
		    ::GetPortBounds(::GetWindowPort(w), &windowBounds);
		    ::InvalWindowRect(w, &windowBounds);
		    ::SetPort(savePort);
		}

		handled = TRUE;
	    }
	}
	
	if (macEvent->what == keyDown)
	{
	    char theKey = macEvent->message & 0x000000ff;
	    
	    if (CHXMacSite::zm_bFullScreenActive && theKey == 0x1b)
	    {
		ExitFullScreen();
	    }
	    else
	    {
		if (m_pUser)
		    m_pUser->HandleEvent(pEvent);
		
		handled = pEvent->handled;
	    }
	}
	
	if (macEvent->what == updateEvt || macEvent->what == activateEvt)
	{
	    HX_ASSERT(_AtSystemTime());
	    
	    WindowPtr w = (WindowPtr)macEvent->message;

	    if (w)
	    {
		if (zm_bFullScreenActive && m_pHXxFullScreenWindow && m_pHXxFullScreenWindow->window
			&& m_pHXxFullScreenWindow->window == w)
		{
		    GrafPtr savePort;
		    ::GetPort(&savePort);
#if defined(_CARBON) || defined(_MAC_UNIX)
		    ::SetPort( GetWindowPort( w ) );
#else
		    ::SetPort(w);
#endif
		    RGBColor holdRGB;
		    RGBColor theRGB = {0x0000, 0x0000, 0x0000};
		    ::GetBackColor(&holdRGB);
		    ::RGBBackColor(&theRGB);
#if defined(_CARBON) || defined(_MAC_UNIX)
		    Rect portRect;
		    GetPortBounds( GetWindowPort( w ), &portRect );
		    ::EraseRect( &portRect );
#else
		    ::EraseRect(&w->portRect);
#endif
		    ::RGBBackColor(&holdRGB);
		    ::SetPort(savePort);
		}

		m_pTopLevelSite->RecomputeClip();

		// see if overlay is active... if so, then we might just need
		// to fill with a color key!
		if (CMacSurface::zm_pOverlaySurface)
		{
		    CMacSurface* pMacSurface = (CMacSurface*)m_pVideoSurface;
		    if (pMacSurface == CMacSurface::zm_pOverlaySurface)
		    {
			// aha! THIS site's surface is in fact the overlay surface.
			m_pVideoSurface->FillColorKey();
		    }
		}
		HXxRect siteRectToDamage;
		siteRectToDamage.left = 0;
		siteRectToDamage.top = 0;
		siteRectToDamage.right = m_size.cx;
		siteRectToDamage.bottom = m_size.cy;
		DamageRect(siteRectToDamage);
        	InternalForceRedraw();
	    }

	    HXxWindow* pWindow = GetWindow();
	    if (pWindow && pWindow->window == (WindowPtr)macEvent->message)
	    {
		// XXXbobclark commented out 'cause it's already done for "honest"
		// update events. I don't wanna do this for fake update events.
//		m_pTopLevelSite->RecomputeClip();
//		ForceRedraw();
		if (pEvent->param2 && _AtSystemTime())
		{
		    // for update events, param2 may contain a RgnHandle into
		    // which we add the area that we are handling updates in,
		    // so the TLC knows it doesn't have to draw there.
		    
		    if (m_bBltHasBeenCalled)
		    {
			if (!m_bThisOrAChildHasBlitted)
			{
			    CHXMacSite* pMacSite = this;
			    while (pMacSite)
			    {
				pMacSite->m_bThisOrAChildHasBlitted = TRUE;
				pMacSite = (CHXMacSite*)pMacSite->m_pParentSite;
			    }
			}
		    }
		    
		    if (m_bThisOrAChildHasBlitted)
		    {
			RgnHandle handledRgn = ::NewRgn();
			RgnHandle passedInRgn = (RgnHandle)pEvent->param2;

			HXxPoint ptSiteOrigin;
			GetMacContentAreaOffset(ptSiteOrigin);

			Rect myRect = { ptSiteOrigin.y, ptSiteOrigin.x,
				ptSiteOrigin.y + m_size.cy,
				ptSiteOrigin.x + m_size.cx };

			::RectRgn(handledRgn, &myRect);
			::UnionRgn(passedInRgn, handledRgn, passedInRgn);
			::DisposeRgn(handledRgn);
		    }
		}
	    }
	    
	    if (m_hHScrollBar || m_hVScrollBar)
	    {
		Point oldOrigin;
		Rect portRect;
		GetPortBounds(GetWindowPort(w), &portRect);
		oldOrigin.h = portRect.left;
		oldOrigin.v = portRect.top;
		
		if (m_hHScrollBar)
		{
		    ::Draw1Control(m_hHScrollBar);
		    handled = TRUE;
		}
		if (m_hVScrollBar)
		{
		    ::Draw1Control(m_hVScrollBar);
		    handled = TRUE;
		}
	    }
	}
	
	if (macEvent->what == mouseDown || macEvent->what == mouseUp)
	{
	    WindowPtr w = nil;

	    ControlHandle theControl = NULL;
	    
	    HXxWindow* pWindow = GetWindow();
	    
	    if (pWindow && pWindow->window)
	    {
		w = (WindowPtr)pWindow->window;
	    }
	    
	    HX_ASSERT(w);
	    
	    if (!w) return HXR_FAIL;

	    GrafPtr savePort;
	    ::GetPort(&savePort);
	    ::SetPort(::GetWindowPort(w));
	    
	    Point oldOrigin;
	    Rect portRect;
	    ::GetPortBounds(::GetWindowPort(w), &portRect);
	    oldOrigin.h = portRect.left;
	    oldOrigin.v = portRect.top;
	    
	    SetOriginAndMaintainClipRgn(0,0); // origin must be at 0,0 for scroll bar maintenence
	    
	    Point localPt = macEvent->where;
	    ::GlobalToLocal(&localPt);
	    
	    short thePart = 0;
	    theControl = ::FindControlUnderMouse(localPt, w, &thePart);
	    
	    if (theControl && ((theControl == m_hHScrollBar) || (theControl == m_hVScrollBar)))
	    {
		short trackedPart = ::TrackControl(theControl, localPt, m_ScrollBarActionProc);
                // xxxbobclark Carbon Porting Notes: TrackControl is deprecated, use HandleControlClick.
		
		long pageSize;
		
		if (theControl == m_hHScrollBar)
		{
		    pageSize = m_nHorizPageSize;
		}
		else
		{
		    pageSize = m_nVertPageSize;
		}
		
		switch (trackedPart)
		{
		    case kControlUpButtonPart:
			::SetControl32BitValue(theControl, ::GetControl32BitValue(theControl)-1);
			break;
		    case kControlDownButtonPart:
			::SetControl32BitValue(theControl, ::GetControl32BitValue(theControl)+1);
			break;
		    case kControlPageUpPart:
			::SetControl32BitValue(theControl, ::GetControl32BitValue(theControl)-pageSize);
			break;
		    case kControlPageDownPart:
			::SetControl32BitValue(theControl, ::GetControl32BitValue(theControl)+pageSize);
			break;
		}
		
		if (theControl == m_hHScrollBar)
		{
		    m_XSliderPos = ::GetControl32BitValue(theControl);
		}
		if (theControl == m_hVScrollBar)
		{
		    m_YSliderPos = ::GetControl32BitValue(theControl);
		}
		
		HXxPoint ptSiteOrigin;
		GetMacContentAreaOffset(ptSiteOrigin);
		Rect invalRect;
		invalRect.left = ptSiteOrigin.x;
		invalRect.top = ptSiteOrigin.y;
		
		if (m_hHScrollBar)
		{
		    Rect controlRect;
		    ::GetControlBounds(m_hHScrollBar, &controlRect);
		    invalRect.right = controlRect.right;
		    invalRect.bottom = controlRect.top;
		}
		if (m_hVScrollBar)
		{
		    Rect controlRect;
		    ::GetControlBounds(m_hVScrollBar, &controlRect);
		    invalRect.right = controlRect.left;
		    invalRect.bottom = controlRect.bottom;
		}
		
		::InvalWindowRect(w, &invalRect);
		handled = TRUE;
	    }
	    
	    if (!handled)
	    {
		HXxWindow* pWindow = GetWindow();
		if (pWindow && pWindow->window)
		{
		    // see if it's in this site

		    SetOriginAndMaintainClipRgn(-pWindow->x, -pWindow->y);
		    Point p = macEvent->where;
		    ::GlobalToLocal(&p);
		    HXxPoint loc;
		    loc.x = p.h;
		    loc.y = p.v;
		    
		    HX_ASSERT(m_RegionForMouse);
		    if (IsPointInClippingRegion(&loc))
		    {
			HXxPoint offset = {0,0};
			GetMacContentAreaOffset(offset);

//			UDrawingUtils::SetOriginAndMaintainClipRgn(-offset.x, -offset.y);


                        if (m_pUser)
                        {
//                            m_pUser->HandleEvent(pEvent);
//                            handled = pEvent->handled;
                        }
		    }
		    
		    SetOriginAndMaintainClipRgn(oldOrigin.h, oldOrigin.v);
		    
		    ::SetPort(savePort);
		}
		
	    }
	}
    }
    return handled;
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_HandleAllOSEvents
 */
/* static */
void CHXMacSite::_HandleAllOSEvents(HXxEvent* pEvent)
{
    EventRecord* macEvent = (EventRecord*) pEvent->param1;
    
    CHXSimpleList::Iterator ndx = zm_ListOfMacSites.Begin();
    for ( ; ndx != zm_ListOfMacSites.End(); ++ndx)
    {
	CHXMacSite* pMacSite = (CHXMacSite*)(*ndx);
	
	HX_ASSERT( pMacSite );
	
	pMacSite->_HandleOSEvents(pEvent);
    }
    
/*
    if (gRecentUpdateEvent)
    {
	EventRecord* macEvent = (EventRecord*)pEvent->param1;
	if (macEvent->what == updateEvt)
	{
	    // XXXbobclark
	    // clearly we're handling the recent update event and since we've
	    // just done it let's clear that puppy out.
	    gRecentUpdateEvent = false;
	}
    }
*/
}


/************************************************************************
 *  Method:
 *    CHXMacSite::_ConvertRegionToMacRegion
 *	utility function to convert between the RealNetworks
 *	regions that the site classes use and Mac-specific
 *	RgnHandle's.
 */
/* static */
RgnHandle
CHXMacSite::_ConvertRegionToMacRegion( HXREGION* pRegion )
{
    HX_ASSERT(IsMacInCooperativeThread());
    if ( !IsMacInCooperativeThread() ) return nil; // Hoo-boy would this ever suck

    RgnHandle rgn = ::NewRgn();
    
    if ( rgn )
    {
	::OpenRgn();
	
	for ( long i = 0; i < pRegion->numRects; i++ )
	{
	    Rect r;
	    r.left = pRegion->rects[i].x1;
	    r.top = pRegion->rects[i].y1;
	    r.right = pRegion->rects[i].x2;
	    r.bottom = pRegion->rects[i].y2;
	    
	    ::FrameRect( &r );
	}
	
	::CloseRgn( rgn );
    }

    return rgn;
}



/************************************************************************
 *  Method:
 *    CHXMacSite::_ConvertToHXEvent
 */
BOOL
CHXMacSite::_ConvertToHXEvent( HXxEvent* pEvent )
{
    if (pEvent->event == mouseDown || pEvent->event == mouseUp)
    {
	HXxWindow* pWindow = GetWindow();
	if (pWindow && pWindow->window)
	{
	    GrafPtr savePort;
	    GetPort(&savePort);

	    WindowPtr w = (WindowPtr)pWindow->window;
	    
	    Point oldOrigin;
#if defined(_CARBON) || defined(_MAC_UNIX)
	    SetPort( GetWindowPort(w) );
	    Rect portRect;
	    GetPortBounds( GetWindowPort(w), &portRect );
	    oldOrigin.h = portRect.left;
	    oldOrigin.v = portRect.top;
#else
	    SetPort( w );
	    oldOrigin.h = w->portRect.left;
	    oldOrigin.v = w->portRect.top;
#endif
	    static HXxPoint realPt = {0,0};
	    
	    EventRecord* macEvent = (EventRecord*)pEvent->param1;
	    Point localPoint = macEvent->where;

	    GlobalToLocal( &localPoint );

	    realPt.x = localPoint.h;
	    realPt.y = localPoint.v;

	    UINT32 flags = 0;
	    if (macEvent->modifiers & shiftKey) flags |= HX_SHIFT_KEY;
	    if (macEvent->modifiers & controlKey) flags |= HX_CTRL_KEY;
	    if (macEvent->modifiers & cmdKey) flags |= HX_ALT_COMMAND_KEY;
	    
	    if (flags & HX_CTRL_KEY)
	    {
		pEvent->event = pEvent->event == mouseDown ?
			HX_CONTEXT_BUTTON_DOWN : HX_CONTEXT_BUTTON_UP;
	    }
	    else
	    {
		pEvent->event = pEvent->event == mouseDown ?
			HX_PRIMARY_BUTTON_DOWN : HX_PRIMARY_BUTTON_UP;
	    }
	    pEvent->param1 = (void*)&realPt;
	    pEvent->param2 = (void*)flags;

	    SetPort(savePort);

	    return FALSE;
	}
    }
    if (pEvent->event == nullEvent && _AtSystemTime())
    {
	EventRecord* macEvent = (EventRecord*)pEvent->param1;
	
	HXxWindow* pWindow = GetWindow();
	if (pWindow && pWindow->window)
	{
	    WindowPtr w = (WindowPtr)pWindow->window;
	    if (w == ::FrontWindow())
	    {
		GrafPtr savePort;
		::GetPort(&savePort);
#if defined(_CARBON) || defined(_MAC_UNIX)
		::SetPort( GetWindowPort(w) );
#else
		::SetPort(w);
#endif

		Point oldOrigin;

#if defined(_CARBON) || defined(_MAC_UNIX)
		Rect portRect;
		GetPortBounds( GetWindowPort( w ), &portRect );
		oldOrigin.h = portRect.left;
		oldOrigin.v = portRect.top;
#else
		oldOrigin.h = w->portRect.left;
		oldOrigin.v = w->portRect.top;
#endif
		
		// see if it's in this site

		Point p = macEvent->where;
		::GlobalToLocal(&p);
		HXxPoint loc;
		loc.x = p.h;
		loc.y = p.v;
		
		HX_ASSERT(m_RegionForMouse);
		if (m_RegionForMouse && IsPointInClippingRegion(&loc))
		{
		    static Point sLastGlobalLocation = {0,0};

		    if (macEvent->where.h != sLastGlobalLocation.h || macEvent->where.v != sLastGlobalLocation.v)
		    {
			sLastGlobalLocation = macEvent->where;
			Point localPt = sLastGlobalLocation;
			::GlobalToLocal(&localPt);

			m_MostRecentConvertedMouseLoc.x = localPt.h;
			m_MostRecentConvertedMouseLoc.y = localPt.v;

			UINT32 flags = 0;
			if (macEvent->modifiers & shiftKey) flags += HX_SHIFT_KEY;
			if (macEvent->modifiers & controlKey) flags += HX_CTRL_KEY;
			if (macEvent->modifiers & cmdKey) flags += HX_ALT_COMMAND_KEY;

			// don't change the event until we're done looking at it!
			// (the pre-converted version that is.)

			pEvent->event = HX_MOUSE_MOVE;
			pEvent->param1 = (void*)&m_MostRecentConvertedMouseLoc;
			pEvent->param2 = (void*)flags;

			// This will eventually be handled by the base site.
			// It's possible that the base site will need to translate
			// this into HX_MOUSE_ENTER and HX_MOUSE_LEAVE first,
			// though, which is why we don't simply handle it here.
		    }
		}
		else
		{
		    if (m_pTopLevelSite->m_pMouseInSite == this)
		    {
			m_pTopLevelSite->GenerateMouseLeaveMessage();
		    }
		}
		
		
		::SetPort(savePort);
	    }
	}
    }
    return FALSE; //pEvent->handled;
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_GenerateOSEvent
 */
void
CHXMacSite::_GenerateOSEvent(HXxEvent* pEvent, HXxEvent* pEvent2)
{
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_GenerateSetCursorEvent
 */
void
CHXMacSite::_GenerateSetCursorEvent()
{
    Point oldOrigin;

    HXxWindow* pWindow = GetWindow();
    if (!pWindow || !pWindow->window)
    {
	return;
    }

    WindowPtr w = (WindowPtr)pWindow->window;

    GrafPtr savePort;
    ::GetPort(&savePort);

#if defined(_CARBON) || defined(_MAC_UNIX)
    ::SetPort(::GetWindowPort(w));
#else
    ::SetPort(w);
#endif

#if defined(_CARBON) || defined(_MAC_UNIX)
    Rect portRect;
    GetPortBounds( GetWindowPort( w ), &portRect );
    oldOrigin.h = portRect.left;
    oldOrigin.v = portRect.top;
#else
    oldOrigin.h = w->portRect.left;
    oldOrigin.v = w->portRect.top;
#endif

    SetOriginAndMaintainClipRgn(-pWindow->x, -pWindow->y);

    HXxPoint offset = {0,0};
    GetMacContentAreaOffset(offset);

    SetOriginAndMaintainClipRgn(-offset.x, -offset.y);
    
    Point location;
    GetMouse(&location);

    HXxEvent theEvent;
    memset(&theEvent, 0, sizeof(theEvent));

    theEvent.event = HX_MOUSE_MOVE;
    
    HXxPoint mouseLoc;
    mouseLoc.x = location.h;
    mouseLoc.y = location.v;
    theEvent.param1 = (void*)&mouseLoc;
    
    SetOriginAndMaintainClipRgn(oldOrigin.h, oldOrigin.v);

    if (m_pUser)
	m_pUser->HandleEvent(&theEvent);

    ::SetPort(savePort);
}


void
CHXMacSite::_ScaleFullScreen(HXxWindow* pWindow)
{
    if (m_pParentSite != nil)
    {
	CHXMacSite* pParentSite = (CHXMacSite*)m_pParentSite;
	m_fStretchMultiple = pParentSite->m_fStretchMultiple;
	m_pHXxFullScreenWindow->window = pParentSite->m_pHXxFullScreenWindow->window;
	
	if (0 /*pParentSite->m_pStatusSite == this*/)
	{
	}
	else
	{
	    if (m_pWindow) pWindow = m_pWindow;
	    
	    m_pHXxFullScreenWindow->x = (long)((double)pWindow->x * m_fStretchMultiple);
	    m_pHXxFullScreenWindow->y = (long)((double)pWindow->y * m_fStretchMultiple);
	    m_pHXxFullScreenWindow->width = (long)((double)pWindow->width * m_fStretchMultiple);
	    m_pHXxFullScreenWindow->height = (long)((double)pWindow->height * m_fStretchMultiple);
	    
	    m_pHXxFullScreenWindow->clipRect.left = (long)((double)pWindow->clipRect.left * m_fStretchMultiple);
	    m_pHXxFullScreenWindow->clipRect.top = (long)((double)pWindow->clipRect.top * m_fStretchMultiple);
	    m_pHXxFullScreenWindow->clipRect.right = (long)((double)pWindow->clipRect.right * m_fStretchMultiple);
	    m_pHXxFullScreenWindow->clipRect.bottom = (long)((double)pWindow->clipRect.bottom * m_fStretchMultiple);
	}
    }


    CHXMapPtrToPtr::Iterator i = m_ChildrenMap.Begin();
    for ( ; i != m_ChildrenMap.End(); ++i)
    {
	CHXBaseSite* pSite = (CHXBaseSite*) *i;
	
	CHXMacSite* pMacSite = (CHXMacSite*)pSite;
	pMacSite->_ScaleFullScreen(pWindow);
    }
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_EnterFullScreen
 */
HX_RESULT
CHXMacSite::_EnterFullScreen()
{
    if (zm_bFullScreenActive)
    {
	return HXR_UNEXPECTED;
    }
    
    zm_bFullScreenActive = TRUE;
    
    if (m_pTopLevelSite == this)
    {
	short desiredWidth, desiredHeight;
	
	GDHandle aGD = ::GetMainDevice();
	
	// Check the UseOverlay preference here, since _OverlayAvailable() doesn't update its
	// value on Preference changes.
	BOOL bDoScreenResSwitch = FALSE;
	IHXPreferences* pPreferences = NULL;
	if (m_pContext && (HXR_OK == m_pContext->QueryInterface(IID_IHXPreferences, (void**)&pPreferences)))
	{
	    IHXBuffer* pBuffer = NULL;
	    if (pPreferences->ReadPref("UseOverlay", pBuffer) == HXR_OK)
	    {
		bDoScreenResSwitch = ::atoi((char*)pBuffer->GetBuffer()) != 1;
	    }
	    HX_RELEASE(pBuffer);
	}
	HX_RELEASE(pPreferences);
	
	if (!bDoScreenResSwitch)
	{
	    // if an overlay exists then let's assume we don't have
	    // to switch resolutions.
	    desiredWidth = (**aGD).gdRect.right - (**aGD).gdRect.left;
	    desiredHeight = (**aGD).gdRect.bottom - (**aGD).gdRect.top;
	}
	else
	{
	    desiredWidth = m_size.cx;
	    desiredHeight = m_size.cy;
	}
	
	::BeginFullScreen(
		&zm_pRememberFullScreenInformation,
		::GetMainDevice(),
		&desiredWidth,
		&desiredHeight,
		nil,
		nil,
		fullScreenAllowEvents );
	
	_DestroySliders();
	
	CMacRootSurface::VisRgnChangedCallback();
	
	GDHandle mainGD = ::GetMainDevice();
	Rect bounds = (**mainGD).gdRect;
	
	if (m_pHXxFullScreenWindow && m_pHXxFullScreenWindow->window)
	{
	    WindowPtr w = (WindowPtr)m_pHXxFullScreenWindow->window;
	    ::ShowWindow(w);
	    ::SizeWindow(w, bounds.right-bounds.left, bounds.bottom-bounds.top, true);
	    ::MoveWindow(w, bounds.left, bounds.top, true);
	    
	    HXxPoint newPosition;
	    newPosition.x = bounds.left;
	    newPosition.y = bounds.top;
	    
	    HXxSize newSize;
	    newSize.cx = bounds.right-bounds.left;
	    newSize.cy = bounds.bottom-bounds.top;
	    
	    double theXZoomFactor = (double)newSize.cx / (double)m_pWindow->width;
	    double theYZoomFactor = (double)newSize.cy / (double)m_pWindow->height;
	    
	    if (theXZoomFactor < theYZoomFactor)
	    {
		theYZoomFactor = theXZoomFactor;
		newSize.cy = (long)((double)m_pWindow->height * theYZoomFactor);
		
		newPosition.y += ((bounds.bottom-bounds.top)-newSize.cy)/2;
	    }
	    else
	    {
		theXZoomFactor = theYZoomFactor;
		newSize.cx = (long)((double)m_pWindow->width * theXZoomFactor);
		
		newPosition.x += ((bounds.right-bounds.left)-newSize.cx)/2;
	    }
	    m_fStretchMultiple = theXZoomFactor;
	    
	    m_pHXxFullScreenWindow->x = newPosition.x;
	    m_pHXxFullScreenWindow->y = newPosition.y;
	    
	    m_pHXxFullScreenWindow->width = newSize.cx;
	    m_pHXxFullScreenWindow->height = newSize.cy;
	    
	    m_pHXxFullScreenWindow->clipRect.left = newPosition.x;
	    m_pHXxFullScreenWindow->clipRect.top = newPosition.y;
	    m_pHXxFullScreenWindow->clipRect.right = newPosition.x + newSize.cx;
	    m_pHXxFullScreenWindow->clipRect.bottom = newPosition.y + newSize.cy;
	    
#if defined(_CARBON) || defined(_MAC_UNIX)
	    ::SetPort( GetWindowPort( (WindowPtr)m_pHXxFullScreenWindow->window ) );
#else
	    ::SetPort((WindowPtr)m_pHXxFullScreenWindow->window);
#endif
	    RGBColor holdRGB;
	    RGBColor theRGB = {0x0000, 0x0000, 0x0000};
	    ::GetBackColor(&holdRGB);
	    ::RGBBackColor(&theRGB);
	    ::EraseRect(&bounds);
	    ::RGBBackColor(&holdRGB);
	    
	    if (m_bInternalResizeOnFullscreen)
	    {
		GetSize(m_RememberNonFullscreenSize);
		GetPosition(m_RememberNonFullscreenPosition);
		m_pTopLevelSite->m_bDisableForceRedraw = TRUE;
		SetSize(newSize);
		m_pTopLevelSite->m_bDisableForceRedraw = FALSE;
		SetPosition(newPosition);
	    }
	    else
	    {
		_ScaleFullScreen(m_pWindow);
	    }

	    SetOriginAndMaintainClipRgn(-m_pHXxFullScreenWindow->x, -m_pHXxFullScreenWindow->y);
	}
	m_bInFullScreen = TRUE;
    }
    
    return HXR_OK;
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_ExitFullScreen
 */
HX_RESULT
CHXMacSite::_ExitFullScreen()
{
    CMacRootSurface::VisRgnChangedCallback();
    if (m_pTopLevelSite == this)
    {
	m_bInFullScreen = FALSE;
	_DestroySliders();
	
	if (m_pHXxFullScreenWindow && m_pHXxFullScreenWindow->window)
	{
	    WindowPtr w = (WindowPtr)m_pHXxFullScreenWindow->window;
	    GrafPtr savePort;
	    ::GetPort(&savePort);
	    ::SetPort(::GetWindowPort(w));
	    // we need to restore the origin for the next time we may
	    // enter fullscreen mode. xxxbobclark
	    SetOriginAndMaintainClipRgn(0,0);
	    ::HideWindow(w);
	    ::SetPort(savePort);
	}

	if (!m_bInternalResizeOnFullscreen)
	{
	    HXxSize fullscreenSize;

	    fullscreenSize.cx = m_pHXxFullScreenWindow->width;
	    fullscreenSize.cy = m_pHXxFullScreenWindow->height;

	    HXxSize nonfullscreenSize;

	    nonfullscreenSize.cx = (long)((double)fullscreenSize.cx / m_fStretchMultiple);
	    nonfullscreenSize.cy = (long)((double)fullscreenSize.cy / m_fStretchMultiple);

	    if (m_pWatcher)
	    {
		HRESULT hres = m_pWatcher->ChangingSize(fullscreenSize, nonfullscreenSize);
	    }
	}
	
	::EndFullScreen(zm_pRememberFullScreenInformation, nil);
	
    }
    
    if (CMacSurface::zm_pOverlaySurface == (CMacSurface*)m_pVideoSurface)
    {
	CMacSurface::CleanUpOverlay();
	CMacSurface::zm_pOverlaySurface = nil;
    }
    zm_bFullScreenActive = FALSE;

    if (m_pTopLevelSite == this)
    {
	if (m_bInternalResizeOnFullscreen)
	{
	    m_pTopLevelSite->m_bDisableForceRedraw = TRUE;
	    SetSize(m_RememberNonFullscreenSize);
	    m_pTopLevelSite->m_bDisableForceRedraw = FALSE;
	    SetPosition(m_RememberNonFullscreenPosition);
	}
    }
    
    return HXR_OK;
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_TestFullScreen
 */
HX_RESULT
CHXMacSite::_TestFullScreen(void* hTestBitmap, const char* pszStatusText)
{
    return HXR_OK;
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_TryCreateXSlider
 */
void
CHXMacSite::_TryCreateXSlider()
{
    if (!IsSiteVisible())
    {
	return;
    }
    
    HXxWindow* pWindow = GetWindow();
    if (!pWindow || !pWindow->window)
    {
	return;
    }
    
    WindowPtr w = (WindowPtr)pWindow->window;
    
    GrafPtr savePort;
    ::GetPort(&savePort);
    ::SetPort(::GetWindowPort(w));
    
    Point oldOrigin;
    Rect portRect;
    ::GetPortBounds(::GetWindowPort(w), &portRect);
    oldOrigin.h = portRect.left;
    oldOrigin.v = portRect.top;
    
    SetOriginAndMaintainClipRgn(0,0); // scroll bar maintenance requires origin at 0,0.
    
    HXxPoint offset = {0,0};
    GetMacContentAreaOffset(offset);
    
    HXxPoint position;
    HXxSize size;
    
    HX_ASSERT(GetParentSite());
    
    if (GetParentSite())
    {
	GetParentSite()->GetSize(size);
	position.x = 0;
	position.y = 0;
    }
    
    Rect controlRect;
    controlRect.left = position.x + offset.x;
    controlRect.top = position.y + offset.y + size.cy - SCROLL_BAR_WIDTH;
    controlRect.right = controlRect.left + size.cx;
    controlRect.bottom = controlRect.top + SCROLL_BAR_WIDTH;
    
    if (m_hHScrollBar && ::GetControlOwner(m_hHScrollBar) != w)
    {
	::DisposeControl(m_hHScrollBar);
	m_hHScrollBar = NULL;
	m_XSliderPos = 0;
    }
    
    if (m_hHScrollBar)
    {
	// if it already exists, then we may simply need to
	// move it...
	Rect oldControlRect;
	::GetControlBounds(m_hHScrollBar, &oldControlRect);
	
	if (!::EqualRect(&oldControlRect, &controlRect))
	{
	    ::SetControlBounds(m_hHScrollBar, &controlRect);
	    ::InvalWindowRect(w, &oldControlRect);
	}
    }
    else
    {
	::CreateScrollBarControl(w, &controlRect, 0, 0, 2, 1, false, NULL, &m_hHScrollBar);
	::SetControlReference(m_hHScrollBar, 0);
    }
    
    // invaling the rect seems to ameliorate this problem where extra scrollbars
    // were being spuriously displayed.
    ::InvalWindowRect(w, &controlRect);
    
    SetOriginAndMaintainClipRgn(oldOrigin.h, oldOrigin.v);
    ::SetPort(savePort);
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_SetXSliderValues
 */
void
CHXMacSite::_SetXSliderValues(INT32 range, INT32 pageSize)
{
    HXxWindow* pWindow = GetWindow();
    if (!pWindow || !pWindow->window)
    {
	return;
    }
    
    WindowPtr w = (WindowPtr)pWindow->window;
    
    Point oldOrigin;
    Rect portRect;
    ::GetPortBounds(::GetWindowPort(w), &portRect);
    oldOrigin.h = portRect.left;
    oldOrigin.v = portRect.top;
    
    SetOriginAndMaintainClipRgn(0,0);
    
    ::SetControl32BitMinimum(m_hHScrollBar, 0);
    ::SetControl32BitMaximum(m_hHScrollBar, range - pageSize);
    ::SetControlViewSize(m_hHScrollBar, pageSize);
    
    ::SetControl32BitValue(m_hHScrollBar, m_XSliderPos);
    
    m_nHorizPageSize = pageSize / 2;
    
    SetOriginAndMaintainClipRgn(oldOrigin.h, oldOrigin.v);
    SetMacControlRange(m_hHScrollBar, range);
    
    m_nHorizPageSize = pageSize;
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_TryCreateYSlider
 */
void
CHXMacSite::_TryCreateYSlider()
{
    if (!IsSiteVisible())
    {
	return;
    }
    
    HXxWindow* pWindow = GetWindow();
    if (!pWindow || !pWindow->window)
    {
	return;
    }
    
    WindowPtr w = (WindowPtr)pWindow->window;
    
    GrafPtr savePort;
    ::GetPort(&savePort);
    ::SetPort(::GetWindowPort(w));
    
    Point oldOrigin;
    Rect portRect;
    ::GetPortBounds(::GetWindowPort(w), &portRect);
    oldOrigin.h = portRect.left;
    oldOrigin.v = portRect.top;
    
    HXxPoint offset = {0,0};
    GetMacContentAreaOffset(offset);
    
    SetOriginAndMaintainClipRgn(0,0);
    
    HXxPoint position;
    HXxSize size;
    
    HX_ASSERT(GetParentSite());
    
    if (GetParentSite())
    {
	GetParentSite()->GetSize(size);
	
	position.x = 0;
	position.y = 0;
    }
    
    Rect controlRect;
    controlRect.left = position.x + offset.x + size.cx - SCROLL_BAR_WIDTH;
    controlRect.top = position.y + offset.y;
    controlRect.right = controlRect.left + SCROLL_BAR_WIDTH;
    controlRect.bottom = controlRect.top + size.cy;
    
    if (_DoesXSliderExist())
    {
	controlRect.bottom -= SCROLL_BAR_WIDTH; // ensure that both scroll bars don't overlap at the bottom right corner
    }
    
    if (m_hVScrollBar && ::GetControlOwner(m_hVScrollBar) != w)
    {
	::DisposeControl(m_hVScrollBar);
	m_hVScrollBar = NULL;
	m_YSliderPos = 0;
    }
    
    if (m_hVScrollBar)
    {
	Rect oldControlRect;
	::GetControlBounds(m_hVScrollBar, &oldControlRect);
	
	if (!::EqualRect(&oldControlRect, &controlRect))
	{
	    ::SetControlBounds(m_hVScrollBar, &controlRect);
	    ::InvalWindowRect(w, &oldControlRect);
	}
    }
    else
    {
	::CreateScrollBarControl(w, &controlRect, 0, 0, 2, 1, false, NULL, &m_hVScrollBar);
	::SetControlReference(m_hVScrollBar, 0);
    }
    
    ::InvalWindowRect(w, &controlRect);
    
    SetOriginAndMaintainClipRgn(oldOrigin.h, oldOrigin.v);
    ::SetPort(savePort);
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_SetYSliderValues
 */
void
CHXMacSite::_SetYSliderValues(INT32 range, INT32 pageSize)
{
    HXxWindow* pWindow = GetWindow();
    if (!pWindow || !pWindow->window)
    {
	return;
    }
    
    WindowPtr w = (WindowPtr)pWindow->window;
    
    Point oldOrigin;
    Rect portRect;
    ::GetPortBounds(::GetWindowPort(w), &portRect);
    oldOrigin.h = portRect.left;
    oldOrigin.v = portRect.top;
    
    SetOriginAndMaintainClipRgn(0,0);
    
    ::SetControl32BitMinimum(m_hVScrollBar, 0);
    ::SetControl32BitMaximum(m_hVScrollBar, range-pageSize);
    ::SetControlViewSize(m_hVScrollBar, pageSize);
    
    ::SetControl32BitValue(m_hVScrollBar, m_YSliderPos);
    
    m_nVertPageSize = pageSize / 2;
    
    SetOriginAndMaintainClipRgn(oldOrigin.h, oldOrigin.v);
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_GetSystemSizeOfSliders
 */
void
CHXMacSite::_GetSystemSizeOfSliders(INT32* pWidth, INT32* pHeight)
{
    if (pWidth) *pWidth = SCROLL_BAR_WIDTH;
    if (pHeight) *pHeight = SCROLL_BAR_WIDTH;
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_IsWindowVisible
 */
BOOL
CHXMacSite::_IsWindowVisible()
{
    return TRUE;
}

/************************************************************************
 *  Method:
 *    CHXMacSite::ShowMacControl
 */
void
CHXMacSite::ShowMacControl(ControlHandle theControl, BOOL bShow)
{
    if (theControl)
    {
	if (bShow)
	{
	    ::ShowControl(theControl);
	}
	else
	{
	    ::HideControl(theControl);
	}
    }
}

/************************************************************************
 *  Method:
 *    CHXMacSite::SetMacControlRectangle
 */
void
CHXMacSite::SetMacControlRectangle(ControlHandle theControl,
		INT32 left, INT32 top, INT32 right, INT32 bottom )
{
    if (theControl)
    {
	::SizeControl(theControl, right-left, bottom-top);
	::MoveControl(theControl, left, top);
    }
}

void
CHXMacSite::SetMacControlRange(ControlHandle theControl, INT32 controlMax)
{
    if (theControl)
    {
        ::SetControl32BitMinimum(theControl, 0);
        ::SetControl32BitMaximum(theControl, controlMax);
    }
}


/************************************************************************
 *  Method:
 *    CHXMacSite::_ShowXSlider
 */
void
CHXMacSite::_ShowXSlider(BOOL bShow)
{
    HXxWindow* pWindow = GetWindow();
    if (!pWindow || !pWindow->window)
    {
	return;
    }
    WindowPtr w = (WindowPtr)pWindow->window;
    Point oldOrigin;
    Rect portRect;
    ::GetPortBounds( ::GetWindowPort(w), &portRect);
    oldOrigin.h = portRect.left;
    oldOrigin.v = portRect.top;
    
    SetOriginAndMaintainClipRgn(0,0);
    
    ShowMacControl(m_hHScrollBar, bShow);
    
    SetOriginAndMaintainClipRgn(oldOrigin.h, oldOrigin.v);
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_MoveXSlider
 */
void
CHXMacSite::_MoveXSlider(INT32 left, INT32 top, INT32 right, INT32 bottom, BOOL bRedraw)
{
    // xxxbobclark do nothing right now
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_ShowYSlider
 */
void
CHXMacSite::_ShowYSlider(BOOL bShow)
{
    HXxWindow* pWindow = GetWindow();
    if (!pWindow || !pWindow->window)
    {
	return;
    }
    WindowPtr w = (WindowPtr)pWindow->window;
    Point oldOrigin;
    Rect portRect;
    ::GetPortBounds(::GetWindowPort(w), &portRect);
    oldOrigin.h = portRect.left;
    oldOrigin.v = portRect.top;
    
    SetOriginAndMaintainClipRgn(0,0);
    
    ShowMacControl(m_hVScrollBar, bShow);
    
    SetOriginAndMaintainClipRgn(oldOrigin.h, oldOrigin.v);
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_MoveYSlider
 */
void
CHXMacSite::_MoveYSlider(INT32 left, INT32 top, INT32 right, INT32 bottom, BOOL bRedraw)
{
    // xxxbobclark don't do anything right now
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_DoesXSliderExist
 */
BOOL
CHXMacSite::_DoesXSliderExist()
{
    if (m_hHScrollBar) return TRUE;
    return FALSE;
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_GetContainingWindow
 */
void*
CHXMacSite::_GetContainingWindow()
{
    if (m_pParentSite) return m_pParentSite->_GetContainingWindow();
    return NULL;
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_GetCursorPos
 */
void
CHXMacSite::_GetCursorPos(HXxPoint* pPoint)
{
    // this will return in global coordinates. (???)

    HX_ASSERT(_AtSystemTime());
    if (!_AtSystemTime()) return;
    
    HX_ASSERT(pPoint);
    if (!pPoint) return;
    
    Point pt;
    ::GetMouse(&pt);
    // pt is in local coordinates
    
    ::LocalToGlobal(&pt);
    
    pPoint->x = pt.h;
    pPoint->y = pt.v;
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_MapPointToOSWindow
 */
void
CHXMacSite::_MapPointToOSWindow(HXxPoint* pPt, void** pWindowHandle)
{
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_GetWindowWithCursor
 */
void*
CHXMacSite::_GetWindowWithCursor()
{
    return NULL;
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_ReInitPrimarySurface
 */
void
CHXMacSite::_ReInitPrimarySurface()
{
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_MoveWindow
 */
BOOL
CHXMacSite::_MoveWindow(void* window, INT32 X, INT32 Y, INT32 nWidth, INT32 nHeight, BOOL bRepaint)
{
    return TRUE;
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_UpdateWindow
 */
BOOL
CHXMacSite::_UpdateWindow(void* hWnd)
{
    return TRUE;
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_ShowWindow
 */
BOOL
CHXMacSite::_ShowWindow(void* hWnd, INT32 nCmdShow)
{
    return TRUE;
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_SetWindowPos
 */
BOOL
CHXMacSite::_SetWindowPos(void* hWnd, void* hWndInsertAfter, INT32 X, INT32 Y, INT32 cx, INT32 cy, INT32 uFlags)
{
    return TRUE;
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_SetWindowRgn
 */
BOOL
CHXMacSite::_SetWindowRgn(void* hWnd, HXREGION* hRgn, BOOL bRedraw)
{
    return TRUE;
}

/************************************************************************
 *  Method:
 *    CHXMacSite::_SetFocus
 */
void
CHXMacSite::_SetFocus(void* pWindow)
{
}


/************************************************************************
 *  Method:
 *    CHXMacSite::GetMacContentAreaOffset
 */
void
CHXMacSite::GetMacContentAreaOffset(REF(HXxPoint)offset)
{
    offset.x = m_topleft.x;
    offset.y = m_topleft.y;
    
    HXxWindow* pWindow = GetWindow();
    
    if (pWindow)
    {
	offset.x += pWindow->x;
	offset.y += pWindow->y;
    }
    
    return;
}


#pragma export on

extern "C" void MacSiteHandleAllEvents(HXxEvent* pEvent)
{
    CHXMacSite::_HandleAllOSEvents(pEvent);
}

#pragma export off


/************************************************************************
 *  Callback implementation
 */

/************************************************************************
 *  Method:
 *    CHXMacSite::MacSiteRedrawCallback ctor
 */

CHXMacSite::MacSiteRedrawCallback::MacSiteRedrawCallback(CHXMacSite* pMacSite)
 : m_lRefCount(0)
 , m_ulMacSiteRedrawCallbackPendingID(0)
 , m_pMacSite(pMacSite)
{
}

/************************************************************************
 *  Method:
 *    CHXMacSite::MacSiteRedrawCallback dtor
 */

CHXMacSite::MacSiteRedrawCallback::~MacSiteRedrawCallback()
{
}

/************************************************************************
 *  Method:
 *    CHXMacSite::MacSiteRedrawCallback::QueryInterface
 */

STDMETHODIMP
CHXMacSite::MacSiteRedrawCallback::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;
}

/************************************************************************
 *  Method:
 *    CHXMacSite::MacSiteRedrawCallback::AddRef
 */

STDMETHODIMP_(ULONG32)
CHXMacSite::MacSiteRedrawCallback::AddRef()
{
    return InterlockedIncrement( &m_lRefCount );
}

/************************************************************************
 *  Method:
 *    CHXMacSite::MacSiteRedrawCallback::Release
 */

STDMETHODIMP_(ULONG32)
CHXMacSite::MacSiteRedrawCallback::Release()
{
    if ( InterlockedDecrement( &m_lRefCount ) > 0 )
    {
	return m_lRefCount;
    }
    
    delete this;
    return 0;
}

/************************************************************************
 *  Method:
 *    CHXMacSite::MacSiteRedrawCallback::Func
 */

STDMETHODIMP
CHXMacSite::MacSiteRedrawCallback::Func()
{
    m_pMacSite->_TLSLock();
    
    m_ulMacSiteRedrawCallbackPendingID = NULL;
    m_pMacSite->ForceRedraw();
    
    m_pMacSite->_TLSUnlock();
    
    return HXR_OK;
}


#ifdef THREADS_SUPPORTED

#ifdef USE_CARBON_TIMER
/************************************************************************
 *  Method:
 *    CHXMacSite::Redraw(something)Timer
 */

/*static*/
#ifdef _MAC_MACHO
void CHXMacSite::RedrawCFTimer(CFRunLoopTimerRef, CHXMacSite* pMacSite)
#else
void CHXMacSite::RedrawCarbonTimer(EventLoopTimerRef, CHXMacSite* pMacSite)
#endif
{
    // XXXMEH
    MLOG_BLT(NULL,
             "%lu\t----macsite.cpp--- RedrawCarbonTimer()\n",
             HX_GET_BETTERTICKCOUNT());
    HX_ASSERT( pMacSite );

    HX_ASSERT(IsMacInCooperativeThread());

    if (pMacSite->m_pIHXCoreMutex) pMacSite->m_pIHXCoreMutex->LockCoreMutex();
    
    // this huge block of code is adapted from the base site's implementation of
    // InternalScheduleUpgrade, where it needs to match up an IHXPlayer with this
    // site. In this case, we're protecting ourselves against rug-pulling, i.e.
    // if a stream has ended and stuff has been deleted, it's still possible (due
    // to the Carbon Timer's behavior of delaying redraws) that there's a pending
    // ForceRedraw() that wants to happen. If there's no player for this site, or
    // if the player is done, then we'll omit the blit.
    
    // On a one-gigahertz processor, this checking function is taking
    // between 20 and 30 microseconds; it may be worthwhile to save the
    // player in a member variable.
    
    bool bPlayerStillRunning = false;
    
    IHXPreferences* pPreferences = NULL;
    IHXBuffer* pBuffer = NULL;
    
    IHXClientEngine* pClientEngine = NULL;
    if (HXR_OK == pMacSite->m_pContext->QueryInterface(IID_IHXClientEngine, (void**)&pClientEngine))
    {
        UINT16 nPlayerCount = pClientEngine->GetPlayerCount();
        IUnknown* pUnknown = NULL;
        
        if (nPlayerCount == 1)
        {
            // wow, this was easy -- this is the only player then.
            pClientEngine->GetPlayer(0, pUnknown);
        }
        else
        {
            IHXSite* pThisSite = NULL;
            
            pMacSite->QueryInterface(IID_IHXSite, (void**)&pThisSite);
            HX_ASSERT(pThisSite);
            
            UINT16 index;
            for (index = 0; index < nPlayerCount; index++)
            {
                IHXSiteManager2* pSiteMgr2 = NULL;
                IUnknown* pUnknownPlayer = NULL;
                
                pClientEngine->GetPlayer(index, pUnknownPlayer);
                HX_ASSERT(pUnknownPlayer);
                
                pUnknownPlayer->QueryInterface(IID_IHXSiteManager2, (void**)&pSiteMgr2);
                if (pSiteMgr2)
                {
                    UINT32 nNumSites;
                    pSiteMgr2->GetNumberOfSites(nNumSites);
                    UINT32 index2;
                    for (index2 = 0; index2 < nNumSites; index2++)
                    {
                        IHXSite* pIterationSite = NULL;
                        pSiteMgr2->GetSiteAt(index2, pIterationSite);
                        if (pThisSite == pIterationSite)
                        {
                            // it matches!
                            HX_ASSERT(pUnknown == NULL);
                            pUnknown = pUnknownPlayer;
                            pUnknown->AddRef();
                        }
                    }
                    HX_RELEASE(pSiteMgr2);
                }
                HX_RELEASE(pUnknownPlayer);
            }
            
            HX_RELEASE(pThisSite);
        }
        
        if (pUnknown)
        {
            IHXPlayer* pPlayer;
            
            pUnknown->QueryInterface(IID_IHXPlayer, (void**)&pPlayer);
            if (pPlayer)
            {
                if (!pPlayer->IsDone())
                {
                    bPlayerStillRunning = true;
                }
                HX_RELEASE(pPlayer);
            }
            HX_RELEASE(pUnknown);
        }
        
        HX_RELEASE(pClientEngine);
    }
    
    if (bPlayerStillRunning)
    {
        pMacSite->ForceRedraw();
    }
    
    if (pMacSite->m_pIHXCoreMutex) pMacSite->m_pIHXCoreMutex->UnlockCoreMutex();
}
#endif
#endif
