File: browser_non_client_frame_view.cc

package info (click to toggle)
chromium 139.0.7258.127-2
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 6,122,156 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (273 lines) | stat: -rw-r--r-- 10,655 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
// Copyright 2012 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/frame/browser_non_client_frame_view.h"

#include "base/metrics/histogram_macros.h"
#include "build/build_config.h"
#include "build/buildflag.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/themes/custom_theme_supplier.h"
#include "chrome/browser/themes/theme_properties.h"
#include "chrome/browser/ui/color/chrome_color_id.h"
#include "chrome/browser/ui/layout_constants.h"
#include "chrome/browser/ui/tabs/tab_types.h"
#include "chrome/browser/ui/view_ids.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/frame/tab_strip_region_view.h"
#include "chrome/browser/ui/web_applications/app_browser_controller.h"
#include "chrome/grit/theme_resources.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/hit_test.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/theme_provider.h"
#include "ui/color/color_id.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/gfx/scoped_canvas.h"
#include "ui/views/background.h"
#include "ui/views/window/hit_test_utils.h"

#if BUILDFLAG(IS_WIN)
#include "chrome/browser/taskbar/taskbar_decorator_win.h"
#include "ui/display/win/screen_win.h"
#include "ui/views/win/hwnd_util.h"
#endif

// static
constexpr int BrowserNonClientFrameView::kMinimumDragHeight;

BrowserNonClientFrameView::BrowserNonClientFrameView(BrowserFrame* frame,
                                                     BrowserView* browser_view)
    : frame_(frame), browser_view_(browser_view) {
  DCHECK(frame_);
  DCHECK(browser_view_);
}

BrowserNonClientFrameView::~BrowserNonClientFrameView() = default;

void BrowserNonClientFrameView::OnBrowserViewInitViewsComplete() {
  UpdateMinimumSize();
}

void BrowserNonClientFrameView::OnFullscreenStateChanged() {
  if (frame_->IsFullscreen()) {
    browser_view_->HideDownloadShelf();
  } else {
    browser_view_->UnhideDownloadShelf();
  }
}

bool BrowserNonClientFrameView::CaptionButtonsOnLeadingEdge() const {
  return false;
}

void BrowserNonClientFrameView::UpdateFullscreenTopUI() {}

bool BrowserNonClientFrameView::ShouldHideTopUIForFullscreen() const {
  return frame_->IsFullscreen();
}

bool BrowserNonClientFrameView::CanUserExitFullscreen() const {
  return true;
}

bool BrowserNonClientFrameView::IsFrameCondensed() const {
  return frame_->IsMaximized() || frame_->IsFullscreen();
}

bool BrowserNonClientFrameView::HasVisibleBackgroundTabShapes(
    BrowserFrameActiveState active_state) const {
  DCHECK(browser_view_->GetSupportsTabStrip());

  TabStrip* const tab_strip = browser_view_->tabstrip();

  const bool active = ShouldPaintAsActiveForState(active_state);
  const std::optional<int> bg_id =
      tab_strip->GetCustomBackgroundId(active_state);
  if (bg_id.has_value()) {
    // If the theme has a custom tab background image, assume tab shapes are
    // visible.  This is pessimistic; the theme may use the same image as the
    // frame, just shifted to align, or a solid-color image the same color as
    // the frame; but to detect this we'd need to do some kind of aligned
    // rendering comparison, which seems not worth it.
    const ui::ThemeProvider* tp = GetThemeProvider();
    if (tp->HasCustomImage(bg_id.value())) {
      return true;
    }

    // Inactive tab background images are copied from the active ones, so in the
    // inactive case, check the active image as well.
    if (!active) {
      const int active_id = browser_view_->GetIncognito()
                                ? IDR_THEME_TAB_BACKGROUND_INCOGNITO
                                : IDR_THEME_TAB_BACKGROUND;
      if (tp->HasCustomImage(active_id)) {
        return true;
      }
    }

    // The tab image is a tinted version of the frame image.  Tabs are visible
    // iff the tint has some visible effect.
    return color_utils::IsHSLShiftMeaningful(
        tp->GetTint(ThemeProperties::TINT_BACKGROUND_TAB));
  }

  // Background tab shapes are visible iff the tab color differs from the frame
  // color.
  return TabStyle::Get()->GetTabBackgroundColor(
             TabStyle::TabSelectionState::kInactive,
             /*hovered=*/false, ShouldPaintAsActiveForState(active_state),
             *GetColorProvider()) != GetFrameColor(active_state);
}

bool BrowserNonClientFrameView::EverHasVisibleBackgroundTabShapes() const {
  return HasVisibleBackgroundTabShapes(BrowserFrameActiveState::kActive) ||
         HasVisibleBackgroundTabShapes(BrowserFrameActiveState::kInactive);
}

bool BrowserNonClientFrameView::CanDrawStrokes() const {
  // Web apps should not draw strokes if they don't have a tab strip.
  return !browser_view_->browser()->app_controller() ||
         browser_view_->browser()->app_controller()->has_tab_strip();
}

SkColor BrowserNonClientFrameView::GetCaptionColor(
    BrowserFrameActiveState active_state) const {
  return GetColorProvider()->GetColor(ShouldPaintAsActiveForState(active_state)
                                          ? kColorFrameCaptionActive
                                          : kColorFrameCaptionInactive);
}

SkColor BrowserNonClientFrameView::GetFrameColor(
    BrowserFrameActiveState active_state) const {
  return GetColorProvider()->GetColor(ShouldPaintAsActiveForState(active_state)
                                          ? ui::kColorFrameActive
                                          : ui::kColorFrameInactive);
}

