blob: 7f1fea1624d00b6e373fa51236eff97a29641da9 [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
John Spurlock257f2832013-09-21 18:41:53 -040019import android.app.StatusBarManager;
Daniel Sandlerc4f2a562012-05-04 11:55:46 -040020import android.content.Context;
Adrian Roos2f2bd9a2015-06-04 18:11:14 -070021import android.content.res.TypedArray;
Daniel Sandler198a0302012-08-17 16:04:31 -040022import android.graphics.Canvas;
23import android.graphics.Paint;
Selim Cineka0fad3b2014-09-19 17:20:05 +020024import android.graphics.PorterDuff;
25import android.graphics.PorterDuffXfermode;
John Spurlockfba91202014-04-22 12:58:26 -040026import android.graphics.Rect;
John Spurlock0b99ea92014-10-01 15:32:22 -040027import android.media.session.MediaSessionLegacyHelper;
Selim Cineka0fad3b2014-09-19 17:20:05 +020028import android.os.IBinder;
Daniel Sandlerc4f2a562012-05-04 11:55:46 -040029import android.util.AttributeSet;
30import android.view.KeyEvent;
Chris Wren5de6e942012-05-16 14:22:21 -040031import android.view.MotionEvent;
Daniel Sandlerb4e56ed2012-09-12 23:07:44 -070032import android.view.View;
Daniel Sandlerb10d8852013-05-08 15:57:06 -040033import android.view.ViewRootImpl;
Selim Cineka0fad3b2014-09-19 17:20:05 +020034import android.view.WindowManager;
35import android.view.WindowManagerGlobal;
Daniel Sandlerc4f2a562012-05-04 11:55:46 -040036import android.widget.FrameLayout;
Daniel Sandlerc4f2a562012-05-04 11:55:46 -040037
Chris Wren5de6e942012-05-16 14:22:21 -040038import com.android.systemui.R;
Daniel Sandler198a0302012-08-17 16:04:31 -040039import com.android.systemui.statusbar.BaseStatusBar;
Jorim Jaggiecbab362014-04-23 16:13:15 +020040import com.android.systemui.statusbar.DragDownHelper;
41import com.android.systemui.statusbar.StatusBarState;
Selim Cinekfab078b2014-03-27 22:45:58 +010042import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
Chris Wren5de6e942012-05-16 14:22:21 -040043
Daniel Sandlerc4f2a562012-05-04 11:55:46 -040044
Jorim Jaggiecbab362014-04-23 16:13:15 +020045public class StatusBarWindowView extends FrameLayout {
Daniel Sandler198a0302012-08-17 16:04:31 -040046 public static final String TAG = "StatusBarWindowView";
47 public static final boolean DEBUG = BaseStatusBar.DEBUG;
Chris Wren5de6e942012-05-16 14:22:21 -040048
Jorim Jaggiecbab362014-04-23 16:13:15 +020049 private DragDownHelper mDragDownHelper;
Selim Cinekb6d85eb2014-03-28 20:21:01 +010050 private NotificationStackScrollLayout mStackScrollLayout;
Daniel Sandlerb4e56ed2012-09-12 23:07:44 -070051 private NotificationPanelView mNotificationPanel;
Adrian Roos9dc32092014-09-02 23:34:10 +020052 private View mBrightnessMirror;
Chris Wren5de6e942012-05-16 14:22:21 -040053
Adrian Roos2f2bd9a2015-06-04 18:11:14 -070054 private int mRightInset = 0;
55
Daniel Sandlerc4f2a562012-05-04 11:55:46 -040056 PhoneStatusBar mService;
Selim Cineka0fad3b2014-09-19 17:20:05 +020057 private final Paint mTransparentSrcPaint = new Paint();
Daniel Sandlerc4f2a562012-05-04 11:55:46 -040058
59 public StatusBarWindowView(Context context, AttributeSet attrs) {
60 super(context, attrs);
Chris Wren5de6e942012-05-16 14:22:21 -040061 setMotionEventSplittingEnabled(false);
Selim Cineka0fad3b2014-09-19 17:20:05 +020062 mTransparentSrcPaint.setColor(0);
63 mTransparentSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
Chris Wren5de6e942012-05-16 14:22:21 -040064 }
65
66 @Override
John Spurlockfba91202014-04-22 12:58:26 -040067 protected boolean fitSystemWindows(Rect insets) {
68 if (getFitsSystemWindows()) {
Adrian Roos2f2bd9a2015-06-04 18:11:14 -070069 boolean paddingChanged = insets.left != getPaddingLeft()
Jorim Jaggi416493b2014-09-13 03:57:32 +020070 || insets.top != getPaddingTop()
Jorim Jaggi416493b2014-09-13 03:57:32 +020071 || insets.bottom != getPaddingBottom();
Jorim Jaggiaa806142015-05-20 18:04:16 -070072
Adrian Roos2f2bd9a2015-06-04 18:11:14 -070073 // Super-special right inset handling, because scrims and backdrop need to ignore it.
74 if (insets.right != mRightInset) {
75 mRightInset = insets.right;
76 applyMargins();
77 }
78 // Drop top inset, apply left inset and pass through bottom inset.
79 if (paddingChanged) {
80 setPadding(insets.left, 0, 0, 0);
Jorim Jaggi416493b2014-09-13 03:57:32 +020081 }
Jorim Jaggid7daab72014-05-06 22:22:20 +020082 insets.left = 0;
83 insets.top = 0;
84 insets.right = 0;
John Spurlockfba91202014-04-22 12:58:26 -040085 } else {
Jorim Jaggi416493b2014-09-13 03:57:32 +020086 boolean changed = getPaddingLeft() != 0
87 || getPaddingRight() != 0
88 || getPaddingTop() != 0
89 || getPaddingBottom() != 0;
90 if (changed) {
91 setPadding(0, 0, 0, 0);
92 }
Jorim Jaggiaa806142015-05-20 18:04:16 -070093 insets.top = 0;
John Spurlockfba91202014-04-22 12:58:26 -040094 }
Jorim Jaggid7daab72014-05-06 22:22:20 +020095 return false;
John Spurlockfba91202014-04-22 12:58:26 -040096 }
97
Adrian Roos2f2bd9a2015-06-04 18:11:14 -070098 private void applyMargins() {
99 final int N = getChildCount();
100 for (int i = 0; i < N; i++) {
101 View child = getChildAt(i);
102 if (child.getLayoutParams() instanceof LayoutParams) {
103 LayoutParams lp = (LayoutParams) child.getLayoutParams();
104 if (!lp.ignoreRightInset && lp.rightMargin != mRightInset) {
105 lp.rightMargin = mRightInset;
106 child.requestLayout();
107 }
108 }
109 }
110 }
111
112 @Override
113 public FrameLayout.LayoutParams generateLayoutParams(AttributeSet attrs) {
114 return new LayoutParams(getContext(), attrs);
115 }
116
117 @Override
118 protected FrameLayout.LayoutParams generateDefaultLayoutParams() {
119 return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
120 }
121
John Spurlockfba91202014-04-22 12:58:26 -0400122 @Override
Chris Wren5de6e942012-05-16 14:22:21 -0400123 protected void onAttachedToWindow () {
124 super.onAttachedToWindow();
Selim Cinek67b22602014-03-10 15:40:16 +0100125
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100126 mStackScrollLayout = (NotificationStackScrollLayout) findViewById(
127 R.id.notification_stack_scroller);
Daniel Sandlerb4e56ed2012-09-12 23:07:44 -0700128 mNotificationPanel = (NotificationPanelView) findViewById(R.id.notification_panel);
Jorim Jaggiecbab362014-04-23 16:13:15 +0200129 mDragDownHelper = new DragDownHelper(getContext(), this, mStackScrollLayout, mService);
Adrian Roos9dc32092014-09-02 23:34:10 +0200130 mBrightnessMirror = findViewById(R.id.brightness_mirror);
Daniel Sandlerb10d8852013-05-08 15:57:06 -0400131
132 // We really need to be able to animate while window animations are going on
133 // so that activities may be started asynchronously from panel animations
134 final ViewRootImpl root = getViewRootImpl();
135 if (root != null) {
136 root.setDrawDuringWindowsAnimating(true);
137 }
Selim Cineka0fad3b2014-09-19 17:20:05 +0200138
139 // We need to ensure that our window doesn't suffer from overdraw which would normally
140 // occur if our window is translucent. Since we are drawing the whole window anyway with
141 // the scrim, we don't need the window to be cleared in the beginning.
Jorim Jaggi0e664392014-09-27 01:30:22 +0200142 if (mService.isScrimSrcModeEnabled()) {
143 IBinder windowToken = getWindowToken();
144 WindowManager.LayoutParams lp = (WindowManager.LayoutParams) getLayoutParams();
145 lp.token = windowToken;
146 setLayoutParams(lp);
147 WindowManagerGlobal.getInstance().changeCanvasOpacity(windowToken, true);
148 setWillNotDraw(false);
149 } else {
150 setWillNotDraw(!DEBUG);
151 }
Daniel Sandlerc4f2a562012-05-04 11:55:46 -0400152 }
153
154 @Override
155 public boolean dispatchKeyEvent(KeyEvent event) {
156 boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
157 switch (event.getKeyCode()) {
Jorim Jaggi8c8bcc12014-04-16 21:36:51 +0200158 case KeyEvent.KEYCODE_BACK:
159 if (!down) {
160 mService.onBackPressed();
161 }
162 return true;
163 case KeyEvent.KEYCODE_MENU:
164 if (!down) {
165 return mService.onMenuPressed();
166 }
Jorim Jaggi34250762014-07-03 23:51:19 +0200167 case KeyEvent.KEYCODE_SPACE:
168 if (!down) {
169 return mService.onSpacePressed();
170 }
John Spurlock0b99ea92014-10-01 15:32:22 -0400171 break;
John Spurlockd06aa572014-09-10 10:40:49 -0400172 case KeyEvent.KEYCODE_VOLUME_DOWN:
173 case KeyEvent.KEYCODE_VOLUME_UP:
John Spurlock0b99ea92014-10-01 15:32:22 -0400174 if (mService.isDozing()) {
175 MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(event, true);
176 return true;
John Spurlockd06aa572014-09-10 10:40:49 -0400177 }
John Spurlock0b99ea92014-10-01 15:32:22 -0400178 break;
Daniel Sandlerc4f2a562012-05-04 11:55:46 -0400179 }
Jorim Jaggidf993512014-05-13 23:06:35 +0200180 if (mService.interceptMediaKey(event)) {
181 return true;
182 }
Daniel Sandlerc4f2a562012-05-04 11:55:46 -0400183 return super.dispatchKeyEvent(event);
184 }
Chris Wren5de6e942012-05-16 14:22:21 -0400185
186 @Override
Adrian Roos9dc32092014-09-02 23:34:10 +0200187 public boolean dispatchTouchEvent(MotionEvent ev) {
188 if (mBrightnessMirror != null && mBrightnessMirror.getVisibility() == VISIBLE) {
189 // Disallow new pointers while the brightness mirror is visible. This is so that you
190 // can't touch anything other than the brightness slider while the mirror is showing
191 // and the rest of the panel is transparent.
192 if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
193 return false;
194 }
195 }
196 return super.dispatchTouchEvent(ev);
197 }
198
199 @Override
Chris Wren5de6e942012-05-16 14:22:21 -0400200 public boolean onInterceptTouchEvent(MotionEvent ev) {
Daniel Sandlerb4e56ed2012-09-12 23:07:44 -0700201 boolean intercept = false;
Selim Cinekfab078b2014-03-27 22:45:58 +0100202 if (mNotificationPanel.isFullyExpanded()
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200203 && mStackScrollLayout.getVisibility() == View.VISIBLE
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200204 && mService.getBarState() == StatusBarState.KEYGUARD
205 && !mService.isBouncerShowing()) {
Jorim Jaggiecbab362014-04-23 16:13:15 +0200206 intercept = mDragDownHelper.onInterceptTouchEvent(ev);
John Spurlock8b12f222014-09-09 11:54:11 -0400207 // wake up on a touch down event, if dozing
208 if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
Jorim Jaggi2a5e4522014-11-24 21:45:20 +0100209 mService.wakeUpIfDozing(ev.getEventTime(), ev);
John Spurlock8b12f222014-09-09 11:54:11 -0400210 }
Daniel Sandlerb4e56ed2012-09-12 23:07:44 -0700211 }
212 if (!intercept) {
213 super.onInterceptTouchEvent(ev);
214 }
Chris Wren5de6e942012-05-16 14:22:21 -0400215 if (intercept) {
Dianne Hackborna4b7f2f2012-05-21 11:28:41 -0700216 MotionEvent cancellation = MotionEvent.obtain(ev);
217 cancellation.setAction(MotionEvent.ACTION_CANCEL);
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100218 mStackScrollLayout.onInterceptTouchEvent(cancellation);
Selim Cinek31094df2014-08-14 19:28:15 +0200219 mNotificationPanel.onInterceptTouchEvent(cancellation);
Dianne Hackborna4b7f2f2012-05-21 11:28:41 -0700220 cancellation.recycle();
Chris Wren5de6e942012-05-16 14:22:21 -0400221 }
222 return intercept;
223 }
224
225 @Override
226 public boolean onTouchEvent(MotionEvent ev) {
Daniel Sandlerb4e56ed2012-09-12 23:07:44 -0700227 boolean handled = false;
Selim Cinekcb9400a2015-06-03 16:56:13 +0200228 if (mService.getBarState() == StatusBarState.KEYGUARD) {
Jorim Jaggiecbab362014-04-23 16:13:15 +0200229 handled = mDragDownHelper.onTouchEvent(ev);
Daniel Sandlerb4e56ed2012-09-12 23:07:44 -0700230 }
231 if (!handled) {
232 handled = super.onTouchEvent(ev);
233 }
John Spurlock257f2832013-09-21 18:41:53 -0400234 final int action = ev.getAction();
John Spurlockd157ca02013-11-04 10:28:05 -0500235 if (!handled && (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL)) {
John Spurlock257f2832013-09-21 18:41:53 -0400236 mService.setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
237 }
Chris Wren5de6e942012-05-16 14:22:21 -0400238 return handled;
239 }
Daniel Sandler198a0302012-08-17 16:04:31 -0400240
241 @Override
242 public void onDraw(Canvas canvas) {
243 super.onDraw(canvas);
Jorim Jaggi0e664392014-09-27 01:30:22 +0200244 if (mService.isScrimSrcModeEnabled()) {
245 // We need to ensure that our window is always drawn fully even when we have paddings,
246 // since we simulate it to be opaque.
247 int paddedBottom = getHeight() - getPaddingBottom();
248 int paddedRight = getWidth() - getPaddingRight();
249 if (getPaddingTop() != 0) {
250 canvas.drawRect(0, 0, getWidth(), getPaddingTop(), mTransparentSrcPaint);
251 }
252 if (getPaddingBottom() != 0) {
253 canvas.drawRect(0, paddedBottom, getWidth(), getHeight(), mTransparentSrcPaint);
254 }
255 if (getPaddingLeft() != 0) {
256 canvas.drawRect(0, getPaddingTop(), getPaddingLeft(), paddedBottom,
257 mTransparentSrcPaint);
258 }
259 if (getPaddingRight() != 0) {
260 canvas.drawRect(paddedRight, getPaddingTop(), getWidth(), paddedBottom,
261 mTransparentSrcPaint);
262 }
Selim Cineka0fad3b2014-09-19 17:20:05 +0200263 }
Daniel Sandler198a0302012-08-17 16:04:31 -0400264 if (DEBUG) {
265 Paint pt = new Paint();
266 pt.setColor(0x80FFFF00);
267 pt.setStrokeWidth(12.0f);
268 pt.setStyle(Paint.Style.STROKE);
269 canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), pt);
270 }
271 }
Daniel Sandlerac47ff72012-10-23 10:41:44 -0400272
273 public void cancelExpandHelper() {
Selim Cinek1408eb52014-06-02 14:45:38 +0200274 if (mStackScrollLayout != null) {
275 mStackScrollLayout.cancelExpandHelper();
Daniel Sandler1a3bdd52012-10-23 19:21:20 -0400276 }
Daniel Sandlerac47ff72012-10-23 10:41:44 -0400277 }
Adrian Roos2f2bd9a2015-06-04 18:11:14 -0700278
279 public class LayoutParams extends FrameLayout.LayoutParams {
280
281 public boolean ignoreRightInset;
282
283 public LayoutParams(int width, int height) {
284 super(width, height);
285 }
286
287 public LayoutParams(Context c, AttributeSet attrs) {
288 super(c, attrs);
289
290 TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.StatusBarWindowView_Layout);
291 ignoreRightInset = a.getBoolean(
292 R.styleable.StatusBarWindowView_Layout_ignoreRightInset, false);
293 a.recycle();
294 }
295 }
Daniel Sandlerc4f2a562012-05-04 11:55:46 -0400296}
297