blob: f58a91b8b369b97b37b984efca16e993b51cd2a9 [file] [log] [blame]
Daniel Sandlerc4f2a562012-05-04 11:55:46 -04001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.systemui.statusbar.phone;
18
Adrian Roos0bd8a4b2016-03-14 16:21:44 -070019import android.annotation.ColorInt;
20import android.annotation.DrawableRes;
21import android.annotation.LayoutRes;
John Spurlock257f2832013-09-21 18:41:53 -040022import android.app.StatusBarManager;
Daniel Sandlerc4f2a562012-05-04 11:55:46 -040023import android.content.Context;
Adrian Roos0bd8a4b2016-03-14 16:21:44 -070024import android.content.res.Configuration;
Adrian Roos2f2bd9a2015-06-04 18:11:14 -070025import android.content.res.TypedArray;
Daniel Sandler198a0302012-08-17 16:04:31 -040026import android.graphics.Canvas;
27import android.graphics.Paint;
Selim Cineka0fad3b2014-09-19 17:20:05 +020028import android.graphics.PorterDuff;
29import android.graphics.PorterDuffXfermode;
John Spurlockfba91202014-04-22 12:58:26 -040030import android.graphics.Rect;
Adrian Roos0bd8a4b2016-03-14 16:21:44 -070031import android.graphics.drawable.Drawable;
Jaewan Kim50269362016-12-23 11:22:02 +090032import android.media.AudioManager;
John Spurlock0b99ea92014-10-01 15:32:22 -040033import android.media.session.MediaSessionLegacyHelper;
Adrian Roos0bd8a4b2016-03-14 16:21:44 -070034import android.net.Uri;
35import android.os.Bundle;
Selim Cineka0fad3b2014-09-19 17:20:05 +020036import android.os.IBinder;
Adrian Roos8008bd12017-02-22 15:02:09 +010037import android.os.SystemClock;
Daniel Sandlerc4f2a562012-05-04 11:55:46 -040038import android.util.AttributeSet;
Adrian Roos0bd8a4b2016-03-14 16:21:44 -070039import android.view.ActionMode;
Selim Cinek48a92a52017-05-02 20:02:30 -070040import android.view.InputDevice;
Adrian Roos0bd8a4b2016-03-14 16:21:44 -070041import android.view.InputQueue;
Daniel Sandlerc4f2a562012-05-04 11:55:46 -040042import android.view.KeyEvent;
Adrian Roos0bd8a4b2016-03-14 16:21:44 -070043import android.view.LayoutInflater;
44import android.view.Menu;
45import android.view.MenuItem;
Chris Wren5de6e942012-05-16 14:22:21 -040046import android.view.MotionEvent;
Adrian Roos0bd8a4b2016-03-14 16:21:44 -070047import android.view.SurfaceHolder;
Daniel Sandlerb4e56ed2012-09-12 23:07:44 -070048import android.view.View;
Adrian Roos0bd8a4b2016-03-14 16:21:44 -070049import android.view.ViewGroup;
50import android.view.ViewTreeObserver;
51import android.view.Window;
Selim Cineka0fad3b2014-09-19 17:20:05 +020052import android.view.WindowManager;
53import android.view.WindowManagerGlobal;
Daniel Sandlerc4f2a562012-05-04 11:55:46 -040054import android.widget.FrameLayout;
Daniel Sandlerc4f2a562012-05-04 11:55:46 -040055
Adrian Roos0bd8a4b2016-03-14 16:21:44 -070056import com.android.internal.view.FloatingActionMode;
57import com.android.internal.widget.FloatingToolbar;
Chris Wren5de6e942012-05-16 14:22:21 -040058import com.android.systemui.R;
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -070059import com.android.systemui.classifier.FalsingManager;
Jorim Jaggiecbab362014-04-23 16:13:15 +020060import com.android.systemui.statusbar.DragDownHelper;
61import com.android.systemui.statusbar.StatusBarState;
Selim Cinekfab078b2014-03-27 22:45:58 +010062import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
Chris Wren5de6e942012-05-16 14:22:21 -040063
Daniel Sandlerc4f2a562012-05-04 11:55:46 -040064
Jorim Jaggiecbab362014-04-23 16:13:15 +020065public class StatusBarWindowView extends FrameLayout {
Daniel Sandler198a0302012-08-17 16:04:31 -040066 public static final String TAG = "StatusBarWindowView";
Jason Monk2a6ea9c2017-01-26 11:14:51 -050067 public static final boolean DEBUG = StatusBar.DEBUG;
Chris Wren5de6e942012-05-16 14:22:21 -040068
Jorim Jaggiecbab362014-04-23 16:13:15 +020069 private DragDownHelper mDragDownHelper;
Adrian Roos8008bd12017-02-22 15:02:09 +010070 private DoubleTapHelper mDoubleTapHelper;
Selim Cinekb6d85eb2014-03-28 20:21:01 +010071 private NotificationStackScrollLayout mStackScrollLayout;
Daniel Sandlerb4e56ed2012-09-12 23:07:44 -070072 private NotificationPanelView mNotificationPanel;
Adrian Roos9dc32092014-09-02 23:34:10 +020073 private View mBrightnessMirror;
Chris Wren5de6e942012-05-16 14:22:21 -040074
Adrian Roos2f2bd9a2015-06-04 18:11:14 -070075 private int mRightInset = 0;
Adrian Roos85d202b2016-06-02 16:27:47 -070076 private int mLeftInset = 0;
Adrian Roos2f2bd9a2015-06-04 18:11:14 -070077
Jason Monk2a6ea9c2017-01-26 11:14:51 -050078 private StatusBar mService;
Selim Cineka0fad3b2014-09-19 17:20:05 +020079 private final Paint mTransparentSrcPaint = new Paint();
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -070080 private FalsingManager mFalsingManager;
Daniel Sandlerc4f2a562012-05-04 11:55:46 -040081
Adrian Roos0bd8a4b2016-03-14 16:21:44 -070082 // Implements the floating action mode for TextView's Cut/Copy/Past menu. Normally provided by
83 // DecorView, but since this is a special window we have to roll our own.
84 private View mFloatingActionModeOriginatingView;
85 private ActionMode mFloatingActionMode;
86 private FloatingToolbar mFloatingToolbar;
87 private ViewTreeObserver.OnPreDrawListener mFloatingToolbarPreDrawListener;
Selim Cinek48a92a52017-05-02 20:02:30 -070088 private boolean mTouchCancelled;
89 private boolean mTouchActive;
Adrian Roos0bd8a4b2016-03-14 16:21:44 -070090
Daniel Sandlerc4f2a562012-05-04 11:55:46 -040091 public StatusBarWindowView(Context context, AttributeSet attrs) {
92 super(context, attrs);
Chris Wren5de6e942012-05-16 14:22:21 -040093 setMotionEventSplittingEnabled(false);
Selim Cineka0fad3b2014-09-19 17:20:05 +020094 mTransparentSrcPaint.setColor(0);
95 mTransparentSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -070096 mFalsingManager = FalsingManager.getInstance(context);
Adrian Roos8008bd12017-02-22 15:02:09 +010097 mDoubleTapHelper = new DoubleTapHelper(this, active -> {}, () -> {
98 mService.wakeUpIfDozing(SystemClock.uptimeMillis(), this);
99 return true;
100 }, null, null);
Chris Wren5de6e942012-05-16 14:22:21 -0400101 }
102
103 @Override
John Spurlockfba91202014-04-22 12:58:26 -0400104 protected boolean fitSystemWindows(Rect insets) {
105 if (getFitsSystemWindows()) {
Adrian Roos85d202b2016-06-02 16:27:47 -0700106 boolean paddingChanged = insets.top != getPaddingTop()
Jorim Jaggi416493b2014-09-13 03:57:32 +0200107 || insets.bottom != getPaddingBottom();
Jorim Jaggiaa806142015-05-20 18:04:16 -0700108
Adrian Roos2f2bd9a2015-06-04 18:11:14 -0700109 // Super-special right inset handling, because scrims and backdrop need to ignore it.
Adrian Roos85d202b2016-06-02 16:27:47 -0700110 if (insets.right != mRightInset || insets.left != mLeftInset) {
Adrian Roos2f2bd9a2015-06-04 18:11:14 -0700111 mRightInset = insets.right;
Adrian Roos85d202b2016-06-02 16:27:47 -0700112 mLeftInset = insets.left;
Adrian Roos2f2bd9a2015-06-04 18:11:14 -0700113 applyMargins();
114 }
Adrian Roos85d202b2016-06-02 16:27:47 -0700115 // Drop top inset, and pass through bottom inset.
Adrian Roos2f2bd9a2015-06-04 18:11:14 -0700116 if (paddingChanged) {
Adrian Roos85d202b2016-06-02 16:27:47 -0700117 setPadding(0, 0, 0, 0);
Jorim Jaggi416493b2014-09-13 03:57:32 +0200118 }
Jorim Jaggid7daab72014-05-06 22:22:20 +0200119 insets.left = 0;
120 insets.top = 0;
121 insets.right = 0;
John Spurlockfba91202014-04-22 12:58:26 -0400122 } else {
Adrian Roos85d202b2016-06-02 16:27:47 -0700123 if (mRightInset != 0 || mLeftInset != 0) {
Adrian Roose49e4092015-06-10 18:50:18 -0700124 mRightInset = 0;
Adrian Roos85d202b2016-06-02 16:27:47 -0700125 mLeftInset = 0;
Adrian Roose49e4092015-06-10 18:50:18 -0700126 applyMargins();
127 }
Jorim Jaggi416493b2014-09-13 03:57:32 +0200128 boolean changed = getPaddingLeft() != 0
129 || getPaddingRight() != 0
130 || getPaddingTop() != 0
131 || getPaddingBottom() != 0;
132 if (changed) {
133 setPadding(0, 0, 0, 0);
134 }
Jorim Jaggiaa806142015-05-20 18:04:16 -0700135 insets.top = 0;
John Spurlockfba91202014-04-22 12:58:26 -0400136 }
Jorim Jaggid7daab72014-05-06 22:22:20 +0200137 return false;
John Spurlockfba91202014-04-22 12:58:26 -0400138 }
139
Adrian Roos2f2bd9a2015-06-04 18:11:14 -0700140 private void applyMargins() {
141 final int N = getChildCount();
142 for (int i = 0; i < N; i++) {
143 View child = getChildAt(i);
144 if (child.getLayoutParams() instanceof LayoutParams) {
145 LayoutParams lp = (LayoutParams) child.getLayoutParams();
Adrian Roos85d202b2016-06-02 16:27:47 -0700146 if (!lp.ignoreRightInset
147 && (lp.rightMargin != mRightInset || lp.leftMargin != mLeftInset)) {
Adrian Roos2f2bd9a2015-06-04 18:11:14 -0700148 lp.rightMargin = mRightInset;
Adrian Roos85d202b2016-06-02 16:27:47 -0700149 lp.leftMargin = mLeftInset;
Adrian Roos2f2bd9a2015-06-04 18:11:14 -0700150 child.requestLayout();
151 }
152 }
153 }
154 }
155
156 @Override
157 public FrameLayout.LayoutParams generateLayoutParams(AttributeSet attrs) {
158 return new LayoutParams(getContext(), attrs);
159 }
160
161 @Override
162 protected FrameLayout.LayoutParams generateDefaultLayoutParams() {
163 return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
164 }
165
John Spurlockfba91202014-04-22 12:58:26 -0400166 @Override
Selim Cinek4e6b2d32015-06-25 20:15:33 -0400167 protected void onFinishInflate() {
168 super.onFinishInflate();
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100169 mStackScrollLayout = (NotificationStackScrollLayout) findViewById(
170 R.id.notification_stack_scroller);
Daniel Sandlerb4e56ed2012-09-12 23:07:44 -0700171 mNotificationPanel = (NotificationPanelView) findViewById(R.id.notification_panel);
Adrian Roos9dc32092014-09-02 23:34:10 +0200172 mBrightnessMirror = findViewById(R.id.brightness_mirror);
Selim Cinek4e6b2d32015-06-25 20:15:33 -0400173 }
174
dooyoung.hwange4b841e2016-11-16 08:59:23 +0900175 @Override
176 public void onViewAdded(View child) {
177 super.onViewAdded(child);
178 if (child.getId() == R.id.brightness_mirror) {
179 mBrightnessMirror = child;
180 }
181 }
182
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500183 public void setService(StatusBar service) {
Selim Cinek4e6b2d32015-06-25 20:15:33 -0400184 mService = service;
185 mDragDownHelper = new DragDownHelper(getContext(), this, mStackScrollLayout, mService);
186 }
187
188 @Override
189 protected void onAttachedToWindow () {
190 super.onAttachedToWindow();
Daniel Sandlerb10d8852013-05-08 15:57:06 -0400191
Selim Cineka0fad3b2014-09-19 17:20:05 +0200192 // We need to ensure that our window doesn't suffer from overdraw which would normally
193 // occur if our window is translucent. Since we are drawing the whole window anyway with
194 // the scrim, we don't need the window to be cleared in the beginning.
Jorim Jaggi0e664392014-09-27 01:30:22 +0200195 if (mService.isScrimSrcModeEnabled()) {
196 IBinder windowToken = getWindowToken();
197 WindowManager.LayoutParams lp = (WindowManager.LayoutParams) getLayoutParams();
198 lp.token = windowToken;
199 setLayoutParams(lp);
200 WindowManagerGlobal.getInstance().changeCanvasOpacity(windowToken, true);
201 setWillNotDraw(false);
202 } else {
203 setWillNotDraw(!DEBUG);
204 }
Daniel Sandlerc4f2a562012-05-04 11:55:46 -0400205 }
206
207 @Override
208 public boolean dispatchKeyEvent(KeyEvent event) {
Adrian Roos56cf73a2016-07-18 14:23:32 -0700209 if (mService.interceptMediaKey(event)) {
210 return true;
211 }
212 if (super.dispatchKeyEvent(event)) {
213 return true;
214 }
Daniel Sandlerc4f2a562012-05-04 11:55:46 -0400215 boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
216 switch (event.getKeyCode()) {
Jorim Jaggi8c8bcc12014-04-16 21:36:51 +0200217 case KeyEvent.KEYCODE_BACK:
218 if (!down) {
219 mService.onBackPressed();
220 }
221 return true;
222 case KeyEvent.KEYCODE_MENU:
223 if (!down) {
224 return mService.onMenuPressed();
225 }
Jorim Jaggi34250762014-07-03 23:51:19 +0200226 case KeyEvent.KEYCODE_SPACE:
227 if (!down) {
228 return mService.onSpacePressed();
229 }
John Spurlock0b99ea92014-10-01 15:32:22 -0400230 break;
John Spurlockd06aa572014-09-10 10:40:49 -0400231 case KeyEvent.KEYCODE_VOLUME_DOWN:
232 case KeyEvent.KEYCODE_VOLUME_UP:
John Spurlock0b99ea92014-10-01 15:32:22 -0400233 if (mService.isDozing()) {
Jaewan Kim50269362016-12-23 11:22:02 +0900234 MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
235 event, AudioManager.USE_DEFAULT_STREAM_TYPE, true);
John Spurlock0b99ea92014-10-01 15:32:22 -0400236 return true;
John Spurlockd06aa572014-09-10 10:40:49 -0400237 }
John Spurlock0b99ea92014-10-01 15:32:22 -0400238 break;
Daniel Sandlerc4f2a562012-05-04 11:55:46 -0400239 }
Adrian Roos56cf73a2016-07-18 14:23:32 -0700240 return false;
Daniel Sandlerc4f2a562012-05-04 11:55:46 -0400241 }
Chris Wren5de6e942012-05-16 14:22:21 -0400242
243 @Override
Adrian Roos9dc32092014-09-02 23:34:10 +0200244 public boolean dispatchTouchEvent(MotionEvent ev) {
Selim Cinek48a92a52017-05-02 20:02:30 -0700245 boolean isDown = ev.getActionMasked() == MotionEvent.ACTION_DOWN;
246 if (isDown && mNotificationPanel.isFullyCollapsed()) {
Jorim Jaggie05256e2016-09-08 14:58:20 -0700247 mNotificationPanel.startExpandLatencyTracking();
248 }
Selim Cinek48a92a52017-05-02 20:02:30 -0700249 if (isDown) {
250 mTouchActive = true;
251 mTouchCancelled = false;
252 } else if (ev.getActionMasked() == MotionEvent.ACTION_UP
253 || ev.getActionMasked() == MotionEvent.ACTION_CANCEL) {
254 mTouchActive = false;
255 }
256 if (mTouchCancelled) {
257 return false;
258 }
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700259 mFalsingManager.onTouchEvent(ev, getWidth(), getHeight());
Adrian Roos9dc32092014-09-02 23:34:10 +0200260 if (mBrightnessMirror != null && mBrightnessMirror.getVisibility() == VISIBLE) {
261 // Disallow new pointers while the brightness mirror is visible. This is so that you
262 // can't touch anything other than the brightness slider while the mirror is showing
263 // and the rest of the panel is transparent.
264 if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
265 return false;
266 }
267 }
Selim Cinek48a92a52017-05-02 20:02:30 -0700268 if (isDown) {
Mady Mellor7a9b2a62016-03-23 07:41:47 -0700269 mStackScrollLayout.closeControlsIfOutsideTouch(ev);
270 }
Adrian Roos67cca742017-04-13 16:52:51 -0700271 if (mService.isDozing()) {
272 mService.mDozeScrimController.extendPulse();
273 }
Mady Mellor7a9b2a62016-03-23 07:41:47 -0700274
Adrian Roos9dc32092014-09-02 23:34:10 +0200275 return super.dispatchTouchEvent(ev);
276 }
277
278 @Override
Chris Wren5de6e942012-05-16 14:22:21 -0400279 public boolean onInterceptTouchEvent(MotionEvent ev) {
Selim Cinekbe2c4432017-05-30 12:11:09 -0700280 if (mService.isDozing() && !mStackScrollLayout.hasPulsingNotifications()) {
Adrian Roos8008bd12017-02-22 15:02:09 +0100281 // Capture all touch events in always-on.
Adrian Roosebea7a72016-10-26 12:51:26 -0700282 return true;
283 }
Daniel Sandlerb4e56ed2012-09-12 23:07:44 -0700284 boolean intercept = false;
Selim Cinekfab078b2014-03-27 22:45:58 +0100285 if (mNotificationPanel.isFullyExpanded()
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200286 && mStackScrollLayout.getVisibility() == View.VISIBLE
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200287 && mService.getBarState() == StatusBarState.KEYGUARD
Adrian Roos500263a2017-01-23 14:49:54 -0800288 && !mService.isBouncerShowing()
289 && !mService.isDozing()) {
Jorim Jaggiecbab362014-04-23 16:13:15 +0200290 intercept = mDragDownHelper.onInterceptTouchEvent(ev);
Daniel Sandlerb4e56ed2012-09-12 23:07:44 -0700291 }
292 if (!intercept) {
293 super.onInterceptTouchEvent(ev);
294 }
Chris Wren5de6e942012-05-16 14:22:21 -0400295 if (intercept) {
Dianne Hackborna4b7f2f2012-05-21 11:28:41 -0700296 MotionEvent cancellation = MotionEvent.obtain(ev);
297 cancellation.setAction(MotionEvent.ACTION_CANCEL);
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100298 mStackScrollLayout.onInterceptTouchEvent(cancellation);
Selim Cinek31094df2014-08-14 19:28:15 +0200299 mNotificationPanel.onInterceptTouchEvent(cancellation);
Dianne Hackborna4b7f2f2012-05-21 11:28:41 -0700300 cancellation.recycle();
Chris Wren5de6e942012-05-16 14:22:21 -0400301 }
302 return intercept;
303 }
304
305 @Override
306 public boolean onTouchEvent(MotionEvent ev) {
Adrian Roos8008bd12017-02-22 15:02:09 +0100307 boolean handled = false;
308 if (mService.isDozing()) {
309 mDoubleTapHelper.onTouchEvent(ev);
310 handled = true;
311 }
Selim Cinek740c1112016-12-22 16:39:54 +0100312 if (mService.getBarState() == StatusBarState.KEYGUARD
313 && (!handled || mDragDownHelper.isDraggingDown())) {
314 // we still want to finish our drag down gesture when locking the screen
Jorim Jaggiecbab362014-04-23 16:13:15 +0200315 handled = mDragDownHelper.onTouchEvent(ev);
Daniel Sandlerb4e56ed2012-09-12 23:07:44 -0700316 }
317 if (!handled) {
318 handled = super.onTouchEvent(ev);
319 }
John Spurlock257f2832013-09-21 18:41:53 -0400320 final int action = ev.getAction();
John Spurlockd157ca02013-11-04 10:28:05 -0500321 if (!handled && (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL)) {
John Spurlock257f2832013-09-21 18:41:53 -0400322 mService.setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
323 }
Chris Wren5de6e942012-05-16 14:22:21 -0400324 return handled;
325 }
Daniel Sandler198a0302012-08-17 16:04:31 -0400326
327 @Override
328 public void onDraw(Canvas canvas) {
329 super.onDraw(canvas);
Jorim Jaggi0e664392014-09-27 01:30:22 +0200330 if (mService.isScrimSrcModeEnabled()) {
331 // We need to ensure that our window is always drawn fully even when we have paddings,
332 // since we simulate it to be opaque.
333 int paddedBottom = getHeight() - getPaddingBottom();
334 int paddedRight = getWidth() - getPaddingRight();
335 if (getPaddingTop() != 0) {
336 canvas.drawRect(0, 0, getWidth(), getPaddingTop(), mTransparentSrcPaint);
337 }
338 if (getPaddingBottom() != 0) {
339 canvas.drawRect(0, paddedBottom, getWidth(), getHeight(), mTransparentSrcPaint);
340 }
341 if (getPaddingLeft() != 0) {
342 canvas.drawRect(0, getPaddingTop(), getPaddingLeft(), paddedBottom,
343 mTransparentSrcPaint);
344 }
345 if (getPaddingRight() != 0) {
346 canvas.drawRect(paddedRight, getPaddingTop(), getWidth(), paddedBottom,
347 mTransparentSrcPaint);
348 }
Selim Cineka0fad3b2014-09-19 17:20:05 +0200349 }
Daniel Sandler198a0302012-08-17 16:04:31 -0400350 if (DEBUG) {
351 Paint pt = new Paint();
352 pt.setColor(0x80FFFF00);
353 pt.setStrokeWidth(12.0f);
354 pt.setStyle(Paint.Style.STROKE);
355 canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), pt);
356 }
357 }
Daniel Sandlerac47ff72012-10-23 10:41:44 -0400358
359 public void cancelExpandHelper() {
Selim Cinek1408eb52014-06-02 14:45:38 +0200360 if (mStackScrollLayout != null) {
361 mStackScrollLayout.cancelExpandHelper();
Daniel Sandler1a3bdd52012-10-23 19:21:20 -0400362 }
Daniel Sandlerac47ff72012-10-23 10:41:44 -0400363 }
Adrian Roos2f2bd9a2015-06-04 18:11:14 -0700364
Selim Cinek48a92a52017-05-02 20:02:30 -0700365 public void cancelCurrentTouch() {
366 if (mTouchActive) {
367 final long now = SystemClock.uptimeMillis();
368 MotionEvent event = MotionEvent.obtain(now, now,
369 MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
370 event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
371 dispatchTouchEvent(event);
372 event.recycle();
373 mTouchCancelled = true;
374 }
375 }
376
Adrian Roos2f2bd9a2015-06-04 18:11:14 -0700377 public class LayoutParams extends FrameLayout.LayoutParams {
378
379 public boolean ignoreRightInset;
380
381 public LayoutParams(int width, int height) {
382 super(width, height);
383 }
384
385 public LayoutParams(Context c, AttributeSet attrs) {
386 super(c, attrs);
387
388 TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.StatusBarWindowView_Layout);
389 ignoreRightInset = a.getBoolean(
390 R.styleable.StatusBarWindowView_Layout_ignoreRightInset, false);
391 a.recycle();
392 }
393 }
Adrian Roos0bd8a4b2016-03-14 16:21:44 -0700394
395 @Override
396 public ActionMode startActionModeForChild(View originalView, ActionMode.Callback callback,
397 int type) {
398 if (type == ActionMode.TYPE_FLOATING) {
399 return startActionMode(originalView, callback, type);
400 }
401 return super.startActionModeForChild(originalView, callback, type);
402 }
403
404 private ActionMode createFloatingActionMode(
405 View originatingView, ActionMode.Callback2 callback) {
406 if (mFloatingActionMode != null) {
407 mFloatingActionMode.finish();
408 }
409 cleanupFloatingActionModeViews();
Abodunrinwa Toki17293cc2017-05-22 14:16:04 +0100410 mFloatingToolbar = new FloatingToolbar(mContext, mFakeWindow);
Adrian Roos0bd8a4b2016-03-14 16:21:44 -0700411 final FloatingActionMode mode =
Abodunrinwa Toki17293cc2017-05-22 14:16:04 +0100412 new FloatingActionMode(mContext, callback, originatingView, mFloatingToolbar);
Adrian Roos0bd8a4b2016-03-14 16:21:44 -0700413 mFloatingActionModeOriginatingView = originatingView;
414 mFloatingToolbarPreDrawListener =
415 new ViewTreeObserver.OnPreDrawListener() {
416 @Override
417 public boolean onPreDraw() {
418 mode.updateViewLocationInWindow();
419 return true;
420 }
421 };
422 return mode;
423 }
424
425 private void setHandledFloatingActionMode(ActionMode mode) {
426 mFloatingActionMode = mode;
Adrian Roos0bd8a4b2016-03-14 16:21:44 -0700427 mFloatingActionMode.invalidate(); // Will show the floating toolbar if necessary.
428 mFloatingActionModeOriginatingView.getViewTreeObserver()
429 .addOnPreDrawListener(mFloatingToolbarPreDrawListener);
430 }
431
432 private void cleanupFloatingActionModeViews() {
433 if (mFloatingToolbar != null) {
434 mFloatingToolbar.dismiss();
435 mFloatingToolbar = null;
436 }
437 if (mFloatingActionModeOriginatingView != null) {
438 if (mFloatingToolbarPreDrawListener != null) {
439 mFloatingActionModeOriginatingView.getViewTreeObserver()
440 .removeOnPreDrawListener(mFloatingToolbarPreDrawListener);
441 mFloatingToolbarPreDrawListener = null;
442 }
443 mFloatingActionModeOriginatingView = null;
444 }
445 }
446
447 private ActionMode startActionMode(
448 View originatingView, ActionMode.Callback callback, int type) {
449 ActionMode.Callback2 wrappedCallback = new ActionModeCallback2Wrapper(callback);
450 ActionMode mode = createFloatingActionMode(originatingView, wrappedCallback);
451 if (mode != null && wrappedCallback.onCreateActionMode(mode, mode.getMenu())) {
452 setHandledFloatingActionMode(mode);
453 } else {
454 mode = null;
455 }
456 return mode;
457 }
458
459 private class ActionModeCallback2Wrapper extends ActionMode.Callback2 {
460 private final ActionMode.Callback mWrapped;
461
462 public ActionModeCallback2Wrapper(ActionMode.Callback wrapped) {
463 mWrapped = wrapped;
464 }
465
466 public boolean onCreateActionMode(ActionMode mode, Menu menu) {
467 return mWrapped.onCreateActionMode(mode, menu);
468 }
469
470 public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
471 requestFitSystemWindows();
472 return mWrapped.onPrepareActionMode(mode, menu);
473 }
474
475 public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
476 return mWrapped.onActionItemClicked(mode, item);
477 }
478
479 public void onDestroyActionMode(ActionMode mode) {
480 mWrapped.onDestroyActionMode(mode);
481 if (mode == mFloatingActionMode) {
482 cleanupFloatingActionModeViews();
483 mFloatingActionMode = null;
484 }
485 requestFitSystemWindows();
486 }
487
488 @Override
489 public void onGetContentRect(ActionMode mode, View view, Rect outRect) {
490 if (mWrapped instanceof ActionMode.Callback2) {
491 ((ActionMode.Callback2) mWrapped).onGetContentRect(mode, view, outRect);
492 } else {
493 super.onGetContentRect(mode, view, outRect);
494 }
495 }
496 }
497
498 /**
499 * Minimal window to satisfy FloatingToolbar.
500 */
501 private Window mFakeWindow = new Window(mContext) {
502 @Override
503 public void takeSurface(SurfaceHolder.Callback2 callback) {
504 }
505
506 @Override
507 public void takeInputQueue(InputQueue.Callback callback) {
508 }
509
510 @Override
511 public boolean isFloating() {
512 return false;
513 }
514
515 @Override
516 public void alwaysReadCloseOnTouchAttr() {
517 }
518
519 @Override
520 public void setContentView(@LayoutRes int layoutResID) {
521 }
522
523 @Override
524 public void setContentView(View view) {
525 }
526
527 @Override
528 public void setContentView(View view, ViewGroup.LayoutParams params) {
529 }
530
531 @Override
532 public void addContentView(View view, ViewGroup.LayoutParams params) {
533 }
534
535 @Override
536 public void clearContentView() {
537 }
538
539 @Override
540 public View getCurrentFocus() {
541 return null;
542 }
543
544 @Override
545 public LayoutInflater getLayoutInflater() {
546 return null;
547 }
548
549 @Override
550 public void setTitle(CharSequence title) {
551 }
552
553 @Override
554 public void setTitleColor(@ColorInt int textColor) {
555 }
556
557 @Override
558 public void openPanel(int featureId, KeyEvent event) {
559 }
560
561 @Override
562 public void closePanel(int featureId) {
563 }
564
565 @Override
566 public void togglePanel(int featureId, KeyEvent event) {
567 }
568
569 @Override
570 public void invalidatePanelMenu(int featureId) {
571 }
572
573 @Override
574 public boolean performPanelShortcut(int featureId, int keyCode, KeyEvent event, int flags) {
575 return false;
576 }
577
578 @Override
579 public boolean performPanelIdentifierAction(int featureId, int id, int flags) {
580 return false;
581 }
582
583 @Override
584 public void closeAllPanels() {
585 }
586
587 @Override
588 public boolean performContextMenuIdentifierAction(int id, int flags) {
589 return false;
590 }
591
592 @Override
593 public void onConfigurationChanged(Configuration newConfig) {
594 }
595
596 @Override
597 public void setBackgroundDrawable(Drawable drawable) {
598 }
599
600 @Override
601 public void setFeatureDrawableResource(int featureId, @DrawableRes int resId) {
602 }
603
604 @Override
605 public void setFeatureDrawableUri(int featureId, Uri uri) {
606 }
607
608 @Override
609 public void setFeatureDrawable(int featureId, Drawable drawable) {
610 }
611
612 @Override
613 public void setFeatureDrawableAlpha(int featureId, int alpha) {
614 }
615
616 @Override
617 public void setFeatureInt(int featureId, int value) {
618 }
619
620 @Override
621 public void takeKeyEvents(boolean get) {
622 }
623
624 @Override
625 public boolean superDispatchKeyEvent(KeyEvent event) {
626 return false;
627 }
628
629 @Override
630 public boolean superDispatchKeyShortcutEvent(KeyEvent event) {
631 return false;
632 }
633
634 @Override
635 public boolean superDispatchTouchEvent(MotionEvent event) {
636 return false;
637 }
638
639 @Override
640 public boolean superDispatchTrackballEvent(MotionEvent event) {
641 return false;
642 }
643
644 @Override
645 public boolean superDispatchGenericMotionEvent(MotionEvent event) {
646 return false;
647 }
648
649 @Override
650 public View getDecorView() {
651 return StatusBarWindowView.this;
652 }
653
654 @Override
655 public View peekDecorView() {
656 return null;
657 }
658
659 @Override
660 public Bundle saveHierarchyState() {
661 return null;
662 }
663
664 @Override
665 public void restoreHierarchyState(Bundle savedInstanceState) {
666 }
667
668 @Override
669 protected void onActive() {
670 }
671
672 @Override
673 public void setChildDrawable(int featureId, Drawable drawable) {
674 }
675
676 @Override
677 public void setChildInt(int featureId, int value) {
678 }
679
680 @Override
681 public boolean isShortcutKey(int keyCode, KeyEvent event) {
682 return false;
683 }
684
685 @Override
686 public void setVolumeControlStream(int streamType) {
687 }
688
689 @Override
690 public int getVolumeControlStream() {
691 return 0;
692 }
693
694 @Override
695 public int getStatusBarColor() {
696 return 0;
697 }
698
699 @Override
700 public void setStatusBarColor(@ColorInt int color) {
701 }
702
703 @Override
704 public int getNavigationBarColor() {
705 return 0;
706 }
707
708 @Override
709 public void setNavigationBarColor(@ColorInt int color) {
710 }
711
712 @Override
713 public void setDecorCaptionShade(int decorCaptionShade) {
714 }
715
716 @Override
717 public void setResizingCaptionDrawable(Drawable drawable) {
718 }
719
720 @Override
Andrii Kulian933076d2016-03-29 17:04:42 -0700721 public void onMultiWindowModeChanged() {
Adrian Roos0bd8a4b2016-03-14 16:21:44 -0700722 }
723
724 @Override
Winson Chung4d8681f2017-05-23 16:22:08 -0700725 public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
726 }
727
728 @Override
Adrian Roos0bd8a4b2016-03-14 16:21:44 -0700729 public void reportActivityRelaunched() {
730 }
731 };
732
Daniel Sandlerc4f2a562012-05-04 11:55:46 -0400733}
734