// 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 #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; }