Loading services/autofill/java/com/android/server/autofill/AnchoredWindow.java 0 → 100644 +133 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.autofill; import static com.android.server.autofill.Helper.DEBUG; import android.content.Context; import android.graphics.Rect; import android.util.Slog; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.widget.FrameLayout; /** * A window above the application that is smartly anchored to a rectangular region. */ final class AnchoredWindow { private static final String TAG = "AutoFill"; private final WindowManager mWm; private final View mRootView; private final View mView; private final int mWidth; private final int mHeight; private boolean mIsShowing = false; /** * Constructor. * * @param wm window manager that draws the view on a window * @param view singleton view in the window * @param width requested width of the view * @param height requested height of the view */ AnchoredWindow(WindowManager wm, View view, int width, int height) { mWm = wm; mRootView = wrapView(view, width, height); mView = view; mWidth = width; mHeight = height; } /** * Shows the window. * * @param bounds the rectangular region this window should be anchored to */ void show(Rect bounds) { LayoutParams params = createBaseLayoutParams(); params.x = bounds.left; params.y = bounds.bottom; if (!mIsShowing) { if (DEBUG) Slog.d(TAG, "adding view " + mView); mWm.addView(mRootView, params); } else { if (DEBUG) Slog.d(TAG, "updating view " + mView); mWm.updateViewLayout(mRootView, params); } mIsShowing = true; } /** * Hides the window. */ void hide() { if (DEBUG) Slog.d(TAG, "removing view " + mView); if (mIsShowing) { mWm.removeView(mRootView); } mIsShowing = false; } /** * Wraps a view with a SelfRemovingView and sets its requested width and height. */ private View wrapView(View view, int width, int height) { ViewGroup viewGroup = new SelfRemovingView(view.getContext()); viewGroup.addView(view, new ViewGroup.LayoutParams(width, height)); return viewGroup; } private static LayoutParams createBaseLayoutParams() { LayoutParams params = new LayoutParams(); // TODO(b/33197203): LayoutParams.TYPE_AUTOFILL params.type = LayoutParams.TYPE_SYSTEM_ALERT; params.flags = LayoutParams.SOFT_INPUT_STATE_UNCHANGED | LayoutParams.FLAG_LAYOUT_IN_SCREEN | LayoutParams.FLAG_LAYOUT_NO_LIMITS | LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; params.gravity = Gravity.TOP | Gravity.LEFT; params.width = LayoutParams.WRAP_CONTENT; params.height = LayoutParams.WRAP_CONTENT; return params; } /** FrameLayout that listens for touch events removes itself if the touch event is outside. */ private final class SelfRemovingView extends FrameLayout { public SelfRemovingView(Context context) { super(context); } @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { hide(); return true; } else { return super.onTouchEvent(event); } } } } Loading
services/autofill/java/com/android/server/autofill/AnchoredWindow.java 0 → 100644 +133 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.autofill; import static com.android.server.autofill.Helper.DEBUG; import android.content.Context; import android.graphics.Rect; import android.util.Slog; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.widget.FrameLayout; /** * A window above the application that is smartly anchored to a rectangular region. */ final class AnchoredWindow { private static final String TAG = "AutoFill"; private final WindowManager mWm; private final View mRootView; private final View mView; private final int mWidth; private final int mHeight; private boolean mIsShowing = false; /** * Constructor. * * @param wm window manager that draws the view on a window * @param view singleton view in the window * @param width requested width of the view * @param height requested height of the view */ AnchoredWindow(WindowManager wm, View view, int width, int height) { mWm = wm; mRootView = wrapView(view, width, height); mView = view; mWidth = width; mHeight = height; } /** * Shows the window. * * @param bounds the rectangular region this window should be anchored to */ void show(Rect bounds) { LayoutParams params = createBaseLayoutParams(); params.x = bounds.left; params.y = bounds.bottom; if (!mIsShowing) { if (DEBUG) Slog.d(TAG, "adding view " + mView); mWm.addView(mRootView, params); } else { if (DEBUG) Slog.d(TAG, "updating view " + mView); mWm.updateViewLayout(mRootView, params); } mIsShowing = true; } /** * Hides the window. */ void hide() { if (DEBUG) Slog.d(TAG, "removing view " + mView); if (mIsShowing) { mWm.removeView(mRootView); } mIsShowing = false; } /** * Wraps a view with a SelfRemovingView and sets its requested width and height. */ private View wrapView(View view, int width, int height) { ViewGroup viewGroup = new SelfRemovingView(view.getContext()); viewGroup.addView(view, new ViewGroup.LayoutParams(width, height)); return viewGroup; } private static LayoutParams createBaseLayoutParams() { LayoutParams params = new LayoutParams(); // TODO(b/33197203): LayoutParams.TYPE_AUTOFILL params.type = LayoutParams.TYPE_SYSTEM_ALERT; params.flags = LayoutParams.SOFT_INPUT_STATE_UNCHANGED | LayoutParams.FLAG_LAYOUT_IN_SCREEN | LayoutParams.FLAG_LAYOUT_NO_LIMITS | LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; params.gravity = Gravity.TOP | Gravity.LEFT; params.width = LayoutParams.WRAP_CONTENT; params.height = LayoutParams.WRAP_CONTENT; return params; } /** FrameLayout that listens for touch events removes itself if the touch event is outside. */ private final class SelfRemovingView extends FrameLayout { public SelfRemovingView(Context context) { super(context); } @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { hide(); return true; } else { return super.onTouchEvent(event); } } } }