helium/ui: add window frame hit test to toolbar (#395)

allows for the toolbar to be the handle for window dragging.
prerequisite for vertical tabs and other UI experiments 👀
This commit is contained in:
wukko
2025-11-04 18:12:30 +06:00
committed by GitHub
parent cc1db76e65
commit eaf2714853
2 changed files with 87 additions and 0 deletions

View File

@@ -0,0 +1,86 @@
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -4868,6 +4868,18 @@ int BrowserView::NonClientHitTest(const
}
}
+ // The empty spaces in toolbar should allow mouse events to fall
+ // through to the caption area.
+ if (toolbar_) {
+ gfx::Point test_point(point);
+ if (ConvertedHitTest(parent(), toolbar_, &test_point)) {
+ if (toolbar_->IsPositionInWindowCaption(test_point)) {
+ return HTCAPTION;
+ }
+ return HTCLIENT;
+ }
+ }
+
// Let the frame handle any events that fall within the bounds of the window
// controls overlay.
if (IsWindowControlsOverlayEnabled() && GetActiveWebContents()) {
--- a/chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -664,6 +664,44 @@ bool ToolbarView::GetAppMenuFocused() co
return app_menu_button_ && app_menu_button_->HasFocus();
}
+bool ToolbarView::IsRectInWindowCaption(const gfx::Rect& rect) const {
+ // Clickable elements are only in container view. If the container view is not
+ // visible, then the rect is in the window caption.
+ if (!container_view_ || !container_view_->GetVisible()) {
+ return true;
+ }
+
+ const auto get_target_rect = [&](views::View* target) {
+ gfx::RectF rect_in_target_coords_f(rect);
+ views::View::ConvertRectToTarget(this, target, &rect_in_target_coords_f);
+ return gfx::ToEnclosingRect(rect_in_target_coords_f);
+ };
+
+ // Check each child view in container_view_ to see if the rect intersects with
+ // any clickable elements. If it does, check if the click is actually on that
+ // element. False if on a clickable element, true if not on a clickable element.
+ for (views::View* const child : container_view_->children()) {
+ if (!child->GetVisible()) {
+ continue;
+ }
+
+ const gfx::Rect target_rect = get_target_rect(child);
+ if (child->GetLocalBounds().Intersects(target_rect)) {
+ // Check if the rect is actually on the child.
+ if (child->HitTestRect(target_rect)) {
+ return false;
+ }
+ }
+ }
+
+ // The rect is not on any clickable element, so it's in the window caption.
+ return true;
+}
+
+bool ToolbarView::IsPositionInWindowCaption(const gfx::Point& point) const {
+ return IsRectInWindowCaption(gfx::Rect(point, gfx::Size(1, 1)));
+}
+
void ToolbarView::ShowIntentPickerBubble(
std::vector<IntentPickerBubbleView::AppInfo> app_info,
bool show_stay_in_chrome,
--- a/chrome/browser/ui/views/toolbar/toolbar_view.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.h
@@ -126,6 +126,15 @@ class ToolbarView : public views::Access
// Returns true if the app menu is focused.
bool GetAppMenuFocused() const;
+ // Returns true if the specified rect is not on a clickable element,
+ // aka container view children: toolbar buttons, location bar, etc.
+ bool IsRectInWindowCaption(const gfx::Rect& rect) const;
+
+ // A convenience function which calls |IsRectInWindowCaption()| with a rect of
+ // size 1x1 and an origin of |point|. |point| is in the local coordinate space
+ // of |this|.
+ bool IsPositionInWindowCaption(const gfx::Point& point) const;
+
void ShowIntentPickerBubble(
std::vector<IntentPickerBubbleView::AppInfo> app_info,
bool show_stay_in_chrome,

View File

@@ -251,3 +251,4 @@ helium/ui/improve-flags-webui.patch
helium/ui/ublock-show-in-settings.patch
helium/ui/licenses-in-credits.patch
helium/ui/remove-autofill-link-to-password-manager.patch
helium/ui/toolbar-window-frame-hit-test.patch