Commit 175b9f29 authored by Tomasz Wiszkowski's avatar Tomasz Wiszkowski Committed by Commit Bot

Detect Suggestion list height / respond to keyboard visibility change

This change is part of Adaptive Suggestions Count feature that aims
at presenting as many suggestions on screen as would fit between the
Omnibox and soft keyboard.

The change introduces no new logic and simply installs a callback
that monitors and responds to suggestion list size changes.

Bug: 1050813
Change-Id: I8fe777c83241cdb47e9cf238fe246b25cdbf78cc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2067659
Commit-Queue: Ender <ender@google.com>
Reviewed-by: default avatarTed Choc <tedchoc@chromium.org>
Reviewed-by: default avatarPatrick Noland <pnoland@chromium.org>
Cr-Commit-Position: refs/heads/master@{#744915}
parent 0c9ff14e
...@@ -67,20 +67,21 @@ public class AutocompleteCoordinatorImpl implements AutocompleteCoordinator { ...@@ -67,20 +67,21 @@ public class AutocompleteCoordinatorImpl implements AutocompleteCoordinator {
Context context = parent.getContext(); Context context = parent.getContext();
PropertyModel listModel = new PropertyModel(SuggestionListProperties.ALL_KEYS); PropertyModel listModel = new PropertyModel(SuggestionListProperties.ALL_KEYS);
ModelList listItems = new ModelList();
mMediator =
new AutocompleteMediator(context, delegate, urlBarEditingTextProvider, listModel);
listModel.set(SuggestionListProperties.EMBEDDER, listEmbedder); listModel.set(SuggestionListProperties.EMBEDDER, listEmbedder);
listModel.set(SuggestionListProperties.VISIBLE, false); listModel.set(SuggestionListProperties.VISIBLE, false);
listModel.set(SuggestionListProperties.OBSERVER, mMediator);
ModelList listItems = new ModelList();
listModel.set(SuggestionListProperties.SUGGESTION_MODELS, listItems); listModel.set(SuggestionListProperties.SUGGESTION_MODELS, listItems);
ViewProvider<SuggestionListViewHolder> viewProvider = ViewProvider<SuggestionListViewHolder> viewProvider =
createViewProvider(context, listItems); createViewProvider(context, listItems);
viewProvider.whenLoaded((holder) -> { mListView = holder.listView; }); viewProvider.whenLoaded((holder) -> { mListView = holder.listView; });
LazyConstructionPropertyMcp.create(listModel, SuggestionListProperties.VISIBLE, LazyConstructionPropertyMcp.create(listModel, SuggestionListProperties.VISIBLE,
viewProvider, SuggestionListViewBinder::bind); viewProvider, SuggestionListViewBinder::bind);
mMediator =
new AutocompleteMediator(context, delegate, urlBarEditingTextProvider, listModel);
// https://crbug.com/966227 Set initial layout direction ahead of inflating the suggestions. // https://crbug.com/966227 Set initial layout direction ahead of inflating the suggestions.
updateSuggestionListLayoutDirection(); updateSuggestionListLayoutDirection();
} }
......
...@@ -28,6 +28,7 @@ import org.chromium.chrome.browser.GlobalDiscardableReferencePool; ...@@ -28,6 +28,7 @@ import org.chromium.chrome.browser.GlobalDiscardableReferencePool;
import org.chromium.chrome.browser.compositor.layouts.EmptyOverviewModeObserver; import org.chromium.chrome.browser.compositor.layouts.EmptyOverviewModeObserver;
import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior; import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior;
import org.chromium.chrome.browser.favicon.LargeIconBridge; import org.chromium.chrome.browser.favicon.LargeIconBridge;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.image_fetcher.ImageFetcher; import org.chromium.chrome.browser.image_fetcher.ImageFetcher;
import org.chromium.chrome.browser.image_fetcher.ImageFetcherConfig; import org.chromium.chrome.browser.image_fetcher.ImageFetcherConfig;
import org.chromium.chrome.browser.image_fetcher.ImageFetcherFactory; import org.chromium.chrome.browser.image_fetcher.ImageFetcherFactory;
...@@ -37,6 +38,7 @@ import org.chromium.chrome.browser.lifecycle.StartStopWithNativeObserver; ...@@ -37,6 +38,7 @@ import org.chromium.chrome.browser.lifecycle.StartStopWithNativeObserver;
import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType;
import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider; import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider;
import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteController.OnSuggestionsReceivedListener; import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteController.OnSuggestionsReceivedListener;
import org.chromium.chrome.browser.omnibox.suggestions.SuggestionListProperties.SuggestionListObserver;
import org.chromium.chrome.browser.omnibox.suggestions.answer.AnswerSuggestionProcessor; import org.chromium.chrome.browser.omnibox.suggestions.answer.AnswerSuggestionProcessor;
import org.chromium.chrome.browser.omnibox.suggestions.basic.BasicSuggestionProcessor; import org.chromium.chrome.browser.omnibox.suggestions.basic.BasicSuggestionProcessor;
import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionHost; import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionHost;
...@@ -68,8 +70,8 @@ import java.util.List; ...@@ -68,8 +70,8 @@ import java.util.List;
/** /**
* Handles updating the model state for the currently visible omnibox suggestions. * Handles updating the model state for the currently visible omnibox suggestions.
*/ */
class AutocompleteMediator class AutocompleteMediator implements OnSuggestionsReceivedListener, SuggestionHost,
implements OnSuggestionsReceivedListener, SuggestionHost, StartStopWithNativeObserver { StartStopWithNativeObserver, SuggestionListObserver {
/** A struct containing information about the suggestion and its view type. */ /** A struct containing information about the suggestion and its view type. */
private static class SuggestionViewInfo { private static class SuggestionViewInfo {
/** Processor managing the suggestion. */ /** Processor managing the suggestion. */
...@@ -119,6 +121,7 @@ class AutocompleteMediator ...@@ -119,6 +121,7 @@ class AutocompleteMediator
private boolean mNativeInitialized; private boolean mNativeInitialized;
private AutocompleteController mAutocomplete; private AutocompleteController mAutocomplete;
private long mUrlFocusTime; private long mUrlFocusTime;
private boolean mEnableAdaptiveSuggestionsCount;
@IntDef({SuggestionVisibilityState.DISALLOWED, SuggestionVisibilityState.PENDING_ALLOW, @IntDef({SuggestionVisibilityState.DISALLOWED, SuggestionVisibilityState.PENDING_ALLOW,
SuggestionVisibilityState.ALLOWED}) SuggestionVisibilityState.ALLOWED})
...@@ -432,6 +435,9 @@ class AutocompleteMediator ...@@ -432,6 +435,9 @@ class AutocompleteMediator
void onNativeInitialized() { void onNativeInitialized() {
mNativeInitialized = true; mNativeInitialized = true;
mEnableAdaptiveSuggestionsCount =
ChromeFeatureList.isEnabled(ChromeFeatureList.OMNIBOX_ADAPTIVE_SUGGESTIONS_COUNT);
for (Runnable deferredRunnable : mDeferredNativeRunnables) { for (Runnable deferredRunnable : mDeferredNativeRunnables) {
mHandler.post(deferredRunnable); mHandler.post(deferredRunnable);
} }
...@@ -1157,4 +1163,17 @@ class AutocompleteMediator ...@@ -1157,4 +1163,17 @@ class AutocompleteMediator
return mShouldLog; return mShouldLog;
} }
} }
/**
* Respond to Suggestion list height change and update list of presented suggestions.
*
* This typically happens as a result of soft keyboard being shown or hidden.
*
* @param newHeightPx New height of the suggestion list in pixels.
*/
@Override
public void onSuggestionListHeightChanged(int newHeightPx) {
if (!mEnableAdaptiveSuggestionsCount) return;
// TODO(crbug.com/1050813): Update visibility of loaded suggestions.
}
} }
...@@ -23,9 +23,12 @@ import android.widget.ListView; ...@@ -23,9 +23,12 @@ import android.widget.ListView;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import org.chromium.base.TraceEvent; import org.chromium.base.TraceEvent;
import org.chromium.base.task.PostTask;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.omnibox.suggestions.SuggestionListProperties.SuggestionListObserver;
import org.chromium.chrome.browser.util.KeyNavigationUtil; import org.chromium.chrome.browser.util.KeyNavigationUtil;
import org.chromium.components.browser_ui.styles.ChromeColors; import org.chromium.components.browser_ui.styles.ChromeColors;
import org.chromium.content_public.browser.UiThreadTaskTraits;
import org.chromium.ui.base.ViewUtils; import org.chromium.ui.base.ViewUtils;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -43,8 +46,11 @@ public class OmniboxSuggestionsList extends ListView { ...@@ -43,8 +46,11 @@ public class OmniboxSuggestionsList extends ListView {
private OmniboxSuggestionListEmbedder mEmbedder; private OmniboxSuggestionListEmbedder mEmbedder;
private View mAnchorView; private View mAnchorView;
private View mAlignmentView; private View mAlignmentView;
private SuggestionListObserver mObserver;
private OnGlobalLayoutListener mAnchorViewLayoutListener; private OnGlobalLayoutListener mAnchorViewLayoutListener;
private OnLayoutChangeListener mAlignmentViewLayoutListener; private OnLayoutChangeListener mAlignmentViewLayoutListener;
private int mListViewMaxHeight;
private int mLastBroadcastedListViewMaxHeight;
/** /**
* Constructs a new list designed for containing omnibox suggestions. * Constructs a new list designed for containing omnibox suggestions.
...@@ -106,6 +112,10 @@ public class OmniboxSuggestionsList extends ListView { ...@@ -106,6 +112,10 @@ public class OmniboxSuggestionsList extends ListView {
} }
} }
void setObserver(SuggestionListObserver observer) {
mObserver = observer;
}
private void adjustSidePadding() { private void adjustSidePadding() {
if (mAlignmentView == null) return; if (mAlignmentView == null) return;
...@@ -162,6 +172,24 @@ public class OmniboxSuggestionsList extends ListView { ...@@ -162,6 +172,24 @@ public class OmniboxSuggestionsList extends ListView {
mEmbedder.getWindowDelegate().getWindowVisibleDisplayFrame(mTempRect); mEmbedder.getWindowDelegate().getWindowVisibleDisplayFrame(mTempRect);
int availableViewportHeight = mTempRect.height() - anchorBottomRelativeToContent; int availableViewportHeight = mTempRect.height() - anchorBottomRelativeToContent;
if (availableViewportHeight != mListViewMaxHeight) {
mListViewMaxHeight = availableViewportHeight;
if (mObserver != null) {
PostTask.postTask(UiThreadTaskTraits.DEFAULT, () -> {
// Detect if there was another change since this task posted.
// This indicates a subsequent task being posted too.
if (mListViewMaxHeight != availableViewportHeight) return;
// Detect if the new height is the same as previously broadcasted.
// The two checks (one above and one below) allow us to detect quick
// A->B->A transitions and suppress the broadcasts.
if (mLastBroadcastedListViewMaxHeight == availableViewportHeight) return;
if (mObserver == null) return;
mObserver.onSuggestionListHeightChanged(availableViewportHeight);
mLastBroadcastedListViewMaxHeight = availableViewportHeight;
});
}
}
super.onMeasure(MeasureSpec.makeMeasureSpec( super.onMeasure(MeasureSpec.makeMeasureSpec(
mAnchorView.getMeasuredWidth(), MeasureSpec.EXACTLY), mAnchorView.getMeasuredWidth(), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(availableViewportHeight, MeasureSpec.makeMeasureSpec(availableViewportHeight,
......
...@@ -13,6 +13,19 @@ import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey; ...@@ -13,6 +13,19 @@ import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey;
* The properties controlling the state of the list of suggestion items. * The properties controlling the state of the list of suggestion items.
*/ */
public class SuggestionListProperties { public class SuggestionListProperties {
/**
* Interface that will receive notifications and callbacks from OmniboxSuggestionList.
*/
public interface SuggestionListObserver {
/**
* Invoked whenever the height of suggestion list changes.
* The height may change as a result of eg. soft keyboard popping up.
*
* @param newHeightPx New height of the suggestion list in pixels.
*/
void onSuggestionListHeightChanged(int newHeightPx);
}
/** Whether the suggestion list is visible. */ /** Whether the suggestion list is visible. */
public static final WritableBooleanPropertyKey VISIBLE = new WritableBooleanPropertyKey(); public static final WritableBooleanPropertyKey VISIBLE = new WritableBooleanPropertyKey();
...@@ -30,6 +43,10 @@ public class SuggestionListProperties { ...@@ -30,6 +43,10 @@ public class SuggestionListProperties {
/** Whether the suggestion list should have a dark background. */ /** Whether the suggestion list should have a dark background. */
public static final WritableBooleanPropertyKey IS_INCOGNITO = new WritableBooleanPropertyKey(); public static final WritableBooleanPropertyKey IS_INCOGNITO = new WritableBooleanPropertyKey();
/** Observer that will receive notifications and callbacks from Suggestion List. */
public static final WritableObjectPropertyKey<SuggestionListObserver> OBSERVER =
new WritableObjectPropertyKey<>();
public static final PropertyKey[] ALL_KEYS = public static final PropertyKey[] ALL_KEYS =
new PropertyKey[] {VISIBLE, EMBEDDER, SUGGESTION_MODELS, IS_INCOGNITO}; new PropertyKey[] {VISIBLE, EMBEDDER, SUGGESTION_MODELS, IS_INCOGNITO, OBSERVER};
} }
...@@ -51,6 +51,8 @@ class SuggestionListViewBinder { ...@@ -51,6 +51,8 @@ class SuggestionListViewBinder {
} }
} else if (SuggestionListProperties.EMBEDDER.equals(propertyKey)) { } else if (SuggestionListProperties.EMBEDDER.equals(propertyKey)) {
view.listView.setEmbedder(model.get(SuggestionListProperties.EMBEDDER)); view.listView.setEmbedder(model.get(SuggestionListProperties.EMBEDDER));
} else if (SuggestionListProperties.OBSERVER.equals(propertyKey)) {
view.listView.setObserver(model.get(SuggestionListProperties.OBSERVER));
} else if (SuggestionListProperties.SUGGESTION_MODELS.equals(propertyKey)) { } else if (SuggestionListProperties.SUGGESTION_MODELS.equals(propertyKey)) {
// This should only ever be bound once. // This should only ever be bound once.
model.get(SuggestionListProperties.SUGGESTION_MODELS) model.get(SuggestionListProperties.SUGGESTION_MODELS)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment