grimfang4 / sdl-gpu

A library for high-performance, modern 2D graphics with SDL written in C.
MIT License
1.19k stars 123 forks source link

Unwanted y offset on android #178

Open damiano-massarelli opened 5 years ago

damiano-massarelli commented 5 years ago

Hi there, I have been using SDL_gpu to develop an android game. So far, every works fine. The only problem is that when drawing on android everything is pushed down along the y axis by a certain offset. This problem does not occur when using plain SDL. Here is an example: this is what the following code produces.

SDL_Window* window = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED,                 
SDL_WINDOWPOS_CENTERED, 0, 0, SDL_WINDOW_SHOWN);

SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);

while (true) {
    SDL_SetRenderDrawColor(renderer, 0xFF, 0, 0, 0xFF);
    SDL_RenderClear(renderer);

   SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0xFF);
   SDL_Rect outlineRect{5, 5, 300, 300};
   SDL_RenderDrawRect(renderer, &outlineRect);

   SDL_RenderPresent(renderer);
}

plain_sdl

This is exactly what I expected. However, doing the same thing with SDL_gpu results in the rectangle being pushed down by a certain amount on the y axis

GPU_SetPreInitFlags(GPU_INIT_ENABLE_VSYNC);
GPU_Target* screen = GPU_Init(0, 0, GPU_DEFAULT_INIT_FLAGS);

while (true) {

    GPU_ClearColor(screen, SDL_Color{255, 0, 0, 255});

    GPU_RectangleFilled(screen, 5, 5, 300, 300, SDL_Color{0, 255, 0, 255});

    GPU_Flip(screen);
}

sdl_gpu

It looks as if SDL_gpu is trying to compensate for the height of the android titlebar. I noticed that this only happens on devices with virtual keys (on my Samsung S7 everything is in the right position).

Besides the weird look of it, it also makes user touches inaccurate. In fact, touch coordinates are correclty detected (with (0, 0) being the actual corner of the window) making it impossible to detect whether the user tapped on an element.

Do you have any idea as to why this is happening? Is there a way to fix it? Thank you very much

damiano-massarelli commented 5 years ago

I found a quick fix for it. It is not a complete solution but it will do the trick. Basically, in SDLActivity.java the following code is executed after the app is launched.

Window window = ((Activity) context).getWindow();
if (window != null) {
    if ((msg.obj instanceof Integer) && (((Integer) msg.obj).intValue() != 0)) {
        int flags = View.SYSTEM_UI_FLAG_FULLSCREEN |
                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
                    View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
                    View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
                    View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.INVISIBLE;
        window.getDecorView().setSystemUiVisibility(flags);        
        window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
        SDLActivity.mFullscreenModeActive = true;
    } else {
        int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_VISIBLE;
        window.getDecorView().setSystemUiVisibility(flags);
        window.addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
        window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        SDLActivity.mFullscreenModeActive = false;
    }
}

(using SDL 2.0.9) The else brach is where full screen is exited. I don't really know what is the purpose of this code but I think it handles commands sent from the sdl thread. That being said, it is still not clear to me why this code is called when SDL_gpu is used but removing the else branch solves (at least until the real reason comes out) the issue.