10f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 20f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 30f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// found in the LICENSE file. 40f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 50f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)package org.chromium.android_webview; 60f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 70f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)import android.os.Handler; 80f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)import android.os.Message; 90f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)import android.view.View; 100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)import android.view.accessibility.AccessibilityEvent; 110f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)/** 130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) * Helper used to post the VIEW_SCROLLED accessibility event. 140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) * 150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) * TODO(mkosiba): Investigate whether this is behavior we want to share with the chrome/ layer. 160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) * TODO(mkosiba): We currently don't handle JS-initiated scrolling for layers other than the root 170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) * layer. 180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) */ 190f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)class ScrollAccessibilityHelper { 200f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // This is copied straight out of android.view.ViewConfiguration. 210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) private static final long SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS = 100; 220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) private class HandlerCallback implements Handler.Callback { 240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) public static final int MSG_VIEW_SCROLLED = 1; 250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) private View mEventSender; 270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) public HandlerCallback(View eventSender) { 290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) mEventSender = eventSender; 300f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) @Override 330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) public boolean handleMessage(Message msg) { 340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) switch(msg.what) { 350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) case MSG_VIEW_SCROLLED: 360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) mMsgViewScrolledQueued = false; 370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) mEventSender.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED); 380f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) break; 390f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) default: 400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) throw new IllegalStateException( 410f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) "AccessibilityInjector: unhandled message: " + msg.what); 420f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 430f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return true; 440f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 450f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 460f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 470f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) private Handler mHandler; 480f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) private boolean mMsgViewScrolledQueued; 490f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 500f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) public ScrollAccessibilityHelper(View eventSender) { 510f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) mHandler = new Handler(new HandlerCallback(eventSender)); 520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) /** 550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event. 560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) * This event is sent at most once every 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * {@link android.view.ViewConfiguration#getSendRecurringAccessibilityEventsInterval()} 580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) */ 590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) public void postViewScrolledAccessibilityEventCallback() { 600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (mMsgViewScrolledQueued) 610f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return; 620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) mMsgViewScrolledQueued = true; 630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) Message msg = mHandler.obtainMessage(HandlerCallback.MSG_VIEW_SCROLLED); 650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) mHandler.sendMessageDelayed(msg, SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS); 660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) public void removePostedViewScrolledAccessibilityEventCallback() { 690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!mMsgViewScrolledQueued) 700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return; 710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) mMsgViewScrolledQueued = false; 720f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 730f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) mHandler.removeMessages(HandlerCallback.MSG_VIEW_SCROLLED); 740f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 760f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) public void removePostedCallbacks() { 770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) removePostedViewScrolledAccessibilityEventCallback(); 780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 80