| | |
| | | /* |
| | | Simple DirectMedia Layer |
| | | Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> |
| | | Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org> |
| | | |
| | | This software is provided 'as-is', without any express or implied |
| | | warranty. In no event will the authors be held liable for any damages |
| | |
| | | #include "SDL_androidwindow.h" |
| | | #include "SDL_hints.h" |
| | | |
| | | /* Currently only one window */ |
| | | SDL_Window *Android_Window = NULL; |
| | | |
| | | int |
| | | Android_CreateWindow(_THIS, SDL_Window * window) |
| | | { |
| | | SDL_WindowData *data; |
| | | |
| | | int retval = 0; |
| | | |
| | | Android_ActivityMutex_Lock_Running(); |
| | | |
| | | if (Android_Window) { |
| | | return SDL_SetError("Android only supports one window"); |
| | | retval = SDL_SetError("Android only supports one window"); |
| | | goto endfunction; |
| | | } |
| | | |
| | | Android_PauseSem = SDL_CreateSemaphore(0); |
| | | Android_ResumeSem = SDL_CreateSemaphore(0); |
| | | |
| | | /* Set orientation */ |
| | | Android_JNI_SetOrientation(window->w, window->h, window->flags & SDL_WINDOW_RESIZABLE, SDL_GetHint(SDL_HINT_ORIENTATIONS)); |
| | |
| | | window->w = Android_SurfaceWidth; |
| | | window->h = Android_SurfaceHeight; |
| | | |
| | | window->flags &= ~SDL_WINDOW_RESIZABLE; /* window is NEVER resizeable */ |
| | | window->flags &= ~SDL_WINDOW_HIDDEN; |
| | | window->flags |= SDL_WINDOW_SHOWN; /* only one window on Android */ |
| | | window->flags |= SDL_WINDOW_INPUT_FOCUS; /* always has input focus */ |
| | | |
| | | /* One window, it always has focus */ |
| | | SDL_SetMouseFocus(window); |
| | | SDL_SetKeyboardFocus(window); |
| | | |
| | | |
| | | data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data)); |
| | | if (!data) { |
| | | return SDL_OutOfMemory(); |
| | | retval = SDL_OutOfMemory(); |
| | | goto endfunction; |
| | | } |
| | | |
| | | |
| | | data->native_window = Android_JNI_GetNativeWindow(); |
| | | |
| | | |
| | | if (!data->native_window) { |
| | | SDL_free(data); |
| | | return SDL_SetError("Could not fetch native window"); |
| | | retval = SDL_SetError("Could not fetch native window"); |
| | | goto endfunction; |
| | | } |
| | | |
| | | /* Do not create EGLSurface for Vulkan window since it will then make the window |
| | | incompatible with vkCreateAndroidSurfaceKHR */ |
| | | if ((window->flags & SDL_WINDOW_VULKAN) == 0) { |
| | | if ((window->flags & SDL_WINDOW_OPENGL) != 0) { |
| | | data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->native_window); |
| | | |
| | | if (data->egl_surface == EGL_NO_SURFACE) { |
| | | ANativeWindow_release(data->native_window); |
| | | SDL_free(data); |
| | | return SDL_SetError("Could not create GLES window surface"); |
| | | retval = -1; |
| | | goto endfunction; |
| | | } |
| | | } |
| | | |
| | | window->driverdata = data; |
| | | Android_Window = window; |
| | | |
| | | return 0; |
| | | |
| | | endfunction: |
| | | |
| | | SDL_UnlockMutex(Android_ActivityMutex); |
| | | |
| | | return retval; |
| | | } |
| | | |
| | | void |
| | | Android_SetWindowTitle(_THIS, SDL_Window * window) |
| | | Android_SetWindowTitle(_THIS, SDL_Window *window) |
| | | { |
| | | Android_JNI_SetActivityTitle(window->title); |
| | | } |
| | | |
| | | void |
| | | Android_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen) |
| | | Android_SetWindowFullscreen(_THIS, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen) |
| | | { |
| | | /* If the window is being destroyed don't change visible state */ |
| | | if (!window->is_destroying) { |
| | | Android_JNI_SetWindowStyle(fullscreen); |
| | | SDL_LockMutex(Android_ActivityMutex); |
| | | |
| | | if (window == Android_Window) { |
| | | |
| | | /* If the window is being destroyed don't change visible state */ |
| | | if (!window->is_destroying) { |
| | | Android_JNI_SetWindowStyle(fullscreen); |
| | | } |
| | | |
| | | /* Ensure our size matches reality after we've executed the window style change. |
| | | * |
| | | * It is possible that we've set width and height to the full-size display, but on |
| | | * Samsung DeX or Chromebooks or other windowed Android environemtns, our window may |
| | | * still not be the full display size. |
| | | */ |
| | | if (!SDL_IsDeXMode() && !SDL_IsChromebook()) { |
| | | goto endfunction; |
| | | } |
| | | |
| | | SDL_WindowData *data = (SDL_WindowData *)window->driverdata; |
| | | |
| | | if (!data || !data->native_window) { |
| | | if (data && !data->native_window) { |
| | | SDL_SetError("Missing native window"); |
| | | } |
| | | goto endfunction; |
| | | } |
| | | |
| | | int old_w = window->w; |
| | | int old_h = window->h; |
| | | |
| | | int new_w = ANativeWindow_getWidth(data->native_window); |
| | | int new_h = ANativeWindow_getHeight(data->native_window); |
| | | |
| | | if (new_w < 0 || new_h < 0) { |
| | | SDL_SetError("ANativeWindow_getWidth/Height() fails"); |
| | | } |
| | | |
| | | if (old_w != new_w || old_h != new_h) { |
| | | SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, new_w, new_h); |
| | | } |
| | | } |
| | | |
| | | /* Ensure our size matches reality after we've executed the window style change. |
| | | * |
| | | * It is possible that we've set width and height to the full-size display, but on |
| | | * Samsung DeX or Chromebooks or other windowed Android environemtns, our window may |
| | | * still not be the full display size. |
| | | */ |
| | | if (!SDL_IsDeXMode() && !SDL_IsChromebook()) { |
| | | return; |
| | | } |
| | | endfunction: |
| | | |
| | | SDL_WindowData * data = (SDL_WindowData *)window->driverdata; |
| | | |
| | | if (!data || !data->native_window) { |
| | | return; |
| | | } |
| | | |
| | | int old_w = window->w; |
| | | int old_h = window->h; |
| | | |
| | | int new_w = ANativeWindow_getWidth(data->native_window); |
| | | int new_h = ANativeWindow_getHeight(data->native_window); |
| | | |
| | | if (old_w != new_w || old_h != new_h) { |
| | | SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, new_w, new_h); |
| | | } |
| | | SDL_UnlockMutex(Android_ActivityMutex); |
| | | } |
| | | |
| | | void |
| | | Android_DestroyWindow(_THIS, SDL_Window * window) |
| | | Android_MinimizeWindow(_THIS, SDL_Window *window) |
| | | { |
| | | SDL_WindowData *data; |
| | | |
| | | Android_JNI_MinizeWindow(); |
| | | } |
| | | |
| | | void |
| | | Android_DestroyWindow(_THIS, SDL_Window *window) |
| | | { |
| | | SDL_LockMutex(Android_ActivityMutex); |
| | | |
| | | if (window == Android_Window) { |
| | | Android_Window = NULL; |
| | | if (Android_PauseSem) SDL_DestroySemaphore(Android_PauseSem); |
| | | if (Android_ResumeSem) SDL_DestroySemaphore(Android_ResumeSem); |
| | | Android_PauseSem = NULL; |
| | | Android_ResumeSem = NULL; |
| | | |
| | | if(window->driverdata) { |
| | | data = (SDL_WindowData *) window->driverdata; |
| | | |
| | | if (window->driverdata) { |
| | | SDL_WindowData *data = (SDL_WindowData *) window->driverdata; |
| | | if (data->egl_surface != EGL_NO_SURFACE) { |
| | | SDL_EGL_DestroySurface(_this, data->egl_surface); |
| | | } |
| | |
| | | window->driverdata = NULL; |
| | | } |
| | | } |
| | | |
| | | SDL_UnlockMutex(Android_ActivityMutex); |
| | | } |
| | | |
| | | SDL_bool |
| | | Android_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info) |
| | | Android_GetWindowWMInfo(_THIS, SDL_Window *window, SDL_SysWMinfo *info) |
| | | { |
| | | SDL_WindowData *data = (SDL_WindowData *) window->driverdata; |
| | | |