native_window.cc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871
  1. // Copyright (c) 2013 GitHub, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #include "shell/browser/native_window.h"
  5. #include <algorithm>
  6. #include <string>
  7. #include <vector>
  8. #include "base/containers/contains.h"
  9. #include "base/memory/ptr_util.h"
  10. #include "base/strings/utf_string_conversions.h"
  11. #include "base/values.h"
  12. #include "content/public/browser/web_contents_user_data.h"
  13. #include "include/core/SkColor.h"
  14. #include "shell/browser/background_throttling_source.h"
  15. #include "shell/browser/browser.h"
  16. #include "shell/browser/draggable_region_provider.h"
  17. #include "shell/browser/native_window_features.h"
  18. #include "shell/browser/ui/drag_util.h"
  19. #include "shell/browser/window_list.h"
  20. #include "shell/common/color_util.h"
  21. #include "shell/common/gin_helper/dictionary.h"
  22. #include "shell/common/gin_helper/persistent_dictionary.h"
  23. #include "shell/common/options_switches.h"
  24. #include "ui/base/hit_test.h"
  25. #include "ui/compositor/compositor.h"
  26. #include "ui/views/widget/widget.h"
  27. #if !BUILDFLAG(IS_MAC)
  28. #include "shell/browser/ui/views/frameless_view.h"
  29. #endif
  30. #if BUILDFLAG(IS_WIN)
  31. #include "ui/display/win/screen_win.h"
  32. #endif
  33. #if defined(USE_OZONE)
  34. #include "ui/base/ui_base_features.h"
  35. #include "ui/ozone/public/ozone_platform.h"
  36. #endif
  37. namespace gin {
  38. template <>
  39. struct Converter<electron::NativeWindow::TitleBarStyle> {
  40. static bool FromV8(v8::Isolate* isolate,
  41. v8::Local<v8::Value> val,
  42. electron::NativeWindow::TitleBarStyle* out) {
  43. using TitleBarStyle = electron::NativeWindow::TitleBarStyle;
  44. std::string title_bar_style;
  45. if (!ConvertFromV8(isolate, val, &title_bar_style))
  46. return false;
  47. if (title_bar_style == "hidden") {
  48. *out = TitleBarStyle::kHidden;
  49. #if BUILDFLAG(IS_MAC)
  50. } else if (title_bar_style == "hiddenInset") {
  51. *out = TitleBarStyle::kHiddenInset;
  52. } else if (title_bar_style == "customButtonsOnHover") {
  53. *out = TitleBarStyle::kCustomButtonsOnHover;
  54. #endif
  55. } else {
  56. return false;
  57. }
  58. return true;
  59. }
  60. };
  61. } // namespace gin
  62. namespace electron {
  63. namespace {
  64. #if BUILDFLAG(IS_WIN)
  65. gfx::Size GetExpandedWindowSize(const NativeWindow* window, gfx::Size size) {
  66. if (!window->transparent())
  67. return size;
  68. gfx::Size min_size = display::win::ScreenWin::ScreenToDIPSize(
  69. window->GetAcceleratedWidget(), gfx::Size(64, 64));
  70. // Some AMD drivers can't display windows that are less than 64x64 pixels,
  71. // so expand them to be at least that size. http://crbug.com/286609
  72. gfx::Size expanded(std::max(size.width(), min_size.width()),
  73. std::max(size.height(), min_size.height()));
  74. return expanded;
  75. }
  76. #endif
  77. } // namespace
  78. NativeWindow::NativeWindow(const gin_helper::Dictionary& options,
  79. NativeWindow* parent)
  80. : widget_(std::make_unique<views::Widget>()), parent_(parent) {
  81. ++next_id_;
  82. options.Get(options::kFrame, &has_frame_);
  83. options.Get(options::kTransparent, &transparent_);
  84. options.Get(options::kEnableLargerThanScreen, &enable_larger_than_screen_);
  85. options.Get(options::kTitleBarStyle, &title_bar_style_);
  86. #if BUILDFLAG(IS_WIN)
  87. options.Get(options::kBackgroundMaterial, &background_material_);
  88. #elif BUILDFLAG(IS_MAC)
  89. options.Get(options::kVibrancyType, &vibrancy_);
  90. #endif
  91. v8::Local<v8::Value> titlebar_overlay;
  92. if (options.Get(options::ktitleBarOverlay, &titlebar_overlay)) {
  93. if (titlebar_overlay->IsBoolean()) {
  94. options.Get(options::ktitleBarOverlay, &titlebar_overlay_);
  95. } else if (titlebar_overlay->IsObject()) {
  96. titlebar_overlay_ = true;
  97. auto titlebar_overlay_dict =
  98. gin_helper::Dictionary::CreateEmpty(options.isolate());
  99. options.Get(options::ktitleBarOverlay, &titlebar_overlay_dict);
  100. int height;
  101. if (titlebar_overlay_dict.Get(options::kOverlayHeight, &height))
  102. titlebar_overlay_height_ = height;
  103. }
  104. }
  105. if (parent)
  106. options.Get("modal", &is_modal_);
  107. #if defined(USE_OZONE)
  108. // Ozone X11 likes to prefer custom frames, but we don't need them unless
  109. // on Wayland.
  110. if (base::FeatureList::IsEnabled(features::kWaylandWindowDecorations) &&
  111. !ui::OzonePlatform::GetInstance()
  112. ->GetPlatformRuntimeProperties()
  113. .supports_server_side_window_decorations) {
  114. has_client_frame_ = true;
  115. }
  116. #endif
  117. WindowList::AddWindow(this);
  118. }
  119. NativeWindow::~NativeWindow() {
  120. // It's possible that the windows gets destroyed before it's closed, in that
  121. // case we need to ensure the Widget delegate gets destroyed and
  122. // OnWindowClosed message is still notified.
  123. if (widget_->widget_delegate())
  124. widget_->OnNativeWidgetDestroyed();
  125. NotifyWindowClosed();
  126. }
  127. void NativeWindow::InitFromOptions(const gin_helper::Dictionary& options) {
  128. // Setup window from options.
  129. int x = -1, y = -1;
  130. bool center;
  131. if (options.Get(options::kX, &x) && options.Get(options::kY, &y)) {
  132. SetPosition(gfx::Point(x, y));
  133. #if BUILDFLAG(IS_WIN)
  134. // FIXME(felixrieseberg): Dirty, dirty workaround for
  135. // https://github.com/electron/electron/issues/10862
  136. // Somehow, we need to call `SetBounds` twice to get
  137. // usable results. The root cause is still unknown.
  138. SetPosition(gfx::Point(x, y));
  139. #endif
  140. } else if (options.Get(options::kCenter, &center) && center) {
  141. Center();
  142. }
  143. bool use_content_size = false;
  144. options.Get(options::kUseContentSize, &use_content_size);
  145. // On Linux and Window we may already have maximum size defined.
  146. extensions::SizeConstraints size_constraints(
  147. use_content_size ? GetContentSizeConstraints() : GetSizeConstraints());
  148. int min_width = size_constraints.GetMinimumSize().width();
  149. int min_height = size_constraints.GetMinimumSize().height();
  150. options.Get(options::kMinWidth, &min_width);
  151. options.Get(options::kMinHeight, &min_height);
  152. size_constraints.set_minimum_size(gfx::Size(min_width, min_height));
  153. gfx::Size max_size = size_constraints.GetMaximumSize();
  154. int max_width = max_size.width() > 0 ? max_size.width() : INT_MAX;
  155. int max_height = max_size.height() > 0 ? max_size.height() : INT_MAX;
  156. bool have_max_width = options.Get(options::kMaxWidth, &max_width);
  157. if (have_max_width && max_width <= 0)
  158. max_width = INT_MAX;
  159. bool have_max_height = options.Get(options::kMaxHeight, &max_height);
  160. if (have_max_height && max_height <= 0)
  161. max_height = INT_MAX;
  162. // By default the window has a default maximum size that prevents it
  163. // from being resized larger than the screen, so we should only set this
  164. // if the user has passed in values.
  165. if (have_max_height || have_max_width || !max_size.IsEmpty())
  166. size_constraints.set_maximum_size(gfx::Size(max_width, max_height));
  167. if (use_content_size) {
  168. SetContentSizeConstraints(size_constraints);
  169. } else {
  170. SetSizeConstraints(size_constraints);
  171. }
  172. #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX)
  173. bool closable;
  174. if (options.Get(options::kClosable, &closable)) {
  175. SetClosable(closable);
  176. }
  177. #endif
  178. bool movable;
  179. if (options.Get(options::kMovable, &movable)) {
  180. SetMovable(movable);
  181. }
  182. bool has_shadow;
  183. if (options.Get(options::kHasShadow, &has_shadow)) {
  184. SetHasShadow(has_shadow);
  185. }
  186. double opacity;
  187. if (options.Get(options::kOpacity, &opacity)) {
  188. SetOpacity(opacity);
  189. }
  190. bool top;
  191. if (options.Get(options::kAlwaysOnTop, &top) && top) {
  192. SetAlwaysOnTop(ui::ZOrderLevel::kFloatingWindow);
  193. }
  194. bool fullscreenable = true;
  195. bool fullscreen = false;
  196. if (options.Get(options::kFullscreen, &fullscreen) && !fullscreen) {
  197. // Disable fullscreen button if 'fullscreen' is specified to false.
  198. #if BUILDFLAG(IS_MAC)
  199. fullscreenable = false;
  200. #endif
  201. }
  202. options.Get(options::kFullScreenable, &fullscreenable);
  203. SetFullScreenable(fullscreenable);
  204. if (fullscreen)
  205. SetFullScreen(true);
  206. bool resizable;
  207. if (options.Get(options::kResizable, &resizable)) {
  208. SetResizable(resizable);
  209. }
  210. bool skip;
  211. if (options.Get(options::kSkipTaskbar, &skip)) {
  212. SetSkipTaskbar(skip);
  213. }
  214. bool kiosk;
  215. if (options.Get(options::kKiosk, &kiosk) && kiosk) {
  216. SetKiosk(kiosk);
  217. }
  218. #if BUILDFLAG(IS_MAC)
  219. std::string type;
  220. if (options.Get(options::kVibrancyType, &type)) {
  221. SetVibrancy(type, 0);
  222. }
  223. #elif BUILDFLAG(IS_WIN)
  224. std::string material;
  225. if (options.Get(options::kBackgroundMaterial, &material)) {
  226. SetBackgroundMaterial(material);
  227. }
  228. #endif
  229. SkColor background_color = SK_ColorWHITE;
  230. if (std::string color; options.Get(options::kBackgroundColor, &color)) {
  231. background_color = ParseCSSColor(color);
  232. } else if (IsTranslucent()) {
  233. background_color = SK_ColorTRANSPARENT;
  234. }
  235. SetBackgroundColor(background_color);
  236. std::string title(Browser::Get()->GetName());
  237. options.Get(options::kTitle, &title);
  238. SetTitle(title);
  239. // Then show it.
  240. bool show = true;
  241. options.Get(options::kShow, &show);
  242. if (show)
  243. Show();
  244. }
  245. bool NativeWindow::IsClosed() const {
  246. return is_closed_;
  247. }
  248. void NativeWindow::SetSize(const gfx::Size& size, bool animate) {
  249. SetBounds(gfx::Rect(GetPosition(), size), animate);
  250. }
  251. gfx::Size NativeWindow::GetSize() const {
  252. return GetBounds().size();
  253. }
  254. void NativeWindow::SetPosition(const gfx::Point& position, bool animate) {
  255. SetBounds(gfx::Rect(position, GetSize()), animate);
  256. }
  257. gfx::Point NativeWindow::GetPosition() const {
  258. return GetBounds().origin();
  259. }
  260. void NativeWindow::SetContentSize(const gfx::Size& size, bool animate) {
  261. SetSize(ContentBoundsToWindowBounds(gfx::Rect(size)).size(), animate);
  262. }
  263. gfx::Size NativeWindow::GetContentSize() const {
  264. return GetContentBounds().size();
  265. }
  266. void NativeWindow::SetContentBounds(const gfx::Rect& bounds, bool animate) {
  267. SetBounds(ContentBoundsToWindowBounds(bounds), animate);
  268. }
  269. gfx::Rect NativeWindow::GetContentBounds() const {
  270. return WindowBoundsToContentBounds(GetBounds());
  271. }
  272. bool NativeWindow::IsNormal() const {
  273. return !IsMinimized() && !IsMaximized() && !IsFullscreen();
  274. }
  275. void NativeWindow::SetSizeConstraints(
  276. const extensions::SizeConstraints& window_constraints) {
  277. size_constraints_ = window_constraints;
  278. content_size_constraints_.reset();
  279. }
  280. extensions::SizeConstraints NativeWindow::GetSizeConstraints() const {
  281. if (size_constraints_)
  282. return *size_constraints_;
  283. if (!content_size_constraints_)
  284. return {};
  285. // Convert content size constraints to window size constraints.
  286. extensions::SizeConstraints constraints;
  287. if (content_size_constraints_->HasMaximumSize()) {
  288. gfx::Rect max_bounds = ContentBoundsToWindowBounds(
  289. gfx::Rect(content_size_constraints_->GetMaximumSize()));
  290. constraints.set_maximum_size(max_bounds.size());
  291. }
  292. if (content_size_constraints_->HasMinimumSize()) {
  293. gfx::Rect min_bounds = ContentBoundsToWindowBounds(
  294. gfx::Rect(content_size_constraints_->GetMinimumSize()));
  295. constraints.set_minimum_size(min_bounds.size());
  296. }
  297. return constraints;
  298. }
  299. void NativeWindow::SetContentSizeConstraints(
  300. const extensions::SizeConstraints& size_constraints) {
  301. content_size_constraints_ = size_constraints;
  302. size_constraints_.reset();
  303. }
  304. // Windows/Linux:
  305. // The return value of GetContentSizeConstraints will be passed to Chromium
  306. // to set min/max sizes of window. Note that we are returning content size
  307. // instead of window size because that is what Chromium expects, see the
  308. // comment of |WidgetSizeIsClientSize| in Chromium's codebase to learn more.
  309. //
  310. // macOS:
  311. // The min/max sizes are set directly by calling NSWindow's methods.
  312. extensions::SizeConstraints NativeWindow::GetContentSizeConstraints() const {
  313. if (content_size_constraints_)
  314. return *content_size_constraints_;
  315. if (!size_constraints_)
  316. return {};
  317. // Convert window size constraints to content size constraints.
  318. // Note that we are not caching the results, because Chromium reccalculates
  319. // window frame size everytime when min/max sizes are passed, and we must
  320. // do the same otherwise the resulting size with frame included will be wrong.
  321. extensions::SizeConstraints constraints;
  322. if (size_constraints_->HasMaximumSize()) {
  323. gfx::Rect max_bounds = WindowBoundsToContentBounds(
  324. gfx::Rect(size_constraints_->GetMaximumSize()));
  325. constraints.set_maximum_size(max_bounds.size());
  326. }
  327. if (size_constraints_->HasMinimumSize()) {
  328. gfx::Rect min_bounds = WindowBoundsToContentBounds(
  329. gfx::Rect(size_constraints_->GetMinimumSize()));
  330. constraints.set_minimum_size(min_bounds.size());
  331. }
  332. return constraints;
  333. }
  334. void NativeWindow::SetMinimumSize(const gfx::Size& size) {
  335. extensions::SizeConstraints size_constraints = GetSizeConstraints();
  336. size_constraints.set_minimum_size(size);
  337. SetSizeConstraints(size_constraints);
  338. }
  339. gfx::Size NativeWindow::GetMinimumSize() const {
  340. return GetSizeConstraints().GetMinimumSize();
  341. }
  342. void NativeWindow::SetMaximumSize(const gfx::Size& size) {
  343. extensions::SizeConstraints size_constraints = GetSizeConstraints();
  344. size_constraints.set_maximum_size(size);
  345. SetSizeConstraints(size_constraints);
  346. }
  347. gfx::Size NativeWindow::GetMaximumSize() const {
  348. return GetSizeConstraints().GetMaximumSize();
  349. }
  350. gfx::Size NativeWindow::GetContentMinimumSize() const {
  351. return GetContentSizeConstraints().GetMinimumSize();
  352. }
  353. gfx::Size NativeWindow::GetContentMaximumSize() const {
  354. gfx::Size maximum_size = GetContentSizeConstraints().GetMaximumSize();
  355. #if BUILDFLAG(IS_WIN)
  356. return GetContentSizeConstraints().HasMaximumSize()
  357. ? GetExpandedWindowSize(this, maximum_size)
  358. : maximum_size;
  359. #else
  360. return maximum_size;
  361. #endif
  362. }
  363. void NativeWindow::SetSheetOffset(const double offsetX, const double offsetY) {
  364. sheet_offset_x_ = offsetX;
  365. sheet_offset_y_ = offsetY;
  366. }
  367. double NativeWindow::GetSheetOffsetX() const {
  368. return sheet_offset_x_;
  369. }
  370. double NativeWindow::GetSheetOffsetY() const {
  371. return sheet_offset_y_;
  372. }
  373. bool NativeWindow::IsTabletMode() const {
  374. return false;
  375. }
  376. std::string NativeWindow::GetRepresentedFilename() const {
  377. return "";
  378. }
  379. bool NativeWindow::IsDocumentEdited() const {
  380. return false;
  381. }
  382. bool NativeWindow::IsFocusable() const {
  383. return false;
  384. }
  385. void NativeWindow::SetParentWindow(NativeWindow* parent) {
  386. parent_ = parent;
  387. }
  388. bool NativeWindow::AddTabbedWindow(NativeWindow* window) {
  389. return true; // for non-Mac platforms
  390. }
  391. std::optional<std::string> NativeWindow::GetTabbingIdentifier() const {
  392. return ""; // for non-Mac platforms
  393. }
  394. void NativeWindow::SetVibrancy(const std::string& type, int duration) {
  395. vibrancy_ = type;
  396. }
  397. void NativeWindow::SetBackgroundMaterial(const std::string& type) {
  398. background_material_ = type;
  399. }
  400. void NativeWindow::SetTouchBar(
  401. std::vector<gin_helper::PersistentDictionary> items) {}
  402. void NativeWindow::SetEscapeTouchBarItem(
  403. gin_helper::PersistentDictionary item) {}
  404. bool NativeWindow::IsMenuBarAutoHide() const {
  405. return false;
  406. }
  407. bool NativeWindow::IsMenuBarVisible() const {
  408. return true;
  409. }
  410. void NativeWindow::SetAspectRatio(double aspect_ratio,
  411. const gfx::Size& extra_size) {
  412. aspect_ratio_ = aspect_ratio;
  413. aspect_ratio_extraSize_ = extra_size;
  414. }
  415. bool NativeWindow::IsSnapped() const {
  416. return false;
  417. }
  418. std::optional<gfx::Rect> NativeWindow::GetWindowControlsOverlayRect() {
  419. return overlay_rect_;
  420. }
  421. void NativeWindow::SetWindowControlsOverlayRect(const gfx::Rect& overlay_rect) {
  422. overlay_rect_ = overlay_rect;
  423. }
  424. void NativeWindow::NotifyWindowRequestPreferredWidth(int* width) {
  425. for (NativeWindowObserver& observer : observers_)
  426. observer.RequestPreferredWidth(width);
  427. }
  428. void NativeWindow::NotifyWindowCloseButtonClicked() {
  429. // First ask the observers whether we want to close.
  430. bool prevent_default = false;
  431. for (NativeWindowObserver& observer : observers_)
  432. observer.WillCloseWindow(&prevent_default);
  433. if (prevent_default) {
  434. WindowList::WindowCloseCancelled(this);
  435. return;
  436. }
  437. // Then ask the observers how should we close the window.
  438. for (NativeWindowObserver& observer : observers_)
  439. observer.OnCloseButtonClicked(&prevent_default);
  440. if (prevent_default)
  441. return;
  442. CloseImmediately();
  443. }
  444. void NativeWindow::NotifyWindowClosed() {
  445. if (is_closed_)
  446. return;
  447. is_closed_ = true;
  448. for (NativeWindowObserver& observer : observers_)
  449. observer.OnWindowClosed();
  450. WindowList::RemoveWindow(this);
  451. }
  452. void NativeWindow::NotifyWindowQueryEndSession(
  453. const std::vector<std::string>& reasons,
  454. bool* prevent_default) {
  455. for (NativeWindowObserver& observer : observers_)
  456. observer.OnWindowQueryEndSession(reasons, prevent_default);
  457. }
  458. void NativeWindow::NotifyWindowEndSession(
  459. const std::vector<std::string>& reasons) {
  460. for (NativeWindowObserver& observer : observers_)
  461. observer.OnWindowEndSession(reasons);
  462. }
  463. void NativeWindow::NotifyWindowBlur() {
  464. for (NativeWindowObserver& observer : observers_)
  465. observer.OnWindowBlur();
  466. }
  467. void NativeWindow::NotifyWindowFocus() {
  468. for (NativeWindowObserver& observer : observers_)
  469. observer.OnWindowFocus();
  470. }
  471. void NativeWindow::NotifyWindowIsKeyChanged(bool is_key) {
  472. for (NativeWindowObserver& observer : observers_)
  473. observer.OnWindowIsKeyChanged(is_key);
  474. }
  475. void NativeWindow::NotifyWindowShow() {
  476. for (NativeWindowObserver& observer : observers_)
  477. observer.OnWindowShow();
  478. }
  479. void NativeWindow::NotifyWindowHide() {
  480. for (NativeWindowObserver& observer : observers_)
  481. observer.OnWindowHide();
  482. }
  483. void NativeWindow::NotifyWindowMaximize() {
  484. for (NativeWindowObserver& observer : observers_)
  485. observer.OnWindowMaximize();
  486. }
  487. void NativeWindow::NotifyWindowUnmaximize() {
  488. for (NativeWindowObserver& observer : observers_)
  489. observer.OnWindowUnmaximize();
  490. }
  491. void NativeWindow::NotifyWindowMinimize() {
  492. for (NativeWindowObserver& observer : observers_)
  493. observer.OnWindowMinimize();
  494. }
  495. void NativeWindow::NotifyWindowRestore() {
  496. for (NativeWindowObserver& observer : observers_)
  497. observer.OnWindowRestore();
  498. }
  499. void NativeWindow::NotifyWindowWillResize(const gfx::Rect& new_bounds,
  500. const gfx::ResizeEdge& edge,
  501. bool* prevent_default) {
  502. for (NativeWindowObserver& observer : observers_)
  503. observer.OnWindowWillResize(new_bounds, edge, prevent_default);
  504. }
  505. void NativeWindow::NotifyWindowWillMove(const gfx::Rect& new_bounds,
  506. bool* prevent_default) {
  507. for (NativeWindowObserver& observer : observers_)
  508. observer.OnWindowWillMove(new_bounds, prevent_default);
  509. }
  510. void NativeWindow::NotifyWindowResize() {
  511. NotifyLayoutWindowControlsOverlay();
  512. for (NativeWindowObserver& observer : observers_)
  513. observer.OnWindowResize();
  514. }
  515. void NativeWindow::NotifyWindowResized() {
  516. for (NativeWindowObserver& observer : observers_)
  517. observer.OnWindowResized();
  518. }
  519. void NativeWindow::NotifyWindowMove() {
  520. for (NativeWindowObserver& observer : observers_)
  521. observer.OnWindowMove();
  522. }
  523. void NativeWindow::NotifyWindowMoved() {
  524. for (NativeWindowObserver& observer : observers_)
  525. observer.OnWindowMoved();
  526. }
  527. void NativeWindow::NotifyWindowEnterFullScreen() {
  528. NotifyLayoutWindowControlsOverlay();
  529. for (NativeWindowObserver& observer : observers_)
  530. observer.OnWindowEnterFullScreen();
  531. }
  532. void NativeWindow::NotifyWindowSwipe(const std::string& direction) {
  533. for (NativeWindowObserver& observer : observers_)
  534. observer.OnWindowSwipe(direction);
  535. }
  536. void NativeWindow::NotifyWindowRotateGesture(float rotation) {
  537. for (NativeWindowObserver& observer : observers_)
  538. observer.OnWindowRotateGesture(rotation);
  539. }
  540. void NativeWindow::NotifyWindowSheetBegin() {
  541. for (NativeWindowObserver& observer : observers_)
  542. observer.OnWindowSheetBegin();
  543. }
  544. void NativeWindow::NotifyWindowSheetEnd() {
  545. for (NativeWindowObserver& observer : observers_)
  546. observer.OnWindowSheetEnd();
  547. }
  548. void NativeWindow::NotifyWindowLeaveFullScreen() {
  549. NotifyLayoutWindowControlsOverlay();
  550. for (NativeWindowObserver& observer : observers_)
  551. observer.OnWindowLeaveFullScreen();
  552. }
  553. void NativeWindow::NotifyWindowEnterHtmlFullScreen() {
  554. for (NativeWindowObserver& observer : observers_)
  555. observer.OnWindowEnterHtmlFullScreen();
  556. }
  557. void NativeWindow::NotifyWindowLeaveHtmlFullScreen() {
  558. for (NativeWindowObserver& observer : observers_)
  559. observer.OnWindowLeaveHtmlFullScreen();
  560. }
  561. void NativeWindow::NotifyWindowAlwaysOnTopChanged() {
  562. for (NativeWindowObserver& observer : observers_)
  563. observer.OnWindowAlwaysOnTopChanged();
  564. }
  565. void NativeWindow::NotifyWindowExecuteAppCommand(
  566. const std::string_view command_name) {
  567. for (NativeWindowObserver& observer : observers_)
  568. observer.OnExecuteAppCommand(command_name);
  569. }
  570. void NativeWindow::NotifyTouchBarItemInteraction(const std::string& item_id,
  571. base::Value::Dict details) {
  572. for (NativeWindowObserver& observer : observers_)
  573. observer.OnTouchBarItemResult(item_id, details);
  574. }
  575. void NativeWindow::NotifyNewWindowForTab() {
  576. for (NativeWindowObserver& observer : observers_)
  577. observer.OnNewWindowForTab();
  578. }
  579. void NativeWindow::NotifyWindowSystemContextMenu(int x,
  580. int y,
  581. bool* prevent_default) {
  582. for (NativeWindowObserver& observer : observers_)
  583. observer.OnSystemContextMenu(x, y, prevent_default);
  584. }
  585. void NativeWindow::NotifyLayoutWindowControlsOverlay() {
  586. auto bounding_rect = GetWindowControlsOverlayRect();
  587. if (bounding_rect.has_value()) {
  588. for (NativeWindowObserver& observer : observers_)
  589. observer.UpdateWindowControlsOverlay(bounding_rect.value());
  590. }
  591. }
  592. #if BUILDFLAG(IS_WIN)
  593. void NativeWindow::NotifyWindowMessage(UINT message,
  594. WPARAM w_param,
  595. LPARAM l_param) {
  596. for (NativeWindowObserver& observer : observers_)
  597. observer.OnWindowMessage(message, w_param, l_param);
  598. }
  599. #endif
  600. int NativeWindow::NonClientHitTest(const gfx::Point& point) {
  601. #if !BUILDFLAG(IS_MAC)
  602. // We need to ensure we account for resizing borders on Windows and Linux.
  603. if ((!has_frame() || has_client_frame()) && IsResizable()) {
  604. auto* frame =
  605. static_cast<FramelessView*>(widget()->non_client_view()->frame_view());
  606. int border_hit = frame->ResizingBorderHitTest(point);
  607. if (border_hit != HTNOWHERE)
  608. return border_hit;
  609. }
  610. #endif
  611. // This is to disable dragging in HTML5 full screen mode.
  612. // Details: https://github.com/electron/electron/issues/41002
  613. if (GetWidget()->IsFullscreen())
  614. return HTNOWHERE;
  615. for (auto* provider : draggable_region_providers_) {
  616. int hit = provider->NonClientHitTest(point);
  617. if (hit != HTNOWHERE)
  618. return hit;
  619. }
  620. return HTNOWHERE;
  621. }
  622. void NativeWindow::AddDraggableRegionProvider(
  623. DraggableRegionProvider* provider) {
  624. if (!base::Contains(draggable_region_providers_, provider)) {
  625. draggable_region_providers_.push_back(provider);
  626. }
  627. }
  628. void NativeWindow::RemoveDraggableRegionProvider(
  629. DraggableRegionProvider* provider) {
  630. draggable_region_providers_.remove_if(
  631. [&provider](DraggableRegionProvider* p) { return p == provider; });
  632. }
  633. void NativeWindow::AddBackgroundThrottlingSource(
  634. BackgroundThrottlingSource* source) {
  635. auto result = background_throttling_sources_.insert(source);
  636. DCHECK(result.second) << "Added already stored BackgroundThrottlingSource.";
  637. UpdateBackgroundThrottlingState();
  638. }
  639. void NativeWindow::RemoveBackgroundThrottlingSource(
  640. BackgroundThrottlingSource* source) {
  641. auto result = background_throttling_sources_.erase(source);
  642. DCHECK(result == 1)
  643. << "Tried to remove non existing BackgroundThrottlingSource.";
  644. UpdateBackgroundThrottlingState();
  645. }
  646. void NativeWindow::UpdateBackgroundThrottlingState() {
  647. if (!GetWidget() || !GetWidget()->GetCompositor()) {
  648. return;
  649. }
  650. bool enable_background_throttling = true;
  651. for (const auto* background_throttling_source :
  652. background_throttling_sources_) {
  653. if (!background_throttling_source->GetBackgroundThrottling()) {
  654. enable_background_throttling = false;
  655. break;
  656. }
  657. }
  658. GetWidget()->GetCompositor()->SetBackgroundThrottling(
  659. enable_background_throttling);
  660. }
  661. views::Widget* NativeWindow::GetWidget() {
  662. return widget();
  663. }
  664. const views::Widget* NativeWindow::GetWidget() const {
  665. return widget();
  666. }
  667. std::u16string NativeWindow::GetAccessibleWindowTitle() const {
  668. if (accessible_title_.empty()) {
  669. return views::WidgetDelegate::GetAccessibleWindowTitle();
  670. }
  671. return accessible_title_;
  672. }
  673. void NativeWindow::SetAccessibleTitle(const std::string& title) {
  674. accessible_title_ = base::UTF8ToUTF16(title);
  675. }
  676. std::string NativeWindow::GetAccessibleTitle() {
  677. return base::UTF16ToUTF8(accessible_title_);
  678. }
  679. void NativeWindow::HandlePendingFullscreenTransitions() {
  680. if (pending_transitions_.empty()) {
  681. set_fullscreen_transition_type(FullScreenTransitionType::kNone);
  682. return;
  683. }
  684. bool next_transition = pending_transitions_.front();
  685. pending_transitions_.pop();
  686. SetFullScreen(next_transition);
  687. }
  688. // static
  689. int32_t NativeWindow::next_id_ = 0;
  690. bool NativeWindow::IsTranslucent() const {
  691. // Transparent windows are translucent
  692. if (transparent()) {
  693. return true;
  694. }
  695. #if BUILDFLAG(IS_MAC)
  696. // Windows with vibrancy set are translucent
  697. if (!vibrancy().empty()) {
  698. return true;
  699. }
  700. #endif
  701. #if BUILDFLAG(IS_WIN)
  702. // Windows with certain background materials may be translucent
  703. const std::string& bg_material = background_material();
  704. if (!bg_material.empty() && bg_material != "none") {
  705. return true;
  706. }
  707. #endif
  708. return false;
  709. }
  710. // static
  711. void NativeWindowRelay::CreateForWebContents(
  712. content::WebContents* web_contents,
  713. base::WeakPtr<NativeWindow> window) {
  714. DCHECK(web_contents);
  715. if (!web_contents->GetUserData(UserDataKey())) {
  716. web_contents->SetUserData(
  717. UserDataKey(),
  718. base::WrapUnique(new NativeWindowRelay(web_contents, window)));
  719. }
  720. }
  721. NativeWindowRelay::NativeWindowRelay(content::WebContents* web_contents,
  722. base::WeakPtr<NativeWindow> window)
  723. : content::WebContentsUserData<NativeWindowRelay>(*web_contents),
  724. native_window_(window) {}
  725. NativeWindowRelay::~NativeWindowRelay() = default;
  726. WEB_CONTENTS_USER_DATA_KEY_IMPL(NativeWindowRelay);
  727. } // namespace electron