std::optional<int> BrowserNonClientFrameView::GetCustomBackgroundId(
    BrowserFrameActiveState active_state) const {
  const ui::ThemeProvider* tp = GetThemeProvider();
  const bool incognito = browser_view_->GetIncognito();
  const bool active = ShouldPaintAsActiveForState(active_state);
  const int active_id =
      incognito ? IDR_THEME_TAB_BACKGROUND_INCOGNITO : IDR_THEME_TAB_BACKGROUND;
  const int inactive_id = incognito
                              ? IDR_THEME_TAB_BACKGROUND_INCOGNITO_INACTIVE
                              : IDR_THEME_TAB_BACKGROUND_INACTIVE;
  const int id = active ? active_id : inactive_id;

  // tp->HasCustomImage() will only return true if the supplied ID has been
  // customized directly.  We also account for the following fallback cases:
  // * The inactive images are copied directly from the active ones if present
  // * Tab backgrounds are generated from frame backgrounds if present, and
  // * The incognito frame image is generated from the normal frame image, so
  //   in incognito mode we look at both.
  const bool has_custom_image =
      tp->HasCustomImage(id) || (!active && tp->HasCustomImage(active_id)) ||
      tp->HasCustomImage(IDR_THEME_FRAME) ||
      (incognito && tp->HasCustomImage(IDR_THEME_FRAME_INCOGNITO));
  return has_custom_image ? std::make_optional(id) : std::nullopt;
}

void BrowserNonClientFrameView::UpdateMinimumSize() {}

gfx::Insets BrowserNonClientFrameView::RestoredMirroredFrameBorderInsets()
    const {
  NOTREACHED();
}

gfx::Insets BrowserNonClientFrameView::GetInputInsets() const {
  NOTREACHED();
}

SkRRect BrowserNonClientFrameView::GetRestoredClipRegion() const {
  NOTREACHED();
}

int BrowserNonClientFrameView::GetTranslucentTopAreaHeight() const {
  return 0;
}

void BrowserNonClientFrameView::SetFrameBounds(const gfx::Rect& bounds) {
  frame_->SetBounds(bounds);
}

void BrowserNonClientFrameView::PaintAsActiveChanged() {
  // Changing the activation state may change the visible frame color.
  SchedulePaint();
}

bool BrowserNonClientFrameView::ShouldPaintAsActiveForState(
    BrowserFrameActiveState active_state) const {
  return (active_state == BrowserFrameActiveState::kUseCurrent)
             ? NonClientFrameView::ShouldPaintAsActive()
             : (active_state == BrowserFrameActiveState::kActive);
}

gfx::ImageSkia BrowserNonClientFrameView::GetFrameImage(
    BrowserFrameActiveState active_state) const {
  const ui::ThemeProvider* tp = GetThemeProvider();
  const int frame_image_id = ShouldPaintAsActiveForState(active_state)
                                 ? IDR_THEME_FRAME
                                 : IDR_THEME_FRAME_INACTIVE;
  return (tp->HasCustomImage(frame_image_id) ||
          tp->HasCustomImage(IDR_THEME_FRAME))
             ? *tp->GetImageSkiaNamed(frame_image_id)
             : gfx::ImageSkia();
}

gfx::ImageSkia BrowserNonClientFrameView::GetFrameOverlayImage(
    BrowserFrameActiveState active_state) const {
  if (browser_view_->GetIncognito() || !browser_view_->GetIsNormalType()) {
    return gfx::ImageSkia();
  }

  const ui::ThemeProvider* tp = GetThemeProvider();
  const int frame_overlay_image_id = ShouldPaintAsActiveForState(active_state)
                                         ? IDR_THEME_FRAME_OVERLAY
                                         : IDR_THEME_FRAME_OVERLAY_INACTIVE;
  return tp->HasCustomImage(frame_overlay_image_id)
             ? *tp->GetImageSkiaNamed(frame_overlay_image_id)
             : gfx::ImageSkia();
}

#if BUILDFLAG(IS_WIN)
// Sending the WM_NCPOINTERDOWN, WM_NCPOINTERUPDATE, and WM_NCPOINTERUP to the
// default window proc does not bring up the system menu on long press, so we
// use the gesture recognizer to turn it into a LONG_TAP gesture and handle it
// here. See https://crbug.com/1327506 for more info.
void BrowserNonClientFrameView::OnGestureEvent(ui::GestureEvent* event) {
  gfx::Point event_loc = event->location();
  // This opens the title bar system context menu on long press in the titlebar.
  // NonClientHitTest returns HTCAPTION if `event_loc` is in the empty space on
  // the titlebar.
  if (event->type() == ui::EventType::kGestureLongTap &&
      NonClientHitTest(event_loc) == HTCAPTION) {
    views::View::ConvertPointToScreen(this, &event_loc);
    event_loc = display::win::GetScreenWin()->DIPToScreenPoint(event_loc);
    views::ShowSystemMenuAtScreenPixelLocation(views::HWNDForView(this),
                                               event_loc);
    event->SetHandled();
  }
}

int BrowserNonClientFrameView::GetSystemMenuY() const {
  if (!browser_view()->GetTabStripVisible()) {
    return GetTopInset(false);
  }
  return GetBoundsForTabStripRegion(
             browser_view()->tab_strip_region_view()->GetMinimumSize())
             .bottom() -
         GetLayoutConstant(TABSTRIP_TOOLBAR_OVERLAP);
}
#endif  // BUILDFLAG(IS_WIN)

BEGIN_METADATA(BrowserNonClientFrameView)
END_METADATA