1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
4 
5   This software is provided 'as-is', without any express or implied
6   warranty.  In no event will the authors be held liable for any damages
7   arising from the use of this software.
8 
9   Permission is granted to anyone to use this software for any purpose,
10   including commercial applications, and to alter it and redistribute it
11   freely, subject to the following restrictions:
12 
13   1. The origin of this software must not be misrepresented; you must not
14      claim that you wrote the original software. If you use this software
15      in a product, an acknowledgment in the product documentation would be
16      appreciated but is not required.
17   2. Altered source versions must be plainly marked as such, and must not be
18      misrepresented as being the original software.
19   3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22 
23 #if SDL_VIDEO_DRIVER_ANDROID
24 
25 #include "SDL_syswm.h"
26 #include "../SDL_sysvideo.h"
27 #include "../../events/SDL_keyboard_c.h"
28 #include "../../events/SDL_mouse_c.h"
29 #include "../../events/SDL_windowevents_c.h"
30 #include "../../core/android/SDL_android.h"
31 
32 #include "SDL_androidvideo.h"
33 #include "SDL_androidwindow.h"
34 #include "SDL_hints.h"
35 
36 /* Currently only one window */
37 SDL_Window *Android_Window = NULL;
38 
39 int
Android_CreateWindow(_THIS,SDL_Window * window)40 Android_CreateWindow(_THIS, SDL_Window * window)
41 {
42     SDL_WindowData *data;
43     int retval = 0;
44 
45     Android_ActivityMutex_Lock_Running();
46 
47     if (Android_Window) {
48         retval = SDL_SetError("Android only supports one window");
49         goto endfunction;
50     }
51 
52     /* Set orientation */
53     Android_JNI_SetOrientation(window->w, window->h, window->flags & SDL_WINDOW_RESIZABLE, SDL_GetHint(SDL_HINT_ORIENTATIONS));
54 
55     /* Adjust the window data to match the screen */
56     window->x = 0;
57     window->y = 0;
58     window->w = Android_SurfaceWidth;
59     window->h = Android_SurfaceHeight;
60 
61     window->flags &= ~SDL_WINDOW_HIDDEN;
62     window->flags |= SDL_WINDOW_SHOWN;          /* only one window on Android */
63 
64     /* One window, it always has focus */
65     SDL_SetMouseFocus(window);
66     SDL_SetKeyboardFocus(window);
67 
68     data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
69     if (!data) {
70         retval = SDL_OutOfMemory();
71         goto endfunction;
72     }
73 
74     data->native_window = Android_JNI_GetNativeWindow();
75 
76     if (!data->native_window) {
77         SDL_free(data);
78         retval = SDL_SetError("Could not fetch native window");
79         goto endfunction;
80     }
81 
82     /* Do not create EGLSurface for Vulkan window since it will then make the window
83        incompatible with vkCreateAndroidSurfaceKHR */
84     if ((window->flags & SDL_WINDOW_OPENGL) != 0) {
85         data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->native_window);
86 
87         if (data->egl_surface == EGL_NO_SURFACE) {
88             ANativeWindow_release(data->native_window);
89             SDL_free(data);
90             retval = -1;
91             goto endfunction;
92         }
93     }
94 
95     window->driverdata = data;
96     Android_Window = window;
97 
98 endfunction:
99 
100     SDL_UnlockMutex(Android_ActivityMutex);
101 
102     return retval;
103 }
104 
105 void
Android_SetWindowTitle(_THIS,SDL_Window * window)106 Android_SetWindowTitle(_THIS, SDL_Window *window)
107 {
108     Android_JNI_SetActivityTitle(window->title);
109 }
110 
111 void
Android_SetWindowFullscreen(_THIS,SDL_Window * window,SDL_VideoDisplay * display,SDL_bool fullscreen)112 Android_SetWindowFullscreen(_THIS, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen)
113 {
114     SDL_LockMutex(Android_ActivityMutex);
115 
116     if (window == Android_Window) {
117 
118         /* If the window is being destroyed don't change visible state */
119         if (!window->is_destroying) {
120             Android_JNI_SetWindowStyle(fullscreen);
121         }
122 
123         /* Ensure our size matches reality after we've executed the window style change.
124          *
125          * It is possible that we've set width and height to the full-size display, but on
126          * Samsung DeX or Chromebooks or other windowed Android environemtns, our window may
127          * still not be the full display size.
128          */
129         if (!SDL_IsDeXMode() && !SDL_IsChromebook()) {
130             goto endfunction;
131         }
132 
133         SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
134 
135         if (!data || !data->native_window) {
136             if (data && !data->native_window) {
137                 SDL_SetError("Missing native window");
138             }
139             goto endfunction;
140         }
141 
142         int old_w = window->w;
143         int old_h = window->h;
144 
145         int new_w = ANativeWindow_getWidth(data->native_window);
146         int new_h = ANativeWindow_getHeight(data->native_window);
147 
148         if (new_w < 0 || new_h < 0) {
149             SDL_SetError("ANativeWindow_getWidth/Height() fails");
150         }
151 
152         if (old_w != new_w || old_h != new_h) {
153             SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, new_w, new_h);
154         }
155     }
156 
157 endfunction:
158 
159     SDL_UnlockMutex(Android_ActivityMutex);
160 }
161 
162 void
Android_MinimizeWindow(_THIS,SDL_Window * window)163 Android_MinimizeWindow(_THIS, SDL_Window *window)
164 {
165     Android_JNI_MinizeWindow();
166 }
167 
168 void
Android_DestroyWindow(_THIS,SDL_Window * window)169 Android_DestroyWindow(_THIS, SDL_Window *window)
170 {
171     SDL_LockMutex(Android_ActivityMutex);
172 
173     if (window == Android_Window) {
174         Android_Window = NULL;
175 
176         if (window->driverdata) {
177             SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
178             if (data->egl_surface != EGL_NO_SURFACE) {
179                 SDL_EGL_DestroySurface(_this, data->egl_surface);
180             }
181             if (data->native_window) {
182                 ANativeWindow_release(data->native_window);
183             }
184             SDL_free(window->driverdata);
185             window->driverdata = NULL;
186         }
187     }
188 
189     SDL_UnlockMutex(Android_ActivityMutex);
190 }
191 
192 SDL_bool
Android_GetWindowWMInfo(_THIS,SDL_Window * window,SDL_SysWMinfo * info)193 Android_GetWindowWMInfo(_THIS, SDL_Window *window, SDL_SysWMinfo *info)
194 {
195     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
196 
197     if (info->version.major == SDL_MAJOR_VERSION &&
198         info->version.minor == SDL_MINOR_VERSION) {
199         info->subsystem = SDL_SYSWM_ANDROID;
200         info->info.android.window = data->native_window;
201         info->info.android.surface = data->egl_surface;
202         return SDL_TRUE;
203     } else {
204         SDL_SetError("Application not compiled with SDL %d.%d",
205                      SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
206         return SDL_FALSE;
207     }
208 }
209 
210 #endif /* SDL_VIDEO_DRIVER_ANDROID */
211 
212 /* vi: set ts=4 sw=4 expandtab: */
213