10cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv/* 20cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv * Copyright (C) 2013 The Android Open Source Project 30cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv * 40cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv * Licensed under the Apache License, Version 2.0 (the "License"); 50cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv * you may not use this file except in compliance with the License. 60cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv * You may obtain a copy of the License at 70cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv * 80cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv * http://www.apache.org/licenses/LICENSE-2.0 90cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv * 100cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv * Unless required by applicable law or agreed to in writing, software 110cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv * distributed under the License is distributed on an "AS IS" BASIS, 120cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv * See the License for the specific language governing permissions and 140cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv * limitations under the License. 150cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv */ 160cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv 175ecd81154fa039961f65bb4e36d18ac555b0d1d6Jim Millerpackage com.android.keyguard; 180cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv 190cbbc5766fb7c56c49ec55eece905fa7764a8b2balanvimport android.content.Context; 200cbbc5766fb7c56c49ec55eece905fa7764a8b2balanvimport android.view.MotionEvent; 210cbbc5766fb7c56c49ec55eece905fa7764a8b2balanvimport android.view.View; 220cbbc5766fb7c56c49ec55eece905fa7764a8b2balanvimport android.view.accessibility.AccessibilityManager; 230cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv 240cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv/** 250cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv * Hover listener that implements lift-to-activate interaction for 260cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv * accessibility. May be added to multiple views. 270cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv */ 280cbbc5766fb7c56c49ec55eece905fa7764a8b2balanvclass LiftToActivateListener implements View.OnHoverListener { 290cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv /** Manager used to query accessibility enabled state. */ 300cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv private final AccessibilityManager mAccessibilityManager; 310cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv 320cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv private boolean mCachedClickableState; 330cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv 340cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv public LiftToActivateListener(Context context) { 350cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv mAccessibilityManager = (AccessibilityManager) context.getSystemService( 360cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv Context.ACCESSIBILITY_SERVICE); 370cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv } 380cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv 390cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv @Override 400cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv public boolean onHover(View v, MotionEvent event) { 410cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv // When touch exploration is turned on, lifting a finger while 420cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv // inside the view bounds should perform a click action. 430cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv if (mAccessibilityManager.isEnabled() 440cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv && mAccessibilityManager.isTouchExplorationEnabled()) { 450cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv switch (event.getActionMasked()) { 460cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv case MotionEvent.ACTION_HOVER_ENTER: 470cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv // Lift-to-type temporarily disables double-tap 480cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv // activation by setting the view as not clickable. 490cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv mCachedClickableState = v.isClickable(); 500cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv v.setClickable(false); 510cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv break; 520cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv case MotionEvent.ACTION_HOVER_EXIT: 530cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv final int x = (int) event.getX(); 540cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv final int y = (int) event.getY(); 550cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv if ((x > v.getPaddingLeft()) && (y > v.getPaddingTop()) 560cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv && (x < v.getWidth() - v.getPaddingRight()) 570cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv && (y < v.getHeight() - v.getPaddingBottom())) { 580cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv v.performClick(); 590cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv } 600cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv v.setClickable(mCachedClickableState); 610cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv break; 620cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv } 630cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv } 640cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv 650cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv // Pass the event to View.onHoverEvent() to handle accessibility. 660cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv v.onHoverEvent(event); 670cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv 680cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv // Consume the event so it doesn't fall through to other views. 690cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv return true; 700cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv } 710cbbc5766fb7c56c49ec55eece905fa7764a8b2balanv}