[HandoffButton] Use Omnibox popup state for split view visibility [chromium/src : main]

0 views
Skip to first unread message

Michelle Abreo (Gerrit)

unread,
Dec 2, 2025, 3:30:57 PM (3 days ago) Dec 2
to Abe Boujane, Chromium LUCI CQ, chromium...@chromium.org, aashna...@google.com, boujan...@google.com, chrstn...@google.com, kenok...@google.com, kmg+...@google.com, mfoltz+wa...@chromium.org
Attention needed from Abe Boujane

Michelle Abreo added 2 comments

File chrome/browser/actor/ui/actor_ui_tab_controller.cc
Line 228, Patchset 28:void ActorUiTabController::OnOmniboxFocusChanged(
OmniboxFocusState state,
OmniboxFocusChangeReason reason) {
bool has_focus = state != OmniboxFocusState::OMNIBOX_FOCUS_NONE;
if (is_focusing_omnibox_ == has_focus) {
return;
}

is_focusing_omnibox_ = has_focus;

if (auto* window_controller =
ActorUiWindowController::From(tab_->GetBrowserWindowInterface())) {
// Notify the window controller about the focus change. This will trigger UI
// updates on all panes.
window_controller->OnOmniboxFocusChanged(this, is_focusing_omnibox_);
} else {
UpdateUi(
base::BindOnce(&LogAndIgnoreCallbackError, "OnOmniboxFocusChanged"));
}
}
Abe Boujane . resolved

the flow of the updates here feels odd. We make each and every tab controller (we'll have 1 for each tab, so potentially tens if not hundreds) observe on the omnibox update, just to send the update up to the window controller, and have it then update the contentcontainer controller's tab controllers.

Instead, why don't we observe on the contentContainer controller level (since those would be mapped to the visible tabs anyway - which we'll have 2 of at most in case of split view), and update the relevant tab controllers then?

Michelle Abreo

updated to handle observation in the contents container controller. also updated the omnibox signal to be the popup opened vs just the omnibox focus, because this is a more accurate fix for the issue of overlap.

