chromium/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.cc

// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.h"

#include "base/feature_list.h"
#include "base/memory/raw_ptr.h"
#include "build/build_config.h"
#include "chrome/browser/themes/theme_service.h"
#include "chrome/browser/ui/color/chrome_color_id.h"
#include "chrome/browser/ui/layout_constants.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
#include "components/omnibox/common/omnibox_features.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/pointer/touch_ui_controller.h"
#include "ui/base/ui_base_features.h"
#include "ui/compositor/layer.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/geometry/rounded_corners_f.h"
#include "ui/views/bubble/bubble_border.h"
#include "ui/views/layout/layout_provider.h"

#if defined(USE_AURA)
#include "ui/aura/window.h"
#include "ui/aura/window_targeter.h"
#endif

#if BUILDFLAG(IS_WIN)
#include "ui/views/widget/native_widget_aura.h"
#endif

namespace {

// Value from the spec controlling appearance of the shadow.
constexpr int kElevation =;

#if !defined(USE_AURA)

struct WidgetEventPair {
  raw_ptr<views::Widget> widget;
  std::unique_ptr<ui::MouseEvent> event;
};

#if BUILDFLAG(IS_MAC)
views::Widget* GetImmersiveFullscreenWidgetForEvent(
    views::View* this_view,
    const ui::MouseEvent* this_event) {
  views::Widget* parent_widget = this_view->GetWidget()->parent();
  BrowserView* browser_view = BrowserView::GetBrowserViewForNativeWindow(
      parent_widget->GetNativeWindow());

  // If the results window is not a child of the overlay widget we are not in
  // immersive fullscreen.
  if (browser_view->overlay_widget() != parent_widget) {
    return nullptr;
  }

  {
    // If the event is located in the location bar send the event to the overlay
    // widget to handle text selection.
    gfx::Point event_location = this_event->location();
    views::View::ConvertPointToScreen(this_view, &event_location);
    views::View::ConvertPointFromScreen(browser_view->GetLocationBarView(),
                                        &event_location);
    if (browser_view->GetLocationBarView()->HitTestPoint(event_location)) {
      return browser_view->overlay_widget();
    }
  }

  {
    // If the event is located in the content view send the event to the browser
    // widget.
    gfx::Point event_location = this_event->location();
    views::View::ConvertPointToScreen(this_view, &event_location);
    views::View::ConvertPointFromScreen(browser_view->contents_container(),
                                        &event_location);
    if (browser_view->contents_container()->HitTestPoint(event_location)) {
      return browser_view->GetWidget();
    }
  }

  // In immersive fullscreen with tabs enabled the floating results shadow
  // spreads into the tab strip area which is hosted in yet another separate
  // widget, the tab widget. Send the rest of the events to the tab widget. This
  // will allow for tab strip interaction in the area covered by the shadow and
  // accurate tab hover card dismissal.
  if (browser_view->tab_overlay_widget()) {
    return browser_view->tab_overlay_widget();
  }

  // If immersive fullscreen with tabs is not enabled, send events to the
  // overlay widget for tab strip interaction in the area covered by the shadow.
  return browser_view->overlay_widget();
}
#endif

WidgetEventPair GetParentWidgetAndEvent(views::View* this_view,
                                        const ui::MouseEvent* this_event) {
  // Note that the floating results view is a top-level widget, so hop up a
  // level before looking for the parent's top-level widget for event
  // forwarding.
  views::Widget* this_widget = this_view->GetWidget();
  views::Widget* parent_widget = this_widget->parent();
  std::unique_ptr<ui::MouseEvent> event(
      static_cast<ui::MouseEvent*>(this_event->Clone().release()));
  if (!parent_widget)
    return {nullptr, std::move(event)};

// On macOS if the parent widget is the overlay widget we are in immersive
// fullscreen. Don't walk any higher up the tree. The overlay or tab widget will
// handle the event.
// TODO(http://crbug.com/1462791): Remove custom event handling.
#if BUILDFLAG(IS_MAC)
  views::Widget* top_level =
      GetImmersiveFullscreenWidgetForEvent(this_view, this_event)
          ?: parent_widget->GetTopLevelWidgetForNativeView(
                 parent_widget->GetNativeView());
#else
  views::Widget* top_level = parent_widget->GetTopLevelWidgetForNativeView(
      parent_widget->GetNativeView());
#endif

  DCHECK_NE(this_widget, top_level);
  if (!top_level)
    return {nullptr, std::move(event)};

  gfx::Point event_location = this_event->location();
  views::View::ConvertPointToScreen(this_view, &event_location);
  views::View::ConvertPointFromScreen(top_level->GetRootView(),
                                      &event_location);

  // Convert location to top level widget coordinate.
  event->set_location(event_location);

  return {top_level, std::move(event)};
}

#endif  // !USE_AURA

// View at the top of the frame which paints transparent pixels to make a hole
// so that the location bar shows through.
class TopBackgroundView : public views::View {};

BEGIN_METADATA()

// Insets used to position |contents_| within |contents_host_|.
gfx::Insets GetContentInsets() {}

}  // namespace

RoundedOmniboxResultsFrame::RoundedOmniboxResultsFrame(
    views::View* contents,
    LocationBarView* location_bar)
    :{}

RoundedOmniboxResultsFrame::~RoundedOmniboxResultsFrame() = default;

// static
void RoundedOmniboxResultsFrame::OnBeforeWidgetInit(
    views::Widget::InitParams* params,
    views::Widget* widget) {}

// static
int RoundedOmniboxResultsFrame::GetNonResultSectionHeight() {}

// static
gfx::Insets RoundedOmniboxResultsFrame::GetLocationBarAlignmentInsets() {}

// static
gfx::Insets RoundedOmniboxResultsFrame::GetShadowInsets() {}

void RoundedOmniboxResultsFrame::Layout(PassKey) {}

void RoundedOmniboxResultsFrame::AddedToWidget() {}

// Note: The OnMouseMoved function is only called for the shadow area, as mouse-
// moved events are not dispatched through the view hierarchy but are direct-
// dispatched by RootView. This OnMouseEvent function is on the dispatch path
// for all mouse events of the window, so be careful to correctly mark events as
// "handled" above in subviews.
#if !defined(USE_AURA)

// Note that mouse moved events can be dispatched through OnMouseEvent, but
// RootView directly calls OnMouseMoved as well, so override OnMouseMoved as
// well to catch 'em all.
void RoundedOmniboxResultsFrame::OnMouseMoved(const ui::MouseEvent& event) {
  auto pair = GetParentWidgetAndEvent(this, &event);
  if (pair.widget)
    pair.widget->OnMouseEvent(pair.event.get());
}

void RoundedOmniboxResultsFrame::OnMouseEvent(ui::MouseEvent* event) {
  auto pair = GetParentWidgetAndEvent(this, event);
  if (pair.widget)
    pair.widget->OnMouseEvent(pair.event.get());
}

#endif  // !USE_AURA

BEGIN_METADATA()