Improve focus handling around ScrollingTabWidget.

When focus enters the tab widget the focus will always be directed to
the last focused tab, instead of selecting the "best" tab.
diff --git a/src/com/android/contacts/ScrollingTabWidget.java b/src/com/android/contacts/ScrollingTabWidget.java
index f6f1ab1..9f4aee8 100644
--- a/src/com/android/contacts/ScrollingTabWidget.java
+++ b/src/com/android/contacts/ScrollingTabWidget.java
@@ -20,24 +20,22 @@
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
-import android.util.Log;
-import android.view.InflateException;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
-import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
 import android.view.View.OnClickListener;
-import android.widget.HorizontalScrollView;
+import android.view.View.OnFocusChangeListener;
 import android.widget.LinearLayout;
 import android.widget.RelativeLayout;
-import android.widget.TabHost;
 
 /*
  * Tab widget that can contain more tabs than can fit on screen at once and scroll over them.
  */
 public class ScrollingTabWidget extends RelativeLayout
-        implements OnClickListener {
+        implements OnClickListener, ViewTreeObserver.OnGlobalFocusChangeListener,
+        OnFocusChangeListener {
 
     private static final String TAG = "ScrollingTabWidget";
 
@@ -67,6 +65,13 @@
         mInflater = (LayoutInflater) mContext.getSystemService(
                 Context.LAYOUT_INFLATER_SERVICE);
 
+        setFocusable(true);
+        setOnFocusChangeListener(this);
+        onLoseFocus();
+//        if (!hasFocus()) {
+//            setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS);
+//        }
+
         mLeftArrowView = (LinearLayout) mInflater.inflate(R.layout.tab_left_arrow, this, false);
         mLeftArrowView.setOnClickListener(this);
         mRightArrowView = (LinearLayout) mInflater.inflate(R.layout.tab_right_arrow, this, false);
@@ -85,6 +90,24 @@
         addView(mRightArrowView);
     }
 
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        final ViewTreeObserver treeObserver = getViewTreeObserver();
+        if (treeObserver != null) {
+            treeObserver.addOnGlobalFocusChangeListener(this);
+        }
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        final ViewTreeObserver treeObserver = getViewTreeObserver();
+        if (treeObserver != null) {
+            treeObserver.removeOnGlobalFocusChangeListener(this);
+        }
+    }
+
     protected void updateArrowVisibility() {
         int scrollViewLeftEdge = mTabsScrollWrapper.getScrollX();
         int tabsViewLeftEdge = mTabsView.getLeft();
@@ -192,15 +215,9 @@
      *  @see #setCurrentTab
      */
     public void focusCurrentTab(int index) {
-        final int oldTab = mSelectedTab;
-
-        // set the tab
         setCurrentTab(index);
+        getChildTabViewAt(index).requestFocus();
 
-        // change the focus if applicable.
-        if (oldTab != index) {
-            getChildTabViewAt(index).requestFocus();
-        }
     }
 
     /**
@@ -236,7 +253,7 @@
         child.setFocusable(true);
         child.setClickable(true);
         child.setOnClickListener(new TabClickListener());
-        child.setOnFocusChangeListener(new TabFocusListener());
+        child.setOnFocusChangeListener(this);
 
         // If we already have at least one tab, then add a divider before adding the next tab.
         if (getTabCount() > 0) {
@@ -260,20 +277,62 @@
         mSelectionChangedListener = listener;
     }
 
-    private class TabFocusListener implements OnFocusChangeListener {
-        public void onFocusChange(View v, boolean hasFocus) {
-            if (hasFocus) {
-                for (int i = 0; i < getTabCount(); i++) {
-                    if (getChildTabViewAt(i) == v) {
-                        setCurrentTab(i);
-                        mSelectionChangedListener.onTabSelectionChanged(i, false);
-                        break;
-                    }
+    public void onGlobalFocusChanged(View oldFocus, View newFocus) {
+        if (isTab(oldFocus) && !isTab(newFocus)) {
+            onLoseFocus();
+        }
+    }
+
+    public void onFocusChange(View v, boolean hasFocus) {
+        if (v == this && hasFocus) {
+            onObtainFocus();
+            return;
+        }
+
+        if (hasFocus) {
+            for (int i = 0; i < getTabCount(); i++) {
+                if (getChildTabViewAt(i) == v) {
+                    setCurrentTab(i);
+                    mSelectionChangedListener.onTabSelectionChanged(i, false);
+                    break;
                 }
             }
         }
     }
 
+    /**
+     * Called when the {@link ScrollingTabWidget} gets focus. Here the
+     * widget decides which of it's tabs should have focus.
+     */
+    protected void onObtainFocus() {
+        // Setting this flag, allows the children of this View to obtain focus.
+        setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
+        // Assign focus to the last selected tab.
+        focusCurrentTab(mSelectedTab);
+        mSelectionChangedListener.onTabSelectionChanged(mSelectedTab, false);
+    }
+
+    /**
+     * Called when the focus has left the {@link ScrollingTabWidget} or its
+     * descendants. At this time we want the children of this view to be marked
+     * as un-focusable, so that next time focus is moved to the widget, the widget
+     * gets control, and can assign focus where it wants.
+     */
+    protected void onLoseFocus() {
+        // Setting this flag will effectively make the tabs unfocusable. This will
+        // be toggled when the widget obtains focus again.
+        setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS);
+    }
+
+    public boolean isTab(View v) {
+        for (int i = 0; i < getTabCount(); i++) {
+            if (getChildTabViewAt(i) == v) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private class TabClickListener implements OnClickListener {
         public void onClick(View v) {
             for (int i = 0; i < getTabCount(); i++) {
diff --git a/src/com/android/contacts/ViewContactActivity.java b/src/com/android/contacts/ViewContactActivity.java
index d00df4a..168eee3 100644
--- a/src/com/android/contacts/ViewContactActivity.java
+++ b/src/com/android/contacts/ViewContactActivity.java
@@ -1021,7 +1021,6 @@
                 views.secondaryActionButton = (ImageView) v.findViewById(
                         R.id.secondary_action_button);
                 views.secondaryActionButton.setOnClickListener(this);
-                views.secondaryActionButton.setFocusable(true);
                 views.secondaryActionDivider = v.findViewById(R.id.divider);
                 v.setTag(views);
             }