Android Window focus

Discussion of issues specific to mobile platforms such as iOS, Android, Symbian and Meego.
Post Reply
libolt
Greenskin
Posts: 126
Joined: Wed Jan 19, 2005 4:48 am
x 9

Android Window focus

Post by libolt »

In my game I am using SDL 2 for input and other stuff and Ogre 1.9 for rendering. Now I have Ogre rendering properly and can read input from the software keyboard. However, SDL does not seem to be receiving any touch input events. I have tried forcing it to grab input but it appears that Ogre may be taking control back over. Is it possible to prevent this? I currently have both SDL and Ogre creating their windows from the Android native window. When I try to have Ogre use the SDL window handle (available on Android in the current development release of 2.04) it crashes creating the window.

Thanks.
User avatar
Argosse
Gnoblar
Posts: 17
Joined: Wed Apr 27, 2011 9:43 pm

Re: Android Window focus

Post by Argosse »

I think you will have to inject the input that ogre receives into your SDL.
libolt
Greenskin
Posts: 126
Joined: Wed Jan 19, 2005 4:48 am
x 9

Re: Android Window focus

Post by libolt »

Do you by chance have an example of how to do such a thing? I never did get this figured out. The software keyboard is read by SDL just fine, but no other events get picked up.
libolt
Greenskin
Posts: 126
Joined: Wed Jan 19, 2005 4:48 am
x 9

Re: Android Window focus

Post by libolt »

Ok to expand on my situation further:

I do not use OgreActivityJNi.java and try to use the minimum amount of JNI calls from my code for initializing or managing ogre. Everything is done in the native c++ code like on linux and Windows, the other platforms I code on. I use a minimal amount of jni code to load SDL_main as follows:

Code: Select all

    
/* Include the SDL main definition header */
#include "SDL_main.h"

/*******************************************************************************
                 Functions called by JNI
*******************************************************************************/
#include <jni.h>

// Called before SDL_main() to initialize JNI bindings in SDL library
extern "C" { void SDL_Android_Init(JNIEnv* env, jclass cls); }

// Start up the SDL app
extern "C"
{
void Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv* env, jclass cls, jobject obj)
{
    // This interface could expand with ABI negotiation, calbacks, etc. 
    SDL_Android_Init(env, cls);

    SDL_SetMainReady();

    // Run the application code! 
    int status;
    char *argv[2];
    argv[0] = SDL_strdup("SDL_app");
    argv[1] = NULL;
    status = SDL_main(1, argv);

    // Do not issue an exit or the whole application will terminate instead of just the SDL thread 
//    exit(status);
}
}
Then I initialize SDL with the following with #ifdefs for Android:

Code: Select all

bool renderEngine::initSDL() // Initializes SDL Subsystem
{
	if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
	{
        fprintf(stderr,
                "\nUnable to initialize SDL:  %s\n",
                SDL_GetError()
               );
#if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID

//        __android_log_print(ANDROID_LOG_DEBUG, "com.libolt.ubc", "SDL Error = %s", SDL_GetError());
        Ogre::String msg = "SDL Error = " +Ogre::StringConverter::toString(SDL_GetError());
        logMsg(msg);
#endif

        return 1;
    }

#if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
    SDL_DisplayMode mode;
	SDL_GetDesktopDisplayMode(0,&mode);

    JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv();

    jclass class_sdl_activity   = env->FindClass("org/libsdl/app/SDLActivity");
    jmethodID method_get_native_surface = env->GetStaticMethodID(class_sdl_activity, "getNativeSurface", "()Landroid/view/Surface;");
    jobject raw_surface = env->CallStaticObjectMethod(class_sdl_activity, method_get_native_surface);
    ANativeWindow* native_window = ANativeWindow_fromSurface(env, raw_surface);

    std::string message = "SDL Window Created!";
	logMsg(message);

#else
    sdlWindow = SDL_CreateWindow("Ultimate Basketball Challenge",
	                             SDL_WINDOWPOS_UNDEFINED,
	                             SDL_WINDOWPOS_UNDEFINED,
	                             1024,768,0);

    SDL_VERSION( &sysInfo.version );


    if (SDL_GetWindowWMInfo(sdlWindow, &sysInfo) <= 0)
    {
    	assert( false );
    }
#endif

	return true;
}
I follow this up by initializing ogre with the following:

Code: Select all

bool renderEngine::initOgre() // Initializes Ogre Subsystem
{

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
	winHandle = Ogre::StringConverter::toString((unsigned long int)sysInfo.info.win.window);
#elif OGRE_PLATFORM == OGRE_PLATFORM_LINUX
	winHandle = Ogre::StringConverter::toString((unsigned long)sysInfo.info.x11.window);
#elif OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
    JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv();

    jclass class_sdl_activity   = env->FindClass("org/libsdl/app/SDLActivity");
    jmethodID method_get_native_surface = env->GetStaticMethodID(class_sdl_activity, "getNativeSurface", "()Landroid/view/Surface;");
    jobject raw_surface = env->CallStaticObjectMethod(class_sdl_activity, method_get_native_surface);
    ANativeWindow* native_window = ANativeWindow_fromSurface(env, raw_surface);

	winHandle =  Ogre::StringConverter::toString((int)native_window);
	logMsg("winHandle = " +winHandle);
#else
	// Error, both can't be defined or undefined same time
#endif

	//std::cout << "winHandle = " << winHandle << std::endl;
	mRoot = new Ogre::Root("", "", "Ogre.log");
	const Ogre::String pluginDir = OGRE_PLUGIN_DIR;

//#if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
//#else
	inputSystem *input = inputSystem::Instance();
//#endif
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
	const Ogre::String buildType = BUILD_TYPE;

	if (buildType == "Debug")
	{
		mRoot->loadPlugin(pluginDir + "/RenderSystem_Direct3D9_d.dll");
		mRoot->loadPlugin(pluginDir + "/Plugin_CgProgramManager_d");
	}
	else
	{
		mRoot->loadPlugin(pluginDir + "/RenderSystem_Direct3D9");
		mRoot->loadPlugin(pluginDir + "/Plugin_CgProgramManager");
	}
#elif OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
	//	    mRoot->loadPlugin();
#ifdef OGRE_STATIC_LIB
	gStaticPluginLoader = new Ogre::StaticPluginLoader();
	gStaticPluginLoader->load();
#endif
#elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE
	mRoot->loadPlugin("RenderSystem_GL");
#else
	mRoot->loadPlugin(pluginDir + "/RenderSystem_GL");
	mRoot->loadPlugin(pluginDir + "/Plugin_CgProgramManager");
#endif

#if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
	mRoot->setRenderSystem(mRoot->getAvailableRenderers().at(0));
	mRoot->initialise(false);
#else
	Ogre::RenderSystemList rsList = mRoot->getAvailableRenderers();

	int c = 0;
	bool foundit = false;
	Ogre::RenderSystem *selectedRenderSystem = 0;
	while (c < (int)rsList.size())
	{
		selectedRenderSystem = rsList.at(c);
		Ogre::String rname = selectedRenderSystem->getName();
		if (rname.compare("OpenGL Rendering Subsystem") == 0)
		{
			foundit = true;
			break;
		}
		c++; // <-- oh how clever
		logMsg(Ogre::StringConverter::toString(c++));
	}

	//we found it, we might as well use it!
	mRoot->setRenderSystem(selectedRenderSystem);
	mWindow = mRoot->initialise(false, "Ultimate Basketball Challenge");
#endif

    logMsg("OGRE initialized successfully!");

	return true;
}
Any help is greatly appreciated. I would like to get touch input working on Android and eventually full game controller / joystick support as well.
Post Reply