electron/shell/browser/ui/views/opaque_frame_view.cc

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

562 lines
21 KiB
C++
Raw Normal View History

// Copyright (c) 2024 Microsoft GmbH.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "shell/browser/ui/views/opaque_frame_view.h"
#include "base/containers/adapters.h"
#include "base/i18n/rtl.h"
chore: bump chromium to 139.0.7256.0 (38-x-y) (#47615) * chore: bump chromium in DEPS to 139.0.7242.0 Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> * chore: update render_widget_host_view_mac.patch no code changes; just updating patch context Do a cleanup pass on the history swiper code | https://chromium-review.googlesource.com/c/chromium/src/+/6604367 Co-authored-by: Charles Kerr <charles@charleskerr.com> * chore: update mas_avoid_private_macos_api_usage.patch.patch no code changes; just updating patch context [tracing] Delete base/trace_event/base_tracing.h | https://chromium-review.googlesource.com/c/chromium/src/+/6624012 Co-authored-by: Charles Kerr <charles@charleskerr.com> * chore: update chore_provide_iswebcontentscreationoverridden_with_full_params.patch no manual changes; just updating patch context [ActorFramework] Refactor Actor Task Management | https://chromium-review.googlesource.com/c/chromium/src/+/6618684 Co-authored-by: Charles Kerr <charles@charleskerr.com> * chore: update fix_move_autopipsettingshelper_behind_branding_buildflag.patch [pip] Tuck picture-in-picture windows when a file dialog is open | https://chromium-review.googlesource.com/c/chromium/src/+/6449682 Reland "[document pip] Restrict the size that a website can request" | https://chromium-review.googlesource.com/c/chromium/src/+/6372104 Co-authored-by: Charles Kerr <charles@charleskerr.com> * chore: update feat_corner_smoothing_css_rule_and_blink_painting.patch Xref: corner-shape: constraint radii based on opposite corner overlap | https://chromium-review.googlesource.com/c/chromium/src/+/6592572 Co-authored-by: Charles Kerr <charles@charleskerr.com> * chore: update revert_code_health_clean_up_stale_macwebcontentsocclusion.patch no manual changes; just updating patch context Co-authored-by: Charles Kerr <charles@charleskerr.com> * chore: update fix_rename_sqlite_win32_exports_to_avoid_conflicts_with_node_js.patch no code changes; just updating patch context Co-authored-by: Charles Kerr <charles@charleskerr.com> * chore: e patches all Co-authored-by: Charles Kerr <charles@charleskerr.com> * Plumb Verify2QwacBinding and hook it up in QwacWebContentsObserver https://chromium-review.googlesource.com/c/chromium/src/+/6624719 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * Remove host delegate OnMainFrameCreatedForBackgroundPage https://chromium-review.googlesource.com/c/chromium/src/+/6631123 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * Extensions: Rename GetResourceURL to ResolveExtensionURL https://chromium-review.googlesource.com/c/chromium/src/+/6625053 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * Consolidate NativeFrameViewMac https://chromium-review.googlesource.com/c/chromium/src/+/6614239 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * ICWYU Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * Remove dead code WidgetAXTreeIDMap https://chromium-review.googlesource.com/c/chromium/src/+/6619701 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * Reland "extensions: Add `WillPrepareForEvaluation` to setup MojoJS" https://chromium-review.googlesource.com/c/chromium/src/+/6630056 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * NavigationThrottleRunner2: Remove MaybeAddThrottle https://chromium-review.googlesource.com/c/chromium/src/+/6628079 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * Tuck picture-in-picture windows when a file dialog is open https://chromium-review.googlesource.com/c/chromium/src/+/6449682 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * build: fix snapshot_blob.bin build error xref: https://issues.chromium.org/issues/416540976 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * chore: e patches all Co-authored-by: Charles Kerr <charles@charleskerr.com> * build: freeup disk space on macos Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * chore: bump chromium in DEPS to 139.0.7244.0 Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> * chore: update printing.patch no manual changes; just updating patch context Co-authored-by: Charles Kerr <charles@charleskerr.com> * chore: remove upstreamed ignore_parse_errors_for_resolveshortcutproperties.patch Prevent Windows crash on unexpected shortcut type | https://chromium-review.googlesource.com/c/chromium/src/+/6633298 Co-authored-by: Charles Kerr <charles@charleskerr.com> * chore: e patches all Co-authored-by: Charles Kerr <charles@charleskerr.com> * Revert "Reland "extensions: Add `WillPrepareForEvaluation` to setup MojoJS"" This reverts commit 77c4f967a637f7e8970114f91311f9fddede0f7c. Revert CL for the high confidence crash culprit for http://crash/28f897bb9743dfe0 | https://chromium-review.googlesource.com/c/chromium/src/+/6641819 Co-authored-by: Charles Kerr <charles@charleskerr.com> * Fix spec's expected base64-encoded PNG strings to match upstream changes. [rust png] Enable by default. | https://chromium-review.googlesource.com/c/chromium/src/+/6085801 Co-authored-by: Charles Kerr <charles@charleskerr.com> * chore: bump chromium in DEPS to 139.0.7246.0 Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> * chore: e patches all Co-authored-by: Charles Kerr <charles@charleskerr.com> * chore: bump chromium in DEPS to 139.0.7248.0 Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> * chore: update patches Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * siso: Enable Siso by default for non-Google builds https://chromium-review.googlesource.com/c/chromium/src/+/6638830 Disabling for now until we are ready to build siso on all platforms. Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * Revert "revert Don't use static variable for UseExternalPopupMenus" This reverts commit e91e3894e6c34cc0ffe69ed45417c0ebec882fb1. Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * Update mac_sdk_min to match minimum required SDK version https://chromium-review.googlesource.com/c/chromium/src/+/6493969 (cherry picked from commit 3e7cbe912d8fe1062d68ed06968aaee22013985f) Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * Use default window styling on Mac https://chromium-review.googlesource.com/c/chromium/src/+/6648665 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * Reland "Force the unintentional renderer process creation check by default" https://chromium-review.googlesource.com/c/chromium/src/+/6626905 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * fixup: Reland "Force the unintentional renderer process creation check by default https://chromium-review.googlesource.com/c/chromium/src/+/6626905 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * chore: bump chromium in DEPS to 139.0.7249.0 Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> * fixup: Reland "Force the unintentional renderer process creation check by default https://chromium-review.googlesource.com/c/chromium/src/+/6626905 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * chore: update patches Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * chore: bump chromium in DEPS to 139.0.7250.0 Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> * chore: bump chromium in DEPS to 139.0.7252.0 Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> * chore: bump chromium in DEPS to 139.0.7254.0 Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> * 6638187: browser level TOCTOU check for coordinate target https://chromium-review.googlesource.com/c/chromium/src/+/6638187 Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> * chore: fixup patch indices Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> * chore: add missing base/notimplemented includes Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> * 6652910: [Frame Cleanup] Push down/hide implementation-specific API https://chromium-review.googlesource.com/c/chromium/src/+/6652910 Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> * chore: bump chromium in DEPS to 139.0.7256.0 Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> * chore: fix lint Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> * fixup! 6652910: [Frame Cleanup] Push down/hide implementation-specific API Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> * fix: move HandleScope location Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> * chore: bump chromium in DEPS to 139.0.7258.0 Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> * fixup! [NonClientFrameView] Consolidate NativeFrameViewMac Co-authored-by: deepak1556 <hop2deep@gmail.com> * Revert "chore: bump chromium in DEPS to 139.0.7258.0" This reverts commit 264b2e934f4b2705c47d9761010052b95d9dd5de. Co-authored-by: deepak1556 <hop2deep@gmail.com> * chore: update patches --------- Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com> Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> Co-authored-by: Charles Kerr <charles@charleskerr.com> Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> Co-authored-by: deepak1556 <hop2deep@gmail.com> Co-authored-by: patchup[bot] <73610968+patchup[bot]@users.noreply.github.com>
2025-06-30 12:29:54 -04:00
#include "chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h" // nogncheck
#include "chrome/grit/generated_resources.h"
#include "components/strings/grit/components_strings.h"
#include "shell/browser/native_window_views.h"
#include "shell/browser/ui/views/caption_button_placeholder_container.h"
#include "ui/base/hit_test.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/compositor/layer.h"
chore: remove more unused #include calls (#43000) * chore: in shell/renderer/renderer_client_base.h, remove include media/base/key_systems_support_registration.h last use removed in c670e38b (##41610) * chore: iwyu electron/fuses.h * chore: iwyu media/base/video_frame.h * chore: iwyu base/functional/callback.h * chore: iwyu base/task/cancelable_task_tracker.h * chore: iwyu shell/browser/draggable_region_provider.h * chore: iwyu shell/browser/ui/inspectable_web_contents_view.h * chore: iwyu ui/aura/window.h * chore: iwyu ui/base/win/shell.h * chore: iwyu ui/display/win/screen_win.h * chore: iwyu ui/gfx/geometry/insets.h * chore: iwyu ui/display/display.h * chore: iwyu ui/gfx/geometry/skia_conversions.h * chore: iwyu ui/gfx/geometry/rect_conversions.h * chore: iwyu ui/gfx/geometry/point.h * chore: iwyu ui/gfx/scoped_canvas.h * chore: iwyu ui/gfx/image/image.h * chore: iwyu ui/accessibility/ax_node_data.h * chore: iwyu ui/views/animation/ink_drop_highlight.h * chore: iwyu ui/gfx/font_list.h * chore: iwyu ui/linux/nav_button_provider.h * chore: iwyu shell/browser/ui/views/frameless_view.h * chore: iwyu services/metrics/public/cpp/ukm_source_id.h * chore: iwyu net/http/http_util.h * chore: iwyu net/base/mime_util.h * chore: iwyu content/public/common/content_client.h * chore: iwyu <list> * chore: iwyu <optional> * chore: iwyu <memory> * chore: iwyu base/files/file_path.h * chore: iwyu ui/base/cursor/cursor.h * chore: iwyu build/build_config.h * chore: iwyu content/public/browser/web_contents.h * chore: iwyu shell/browser/hid/hid_chooser_context.h * chore: iwyu shell/common/platform_util.h * chore: iwyu base/task/single_thread_task_runner.h * chore: iwyu content/browser/renderer_host/render_widget_host_impl.h * chore: iwyu content/public/browser/render_widget_host.h * chore: iwyu shell/browser/electron_browser_context.h * chore: iwyu content/public/browser/web_contents_observer.h * chore: iwyu content/public/browser/render_frame_host.h * chore: iwyu content/public/browser/media_stream_request.h * chore: iwyu chrome/common/chrome_paths.h * chore: iwyu chrome/browser/icon_manager.h * chore: iwyu printing/print_settings.h * chore: iwyu renderer/pepper_helper.h * chore: iwyu shell/browser/api/process_metric.h * chore: iwyu shell/browser/electron_browser_client.h * chore: iwyu shell/browser/electron_browser_context.h * chore: iwyu shell/browser/api/electron_api_session.h * chore: iwyu shell/browser/api/electron_api_app.h * chore: iwyu shell/browser/ui/views/client_frame_view_linux.h * chore: iwyu shell/browser/native_window_views.h * chore: iwyu base/win/windows_version.h * chore: iwyu shell/common/electron_paths.h * chore: iwyu content/public/common/content_switches.h * chore: iwyu third_party/skia/include/core/SkRRect.h * chore: iwyu third_party/skia/include/core/SkBitmap.h * chore: iwyu third_party/skia * chore: iwyu shell/browser/osr/osr_host_display_client.h * chore: iwyu shell/browser/login_handler.h * chore: iwyu shell/browser/javascript_environment.h * chore: iwyu shell/browser/event_emitter_mixin.h * fix: mac * fix: mac * chore: iwyu base/nix/xdg_util.h * fix: win * fix: win * fix: win * fix: win
2024-07-25 04:25:45 -05:00
#include "ui/gfx/font_list.h"
#include "ui/linux/linux_ui.h"
#include "ui/views/background.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/window/frame_caption_button.h"
#include "ui/views/window/vector_icons/vector_icons.h"
namespace electron {
namespace {
// These values should be the same as Chromium uses.
constexpr int kCaptionButtonHeight = 18;
bool HitTestCaptionButton(views::Button* button, const gfx::Point& point) {
return button && button->GetVisible() &&
button->GetMirroredBounds().Contains(point);
}
// The frame has a 2 px 3D edge along the top. This is overridable by
// subclasses, so RestoredFrameEdgeInsets() should be used instead of using this
// constant directly.
const int kTopFrameEdgeThickness = 2;
// The frame has a 1 px 3D edge along the side. This is overridable by
// subclasses, so RestoredFrameEdgeInsets() should be used instead of using this
// constant directly.
const int kSideFrameEdgeThickness = 1;
// The minimum vertical padding between the bottom of the caption buttons and
// the top of the content shadow.
const int kCaptionButtonBottomPadding = 3;
} // namespace
// The content edge images have a shadow built into them.
const int OpaqueFrameView::kContentEdgeShadowThickness = 2;
OpaqueFrameView::OpaqueFrameView() = default;
OpaqueFrameView::~OpaqueFrameView() = default;
void OpaqueFrameView::Init(NativeWindowViews* window, views::Widget* frame) {
FramelessView::Init(window, frame);
if (!window->IsWindowControlsOverlayEnabled())
return;
caption_button_placeholder_container_ =
AddChildView(std::make_unique<CaptionButtonPlaceholderContainer>());
minimize_button_ = CreateButton(
VIEW_ID_MINIMIZE_BUTTON, IDS_ACCNAME_MINIMIZE,
views::CAPTION_BUTTON_ICON_MINIMIZE, HTMINBUTTON,
views::kWindowControlMinimizeIcon,
base::BindRepeating(&views::Widget::Minimize, base::Unretained(frame)));
maximize_button_ = CreateButton(
VIEW_ID_MAXIMIZE_BUTTON, IDS_ACCNAME_MAXIMIZE,
views::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE, HTMAXBUTTON,
views::kWindowControlMaximizeIcon,
base::BindRepeating(&views::Widget::Maximize, base::Unretained(frame)));
restore_button_ = CreateButton(
VIEW_ID_RESTORE_BUTTON, IDS_ACCNAME_RESTORE,
views::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE, HTMAXBUTTON,
views::kWindowControlRestoreIcon,
base::BindRepeating(&views::Widget::Restore, base::Unretained(frame)));
close_button_ = CreateButton(
VIEW_ID_CLOSE_BUTTON, IDS_ACCNAME_CLOSE, views::CAPTION_BUTTON_ICON_CLOSE,
HTMAXBUTTON, views::kWindowControlCloseIcon,
base::BindRepeating(&views::Widget::CloseWithReason,
base::Unretained(frame),
views::Widget::ClosedReason::kCloseButtonClicked));
// Unretained() is safe because the subscription is saved into an instance
// member and thus will be cancelled upon the instance's destruction.
paint_as_active_changed_subscription_ =
frame->RegisterPaintAsActiveChangedCallback(base::BindRepeating(
&OpaqueFrameView::PaintAsActiveChanged, base::Unretained(this)));
}
int OpaqueFrameView::ResizingBorderHitTest(const gfx::Point& point) {
return FramelessView::ResizingBorderHitTest(point);
}
void OpaqueFrameView::InvalidateCaptionButtons() {
UpdateCaptionButtonPlaceholderContainerBackground();
UpdateFrameCaptionButtons();
LayoutWindowControlsOverlay();
InvalidateLayout();
}
gfx::Rect OpaqueFrameView::GetBoundsForClientView() const {
if (window()->IsWindowControlsOverlayEnabled()) {
auto border_thickness = FrameBorderInsets(false);
int top_height = border_thickness.top();
return gfx::Rect(
border_thickness.left(), top_height,
std::max(0, width() - border_thickness.width()),
std::max(0, height() - top_height - border_thickness.bottom()));
}
return FramelessView::GetBoundsForClientView();
}
gfx::Rect OpaqueFrameView::GetWindowBoundsForClientBounds(
const gfx::Rect& client_bounds) const {
if (window()->IsWindowControlsOverlayEnabled()) {
int top_height = NonClientTopHeight(false);
auto border_insets = FrameBorderInsets(false);
return gfx::Rect(
std::max(0, client_bounds.x() - border_insets.left()),
std::max(0, client_bounds.y() - top_height),
client_bounds.width() + border_insets.width(),
client_bounds.height() + top_height + border_insets.bottom());
}
return FramelessView::GetWindowBoundsForClientBounds(client_bounds);
}
int OpaqueFrameView::NonClientHitTest(const gfx::Point& point) {
if (window()->IsWindowControlsOverlayEnabled()) {
// Ensure support for resizing frameless window with border drag.
int frame_component = ResizingBorderHitTest(point);
if (frame_component != HTNOWHERE)
return frame_component;
if (HitTestCaptionButton(close_button_, point))
return HTCLOSE;
if (HitTestCaptionButton(restore_button_, point))
return HTMAXBUTTON;
if (HitTestCaptionButton(maximize_button_, point))
return HTMAXBUTTON;
if (HitTestCaptionButton(minimize_button_, point))
return HTMINBUTTON;
if (caption_button_placeholder_container_->GetMirroredBounds().Contains(
point)) {
return HTCAPTION;
}
}
return FramelessView::NonClientHitTest(point);
}
void OpaqueFrameView::ResetWindowControls() {
NonClientFrameView::ResetWindowControls();
if (restore_button_)
restore_button_->SetState(views::Button::STATE_NORMAL);
if (minimize_button_)
minimize_button_->SetState(views::Button::STATE_NORMAL);
if (maximize_button_)
maximize_button_->SetState(views::Button::STATE_NORMAL);
// The close button isn't affected by this constraint.
}
views::View* OpaqueFrameView::TargetForRect(views::View* root,
const gfx::Rect& rect) {
return views::NonClientFrameView::TargetForRect(root, rect);
}
void OpaqueFrameView::Layout(PassKey) {
LayoutSuperclass<FramelessView>(this);
if (!window()->IsWindowControlsOverlayEnabled())
return;
// Reset all our data so that everything is invisible.
TopAreaPadding top_area_padding = GetTopAreaPadding();
available_space_leading_x_ = top_area_padding.leading;
available_space_trailing_x_ = width() - top_area_padding.trailing;
minimum_size_for_buttons_ =
available_space_leading_x_ + width() - available_space_trailing_x_;
placed_leading_button_ = false;
placed_trailing_button_ = false;
LayoutWindowControls();
int height = NonClientTopHeight(false);
auto insets = FrameBorderInsets(false);
int container_x = placed_trailing_button_ ? available_space_trailing_x_ : 0;
caption_button_placeholder_container_->SetBounds(
container_x, insets.top(), minimum_size_for_buttons_ - insets.width(),
height - insets.top());
LayoutWindowControlsOverlay();
}
void OpaqueFrameView::OnPaint(gfx::Canvas* canvas) {
if (!window()->IsWindowControlsOverlayEnabled())
return;
if (frame()->IsFullscreen())
return;
UpdateFrameCaptionButtons();
}
void OpaqueFrameView::PaintAsActiveChanged() {
if (!window()->IsWindowControlsOverlayEnabled())
return;
UpdateCaptionButtonPlaceholderContainerBackground();
UpdateFrameCaptionButtons();
}
void OpaqueFrameView::UpdateFrameCaptionButtons() {
const bool active = ShouldPaintAsActive();
const SkColor symbol_color = window()->overlay_symbol_color();
const SkColor background_color = window()->overlay_button_color();
SkColor frame_color =
background_color == SkColor() ? GetFrameColor() : background_color;
for (views::Button* button :
{minimize_button_, maximize_button_, restore_button_, close_button_}) {
DCHECK_EQ(std::string(views::FrameCaptionButton::kViewClassName),
button->GetClassName());
views::FrameCaptionButton* frame_caption_button =
static_cast<views::FrameCaptionButton*>(button);
frame_caption_button->SetPaintAsActive(active);
frame_caption_button->SetButtonColor(symbol_color);
frame_caption_button->SetBackgroundColor(frame_color);
}
}
void OpaqueFrameView::UpdateCaptionButtonPlaceholderContainerBackground() {
if (caption_button_placeholder_container_) {
const SkColor obc = window()->overlay_button_color();
const SkColor bg_color = obc == SkColor() ? GetFrameColor() : obc;
caption_button_placeholder_container_->SetBackground(
views::CreateSolidBackground(bg_color));
}
}
void OpaqueFrameView::LayoutWindowControls() {
// Keep a list of all buttons that we don't show.
std::vector<views::FrameButton> buttons_not_shown;
buttons_not_shown.push_back(views::FrameButton::kMaximize);
buttons_not_shown.push_back(views::FrameButton::kMinimize);
buttons_not_shown.push_back(views::FrameButton::kClose);
// We do not want to show the buttons in fullscreen mode.
if (!frame()->IsFullscreen()) {
for (const auto& button : leading_buttons_) {
ConfigureButton(button, ALIGN_LEADING);
std::erase(buttons_not_shown, button);
}
for (const auto& button : base::Reversed(trailing_buttons_)) {
ConfigureButton(button, ALIGN_TRAILING);
std::erase(buttons_not_shown, button);
}
}
for (const auto& button_id : buttons_not_shown)
HideButton(button_id);
}
void OpaqueFrameView::LayoutWindowControlsOverlay() {
int overlay_height = window()->titlebar_overlay_height();
if (overlay_height == 0) {
// Accounting for the 1 pixel margin at the top of the button container
overlay_height =
window()->IsMaximized()
? caption_button_placeholder_container_->size().height()
: caption_button_placeholder_container_->size().height() + 1;
}
int overlay_width = caption_button_placeholder_container_->size().width();
int bounding_rect_width = width() - overlay_width;
auto bounding_rect =
GetMirroredRect(gfx::Rect(0, 0, bounding_rect_width, overlay_height));
window()->SetWindowControlsOverlayRect(bounding_rect);
window()->NotifyLayoutWindowControlsOverlay();
}
views::Button* OpaqueFrameView::CreateButton(
ViewID view_id,
int accessibility_string_id,
views::CaptionButtonIcon icon_type,
int ht_component,
const gfx::VectorIcon& icon_image,
views::Button::PressedCallback callback) {
auto button = std::make_unique<views::FrameCaptionButton>(
views::Button::PressedCallback(), icon_type, ht_component);
button->SetImage(button->GetIcon(), views::FrameCaptionButton::Animate::kNo,
icon_image);
button->SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY);
button->SetCallback(std::move(callback));
button->SetAccessibleName(l10n_util::GetStringUTF16(accessibility_string_id));
button->SetID(view_id);
button->SetPaintToLayer();
button->layer()->SetFillsBoundsOpaquely(false);
return AddChildView(std::move(button));
}
gfx::Insets OpaqueFrameView::FrameBorderInsets(bool restored) const {
return !restored && IsFrameCondensed() ? gfx::Insets()
: RestoredFrameBorderInsets();
}
int OpaqueFrameView::FrameTopBorderThickness(bool restored) const {
int thickness = FrameBorderInsets(restored).top();
if ((restored || !IsFrameCondensed()) && thickness > 0)
thickness += NonClientExtraTopThickness();
return thickness;
}
OpaqueFrameView::TopAreaPadding OpaqueFrameView::GetTopAreaPadding(
bool has_leading_buttons,
bool has_trailing_buttons) const {
const auto padding = FrameBorderInsets(false);
return TopAreaPadding{padding.left(), padding.right()};
}
bool OpaqueFrameView::IsFrameCondensed() const {
return frame()->IsMaximized() || frame()->IsFullscreen();
}
gfx::Insets OpaqueFrameView::RestoredFrameBorderInsets() const {
return {};
}
gfx::Insets OpaqueFrameView::RestoredFrameEdgeInsets() const {
return gfx::Insets::TLBR(kTopFrameEdgeThickness, kSideFrameEdgeThickness,
kSideFrameEdgeThickness, kSideFrameEdgeThickness);
}
int OpaqueFrameView::NonClientExtraTopThickness() const {
return kNonClientExtraTopThickness;
}
int OpaqueFrameView::NonClientTopHeight(bool restored) const {
// Adding 2px of vertical padding puts at least 1 px of space on the top and
// bottom of the element.
constexpr int kVerticalPadding = 2;
const int icon_height = GetIconSize() + kVerticalPadding;
const int caption_button_height = DefaultCaptionButtonY(restored) +
kCaptionButtonHeight +
kCaptionButtonBottomPadding;
int custom_height = window()->titlebar_overlay_height();
return custom_height ? custom_height
: std::max(icon_height, caption_button_height) +
kContentEdgeShadowThickness;
}
int OpaqueFrameView::CaptionButtonY(views::FrameButton button_id,
bool restored) const {
return DefaultCaptionButtonY(restored);
}
int OpaqueFrameView::DefaultCaptionButtonY(bool restored) const {
// Maximized buttons start at window top, since the window has no border. This
// offset is for the image (the actual clickable bounds extend all the way to
// the top to take Fitts' Law into account).
const bool start_at_top_of_frame = !restored && IsFrameCondensed();
return start_at_top_of_frame
? FrameBorderInsets(false).top()
chore: bump chromium to 139.0.7256.0 (38-x-y) (#47615) * chore: bump chromium in DEPS to 139.0.7242.0 Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> * chore: update render_widget_host_view_mac.patch no code changes; just updating patch context Do a cleanup pass on the history swiper code | https://chromium-review.googlesource.com/c/chromium/src/+/6604367 Co-authored-by: Charles Kerr <charles@charleskerr.com> * chore: update mas_avoid_private_macos_api_usage.patch.patch no code changes; just updating patch context [tracing] Delete base/trace_event/base_tracing.h | https://chromium-review.googlesource.com/c/chromium/src/+/6624012 Co-authored-by: Charles Kerr <charles@charleskerr.com> * chore: update chore_provide_iswebcontentscreationoverridden_with_full_params.patch no manual changes; just updating patch context [ActorFramework] Refactor Actor Task Management | https://chromium-review.googlesource.com/c/chromium/src/+/6618684 Co-authored-by: Charles Kerr <charles@charleskerr.com> * chore: update fix_move_autopipsettingshelper_behind_branding_buildflag.patch [pip] Tuck picture-in-picture windows when a file dialog is open | https://chromium-review.googlesource.com/c/chromium/src/+/6449682 Reland "[document pip] Restrict the size that a website can request" | https://chromium-review.googlesource.com/c/chromium/src/+/6372104 Co-authored-by: Charles Kerr <charles@charleskerr.com> * chore: update feat_corner_smoothing_css_rule_and_blink_painting.patch Xref: corner-shape: constraint radii based on opposite corner overlap | https://chromium-review.googlesource.com/c/chromium/src/+/6592572 Co-authored-by: Charles Kerr <charles@charleskerr.com> * chore: update revert_code_health_clean_up_stale_macwebcontentsocclusion.patch no manual changes; just updating patch context Co-authored-by: Charles Kerr <charles@charleskerr.com> * chore: update fix_rename_sqlite_win32_exports_to_avoid_conflicts_with_node_js.patch no code changes; just updating patch context Co-authored-by: Charles Kerr <charles@charleskerr.com> * chore: e patches all Co-authored-by: Charles Kerr <charles@charleskerr.com> * Plumb Verify2QwacBinding and hook it up in QwacWebContentsObserver https://chromium-review.googlesource.com/c/chromium/src/+/6624719 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * Remove host delegate OnMainFrameCreatedForBackgroundPage https://chromium-review.googlesource.com/c/chromium/src/+/6631123 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * Extensions: Rename GetResourceURL to ResolveExtensionURL https://chromium-review.googlesource.com/c/chromium/src/+/6625053 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * Consolidate NativeFrameViewMac https://chromium-review.googlesource.com/c/chromium/src/+/6614239 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * ICWYU Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * Remove dead code WidgetAXTreeIDMap https://chromium-review.googlesource.com/c/chromium/src/+/6619701 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * Reland "extensions: Add `WillPrepareForEvaluation` to setup MojoJS" https://chromium-review.googlesource.com/c/chromium/src/+/6630056 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * NavigationThrottleRunner2: Remove MaybeAddThrottle https://chromium-review.googlesource.com/c/chromium/src/+/6628079 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * Tuck picture-in-picture windows when a file dialog is open https://chromium-review.googlesource.com/c/chromium/src/+/6449682 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * build: fix snapshot_blob.bin build error xref: https://issues.chromium.org/issues/416540976 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * chore: e patches all Co-authored-by: Charles Kerr <charles@charleskerr.com> * build: freeup disk space on macos Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * chore: bump chromium in DEPS to 139.0.7244.0 Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> * chore: update printing.patch no manual changes; just updating patch context Co-authored-by: Charles Kerr <charles@charleskerr.com> * chore: remove upstreamed ignore_parse_errors_for_resolveshortcutproperties.patch Prevent Windows crash on unexpected shortcut type | https://chromium-review.googlesource.com/c/chromium/src/+/6633298 Co-authored-by: Charles Kerr <charles@charleskerr.com> * chore: e patches all Co-authored-by: Charles Kerr <charles@charleskerr.com> * Revert "Reland "extensions: Add `WillPrepareForEvaluation` to setup MojoJS"" This reverts commit 77c4f967a637f7e8970114f91311f9fddede0f7c. Revert CL for the high confidence crash culprit for http://crash/28f897bb9743dfe0 | https://chromium-review.googlesource.com/c/chromium/src/+/6641819 Co-authored-by: Charles Kerr <charles@charleskerr.com> * Fix spec's expected base64-encoded PNG strings to match upstream changes. [rust png] Enable by default. | https://chromium-review.googlesource.com/c/chromium/src/+/6085801 Co-authored-by: Charles Kerr <charles@charleskerr.com> * chore: bump chromium in DEPS to 139.0.7246.0 Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> * chore: e patches all Co-authored-by: Charles Kerr <charles@charleskerr.com> * chore: bump chromium in DEPS to 139.0.7248.0 Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> * chore: update patches Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * siso: Enable Siso by default for non-Google builds https://chromium-review.googlesource.com/c/chromium/src/+/6638830 Disabling for now until we are ready to build siso on all platforms. Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * Revert "revert Don't use static variable for UseExternalPopupMenus" This reverts commit e91e3894e6c34cc0ffe69ed45417c0ebec882fb1. Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * Update mac_sdk_min to match minimum required SDK version https://chromium-review.googlesource.com/c/chromium/src/+/6493969 (cherry picked from commit 3e7cbe912d8fe1062d68ed06968aaee22013985f) Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * Use default window styling on Mac https://chromium-review.googlesource.com/c/chromium/src/+/6648665 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * Reland "Force the unintentional renderer process creation check by default" https://chromium-review.googlesource.com/c/chromium/src/+/6626905 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * fixup: Reland "Force the unintentional renderer process creation check by default https://chromium-review.googlesource.com/c/chromium/src/+/6626905 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * chore: bump chromium in DEPS to 139.0.7249.0 Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> * fixup: Reland "Force the unintentional renderer process creation check by default https://chromium-review.googlesource.com/c/chromium/src/+/6626905 Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * chore: update patches Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * chore: bump chromium in DEPS to 139.0.7250.0 Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> * chore: bump chromium in DEPS to 139.0.7252.0 Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> * chore: bump chromium in DEPS to 139.0.7254.0 Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> * 6638187: browser level TOCTOU check for coordinate target https://chromium-review.googlesource.com/c/chromium/src/+/6638187 Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> * chore: fixup patch indices Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> * chore: add missing base/notimplemented includes Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> * 6652910: [Frame Cleanup] Push down/hide implementation-specific API https://chromium-review.googlesource.com/c/chromium/src/+/6652910 Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> * chore: bump chromium in DEPS to 139.0.7256.0 Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> * chore: fix lint Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> * fixup! 6652910: [Frame Cleanup] Push down/hide implementation-specific API Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> * fix: move HandleScope location Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> * chore: bump chromium in DEPS to 139.0.7258.0 Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> * fixup! [NonClientFrameView] Consolidate NativeFrameViewMac Co-authored-by: deepak1556 <hop2deep@gmail.com> * Revert "chore: bump chromium in DEPS to 139.0.7258.0" This reverts commit 264b2e934f4b2705c47d9761010052b95d9dd5de. Co-authored-by: deepak1556 <hop2deep@gmail.com> * chore: update patches --------- Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com> Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> Co-authored-by: Charles Kerr <charles@charleskerr.com> Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> Co-authored-by: deepak1556 <hop2deep@gmail.com> Co-authored-by: patchup[bot] <73610968+patchup[bot]@users.noreply.github.com>
2025-06-30 12:29:54 -04:00
: OpaqueBrowserFrameViewLayout::kFrameShadowThickness;
}
gfx::Insets OpaqueFrameView::FrameEdgeInsets(bool restored) const {
return RestoredFrameEdgeInsets();
}
int OpaqueFrameView::GetIconSize() const {
// The icon never shrinks below 16 px on a side.
const int kIconMinimumSize = 16;
return std::max(gfx::FontList().GetHeight(), kIconMinimumSize);
}
OpaqueFrameView::TopAreaPadding OpaqueFrameView::GetTopAreaPadding() const {
return GetTopAreaPadding(!leading_buttons_.empty(),
!trailing_buttons_.empty());
}
SkColor OpaqueFrameView::GetFrameColor() const {
return GetColorProvider()->GetColor(
ShouldPaintAsActive() ? ui::kColorFrameActive : ui::kColorFrameInactive);
}
void OpaqueFrameView::ConfigureButton(views::FrameButton button_id,
ButtonAlignment alignment) {
switch (button_id) {
case views::FrameButton::kMinimize: {
if (window()->IsMinimizable()) {
minimize_button_->SetVisible(true);
SetBoundsForButton(button_id, minimize_button_, alignment);
} else {
HideButton(button_id);
}
break;
}
case views::FrameButton::kMaximize: {
if (window()->IsMaximizable()) {
// When the window is restored, we show a maximized button; otherwise,
// we show a restore button.
bool is_restored = !window()->IsMaximized() && !window()->IsMinimized();
views::Button* invisible_button =
is_restored ? restore_button_ : maximize_button_;
invisible_button->SetVisible(false);
views::Button* visible_button =
is_restored ? maximize_button_ : restore_button_;
visible_button->SetVisible(true);
SetBoundsForButton(button_id, visible_button, alignment);
} else {
HideButton(button_id);
}
break;
}
case views::FrameButton::kClose: {
if (window()->IsClosable()) {
close_button_->SetVisible(true);
SetBoundsForButton(button_id, close_button_, alignment);
} else {
HideButton(button_id);
}
break;
}
}
}
void OpaqueFrameView::HideButton(views::FrameButton button_id) {
switch (button_id) {
case views::FrameButton::kMinimize:
minimize_button_->SetVisible(false);
break;
case views::FrameButton::kMaximize:
restore_button_->SetVisible(false);
maximize_button_->SetVisible(false);
break;
case views::FrameButton::kClose:
close_button_->SetVisible(false);
break;
}
}
void OpaqueFrameView::SetBoundsForButton(views::FrameButton button_id,
views::Button* button,
ButtonAlignment alignment) {
const int caption_y = CaptionButtonY(button_id, false);
// There should always be the same number of non-shadow pixels visible to the
// side of the caption buttons. In maximized mode we extend buttons to the
// screen top and the rightmost button to the screen right (or leftmost button
// to the screen left, for left-aligned buttons) to obey Fitts' Law.
const bool is_frame_condensed = IsFrameCondensed();
const int button_width = views::GetCaptionButtonWidth();
gfx::Size button_size = button->GetPreferredSize();
DCHECK_EQ(std::string(views::FrameCaptionButton::kViewClassName),
button->GetClassName());
const int caption_button_center_size =
button_width - 2 * views::kCaptionButtonInkDropDefaultCornerRadius;
const int height = GetTopAreaHeight() - FrameEdgeInsets(false).top();
const int corner_radius =
std::clamp((height - caption_button_center_size) / 2, 0,
views::kCaptionButtonInkDropDefaultCornerRadius);
button_size = gfx::Size(button_width, height);
button->SetPreferredSize(button_size);
static_cast<views::FrameCaptionButton*>(button)->SetInkDropCornerRadius(
corner_radius);
TopAreaPadding top_area_padding = GetTopAreaPadding();
switch (alignment) {
case ALIGN_LEADING: {
int extra_width = top_area_padding.leading;
int button_start_spacing =
GetWindowCaptionSpacing(button_id, true, !placed_leading_button_);
available_space_leading_x_ += button_start_spacing;
minimum_size_for_buttons_ += button_start_spacing;
bool top_spacing_clickable = is_frame_condensed;
bool start_spacing_clickable =
is_frame_condensed && !placed_leading_button_;
button->SetBounds(
available_space_leading_x_ - (start_spacing_clickable
? button_start_spacing + extra_width
: 0),
top_spacing_clickable ? 0 : caption_y,
button_size.width() + (start_spacing_clickable
? button_start_spacing + extra_width
: 0),
button_size.height() + (top_spacing_clickable ? caption_y : 0));
int button_end_spacing =
GetWindowCaptionSpacing(button_id, false, !placed_leading_button_);
available_space_leading_x_ += button_size.width() + button_end_spacing;
minimum_size_for_buttons_ += button_size.width() + button_end_spacing;
placed_leading_button_ = true;
break;
}
case ALIGN_TRAILING: {
int extra_width = top_area_padding.trailing;
int button_start_spacing =
GetWindowCaptionSpacing(button_id, true, !placed_trailing_button_);
available_space_trailing_x_ -= button_start_spacing;
minimum_size_for_buttons_ += button_start_spacing;
bool top_spacing_clickable = is_frame_condensed;
bool start_spacing_clickable =
is_frame_condensed && !placed_trailing_button_;
button->SetBounds(
available_space_trailing_x_ - button_size.width(),
top_spacing_clickable ? 0 : caption_y,
button_size.width() + (start_spacing_clickable
? button_start_spacing + extra_width
: 0),
button_size.height() + (top_spacing_clickable ? caption_y : 0));
int button_end_spacing =
GetWindowCaptionSpacing(button_id, false, !placed_trailing_button_);
available_space_trailing_x_ -= button_size.width() + button_end_spacing;
minimum_size_for_buttons_ += button_size.width() + button_end_spacing;
placed_trailing_button_ = true;
break;
}
}
}
int OpaqueFrameView::GetTopAreaHeight() const {
int top_height = NonClientTopHeight(false);
return top_height;
}
int OpaqueFrameView::GetWindowCaptionSpacing(views::FrameButton button_id,
bool leading_spacing,
bool is_leading_button) const {
return 0;
}
BEGIN_METADATA(OpaqueFrameView)
END_METADATA
} // namespace electron