5package io.flutter.plugin.platform;
7import static android.content.Context.WINDOW_SERVICE;
8import static android.view.View.OnFocusChangeListener;
13import android.content.ContextWrapper;
14import android.content.MutableContextWrapper;
15import android.graphics.drawable.ColorDrawable;
19import android.view.WindowManager;
20import android.view.accessibility.AccessibilityEvent;
21import android.view.inputmethod.InputMethodManager;
22import android.widget.FrameLayout;
23import androidx.annotation.Keep;
24import androidx.annotation.NonNull;
25import androidx.annotation.Nullable;
46 private static final String TAG =
"PlatformViewsController";
71 private final OnFocusChangeListener focusChangeListener;
81 private AccessibilityDelegatingFrameLayout rootView;
85 private FrameLayout container;
89 private boolean startFocused =
false;
92 private final Context outerContext;
104 OnFocusChangeListener focusChangeListener) {
105 super(
new ImmContext(outerContext), display);
106 this.accessibilityEventsDelegate = accessibilityEventsDelegate;
107 this.viewId = viewId;
108 this.focusChangeListener = focusChangeListener;
109 this.outerContext = outerContext;
111 state.platformView = view;
114 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
115 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
116 getWindow().setType(WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION);
125 Context outerContext,
129 OnFocusChangeListener focusChangeListener,
130 boolean startFocused) {
131 super(
new ImmContext(outerContext), display);
132 this.accessibilityEventsDelegate = accessibilityEventsDelegate;
134 this.focusChangeListener = focusChangeListener;
135 this.outerContext = outerContext;
138 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
139 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
140 this.startFocused = startFocused;
144 protected void onCreate(Bundle savedInstanceState) {
145 super.onCreate(savedInstanceState);
147 getWindow().setBackgroundDrawable(
new ColorDrawable(
android.graphics.Color.TRANSPARENT));
148 if (
state.fakeWindowViewGroup ==
null) {
151 if (
state.windowManagerHandler ==
null) {
152 WindowManager windowManagerDelegate =
153 (WindowManager) getContext().getSystemService(WINDOW_SERVICE);
154 state.windowManagerHandler =
158 container =
new FrameLayout(getContext());
162 Context baseContext =
163 new PresentationContext(getContext(),
state.windowManagerHandler, outerContext);
165 View embeddedView =
state.platformView.getView();
166 if (embeddedView.getContext() instanceof MutableContextWrapper) {
167 MutableContextWrapper currentContext = (MutableContextWrapper) embeddedView.getContext();
168 currentContext.setBaseContext(baseContext);
178 "Unexpected platform view context for view ID "
180 +
"; some functionality may not work correctly. When constructing a platform view "
181 +
"in the factory, ensure that the view returned from PlatformViewFactory#create "
182 +
"returns the provided context from getContext(). If you are unable to associate "
183 +
"the view with that context, consider using Hybrid Composition instead.");
186 container.addView(embeddedView);
188 new AccessibilityDelegatingFrameLayout(
189 getContext(), accessibilityEventsDelegate, embeddedView);
190 rootView.addView(container);
191 rootView.addView(
state.fakeWindowViewGroup);
193 embeddedView.setOnFocusChangeListener(focusChangeListener);
194 rootView.setFocusableInTouchMode(
true);
196 embeddedView.requestFocus();
198 rootView.requestFocus();
200 setContentView(rootView);
205 if (container !=
null) {
206 container.removeAllViews();
208 if (rootView !=
null) {
209 rootView.removeAllViews();
216 return state.platformView;
224 private static class ImmContext
extends ContextWrapper {
225 private @NonNull
final InputMethodManager inputMethodManager;
227 ImmContext(Context
base) {
231 private ImmContext(Context
base, @Nullable InputMethodManager inputMethodManager) {
233 this.inputMethodManager =
234 inputMethodManager !=
null
236 : (InputMethodManager)
base.getSystemService(INPUT_METHOD_SERVICE);
240 public Object getSystemService(String
name) {
241 if (INPUT_METHOD_SERVICE.equals(
name)) {
242 return inputMethodManager;
244 return super.getSystemService(
name);
248 public Context createDisplayContext(Display display) {
249 Context displayContext = super.createDisplayContext(display);
250 return new ImmContext(displayContext, inputMethodManager);
259 private static class PresentationContext
extends ContextWrapper {
260 private @NonNull
final WindowManagerHandler windowManagerHandler;
261 private @Nullable WindowManager windowManager;
262 private final Context flutterAppWindowContext;
266 @NonNull WindowManagerHandler windowManagerHandler,
267 Context flutterAppWindowContext) {
269 this.windowManagerHandler = windowManagerHandler;
270 this.flutterAppWindowContext = flutterAppWindowContext;
274 public Object getSystemService(String
name) {
275 if (WINDOW_SERVICE.equals(
name)) {
276 if (isCalledFromAlertDialog()) {
288 return flutterAppWindowContext.getSystemService(
name);
290 return getWindowManager();
292 return super.getSystemService(
name);
295 private WindowManager getWindowManager() {
296 if (windowManager ==
null) {
297 windowManager = windowManagerHandler;
299 return windowManager;
302 private boolean isCalledFromAlertDialog() {
303 StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
304 for (
int i = 0;
i < stackTraceElements.length &&
i < 11;
i++) {
305 if (stackTraceElements[
i].getClassName().
equals(AlertDialog.class.getCanonicalName())
306 && stackTraceElements[
i].getMethodName().equals(
"<init>")) {
314 private static class AccessibilityDelegatingFrameLayout
extends FrameLayout {
315 private final AccessibilityEventsDelegate accessibilityEventsDelegate;
316 private final View embeddedView;
318 public AccessibilityDelegatingFrameLayout(
320 AccessibilityEventsDelegate accessibilityEventsDelegate,
323 this.accessibilityEventsDelegate = accessibilityEventsDelegate;
324 this.embeddedView = embeddedView;
328 public boolean requestSendAccessibilityEvent(View child, AccessibilityEvent
event) {
329 return accessibilityEventsDelegate.requestSendAccessibilityEvent(embeddedView, child,
event);
bool equals(SkDrawable *a, SkDrawable *b)
static void w(@NonNull String tag, @NonNull String message)
DEF_SWITCHES_START aot vmservice shared library name