1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.chrome.browser.ntp;
6 
7 import android.annotation.SuppressLint;
8 import android.content.Context;
9 import android.util.AttributeSet;
10 import android.view.GestureDetector;
11 import android.view.KeyEvent;
12 import android.view.MotionEvent;
13 import android.view.View;
14 import android.view.inputmethod.EditorInfo;
15 import android.view.inputmethod.InputConnection;
16 import android.widget.ScrollView;
17 
18 /**
19  * Simple wrapper on top of a ScrollView that will acquire focus when tapped.  Ensures the
20  * New Tab page receives focus when clicked. This is only used in the Incognito NTP.
21  */
22 public class NewTabPageScrollView extends ScrollView {
23 
24     private GestureDetector mGestureDetector;
25 
26     /**
27      * Constructor needed to inflate from XML.
28      */
NewTabPageScrollView(Context context, AttributeSet attrs)29     public NewTabPageScrollView(Context context, AttributeSet attrs) {
30         super(context, attrs);
31 
32         mGestureDetector = new GestureDetector(
33                 getContext(), new GestureDetector.SimpleOnGestureListener() {
34                     @Override
35                     public boolean onSingleTapUp(MotionEvent e) {
36                         boolean retVal = super.onSingleTapUp(e);
37                         requestFocus();
38                         return retVal;
39                     }
40                 });
41     }
42 
43     @Override
onInterceptTouchEvent(MotionEvent ev)44     public boolean onInterceptTouchEvent(MotionEvent ev) {
45         mGestureDetector.onTouchEvent(ev);
46         return super.onInterceptTouchEvent(ev);
47     }
48 
49     @Override
50     @SuppressLint("ClickableViewAccessibility")
onTouchEvent(MotionEvent ev)51     public boolean onTouchEvent(MotionEvent ev) {
52         // Action down would already have been handled in onInterceptTouchEvent
53         if (ev.getActionMasked() != MotionEvent.ACTION_DOWN) {
54             mGestureDetector.onTouchEvent(ev);
55         }
56         return super.onTouchEvent(ev);
57     }
58 
59     @Override
focusableViewAvailable(View v)60     public void focusableViewAvailable(View v) {
61         // To avoid odd jumps during NTP animation transitions, we do not attempt to give focus
62         // to child views if this scroll view already has focus.
63         if (hasFocus()) return;
64         super.focusableViewAvailable(v);
65     }
66 
67     @Override
executeKeyEvent(KeyEvent event)68     public boolean executeKeyEvent(KeyEvent event) {
69         // Ignore all key events except arrow keys and spacebar. Otherwise, the ScrollView consumes
70         // unwanted events (including the hardware menu button and app-level keyboard shortcuts).
71         // http://crbug.com/308322
72         switch (event.getKeyCode()) {
73             case KeyEvent.KEYCODE_DPAD_UP:
74             case KeyEvent.KEYCODE_DPAD_DOWN:
75             case KeyEvent.KEYCODE_SPACE:
76                 return super.executeKeyEvent(event);
77             default:
78                 return false;
79         }
80     }
81 
82     @Override
onCreateInputConnection(EditorInfo outAttrs)83     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
84         // Fixes lanscape transitions when unfocusing the URL bar: crbug.com/288546
85         outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN;
86         return super.onCreateInputConnection(outAttrs);
87     }
88 }
89