blob: 634270c126513760c52cb11a897921ba93cd6fde [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 {
Adrian Roose49e4092015-06-10 18:50:18 -070086 if (mRightInset != 0) {
87 mRightInset = 0;
88 applyMargins();
89 }
Jorim Jaggi416493b2014-09-13 03:57:32 +020090 boolean changed = getPaddingLeft() != 0
91 || getPaddingRight() != 0
92 || getPaddingTop() != 0
93 || getPaddingBottom() != 0;
94 if (changed) {
95 setPadding(0, 0, 0, 0);
96 }
Jorim Jaggiaa806142015-05-20 18:04:16 -070097 insets.top = 0;
John Spurlockfba91202014-04-22 12:58:26 -040098 }
Jorim Jaggid7daab72014-05-06 22:22:20 +020099 return false;
John Spurlockfba91202014-04-22 12:58:26 -0400100 }
101
Adrian Roos2f2bd9a2015-06-04 18:11:14 -0700102 private void applyMargins() {
103 final int N = getChildCount();
104 for (int i = 0; i < N; i++) {
105 View child = getChildAt(i);
106 if (child.getLayoutParams() instanceof LayoutParams) {
107 LayoutParams lp = (LayoutParams) child.getLayoutParams();
108 if (!lp.ignoreRightInset && lp.rightMargin != mRightInset) {
109 lp.rightMargin = mRightInset;
110 child.requestLayout();
111 }
112 }
113 }
114 }
115
116 @Override
117 public FrameLayout.LayoutParams generateLayoutParams(AttributeSet attrs) {
118 return new LayoutParams(getContext(), attrs);
119 }
120
121 @Override
122 protected FrameLayout.LayoutParams generateDefaultLayoutParams() {
123 return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
124 }
125
John Spurlockfba91202014-04-22 12:58:26 -0400126 @Override
Chris Wren5de6e942012-05-16 14:22:21 -0400127 protected void onAttachedToWindow () {
128 super.onAttachedToWindow();
Selim Cinek67b22602014-03-10 15:40:16 +0100129
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100130 mStackScrollLayout = (NotificationStackScrollLayout) findViewById(
131 R.id.notification_stack_scroller);
Daniel Sandlerb4e56ed2012-09-12 23:07:44 -0700132 mNotificationPanel = (NotificationPanelView) findViewById(R.id.notification_panel);
Jorim Jaggiecbab362014-04-23 16:13:15 +0200133 mDragDownHelper = new DragDownHelper(getContext(), this, mStackScrollLayout, mService);
Adrian Roos9dc32092014-09-02 23:34:10 +0200134 mBrightnessMirror = findViewById(R.id.brightness_mirror);
Daniel Sandlerb10d8852013-05-08 15:57:06 -0400135
136 // We really need to be able to animate while window animations are going on
137 // so that activities may be started asynchronously from panel animations
138 final ViewRootImpl root = getViewRootImpl();
139 if (root != null) {
140 root.setDrawDuringWindowsAnimating(true);
141 }
Selim Cineka0fad3b2014-09-19 17:20:05 +0200142
143 // We need to ensure that our window doesn't suffer from overdraw which would normally
144 // occur if our window is translucent. Since we are drawing the whole window anyway with
145 // the scrim, we don't need the window to be cleared in the beginning.
Jorim Jaggi0e664392014-09-27 01:30:22 +0200146 if (mService.isScrimSrcModeEnabled()) {
147 IBinder windowToken = getWindowToken();
148 WindowManager.LayoutParams lp = (WindowManager.LayoutParams) getLayoutParams();
149 lp.token = windowToken;
150 setLayoutParams(lp);
151 WindowManagerGlobal.getInstance().changeCanvasOpacity(windowToken, true);
152 setWillNotDraw(false);
153 } else {
154 setWillNotDraw(!DEBUG);
155 }
Daniel Sandlerc4f2a562012-05-04 11:55:46 -0400156 }
157
158 @Override
159 public boolean dispatchKeyEvent(KeyEvent event) {
160 boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
161 switch (event.getKeyCode()) {
Jorim Jaggi8c8bcc12014-04-16 21:36:51 +0200162 case KeyEvent.KEYCODE_BACK:
163 if (!down) {
164 mService.onBackPressed();
165 }
166 return true;
167 case KeyEvent.KEYCODE_MENU:
168 if (!down) {
169 return mService.onMenuPressed();
170 }
Jorim Jaggi34250762014-07-03 23:51:19 +0200171 case KeyEvent.KEYCODE_SPACE:
172 if (!down) {
173 return mService.onSpacePressed();
174 }
John Spurlock0b99ea92014-10-01 15:32:22 -0400175 break;
John Spurlockd06aa572014-09-10 10:40:49 -0400176 case KeyEvent.KEYCODE_VOLUME_DOWN:
177 case KeyEvent.KEYCODE_VOLUME_UP:
John Spurlock0b99ea92014-10-01 15:32:22 -0400178 if (mService.isDozing()) {
179 MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(event, true);
180 return true;
John Spurlockd06aa572014-09-10 10:40:49 -0400181 }
John Spurlock0b99ea92014-10-01 15:32:22 -0400182 break;
Daniel Sandlerc4f2a562012-05-04 11:55:46 -0400183 }
Jorim Jaggidf993512014-05-13 23:06:35 +0200184 if (mService.interceptMediaKey(event)) {
185 return true;
186 }
Daniel Sandlerc4f2a562012-05-04 11:55:46 -0400187 return super.dispatchKeyEvent(event);
188 }
Chris Wren5de6e942012-05-16 14:22:21 -0400189
190 @Override
Adrian Roos9dc32092014-09-02 23:34:10 +0200191 public boolean dispatchTouchEvent(MotionEvent ev) {
192 if (mBrightnessMirror != null && mBrightnessMirror.getVisibility() == VISIBLE) {
193 // Disallow new pointers while the brightness mirror is visible. This is so that you
194 // can't touch anything other than the brightness slider while the mirror is showing
195 // and the rest of the panel is transparent.
196 if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
197 return false;
198 }
199 }
200 return super.dispatchTouchEvent(ev);
201 }
202
203 @Override
Chris Wren5de6e942012-05-16 14:22:21 -0400204 public boolean onInterceptTouchEvent(MotionEvent ev) {
Daniel Sandlerb4e56ed2012-09-12 23:07:44 -0700205 boolean intercept = false;
Selim Cinekfab078b2014-03-27 22:45:58 +0100206 if (mNotificationPanel.isFullyExpanded()
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200207 && mStackScrollLayout.getVisibility() == View.VISIBLE
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200208 && mService.getBarState() == StatusBarState.KEYGUARD
209 && !mService.isBouncerShowing()) {
Jorim Jaggiecbab362014-04-23 16:13:15 +0200210 intercept = mDragDownHelper.onInterceptTouchEvent(ev);
John Spurlock8b12f222014-09-09 11:54:11 -0400211 // wake up on a touch down event, if dozing
212 if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
Jorim Jaggi2a5e4522014-11-24 21:45:20 +0100213 mService.wakeUpIfDozing(ev.getEventTime(), ev);
John Spurlock8b12f222014-09-09 11:54:11 -0400214 }
Daniel Sandlerb4e56ed2012-09-12 23:07:44 -0700215 }
216 if (!intercept) {
217 super.onInterceptTouchEvent(ev);
218 }
Chris Wren5de6e942012-05-16 14:22:21 -0400219 if (intercept) {
Dianne Hackborna4b7f2f2012-05-21 11:28:41 -0700220 MotionEvent cancellation = MotionEvent.obtain(ev);
221 cancellation.setAction(MotionEvent.ACTION_CANCEL);
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100222 mStackScrollLayout.onInterceptTouchEvent(cancellation);
Selim Cinek31094df2014-08-14 19:28:15 +0200223 mNotificationPanel.onInterceptTouchEvent(cancellation);
Dianne Hackborna4b7f2f2012-05-21 11:28:41 -0700224 cancellation.recycle();
Chris Wren5de6e942012-05-16 14:22:21 -0400225 }
226 return intercept;
227 }
228
229 @Override
230 public boolean onTouchEvent(MotionEvent ev) {
Daniel Sandlerb4e56ed2012-09-12 23:07:44 -0700231 boolean handled = false;
Selim Cinekcb9400a2015-06-03 16:56:13 +0200232 if (mService.getBarState() == StatusBarState.KEYGUARD) {
Jorim Jaggiecbab362014-04-23 16:13:15 +0200233 handled = mDragDownHelper.onTouchEvent(ev);
Daniel Sandlerb4e56ed2012-09-12 23:07:44 -0700234 }
235 if (!handled) {
236 handled = super.onTouchEvent(ev);
237 }
John Spurlock257f2832013-09-21 18:41:53 -0400238 final int action = ev.getAction();
John Spurlockd157ca02013-11-04 10:28:05 -0500239 if (!handled && (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL)) {
John Spurlock257f2832013-09-21 18:41:53 -0400240 mService.setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
241 }
Chris Wren5de6e942012-05-16 14:22:21 -0400242 return handled;
243 }
Daniel Sandler198a0302012-08-17 16:04:31 -0400244
245 @Override
246 public void onDraw(Canvas canvas) {
247 super.onDraw(canvas);
Jorim Jaggi0e664392014-09-27 01:30:22 +0200248 if (mService.isScrimSrcModeEnabled()) {
249 // We need to ensure that our window is always drawn fully even when we have paddings,
250 // since we simulate it to be opaque.
251 int paddedBottom = getHeight() - getPaddingBottom();
252 int paddedRight = getWidth() - getPaddingRight();
253 if (getPaddingTop() != 0) {
254 canvas.drawRect(0, 0, getWidth(), getPaddingTop(), mTransparentSrcPaint);
255 }
256 if (getPaddingBottom() != 0) {
257 canvas.drawRect(0, paddedBottom, getWidth(), getHeight(), mTransparentSrcPaint);
258 }
259 if (getPaddingLeft() != 0) {
260 canvas.drawRect(0, getPaddingTop(), getPaddingLeft(), paddedBottom,
261 mTransparentSrcPaint);
262 }
263 if (getPaddingRight() != 0) {
264 canvas.drawRect(paddedRight, getPaddingTop(), getWidth(), paddedBottom,
265 mTransparentSrcPaint);
266 }
Selim Cineka0fad3b2014-09-19 17:20:05 +0200267 }
Daniel Sandler198a0302012-08-17 16:04:31 -0400268 if (DEBUG) {
269 Paint pt = new Paint();
270 pt.setColor(0x80FFFF00);
271 pt.setStrokeWidth(12.0f);
272 pt.setStyle(Paint.Style.STROKE);
273 canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), pt);
274 }
275 }
Daniel Sandlerac47ff72012-10-23 10:41:44 -0400276
277 public void cancelExpandHelper() {
Selim Cinek1408eb52014-06-02 14:45:38 +0200278 if (mStackScrollLayout != null) {
279 mStackScrollLayout.cancelExpandHelper();
Daniel Sandler1a3bdd52012-10-23 19:21:20 -0400280 }
Daniel Sandlerac47ff72012-10-23 10:41:44 -0400281 }
Adrian Roos2f2bd9a2015-06-04 18:11:14 -0700282
283 public class LayoutParams extends FrameLayout.LayoutParams {
284
285 public boolean ignoreRightInset;
286
287 public LayoutParams(int width, int height) {
288 super(width, height);
289 }
290
291 public LayoutParams(Context c, AttributeSet attrs) {
292 super(c, attrs);
293
294 TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.StatusBarWindowView_Layout);
295 ignoreRightInset = a.getBoolean(
296 R.styleable.StatusBarWindowView_Layout_ignoreRightInset, false);
297 a.recycle();
298 }
299 }
Daniel Sandlerc4f2a562012-05-04 11:55:46 -0400300}
301