Line 315, Patchset 28: if (window_controller->IsOmniboxFocusedInOtherPane(this)) {
Abe Boujane . resolved

this becomes IsOmniboxFocused in general. right?

Michelle Abreo

yes, updated with the new check for popup visibility.

Open in Gerrit

Related details

Attention is currently required from:
  • Abe Boujane
Submit Requirements:
  • requirement satisfiedCode-Coverage
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: I103e305a3d3e89b0086b24b97a3453a3822e41af
Gerrit-Change-Number: 7147688
Gerrit-PatchSet: 48
Gerrit-Owner: Michelle Abreo <michel...@google.com>
Gerrit-Reviewer: Abe Boujane <bou...@google.com>
Gerrit-Reviewer: Michelle Abreo <michel...@google.com>
Gerrit-Attention: Abe Boujane <bou...@google.com>
Gerrit-Comment-Date: Tue, 02 Dec 2025 20:30:51 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: Abe Boujane <bou...@google.com>
satisfied_requirement
unsatisfied_requirement
open
diffy

Abe Boujane (Gerrit)

unread,
Dec 3, 2025, 12:47:11 PM (3 days ago) Dec 3
to Michelle Abreo, Chromium LUCI CQ, chromium...@chromium.org, aashna...@google.com, boujan...@google.com, chrstn...@google.com, kenok...@google.com, kmg+...@google.com, mfoltz+wa...@chromium.org
Attention needed from Michelle Abreo

Abe Boujane added 5 comments

File chrome/browser/actor/ui/actor_ui_tab_controller.h
Line 14, Patchset 49 (Latest):#include "components/omnibox/common/omnibox_focus_state.h"
Abe Boujane . unresolved

is this import needed?

Line 10, Patchset 49 (Latest):#include "base/timer/timer.h"
Abe Boujane . unresolved

is this import needed?

File chrome/browser/actor/ui/actor_ui_window_controller.cc
Line 177, Patchset 49 (Latest): // If the WebView's current WebContents is not the one we are observing,
// we have been detached and should stop processing.
if (contents_container_view_->GetWebContents() != web_contents()) {
return;
}
auto* tab_controller = GetActorUiTabController();
if (!tab_controller) {
return;
}
Abe Boujane . unresolved

Consider passing `ActorUiWindowController*` directly to the `ActorUiContentsContainerController` constructor. This will allow you to access it directly.

**Current Flow:**
`ActorUiContentsContainerController` -> `WebContents` -> `TabInterface` -> `BrowserWindowInterface` -> `ActorUiWindowController::From(...)`

**Proposed Flow (Direct Access):**
`ActorUiContentsContainerController` (holds `window_controller_` ptr) -> `window_controller_->OnOmniboxPopupVisibilityChanged(...)`

This would leverage the direct ownership relationship.

Line 283, Patchset 49 (Latest): if (omnibox_focused_tab_controller_ &&
omnibox_focused_tab_controller_.get() == sender.get()) {
Abe Boujane . unresolved

It's unclear when the `omnibox_focused_tab_controller_` is cleared/changed etc.
Is a better approach to never store the sender at all at the window controller level, and simply keep the bits we get at the contentsContainer level?

You can still have an aggregator function at the WindowController level, its logic could be something like:
```
IsAnyOmniboxPopupOpened(){
for(contentContainerCOntroller){
if(contentCOntainerController->IsOmniboxOpen() return true;
}
return false;
```

Line 291, Patchset 49 (Latest): for (const auto& container_controller : contents_container_controllers_) {
if (auto* contents = container_controller->web_contents()) {
if (auto* tab = tabs::TabInterface::MaybeGetFromContents(contents)) {
if (auto* tab_controller =
actor::ui::ActorUiTabControllerInterface::From(tab)) {
tab_controller->OnWindowOmniboxPopupVisibilityChanged();
}
}
}
}
Abe Boujane . unresolved

I think we should just delegate to the conteintsContainerVOntroller here:

```
for(contenteCOntainer: containers) {
container->NotifyWindowOmniboxPopupVisibilityCHanged();
}
```

and then have the contents container controllers implement NotifyWindowOmniboxPopupVisibilityChanged() :

```
ContentsContainerCOntroller::NotifyWindowOmniboxPopupVisibilityChanged(){
if (auto* tab_controller = GetActorUiTabController()) {
tab_controller->OnWindowOmniboxPopupVisibilityChanged();
}
}
```
Open in Gerrit

Related details

Attention is currently required from:
  • Michelle Abreo
Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement is not satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: I103e305a3d3e89b0086b24b97a3453a3822e41af
    Gerrit-Change-Number: 7147688
    Gerrit-PatchSet: 49
    Gerrit-Owner: Michelle Abreo <michel...@google.com>
    Gerrit-Reviewer: Abe Boujane <bou...@google.com>
    Gerrit-Reviewer: Michelle Abreo <michel...@google.com>
    Gerrit-Attention: Michelle Abreo <michel...@google.com>
    Gerrit-Comment-Date: Wed, 03 Dec 2025 17:47:06 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Michelle Abreo (Gerrit)

    unread,
    Dec 4, 2025, 12:34:20 PM (2 days ago) Dec 4
    to Abe Boujane, Chromium LUCI CQ, chromium...@chromium.org, aashna...@google.com, boujan...@google.com, chrstn...@google.com, kenok...@google.com, kmg+...@google.com, mfoltz+wa...@chromium.org
    Attention needed from Abe Boujane

    Michelle Abreo added 5 comments

    File chrome/browser/actor/ui/actor_ui_tab_controller.h
    Line 14, Patchset 49:#include "components/omnibox/common/omnibox_focus_state.h"
    Abe Boujane . resolved

    is this import needed?

    Michelle Abreo

    this one was leftover from a prev patchset, removed!

    Line 10, Patchset 49:#include "base/timer/timer.h"
    Abe Boujane . resolved

    is this import needed?

    Michelle Abreo

    It looks like it is necessary. I got a build error (no type named 'RetainingOneShotTimer') after removing omnibox_tab_helper.h.

    It seems omnibox_tab_helper.h was the only remaining header transitively providing the timer definition. so I added #include "base/timer/timer.h" to fix the break.

    File chrome/browser/actor/ui/actor_ui_window_controller.cc
    Line 177, Patchset 49: // If the WebView's current WebContents is not the one we are observing,

    // we have been detached and should stop processing.
    if (contents_container_view_->GetWebContents() != web_contents()) {
    return;
    }
    auto* tab_controller = GetActorUiTabController();
    if (!tab_controller) {
    return;
    }
    Abe Boujane . resolved

    Consider passing `ActorUiWindowController*` directly to the `ActorUiContentsContainerController` constructor. This will allow you to access it directly.

    **Current Flow:**
    `ActorUiContentsContainerController` -> `WebContents` -> `TabInterface` -> `BrowserWindowInterface` -> `ActorUiWindowController::From(...)`

    **Proposed Flow (Direct Access):**
    `ActorUiContentsContainerController` (holds `window_controller_` ptr) -> `window_controller_->OnOmniboxPopupVisibilityChanged(...)`

    This would leverage the direct ownership relationship.

    Michelle Abreo

    good idea, updated!

    Line 283, Patchset 49: if (omnibox_focused_tab_controller_ &&
    omnibox_focused_tab_controller_.get() == sender.get()) {
    Abe Boujane . resolved

    It's unclear when the `omnibox_focused_tab_controller_` is cleared/changed etc.
    Is a better approach to never store the sender at all at the window controller level, and simply keep the bits we get at the contentsContainer level?

    You can still have an aggregator function at the WindowController level, its logic could be something like:
    ```
    IsAnyOmniboxPopupOpened(){
    for(contentContainerCOntroller){
    if(contentCOntainerController->IsOmniboxOpen() return true;
    }
    return false;
    ```

    Michelle Abreo

    Done. I've refactored this to use the aggregation pattern as suggested.

    some context on the implementation: To support the popup fade-out animation (preventing the button from snapping back while the popup is still visible), we need the system to report 'Open' for a few hundred milliseconds after the logical close.

    Since the window controller no longer stores the state in `omnibox_focused_tab_controller_`, I moved this delay logic into ActorUiContentsContainerController. It now uses a PostDelayedTask and a cancellable closure to maintain the is_popup_open_ state during the fade-out.

    Line 291, Patchset 49: for (const auto& container_controller : contents_container_controllers_) {

    if (auto* contents = container_controller->web_contents()) {
    if (auto* tab = tabs::TabInterface::MaybeGetFromContents(contents)) {
    if (auto* tab_controller =
    actor::ui::ActorUiTabControllerInterface::From(tab)) {
    tab_controller->OnWindowOmniboxPopupVisibilityChanged();
    }
    }
    }
    }
    Abe Boujane . resolved

    I think we should just delegate to the conteintsContainerVOntroller here:

    ```
    for(contenteCOntainer: containers) {
    container->NotifyWindowOmniboxPopupVisibilityCHanged();
    }
    ```

    and then have the contents container controllers implement NotifyWindowOmniboxPopupVisibilityChanged() :

    ```
    ContentsContainerCOntroller::NotifyWindowOmniboxPopupVisibilityChanged(){
    if (auto* tab_controller = GetActorUiTabController()) {
    tab_controller->OnWindowOmniboxPopupVisibilityChanged();
    }
    }
    ```
    Michelle Abreo

    Done

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Abe Boujane
    Submit Requirements:
      • requirement satisfiedCode-Coverage
      • requirement is not satisfiedCode-Owners
      • requirement is not satisfiedCode-Review
      • requirement is not satisfiedReview-Enforcement
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: comment
      Gerrit-Project: chromium/src
      Gerrit-Branch: main
      Gerrit-Change-Id: I103e305a3d3e89b0086b24b97a3453a3822e41af
      Gerrit-Change-Number: 7147688
      Gerrit-PatchSet: 56
      Gerrit-Owner: Michelle Abreo <michel...@google.com>
      Gerrit-Reviewer: Abe Boujane <bou...@google.com>
      Gerrit-Reviewer: Michelle Abreo <michel...@google.com>
      Gerrit-Attention: Abe Boujane <bou...@google.com>
      Gerrit-Comment-Date: Thu, 04 Dec 2025 17:34:14 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      Comment-In-Reply-To: Abe Boujane <bou...@google.com>
      satisfied_requirement
      unsatisfied_requirement
      open
      diffy

      Abe Boujane (Gerrit)

      unread,
      Dec 5, 2025, 9:46:42 AM (17 hours ago) Dec 5
      to Michelle Abreo, Chromium LUCI CQ, chromium...@chromium.org, aashna...@google.com, boujan...@google.com, chrstn...@google.com, kenok...@google.com, kmg+...@google.com, mfoltz+wa...@chromium.org
      Attention needed from Michelle Abreo

      Abe Boujane added 5 comments

      File chrome/browser/actor/ui/actor_ui_tab_controller.h
      Line 119, Patchset 58 (Latest): bool is_focusing_omnibox_ = false;
      Abe Boujane . unresolved

      no longer needed.

      Line 25, Patchset 58 (Latest):class ActorUiTabController : public ActorUiTabControllerInterface,
      public ImmersiveModeController::Observer {
      Abe Boujane . unresolved

      perhaps we should have this chained after your other ImmersiveMode CL? otherwise you'll have some significat merge conflicts I think.

      File chrome/browser/actor/ui/actor_ui_window_controller.h
      Line 81, Patchset 58 (Latest): bool IsOmniboxPopupOpen() const;
      void NotifyWindowOmniboxPopupVisibilityChanged();
      Abe Boujane . unresolved

      please add documentation for these methoda

      File chrome/browser/actor/ui/actor_ui_window_controller.cc
      Line 199, Patchset 58 (Latest): close_popup_task_ = std::make_unique<base::CancelableOnceClosure>(
      base::BindOnce(&ActorUiContentsContainerController::HandlePopupClosed,
      weak_ptr_factory_.GetWeakPtr()));

      content::GetUIThreadTaskRunner({})->PostDelayedTask(
      FROM_HERE, close_popup_task_->callback(),
      base::Milliseconds(kOmniboxPopupHandoffButtonDelay));
      Abe Boujane . unresolved
      not sure this is the correct approach. I think if you want to know for sure that the omnibox is closed ( no longer appearing on the screen), then Widget Observer is what we want. it has a method you can override: OnWidgetVisibilityChanged. You can get the OmniboxPopup via BrowserElementsViews::From(bwi)
      ->GetViewAs<WhateverTheOmniboxPopupViewIs>(kWhateverTheElementIdIs) (or via other ways)
      Line 210, Patchset 58 (Latest): is_popup_open_ = false;
      Abe Boujane . unresolved

      Popup terminology is a bit unclear. Can we call it OmniboxPopup?

      Open in Gerrit

      Related details

      Attention is currently required from:
      • Michelle Abreo
      Submit Requirements:
        • requirement satisfiedCode-Coverage
        • requirement is not satisfiedCode-Owners
        • requirement is not satisfiedCode-Review
        • requirement is not satisfiedNo-Unresolved-Comments
        • requirement is not satisfiedReview-Enforcement
        Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
        Gerrit-MessageType: comment
        Gerrit-Project: chromium/src
        Gerrit-Branch: main
        Gerrit-Change-Id: I103e305a3d3e89b0086b24b97a3453a3822e41af
        Gerrit-Change-Number: 7147688
        Gerrit-PatchSet: 58
        Gerrit-Owner: Michelle Abreo <michel...@google.com>
        Gerrit-Reviewer: Abe Boujane <bou...@google.com>
        Gerrit-Reviewer: Michelle Abreo <michel...@google.com>
        Gerrit-Attention: Michelle Abreo <michel...@google.com>
        Gerrit-Comment-Date: Fri, 05 Dec 2025 14:46:36 +0000
        Gerrit-HasComments: Yes
        Gerrit-Has-Labels: No
        satisfied_requirement
        unsatisfied_requirement
        open
        diffy

        Michelle Abreo (Gerrit)

        unread,
        Dec 5, 2025, 1:29:30 PM (13 hours ago) Dec 5
        to Abe Boujane, Chromium LUCI CQ, chromium...@chromium.org, aashna...@google.com, boujan...@google.com, chrstn...@google.com, kenok...@google.com, kmg+...@google.com, mfoltz+wa...@chromium.org
        Attention needed from Abe Boujane

        Michelle Abreo added 5 comments

        File chrome/browser/actor/ui/actor_ui_tab_controller.h
        Line 119, Patchset 58: bool is_focusing_omnibox_ = false;
        Abe Boujane . resolved

        no longer needed.

        Michelle Abreo

        Done

        Line 25, Patchset 58:class ActorUiTabController : public ActorUiTabControllerInterface,
        public ImmersiveModeController::Observer {
        Abe Boujane . resolved

        perhaps we should have this chained after your other ImmersiveMode CL? otherwise you'll have some significat merge conflicts I think.

        Michelle Abreo

        Done

        File chrome/browser/actor/ui/actor_ui_window_controller.h
        Line 81, Patchset 58: bool IsOmniboxPopupOpen() const;
        void NotifyWindowOmniboxPopupVisibilityChanged();
        Abe Boujane . resolved

        please add documentation for these methoda

        Michelle Abreo

        Done

        File chrome/browser/actor/ui/actor_ui_window_controller.cc
        Line 199, Patchset 58: close_popup_task_ = std::make_unique<base::CancelableOnceClosure>(

        base::BindOnce(&ActorUiContentsContainerController::HandlePopupClosed,
        weak_ptr_factory_.GetWeakPtr()));

        content::GetUIThreadTaskRunner({})->PostDelayedTask(
        FROM_HERE, close_popup_task_->callback(),
        base::Milliseconds(kOmniboxPopupHandoffButtonDelay));
        Abe Boujane . unresolved
        not sure this is the correct approach. I think if you want to know for sure that the omnibox is closed ( no longer appearing on the screen), then Widget Observer is what we want. it has a method you can override: OnWidgetVisibilityChanged. You can get the OmniboxPopup via BrowserElementsViews::From(bwi)
        ->GetViewAs<WhateverTheOmniboxPopupViewIs>(kWhateverTheElementIdIs) (or via other ways)
        Michelle Abreo

        I looked into the WidgetObserver idea, but it feels like a bit of overkill for this one edge case.

        the main blocker is that there isn't a clean way to get that popup widget. it doesn't have a public element ID, and the OmniboxView interface doesn't expose it, so i’d have to include omnibox_view_views.h and explicitly downcast to the concrete OmniboxViewViews implementation. it feels weird to break that abstraction and couple this controller to the internal omnibox UI code just to catch the end of an animation.

        I also checked LocationBarView::OnPopupStateChanged, and it handles this exact asynchronous transition issue by simply posting a task with a 100ms delay. so sticking with a PostDelayedTask (i'm using 150ms to be safe, [the actual fade-out duration is hardcoded to 82ms](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/ui/views/omnibox/omnibox_popup_view_views.cc;l=222-223;drc=c8fb498259ce5c219f957dbe367da21a82a361c0)) seems to follow the established pattern for handling these fade-outs, rather than introducing new dependencies.

        since this is purely for visual smoothing in a rare edge case (focusing the actuating tab's omnibox and then immediately clicking the other split pane) I feel like sticking with the timer is a cleaner trade-off.

        Does that sound reasonable? happy to add the observer if you feel strongly, but wanted to double check.

        Line 210, Patchset 58: is_popup_open_ = false;
        Abe Boujane . resolved

        Popup terminology is a bit unclear. Can we call it OmniboxPopup?

        Michelle Abreo

        Done

        Open in Gerrit

        Related details

        Attention is currently required from:
        • Abe Boujane
        Submit Requirements:
        • requirement satisfiedCode-Coverage
        • requirement is not satisfiedCode-Owners
        • requirement is not satisfiedCode-Review
        • requirement is not satisfiedNo-Unresolved-Comments
        • requirement is not satisfiedReview-Enforcement
        Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
        Gerrit-MessageType: comment
        Gerrit-Project: chromium/src
        Gerrit-Branch: main
        Gerrit-Change-Id: I103e305a3d3e89b0086b24b97a3453a3822e41af
        Gerrit-Change-Number: 7147688
        Gerrit-PatchSet: 61
        Gerrit-Owner: Michelle Abreo <michel...@google.com>
        Gerrit-Reviewer: Abe Boujane <bou...@google.com>
        Gerrit-Reviewer: Michelle Abreo <michel...@google.com>
        Gerrit-Attention: Abe Boujane <bou...@google.com>
        Gerrit-Comment-Date: Fri, 05 Dec 2025 18:29:24 +0000
        Gerrit-HasComments: Yes
        Gerrit-Has-Labels: No
        Comment-In-Reply-To: Abe Boujane <bou...@google.com>
        satisfied_requirement
        unsatisfied_requirement
        open
        diffy

        Abe Boujane (Gerrit)

        unread,
        Dec 5, 2025, 2:10:20 PM (13 hours ago) Dec 5
        to Michelle Abreo, Chromium LUCI CQ, chromium...@chromium.org, aashna...@google.com, boujan...@google.com, chrstn...@google.com, kenok...@google.com, kmg+...@google.com, mfoltz+wa...@chromium.org
        Attention needed from Michelle Abreo

        Abe Boujane added 1 comment

        File chrome/browser/actor/ui/actor_ui_window_controller.cc
        Line 199, Patchset 58: close_popup_task_ = std::make_unique<base::CancelableOnceClosure>(
        base::BindOnce(&ActorUiContentsContainerController::HandlePopupClosed,
        weak_ptr_factory_.GetWeakPtr()));

        content::GetUIThreadTaskRunner({})->PostDelayedTask(
        FROM_HERE, close_popup_task_->callback(),
        base::Milliseconds(kOmniboxPopupHandoffButtonDelay));
        Abe Boujane . unresolved
        not sure this is the correct approach. I think if you want to know for sure that the omnibox is closed ( no longer appearing on the screen), then Widget Observer is what we want. it has a method you can override: OnWidgetVisibilityChanged. You can get the OmniboxPopup via BrowserElementsViews::From(bwi)
        ->GetViewAs<WhateverTheOmniboxPopupViewIs>(kWhateverTheElementIdIs) (or via other ways)
        Michelle Abreo

        I looked into the WidgetObserver idea, but it feels like a bit of overkill for this one edge case.

        the main blocker is that there isn't a clean way to get that popup widget. it doesn't have a public element ID, and the OmniboxView interface doesn't expose it, so i’d have to include omnibox_view_views.h and explicitly downcast to the concrete OmniboxViewViews implementation. it feels weird to break that abstraction and couple this controller to the internal omnibox UI code just to catch the end of an animation.

        I also checked LocationBarView::OnPopupStateChanged, and it handles this exact asynchronous transition issue by simply posting a task with a 100ms delay. so sticking with a PostDelayedTask (i'm using 150ms to be safe, [the actual fade-out duration is hardcoded to 82ms](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/ui/views/omnibox/omnibox_popup_view_views.cc;l=222-223;drc=c8fb498259ce5c219f957dbe367da21a82a361c0)) seems to follow the established pattern for handling these fade-outs, rather than introducing new dependencies.

        since this is purely for visual smoothing in a rare edge case (focusing the actuating tab's omnibox and then immediately clicking the other split pane) I feel like sticking with the timer is a cleaner trade-off.

        Does that sound reasonable? happy to add the observer if you feel strongly, but wanted to double check.

        Abe Boujane

        Thanks for looking into it. Do we actutally need new dependencies here? Instead of GetViewAs<> you can simply use GetView(ElementId). That way the only dependency is on the view.h (Which we're already pulling in since we depend on webview.h). You can then get the widget from the view etc.

        Other thing is, I think we can just add the element Id property to the OmniboxPopupViewViews in chrome/browser/ui/views/omnibox/omnibox_popup_view_views.cc. Something like SetProperty(views::kElementIdentifierKey, kOmniboxPopupView);

        At the end of the day, with a 150ms delay or with a direct dependency on visibility, the dependency is there. this component cares about when the OmniboxPopup is truly no longer visible. the explicit dependency in this case (without actual new imports) is preferred compared to the implicit temporal dependency.

        Having these (seemingly random) timeouts in the code is still an intrinsic dependency that is less robust for a number of reasons ( the fade-out duration of the omnibox popup could change at any moment, and it's not actually guaranteed that the it would take 82 seconds to disappear)

        does this make sense/seem reasonable?

        Open in Gerrit

        Related details

        Attention is currently required from:
        • Michelle Abreo
        Submit Requirements:
        • requirement satisfiedCode-Coverage
        • requirement is not satisfiedCode-Owners
        • requirement is not satisfiedCode-Review
        • requirement is not satisfiedNo-Unresolved-Comments
        • requirement is not satisfiedReview-Enforcement
        Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
        Gerrit-MessageType: comment
        Gerrit-Project: chromium/src
        Gerrit-Branch: main
        Gerrit-Change-Id: I103e305a3d3e89b0086b24b97a3453a3822e41af
        Gerrit-Change-Number: 7147688
        Gerrit-PatchSet: 62
        Gerrit-Owner: Michelle Abreo <michel...@google.com>
        Gerrit-Reviewer: Abe Boujane <bou...@google.com>
        Gerrit-Reviewer: Michelle Abreo <michel...@google.com>
        Gerrit-Attention: Michelle Abreo <michel...@google.com>
        Gerrit-Comment-Date: Fri, 05 Dec 2025 19:10:14 +0000
        Gerrit-HasComments: Yes
        Gerrit-Has-Labels: No
        Comment-In-Reply-To: Abe Boujane <bou...@google.com>
        Comment-In-Reply-To: Michelle Abreo <michel...@google.com>
        satisfied_requirement
        unsatisfied_requirement
        open
        diffy

        Michelle Abreo (Gerrit)

        unread,
        Dec 5, 2025, 6:14:38 PM (9 hours ago) Dec 5
        to AyeAye, Abe Boujane, Chromium LUCI CQ, chromium...@chromium.org, omnibox-...@chromium.org, jdonnel...@chromium.org, aashna...@google.com, boujan...@google.com, chrstn...@google.com, kenok...@google.com, kmg+...@google.com, mfoltz+wa...@chromium.org
        Attention needed from Abe Boujane

        Michelle Abreo voted and added 1 comment

        Votes added by Michelle Abreo

        Commit-Queue+1

        1 comment

        File chrome/browser/actor/ui/actor_ui_window_controller.cc
        Line 199, Patchset 58: close_popup_task_ = std::make_unique<base::CancelableOnceClosure>(
        base::BindOnce(&ActorUiContentsContainerController::HandlePopupClosed,
        weak_ptr_factory_.GetWeakPtr()));

        content::GetUIThreadTaskRunner({})->PostDelayedTask(
        FROM_HERE, close_popup_task_->callback(),
        base::Milliseconds(kOmniboxPopupHandoffButtonDelay));
        Abe Boujane . resolved
        not sure this is the correct approach. I think if you want to know for sure that the omnibox is closed ( no longer appearing on the screen), then Widget Observer is what we want. it has a method you can override: OnWidgetVisibilityChanged. You can get the OmniboxPopup via BrowserElementsViews::From(bwi)
        ->GetViewAs<WhateverTheOmniboxPopupViewIs>(kWhateverTheElementIdIs) (or via other ways)
        Michelle Abreo

        I looked into the WidgetObserver idea, but it feels like a bit of overkill for this one edge case.

        the main blocker is that there isn't a clean way to get that popup widget. it doesn't have a public element ID, and the OmniboxView interface doesn't expose it, so i’d have to include omnibox_view_views.h and explicitly downcast to the concrete OmniboxViewViews implementation. it feels weird to break that abstraction and couple this controller to the internal omnibox UI code just to catch the end of an animation.

        I also checked LocationBarView::OnPopupStateChanged, and it handles this exact asynchronous transition issue by simply posting a task with a 100ms delay. so sticking with a PostDelayedTask (i'm using 150ms to be safe, [the actual fade-out duration is hardcoded to 82ms](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/ui/views/omnibox/omnibox_popup_view_views.cc;l=222-223;drc=c8fb498259ce5c219f957dbe367da21a82a361c0)) seems to follow the established pattern for handling these fade-outs, rather than introducing new dependencies.

        since this is purely for visual smoothing in a rare edge case (focusing the actuating tab's omnibox and then immediately clicking the other split pane) I feel like sticking with the timer is a cleaner trade-off.

        Does that sound reasonable? happy to add the observer if you feel strongly, but wanted to double check.

        Abe Boujane

        Thanks for looking into it. Do we actutally need new dependencies here? Instead of GetViewAs<> you can simply use GetView(ElementId). That way the only dependency is on the view.h (Which we're already pulling in since we depend on webview.h). You can then get the widget from the view etc.

        Other thing is, I think we can just add the element Id property to the OmniboxPopupViewViews in chrome/browser/ui/views/omnibox/omnibox_popup_view_views.cc. Something like SetProperty(views::kElementIdentifierKey, kOmniboxPopupView);

        At the end of the day, with a 150ms delay or with a direct dependency on visibility, the dependency is there. this component cares about when the OmniboxPopup is truly no longer visible. the explicit dependency in this case (without actual new imports) is preferred compared to the implicit temporal dependency.

        Having these (seemingly random) timeouts in the code is still an intrinsic dependency that is less robust for a number of reasons ( the fade-out duration of the omnibox popup could change at any moment, and it's not actually guaranteed that the it would take 82 seconds to disappear)

        does this make sense/seem reasonable?

        Michelle Abreo

        discussed offline, implemented widget observer pattern.

        Open in Gerrit

        Related details

        Attention is currently required from:
        • Abe Boujane
        Submit Requirements:
          • requirement satisfiedCode-Coverage
          • requirement is not satisfiedCode-Owners
          • requirement is not satisfiedCode-Review
          • requirement is not satisfiedReview-Enforcement
          Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
          Gerrit-MessageType: comment
          Gerrit-Project: chromium/src
          Gerrit-Branch: main
          Gerrit-Change-Id: I103e305a3d3e89b0086b24b97a3453a3822e41af
          Gerrit-Change-Number: 7147688
          Gerrit-PatchSet: 66
          Gerrit-Owner: Michelle Abreo <michel...@google.com>
          Gerrit-Reviewer: Abe Boujane <bou...@google.com>
          Gerrit-Reviewer: Michelle Abreo <michel...@google.com>
          Gerrit-Attention: Abe Boujane <bou...@google.com>
          Gerrit-Comment-Date: Fri, 05 Dec 2025 23:14:28 +0000
          Gerrit-HasComments: Yes
          Gerrit-Has-Labels: Yes
          satisfied_requirement
          unsatisfied_requirement
          open
          diffy

          Moe Ahmadi (Gerrit)

          unread,
          Dec 5, 2025, 10:24:49 PM (5 hours ago) Dec 5
          to Michelle Abreo, AyeAye, Abe Boujane, Chromium LUCI CQ, chromium...@chromium.org, omnibox-...@chromium.org, jdonnel...@chromium.org, aashna...@google.com, boujan...@google.com, chrstn...@google.com, kenok...@google.com, kmg+...@google.com, mfoltz+wa...@chromium.org
          Attention needed from Abe Boujane and Michelle Abreo

          Moe Ahmadi added 1 comment

          Patchset-level comments
          File-level comment, Patchset 66 (Latest):
          Moe Ahmadi . unresolved

          Please consult the Omnibox team before introducing a dependency on the Omnibox Popup state. We are in the process of re-implementing the Omnibox and refactoring the code.

          Open in Gerrit

          Related details

          Attention is currently required from:
          • Abe Boujane
          • Michelle Abreo
          Submit Requirements:
            • requirement satisfiedCode-Coverage
            • requirement is not satisfiedCode-Owners
            • requirement is not satisfiedCode-Review
            • requirement is not satisfiedNo-Unresolved-Comments
            • requirement is not satisfiedReview-Enforcement
            Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
            Gerrit-MessageType: comment
            Gerrit-Project: chromium/src
            Gerrit-Branch: main
            Gerrit-Change-Id: I103e305a3d3e89b0086b24b97a3453a3822e41af
            Gerrit-Change-Number: 7147688
            Gerrit-PatchSet: 66
            Gerrit-Owner: Michelle Abreo <michel...@google.com>
            Gerrit-Reviewer: Abe Boujane <bou...@google.com>
            Gerrit-Reviewer: Michelle Abreo <michel...@google.com>
            Gerrit-CC: Moe Ahmadi <mah...@chromium.org>
            Gerrit-Attention: Abe Boujane <bou...@google.com>
            Gerrit-Attention: Michelle Abreo <michel...@google.com>
            Gerrit-Comment-Date: Sat, 06 Dec 2025 03:24:37 +0000
            Gerrit-HasComments: Yes
            Gerrit-Has-Labels: No
            satisfied_requirement
            unsatisfied_requirement
            open
            diffy
            Reply all
            Reply to author
            Forward
            0 new messages