bool OculusRift::attachToWindow( const ci::app::WindowRef& window )
{
	if( ! mHmd )
		return false;
	
	if( ! isValid( window ) )
		return false;
	
	if( isDesktopExtended() ) {
		mImpl = std::unique_ptr<ExtendedModeImpl>( new ExtendedModeImpl{ this } );
	} else {
		mImpl = std::unique_ptr<DirectModeImpl>( new DirectModeImpl{ this } );
	}
	
	if( ! mImpl->initialize( window ) )
		return false;
	
	// Override the window's startDraw() and finishDraw() methods, so we can inject our own code.
	RendererGlRef rendererGl = std::dynamic_pointer_cast<RendererGl>( window->getRenderer() );
	if( rendererGl ) {
		rendererGl->setStartDrawFn( std::bind( &OculusRift::startDrawFn, this, std::placeholders::_1 ) );
		rendererGl->setFinishDrawFn( std::bind( &OculusRift::finishDrawFn, this, std::placeholders::_1 ) );
	}
	else {
		throw std::runtime_error( "OculusRift can only be used in combination with RendererGl." );
	}
	// Connect to the window close event, so we can properly destroy our HMD.
	window->getSignalClose().connect( std::bind( [&]( ovrHmd hmd ) { assert( hmd == mHmd ); detachFromWindow(); }, mHmd ) );
	
	ovrHmd_ConfigureTracking( mHmd, mTrackingCaps, 0 );
	ovrGLConfig cfg;
	cfg.OGL.Header.API = ovrRenderAPI_OpenGL;
	cfg.OGL.Header.BackBufferSize = mHmd->Resolution;
	cfg.OGL.Header.Multisample = 1; // TODO: support multi-sampling
#if defined( CINDER_MSW )
	cfg.OGL.Window = static_cast<HWND>( window->getNative() );
	cfg.OGL.DC = window->getDc();
#endif
	if( ! ovrHmd_ConfigureRendering( mHmd, &cfg.Config, mDistortionCaps, mHmd->MaxEyeFov, mEyeRenderDesc ) ) {
		throw std::runtime_error( "Failed to configure rendering." );
	}
	updateHmdSettings();
	
	mWindow = window;
	return true;
}