mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
chrome: Improve positioning of the "Find" widget (fixes #3461)
The "Find" widget will be excluded from regions near the edges of the window that contain overlays, draggable regions or titlebar.
This commit is contained in:
102
libcef/browser/geometry_util.cc
Normal file
102
libcef/browser/geometry_util.cc
Normal file
@@ -0,0 +1,102 @@
|
||||
// Copyright (c) 2022 The Chromium Embedded Framework Authors. All rights
|
||||
// reserved. Use of this source code is governed by a BSD-style license that
|
||||
// can be found in the LICENSE file.
|
||||
|
||||
#include "libcef/browser/geometry_util.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "ui/gfx/geometry/rect.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int kMinWidth = 0;
|
||||
constexpr int kMinHeight = 0;
|
||||
|
||||
// Makes sure that line segment lies entirely between min and max.
|
||||
int clamp_segment_start(int start, int len, int min, int max) {
|
||||
start = std::clamp(start, min, max);
|
||||
const int end = start + len;
|
||||
const int excess = end - max;
|
||||
|
||||
if (excess > 0) {
|
||||
start = start - excess;
|
||||
}
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
gfx::Rect MakeVisibleOnScreenRect(const gfx::Rect& rect,
|
||||
const gfx::Rect& screen) {
|
||||
const int width = std::clamp(rect.width(), kMinWidth, screen.width());
|
||||
const int height = std::clamp(rect.height(), kMinHeight, screen.height());
|
||||
|
||||
const int right_border = screen.x() + screen.width();
|
||||
const int x = clamp_segment_start(rect.x(), width, screen.x(), right_border);
|
||||
|
||||
const int bottom_border = screen.y() + screen.height();
|
||||
const int y =
|
||||
clamp_segment_start(rect.y(), height, screen.y(), bottom_border);
|
||||
|
||||
return gfx::Rect(x, y, width, height);
|
||||
}
|
||||
|
||||
gfx::Rect SubtractOverlayFromBoundingBox(const gfx::Rect& bounds,
|
||||
const gfx::Rect& overlay,
|
||||
int max_distance) {
|
||||
if (overlay.Contains(bounds)) {
|
||||
// Early exit; |bounds| is completely inside |overlay|.
|
||||
return bounds;
|
||||
}
|
||||
|
||||
// Portion of |overlay| that is inside |bounds|.
|
||||
auto overlap = overlay;
|
||||
overlap.Intersect(bounds);
|
||||
if (overlap.IsEmpty()) {
|
||||
// Early exit; |bounds| and |overlay| don't intersect.
|
||||
return bounds;
|
||||
}
|
||||
|
||||
gfx::Insets insets;
|
||||
|
||||
if (overlap.width() >= overlap.height()) {
|
||||
// Wide overlay; maybe inset |bounds| in the Y direction.
|
||||
const int delta_top = overlap.y() - bounds.y();
|
||||
const int delta_bottom =
|
||||
bounds.y() + bounds.height() - overlap.y() - overlap.height();
|
||||
|
||||
// Inset from the closest side that meets |max_distance| requirements.
|
||||
if (delta_top <= delta_bottom && delta_top <= max_distance) {
|
||||
// Inset from the top.
|
||||
insets.set_top(delta_top + overlap.height());
|
||||
} else if (delta_bottom <= max_distance) {
|
||||
// Inset from the bottom.
|
||||
insets.set_bottom(delta_bottom + overlap.height());
|
||||
}
|
||||
} else {
|
||||
// Tall overlay; maybe inset |bounds| in the X direction.
|
||||
const int delta_left = overlap.x() - bounds.x();
|
||||
const int delta_right =
|
||||
bounds.x() + bounds.width() - overlap.x() - overlap.width();
|
||||
|
||||
// Inset from the closest side that meets |max_distance| requirements.
|
||||
if (delta_left <= delta_right && delta_left <= max_distance) {
|
||||
// Inset from the left.
|
||||
insets.set_left(delta_left + overlap.width());
|
||||
} else if (delta_right <= max_distance) {
|
||||
// Inset from the right.
|
||||
insets.set_right(delta_right + overlap.width());
|
||||
}
|
||||
}
|
||||
|
||||
if (insets.IsEmpty()) {
|
||||
// |overlay| is too far inside |bounds| to trigger insets.
|
||||
return bounds;
|
||||
}
|
||||
|
||||
auto result = bounds;
|
||||
result.Inset(insets);
|
||||
return result;
|
||||
}
|
Reference in New Issue
Block a user