native_widget_mac_ns_window_host.mm 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ui/views/cocoa/native_widget_mac_ns_window_host.h"
  5. #include <tuple>
  6. #include <utility>
  7. #include "base/base64.h"
  8. #include "base/containers/contains.h"
  9. #include "base/mac/foundation_util.h"
  10. #include "base/no_destructor.h"
  11. #include "base/numerics/safe_conversions.h"
  12. #include "base/strings/sys_string_conversions.h"
  13. #include "base/time/time.h"
  14. #include "components/remote_cocoa/app_shim/mouse_capture.h"
  15. #include "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h"
  16. #include "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h"
  17. #include "components/remote_cocoa/browser/ns_view_ids.h"
  18. #include "components/remote_cocoa/browser/window.h"
  19. #include "mojo/public/cpp/bindings/self_owned_associated_receiver.h"
  20. #include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
  21. #include "ui/base/cocoa/animation_utils.h"
  22. #include "ui/base/cocoa/nswindow_test_util.h"
  23. #include "ui/base/cocoa/remote_accessibility_api.h"
  24. #include "ui/base/cocoa/remote_layer_api.h"
  25. #include "ui/base/hit_test.h"
  26. #include "ui/base/ime/input_method.h"
  27. #include "ui/compositor/layer.h"
  28. #include "ui/compositor/recyclable_compositor_mac.h"
  29. #include "ui/display/screen.h"
  30. #include "ui/events/cocoa/cocoa_event_utils.h"
  31. #include "ui/gfx/geometry/dip_util.h"
  32. #include "ui/gfx/geometry/size_conversions.h"
  33. #include "ui/gfx/mac/coordinate_conversion.h"
  34. #include "ui/native_theme/native_theme_mac.h"
  35. #include "ui/views/cocoa/immersive_mode_delegate_mac.h"
  36. #include "ui/views/cocoa/text_input_host.h"
  37. #include "ui/views/cocoa/tooltip_manager_mac.h"
  38. #include "ui/views/controls/label.h"
  39. #include "ui/views/controls/menu/menu_config.h"
  40. #include "ui/views/controls/menu/menu_controller.h"
  41. #include "ui/views/views_delegate.h"
  42. #include "ui/views/widget/native_widget_mac.h"
  43. #include "ui/views/widget/widget_delegate.h"
  44. #include "ui/views/widget/widget_utils_mac.h"
  45. #include "ui/views/window/dialog_delegate.h"
  46. #include "ui/views/word_lookup_client.h"
  47. using remote_cocoa::mojom::NativeWidgetNSWindowInitParams;
  48. using remote_cocoa::mojom::WindowVisibilityState;
  49. namespace views {
  50. namespace {
  51. // Dummy implementation of the BridgedNativeWidgetHost interface. This structure
  52. // exists to work around a bug wherein synchronous mojo calls to an associated
  53. // interface can hang if the interface request is unbound. This structure is
  54. // bound to the real host's interface, and then deletes itself only once the
  55. // underlying connection closes.
  56. // https://crbug.com/915572
  57. class BridgedNativeWidgetHostDummy
  58. : public remote_cocoa::mojom::NativeWidgetNSWindowHost {
  59. public:
  60. BridgedNativeWidgetHostDummy() = default;
  61. ~BridgedNativeWidgetHostDummy() override = default;
  62. private:
  63. void OnVisibilityChanged(bool visible) override {}
  64. void OnWindowNativeThemeChanged() override {}
  65. void OnViewSizeChanged(const gfx::Size& new_size) override {}
  66. void SetKeyboardAccessible(bool enabled) override {}
  67. void OnIsFirstResponderChanged(bool is_first_responder) override {}
  68. void OnMouseCaptureActiveChanged(bool capture_is_active) override {}
  69. void OnScrollEvent(std::unique_ptr<ui::Event> event) override {}
  70. void OnMouseEvent(std::unique_ptr<ui::Event> event) override {}
  71. void OnGestureEvent(std::unique_ptr<ui::Event> event) override {}
  72. void OnWindowGeometryChanged(
  73. const gfx::Rect& window_bounds_in_screen_dips,
  74. const gfx::Rect& content_bounds_in_screen_dips) override {}
  75. void OnWindowFullscreenTransitionStart(
  76. bool target_fullscreen_state) override {}
  77. void OnWindowFullscreenTransitionComplete(bool is_fullscreen) override {}
  78. void OnWindowMiniaturizedChanged(bool miniaturized) override {}
  79. void OnWindowDisplayChanged(const display::Display& display) override {}
  80. void OnWindowWillClose() override {}
  81. void OnWindowHasClosed() override {}
  82. void OnWindowKeyStatusChanged(bool is_key,
  83. bool is_content_first_responder,
  84. bool full_keyboard_access_enabled) override {}
  85. void OnWindowStateRestorationDataChanged(
  86. const std::vector<uint8_t>& data) override {}
  87. void DoDialogButtonAction(ui::DialogButton button) override {}
  88. void OnFocusWindowToolbar() override {}
  89. void SetRemoteAccessibilityTokens(
  90. const std::vector<uint8_t>& window_token,
  91. const std::vector<uint8_t>& view_token) override {}
  92. void GetSheetOffsetY(GetSheetOffsetYCallback callback) override {
  93. float offset_y = 0;
  94. std::move(callback).Run(offset_y);
  95. }
  96. void DispatchKeyEventRemote(
  97. std::unique_ptr<ui::Event> event,
  98. DispatchKeyEventRemoteCallback callback) override {
  99. bool event_handled = false;
  100. std::move(callback).Run(event_handled);
  101. }
  102. void DispatchKeyEventToMenuControllerRemote(
  103. std::unique_ptr<ui::Event> event,
  104. DispatchKeyEventToMenuControllerRemoteCallback callback) override {
  105. ui::KeyEvent* key_event = event->AsKeyEvent();
  106. bool event_swallowed = false;
  107. std::move(callback).Run(event_swallowed, key_event->handled());
  108. }
  109. void DispatchMonitorEvent(std::unique_ptr<ui::Event> event,
  110. DispatchMonitorEventCallback callback) override {
  111. bool event_handled = false;
  112. std::move(callback).Run(event_handled);
  113. }
  114. void GetHasMenuController(GetHasMenuControllerCallback callback) override {
  115. bool has_menu_controller = false;
  116. std::move(callback).Run(has_menu_controller);
  117. }
  118. void GetIsDraggableBackgroundAt(
  119. const gfx::Point& location_in_content,
  120. GetIsDraggableBackgroundAtCallback callback) override {
  121. bool is_draggable_background = false;
  122. std::move(callback).Run(is_draggable_background);
  123. }
  124. void GetTooltipTextAt(const gfx::Point& location_in_content,
  125. GetTooltipTextAtCallback callback) override {
  126. std::u16string new_tooltip_text;
  127. std::move(callback).Run(new_tooltip_text);
  128. }
  129. void GetIsFocusedViewTextual(
  130. GetIsFocusedViewTextualCallback callback) override {
  131. bool is_textual = false;
  132. std::move(callback).Run(is_textual);
  133. }
  134. void GetWidgetIsModal(GetWidgetIsModalCallback callback) override {
  135. bool widget_is_modal = false;
  136. std::move(callback).Run(widget_is_modal);
  137. }
  138. void GetDialogButtonInfo(ui::DialogButton button,
  139. GetDialogButtonInfoCallback callback) override {
  140. bool exists = false;
  141. std::u16string label;
  142. bool is_enabled = false;
  143. bool is_default = false;
  144. std::move(callback).Run(exists, label, is_enabled, is_default);
  145. }
  146. void GetDoDialogButtonsExist(
  147. GetDoDialogButtonsExistCallback callback) override {
  148. bool buttons_exist = false;
  149. std::move(callback).Run(buttons_exist);
  150. }
  151. void GetShouldShowWindowTitle(
  152. GetShouldShowWindowTitleCallback callback) override {
  153. bool should_show_window_title = false;
  154. std::move(callback).Run(should_show_window_title);
  155. }
  156. void GetCanWindowBecomeKey(GetCanWindowBecomeKeyCallback callback) override {
  157. bool can_window_become_key = false;
  158. std::move(callback).Run(can_window_become_key);
  159. }
  160. void GetAlwaysRenderWindowAsKey(
  161. GetAlwaysRenderWindowAsKeyCallback callback) override {
  162. bool always_render_as_key = false;
  163. std::move(callback).Run(always_render_as_key);
  164. }
  165. void OnWindowCloseRequested(
  166. OnWindowCloseRequestedCallback callback) override {
  167. bool can_window_close = false;
  168. std::move(callback).Run(can_window_close);
  169. }
  170. void GetWindowFrameTitlebarHeight(
  171. GetWindowFrameTitlebarHeightCallback callback) override {
  172. bool override_titlebar_height = false;
  173. float titlebar_height = 0;
  174. std::move(callback).Run(override_titlebar_height, titlebar_height);
  175. }
  176. void GetRootViewAccessibilityToken(
  177. GetRootViewAccessibilityTokenCallback callback) override {
  178. std::vector<uint8_t> token;
  179. int64_t pid = 0;
  180. std::move(callback).Run(pid, token);
  181. }
  182. void ValidateUserInterfaceItem(
  183. int32_t command,
  184. ValidateUserInterfaceItemCallback callback) override {
  185. remote_cocoa::mojom::ValidateUserInterfaceItemResultPtr result;
  186. std::move(callback).Run(std::move(result));
  187. }
  188. void ExecuteCommand(int32_t command,
  189. WindowOpenDisposition window_open_disposition,
  190. bool is_before_first_responder,
  191. ExecuteCommandCallback callback) override {
  192. bool was_executed = false;
  193. std::move(callback).Run(was_executed);
  194. }
  195. void HandleAccelerator(const ui::Accelerator& accelerator,
  196. bool require_priority_handler,
  197. HandleAcceleratorCallback callback) override {
  198. bool was_handled = false;
  199. std::move(callback).Run(was_handled);
  200. }
  201. };
  202. std::map<uint64_t, NativeWidgetMacNSWindowHost*>& GetIdToWidgetHostImplMap() {
  203. static base::NoDestructor<std::map<uint64_t, NativeWidgetMacNSWindowHost*>>
  204. id_map;
  205. return *id_map;
  206. }
  207. uint64_t g_last_bridged_native_widget_id = 0;
  208. NSWindow* OriginalHostingWindowFromFullScreenWindow(
  209. NSWindow* full_screen_window) {
  210. if ([full_screen_window.delegate
  211. conformsToProtocol:@protocol(ImmersiveModeDelegate)]) {
  212. return base::mac::ObjCCastStrict<NSObject<ImmersiveModeDelegate>>(
  213. full_screen_window.delegate)
  214. .originalHostingWindow;
  215. }
  216. return nullptr;
  217. }
  218. } // namespace
  219. // static
  220. NativeWidgetMacNSWindowHost* NativeWidgetMacNSWindowHost::GetFromNativeWindow(
  221. gfx::NativeWindow native_window) {
  222. NSWindow* window = native_window.GetNativeNSWindow();
  223. if (NativeWidgetMacNSWindow* widget_window =
  224. base::mac::ObjCCast<NativeWidgetMacNSWindow>(window)) {
  225. return GetFromId([widget_window bridgedNativeWidgetId]);
  226. }
  227. // If the window is a system created NSToolbarFullScreenWindow we need to do
  228. // some additional work to find the original window.
  229. if (views::IsNSToolbarFullScreenWindow(window)) {
  230. NSWindow* original = OriginalHostingWindowFromFullScreenWindow(window);
  231. if (NativeWidgetMacNSWindow* widget_window =
  232. base::mac::ObjCCast<NativeWidgetMacNSWindow>(original)) {
  233. return GetFromId([widget_window bridgedNativeWidgetId]);
  234. }
  235. }
  236. return nullptr; // Not created by NativeWidgetMac.
  237. }
  238. // static
  239. NativeWidgetMacNSWindowHost* NativeWidgetMacNSWindowHost::GetFromNativeView(
  240. gfx::NativeView native_view) {
  241. return GetFromNativeWindow([native_view.GetNativeNSView() window]);
  242. }
  243. // static
  244. const char NativeWidgetMacNSWindowHost::kImmersiveContentNSView[] =
  245. "kImmersiveContentNSView";
  246. // static
  247. NativeWidgetMacNSWindowHost* NativeWidgetMacNSWindowHost::GetFromId(
  248. uint64_t bridged_native_widget_id) {
  249. auto found = GetIdToWidgetHostImplMap().find(bridged_native_widget_id);
  250. if (found == GetIdToWidgetHostImplMap().end())
  251. return nullptr;
  252. return found->second;
  253. }
  254. NativeWidgetMacNSWindowHost::NativeWidgetMacNSWindowHost(NativeWidgetMac* owner)
  255. : widget_id_(++g_last_bridged_native_widget_id),
  256. native_widget_mac_(owner),
  257. root_view_id_(remote_cocoa::GetNewNSViewId()),
  258. accessibility_focus_overrider_(this),
  259. text_input_host_(new TextInputHost(this)) {
  260. DCHECK(GetIdToWidgetHostImplMap().find(widget_id_) ==
  261. GetIdToWidgetHostImplMap().end());
  262. GetIdToWidgetHostImplMap().emplace(widget_id_, this);
  263. DCHECK(owner);
  264. }
  265. NativeWidgetMacNSWindowHost::~NativeWidgetMacNSWindowHost() {
  266. DCHECK(children_.empty());
  267. native_window_mapping_.reset();
  268. if (application_host_) {
  269. remote_ns_window_remote_.reset();
  270. application_host_->RemoveObserver(this);
  271. application_host_ = nullptr;
  272. }
  273. // Workaround for https://crbug.com/915572
  274. if (remote_ns_window_host_receiver_.is_bound()) {
  275. auto receiver = remote_ns_window_host_receiver_.Unbind();
  276. if (receiver.is_valid()) {
  277. mojo::MakeSelfOwnedAssociatedReceiver(
  278. std::make_unique<BridgedNativeWidgetHostDummy>(),
  279. std::move(receiver));
  280. }
  281. }
  282. // Ensure that |this| cannot be reached by its id while it is being destroyed.
  283. auto found = GetIdToWidgetHostImplMap().find(widget_id_);
  284. DCHECK(found != GetIdToWidgetHostImplMap().end());
  285. DCHECK_EQ(found->second, this);
  286. GetIdToWidgetHostImplMap().erase(found);
  287. // Destroy the bridge first to prevent any calls back into this during
  288. // destruction.
  289. // TODO(ccameron): When all communication from |bridge_| to this goes through
  290. // the BridgedNativeWidgetHost, this can be replaced with closing that pipe.
  291. in_process_ns_window_bridge_.reset();
  292. DestroyCompositor();
  293. }
  294. NativeWidgetMacNSWindow* NativeWidgetMacNSWindowHost::GetInProcessNSWindow()
  295. const {
  296. return in_process_ns_window_.get();
  297. }
  298. gfx::NativeViewAccessible
  299. NativeWidgetMacNSWindowHost::GetNativeViewAccessibleForNSView() const {
  300. if (in_process_ns_window_bridge_)
  301. return in_process_ns_window_bridge_->ns_view();
  302. return remote_view_accessible_.get();
  303. }
  304. gfx::NativeViewAccessible
  305. NativeWidgetMacNSWindowHost::GetNativeViewAccessibleForNSWindow() const {
  306. if (in_process_ns_window_bridge_)
  307. return in_process_ns_window_bridge_->ns_window();
  308. return remote_window_accessible_.get();
  309. }
  310. remote_cocoa::mojom::NativeWidgetNSWindow*
  311. NativeWidgetMacNSWindowHost::GetNSWindowMojo() const {
  312. if (remote_ns_window_remote_)
  313. return remote_ns_window_remote_.get();
  314. if (in_process_ns_window_bridge_)
  315. return in_process_ns_window_bridge_.get();
  316. return nullptr;
  317. }
  318. void NativeWidgetMacNSWindowHost::CreateInProcessNSWindowBridge(
  319. base::scoped_nsobject<NativeWidgetMacNSWindow> window) {
  320. in_process_ns_window_ = window;
  321. in_process_ns_window_bridge_ =
  322. std::make_unique<remote_cocoa::NativeWidgetNSWindowBridge>(
  323. widget_id_, this, this, text_input_host_.get());
  324. in_process_ns_window_bridge_->SetWindow(window);
  325. }
  326. void NativeWidgetMacNSWindowHost::CreateRemoteNSWindow(
  327. remote_cocoa::ApplicationHost* application_host,
  328. remote_cocoa::mojom::CreateWindowParamsPtr window_create_params) {
  329. accessibility_focus_overrider_.SetAppIsRemote(true);
  330. application_host_ = application_host;
  331. application_host_->AddObserver(this);
  332. // Create a local invisible window that will be used as the gfx::NativeWindow
  333. // handle to track this window in this process.
  334. {
  335. auto in_process_ns_window_create_params =
  336. remote_cocoa::mojom::CreateWindowParams::New();
  337. in_process_ns_window_create_params->style_mask =
  338. NSWindowStyleMaskBorderless;
  339. in_process_ns_window_ =
  340. remote_cocoa::NativeWidgetNSWindowBridge::CreateNSWindow(
  341. in_process_ns_window_create_params.get());
  342. [in_process_ns_window_ setBridgedNativeWidgetId:widget_id_];
  343. [in_process_ns_window_ setAlphaValue:0.0];
  344. in_process_view_id_mapping_ =
  345. std::make_unique<remote_cocoa::ScopedNSViewIdMapping>(
  346. root_view_id_, [in_process_ns_window_ contentView]);
  347. [in_process_ns_window_ enforceNeverMadeVisible];
  348. }
  349. // Initialize |remote_ns_window_remote_| to point to a bridge created by
  350. // |factory|.
  351. mojo::PendingAssociatedRemote<remote_cocoa::mojom::TextInputHost>
  352. text_input_host_remote;
  353. text_input_host_->BindReceiver(
  354. text_input_host_remote.InitWithNewEndpointAndPassReceiver());
  355. application_host_->GetApplication()->CreateNativeWidgetNSWindow(
  356. widget_id_, remote_ns_window_remote_.BindNewEndpointAndPassReceiver(),
  357. remote_ns_window_host_receiver_.BindNewEndpointAndPassRemote(
  358. ui::WindowResizeHelperMac::Get()->task_runner()),
  359. std::move(text_input_host_remote));
  360. // Create the window in its process, and attach it to its parent window.
  361. GetNSWindowMojo()->CreateWindow(std::move(window_create_params));
  362. }
  363. void NativeWidgetMacNSWindowHost::InitWindow(
  364. const Widget::InitParams& params,
  365. const gfx::Rect& initial_bounds_in_screen) {
  366. native_window_mapping_ =
  367. std::make_unique<remote_cocoa::ScopedNativeWindowMapping>(
  368. gfx::NativeWindow(in_process_ns_window_.get()), application_host_,
  369. in_process_ns_window_bridge_.get(), GetNSWindowMojo());
  370. Widget* widget = native_widget_mac_->GetWidget();
  371. widget_type_ = params.type;
  372. bool is_tooltip = params.type == Widget::InitParams::TYPE_TOOLTIP;
  373. if (!is_tooltip)
  374. tooltip_manager_ = std::make_unique<TooltipManagerMac>(GetNSWindowMojo());
  375. if (params.workspace.length()) {
  376. std::string restoration_data;
  377. if (base::Base64Decode(params.workspace, &restoration_data)) {
  378. state_restoration_data_ = std::vector<uint8_t>(restoration_data.begin(),
  379. restoration_data.end());
  380. } else {
  381. DLOG(ERROR) << "Failed to decode a window's state restoration data.";
  382. }
  383. }
  384. // Initialize the window.
  385. {
  386. auto window_params = NativeWidgetNSWindowInitParams::New();
  387. window_params->modal_type = widget->widget_delegate()->GetModalType();
  388. window_params->is_translucent =
  389. params.opacity == Widget::InitParams::WindowOpacity::kTranslucent;
  390. window_params->is_headless_mode_window = params.headless_mode;
  391. window_params->is_tooltip = is_tooltip;
  392. is_headless_mode_window_ = params.headless_mode;
  393. // OSX likes to put shadows on most things. However, frameless windows (with
  394. // styleMask = NSWindowStyleMaskBorderless) default to no shadow. So change
  395. // that. ShadowType::kDrop is used for Menus, which get the same shadow
  396. // style on Mac.
  397. switch (params.shadow_type) {
  398. case Widget::InitParams::ShadowType::kNone:
  399. window_params->has_window_server_shadow = false;
  400. break;
  401. case Widget::InitParams::ShadowType::kDefault:
  402. // Controls should get views shadows instead of native shadows.
  403. window_params->has_window_server_shadow =
  404. params.type != Widget::InitParams::TYPE_CONTROL;
  405. break;
  406. case Widget::InitParams::ShadowType::kDrop:
  407. window_params->has_window_server_shadow = true;
  408. break;
  409. } // No default case, to pick up new types.
  410. // Include "regular" windows without the standard frame in the window cycle.
  411. // These use NSWindowStyleMaskBorderless so do not get it by default.
  412. window_params->force_into_collection_cycle =
  413. widget_type_ == Widget::InitParams::TYPE_WINDOW &&
  414. params.remove_standard_frame;
  415. window_params->state_restoration_data = state_restoration_data_;
  416. GetNSWindowMojo()->InitWindow(std::move(window_params));
  417. }
  418. // Set a meaningful initial bounds. Note that except for frameless widgets
  419. // with no WidgetDelegate, the bounds will be set again by Widget after
  420. // initializing the non-client view. In the former case, if bounds were not
  421. // set at all, the creator of the Widget is expected to call SetBounds()
  422. // before calling Widget::Show() to avoid a kWindowSizeDeterminedLater-sized
  423. // (i.e. 1x1) window appearing.
  424. UpdateLocalWindowFrame(initial_bounds_in_screen);
  425. GetNSWindowMojo()->SetInitialBounds(initial_bounds_in_screen,
  426. widget->GetMinimumSize());
  427. // TODO(ccameron): Correctly set these based |in_process_ns_window_|.
  428. window_bounds_in_screen_ = initial_bounds_in_screen;
  429. content_bounds_in_screen_ = initial_bounds_in_screen;
  430. // Widgets for UI controls (usually layered above web contents) start visible.
  431. if (widget_type_ == Widget::InitParams::TYPE_CONTROL)
  432. GetNSWindowMojo()->SetVisibilityState(WindowVisibilityState::kShowInactive);
  433. }
  434. void NativeWidgetMacNSWindowHost::CloseWindowNow() {
  435. bool is_out_of_process = !in_process_ns_window_bridge_;
  436. // Note that CloseWindowNow may delete |this| for in-process windows.
  437. if (GetNSWindowMojo())
  438. GetNSWindowMojo()->CloseWindowNow();
  439. // If it is out-of-process, then simulate the calls that would have been
  440. // during window closure.
  441. if (is_out_of_process) {
  442. OnWindowWillClose();
  443. while (!children_.empty())
  444. children_.front()->CloseWindowNow();
  445. OnWindowHasClosed();
  446. }
  447. }
  448. void NativeWidgetMacNSWindowHost::SetBoundsInScreen(const gfx::Rect& bounds) {
  449. UpdateLocalWindowFrame(bounds);
  450. GetNSWindowMojo()->SetBounds(
  451. bounds, native_widget_mac_->GetWidget()->GetMinimumSize());
  452. if (remote_ns_window_remote_) {
  453. gfx::Rect window_in_screen =
  454. gfx::ScreenRectFromNSRect([in_process_ns_window_ frame]);
  455. gfx::Rect content_in_screen =
  456. gfx::ScreenRectFromNSRect([in_process_ns_window_
  457. contentRectForFrameRect:[in_process_ns_window_ frame]]);
  458. OnWindowGeometryChanged(window_in_screen, content_in_screen);
  459. }
  460. }
  461. void NativeWidgetMacNSWindowHost::SetFullscreen(bool fullscreen,
  462. int64_t target_display_id) {
  463. // Note that when the NSWindow begins a fullscreen transition, the value of
  464. // |target_fullscreen_state_| updates via OnWindowFullscreenTransitionStart.
  465. // The update here is necessary for the case where we are currently in
  466. // transition (and therefore OnWindowFullscreenTransitionStart will not be
  467. // called until the current transition completes).
  468. target_fullscreen_state_ = fullscreen;
  469. if (target_fullscreen_state_)
  470. GetNSWindowMojo()->EnterFullscreen(target_display_id);
  471. else
  472. GetNSWindowMojo()->ExitFullscreen();
  473. }
  474. void NativeWidgetMacNSWindowHost::SetRootView(views::View* root_view) {
  475. root_view_ = root_view;
  476. if (root_view_) {
  477. // TODO(ccameron): Drag-drop functionality does not yet run over mojo.
  478. if (in_process_ns_window_bridge_) {
  479. drag_drop_client_ = std::make_unique<DragDropClientMac>(
  480. in_process_ns_window_bridge_.get(), root_view_);
  481. }
  482. } else {
  483. drag_drop_client_.reset();
  484. }
  485. }
  486. void NativeWidgetMacNSWindowHost::CreateCompositor(
  487. const Widget::InitParams& params) {
  488. DCHECK(!compositor_);
  489. DCHECK(!layer());
  490. DCHECK(ViewsDelegate::GetInstance());
  491. // "Infer" must be handled by ViewsDelegate::OnBeforeWidgetInit().
  492. DCHECK_NE(Widget::InitParams::WindowOpacity::kInferred, params.opacity);
  493. bool translucent =
  494. params.opacity == Widget::InitParams::WindowOpacity::kTranslucent;
  495. // Create the layer.
  496. SetLayer(std::make_unique<ui::Layer>(params.layer_type));
  497. layer()->set_delegate(this);
  498. layer()->SetFillsBoundsOpaquely(!translucent);
  499. // Create the compositor and attach the layer to it.
  500. ui::ContextFactory* context_factory =
  501. ViewsDelegate::GetInstance()->GetContextFactory();
  502. DCHECK(context_factory);
  503. compositor_ = std::make_unique<ui::RecyclableCompositorMac>(context_factory);
  504. compositor_->widget()->SetNSView(this);
  505. compositor_->compositor()->SetBackgroundColor(
  506. translucent ? SK_ColorTRANSPARENT : SK_ColorWHITE);
  507. compositor_->compositor()->SetRootLayer(layer());
  508. // The compositor is locked (prevented from producing frames) until the widget
  509. // is made visible unless the window was created in headless mode in which
  510. // case it will never become visible but we want its compositor to produce
  511. // frames for screenshooting and screencasting.
  512. UpdateCompositorProperties();
  513. layer()->SetVisible(is_visible_);
  514. if (is_visible_ || is_headless_mode_window_)
  515. compositor_->Unsuspend();
  516. // Register the CGWindowID (used to identify this window for video capture)
  517. // when it is received. Note that this is done at this moment (as opposed to
  518. // as a callback to CreateWindow) so that we can associate the CGWindowID with
  519. // the (now existing) compositor.
  520. auto lambda = [](NativeWidgetMacNSWindowHost* host, uint32_t cg_window_id) {
  521. if (!host->compositor_)
  522. return;
  523. host->scoped_cg_window_id_ =
  524. std::make_unique<remote_cocoa::ScopedCGWindowID>(
  525. cg_window_id, host->compositor_->compositor()->frame_sink_id());
  526. };
  527. GetNSWindowMojo()->InitCompositorView(
  528. base::BindOnce(lambda, base::Unretained(this)));
  529. }
  530. void NativeWidgetMacNSWindowHost::UpdateCompositorProperties() {
  531. if (!compositor_)
  532. return;
  533. layer()->SetBounds(gfx::Rect(content_bounds_in_screen_.size()));
  534. // Mac device scale factor is always an integer so the result here is an
  535. // integer pixel size.
  536. gfx::Size content_bounds_in_pixels =
  537. gfx::ToRoundedSize(gfx::ConvertSizeToPixels(
  538. content_bounds_in_screen_.size(), display_.device_scale_factor()));
  539. compositor_->UpdateSurface(content_bounds_in_pixels,
  540. display_.device_scale_factor(),
  541. display_.color_spaces());
  542. }
  543. void NativeWidgetMacNSWindowHost::DestroyCompositor() {
  544. if (layer()) {
  545. // LayerOwner supports a change in ownership, e.g., to animate a closing
  546. // window, but that won't work as expected for the root layer in
  547. // NativeWidgetNSWindowBridge.
  548. DCHECK_EQ(this, layer()->owner());
  549. layer()->CompleteAllAnimations();
  550. }
  551. DestroyLayer();
  552. if (!compositor_)
  553. return;
  554. compositor_->widget()->ResetNSView();
  555. compositor_->compositor()->SetRootLayer(nullptr);
  556. compositor_.reset();
  557. }
  558. bool NativeWidgetMacNSWindowHost::SetWindowTitle(const std::u16string& title) {
  559. if (window_title_ == title)
  560. return false;
  561. window_title_ = title;
  562. GetNSWindowMojo()->SetWindowTitle(window_title_);
  563. return true;
  564. }
  565. void NativeWidgetMacNSWindowHost::OnWidgetInitDone() {
  566. Widget* widget = native_widget_mac_->GetWidget();
  567. if (DialogDelegate* dialog = widget->widget_delegate()->AsDialogDelegate())
  568. dialog->AddObserver(this);
  569. }
  570. bool NativeWidgetMacNSWindowHost::RedispatchKeyEvent(NSEvent* event) {
  571. // If the target window is in-process, then redispatch the event directly,
  572. // and give an accurate return value.
  573. if (in_process_ns_window_bridge_)
  574. return in_process_ns_window_bridge_->RedispatchKeyEvent(event);
  575. // If the target window is out of process then always report the event as
  576. // handled (because it should never be handled in this process).
  577. GetNSWindowMojo()->RedispatchKeyEvent(ui::EventToData(event));
  578. return true;
  579. }
  580. gfx::Rect NativeWidgetMacNSWindowHost::GetContentBoundsInScreen() const {
  581. NSView* contentView =
  582. (NSView*)GetNativeWindowProperty(kImmersiveContentNSView);
  583. if (!contentView)
  584. return content_bounds_in_screen_;
  585. // In immersive fullscreen, the content view is hosted in another NSWindow.
  586. NSRect boundsInWindow = [contentView convertRect:contentView.bounds
  587. toView:nil];
  588. NSRect boundsInScreen =
  589. [contentView.window convertRectToScreen:boundsInWindow];
  590. return gfx::ScreenRectFromNSRect(boundsInScreen);
  591. }
  592. gfx::Rect NativeWidgetMacNSWindowHost::GetRestoredBounds() const {
  593. if (target_fullscreen_state_ || in_fullscreen_transition_)
  594. return window_bounds_before_fullscreen_;
  595. return window_bounds_in_screen_;
  596. }
  597. const std::vector<uint8_t>&
  598. NativeWidgetMacNSWindowHost::GetWindowStateRestorationData() const {
  599. return state_restoration_data_;
  600. }
  601. void NativeWidgetMacNSWindowHost::SetNativeWindowProperty(const char* name,
  602. void* value) {
  603. if (value)
  604. native_window_properties_[name] = value;
  605. else
  606. native_window_properties_.erase(name);
  607. }
  608. void* NativeWidgetMacNSWindowHost::GetNativeWindowProperty(
  609. const char* name) const {
  610. auto found = native_window_properties_.find(name);
  611. if (found == native_window_properties_.end())
  612. return nullptr;
  613. return found->second;
  614. }
  615. void NativeWidgetMacNSWindowHost::SetParent(
  616. NativeWidgetMacNSWindowHost* new_parent) {
  617. if (new_parent == parent_)
  618. return;
  619. if (parent_) {
  620. auto found =
  621. std::find(parent_->children_.begin(), parent_->children_.end(), this);
  622. DCHECK(found != parent_->children_.end());
  623. parent_->children_.erase(found);
  624. parent_ = nullptr;
  625. }
  626. // We can only re-parent to another Widget if that Widget is hosted in the
  627. // same process that we were already hosted by. If this is not the case, just
  628. // close the Widget.
  629. // https://crbug.com/957927
  630. remote_cocoa::ApplicationHost* new_application_host =
  631. new_parent ? new_parent->application_host() : application_host_.get();
  632. if (new_application_host != application_host_) {
  633. DLOG(ERROR) << "Cannot migrate views::NativeWidget to another process, "
  634. "closing it instead.";
  635. GetNSWindowMojo()->CloseWindow();
  636. return;
  637. }
  638. parent_ = new_parent;
  639. if (parent_) {
  640. parent_->children_.push_back(this);
  641. GetNSWindowMojo()->SetParent(parent_->bridged_native_widget_id());
  642. } else {
  643. GetNSWindowMojo()->SetParent(0);
  644. }
  645. }
  646. void NativeWidgetMacNSWindowHost::OnNativeViewHostAttach(const View* view,
  647. NSView* native_view) {
  648. DCHECK_EQ(0u, attached_native_view_host_views_.count(view));
  649. attached_native_view_host_views_[view] = native_view;
  650. native_widget_mac_->GetWidget()->ReorderNativeViews();
  651. }
  652. void NativeWidgetMacNSWindowHost::OnNativeViewHostDetach(const View* view) {
  653. auto it = attached_native_view_host_views_.find(view);
  654. DCHECK(it != attached_native_view_host_views_.end());
  655. attached_native_view_host_views_.erase(it);
  656. }
  657. void NativeWidgetMacNSWindowHost::ReorderChildViews() {
  658. Widget* widget = native_widget_mac_->GetWidget();
  659. if (!widget->GetRootView())
  660. return;
  661. // Get the ordering for the NSViews in |attached_native_view_host_views_|.
  662. std::vector<NSView*> attached_subviews;
  663. GetAttachedNativeViewHostViewsRecursive(widget->GetRootView(),
  664. &attached_subviews);
  665. // Convert to NSView ids that can go over mojo. If need be, create temporary
  666. // NSView ids.
  667. std::vector<uint64_t> attached_subview_ids;
  668. std::list<remote_cocoa::ScopedNSViewIdMapping> temp_ids;
  669. for (NSView* subview : attached_subviews) {
  670. uint64_t ns_view_id = remote_cocoa::GetIdFromNSView(subview);
  671. if (!ns_view_id) {
  672. // Subviews that do not already have an id will not work if the target is
  673. // in a different process.
  674. DCHECK(in_process_ns_window_bridge_);
  675. ns_view_id = remote_cocoa::GetNewNSViewId();
  676. temp_ids.emplace_back(ns_view_id, subview);
  677. }
  678. attached_subview_ids.push_back(ns_view_id);
  679. }
  680. GetNSWindowMojo()->SortSubviews(attached_subview_ids);
  681. }
  682. void NativeWidgetMacNSWindowHost::GetAttachedNativeViewHostViewsRecursive(
  683. View* view,
  684. std::vector<NSView*>* order) const {
  685. auto found = attached_native_view_host_views_.find(view);
  686. if (found != attached_native_view_host_views_.end())
  687. order->push_back(found->second);
  688. for (View* child : view->children())
  689. GetAttachedNativeViewHostViewsRecursive(child, order);
  690. }
  691. void NativeWidgetMacNSWindowHost::UpdateLocalWindowFrame(
  692. const gfx::Rect& frame) {
  693. if (!remote_ns_window_remote_)
  694. return;
  695. [in_process_ns_window_ setFrame:gfx::ScreenRectToNSRect(frame)
  696. display:NO
  697. animate:NO];
  698. }
  699. std::unique_ptr<NativeWidgetMacEventMonitor>
  700. NativeWidgetMacNSWindowHost::AddEventMonitor(
  701. NativeWidgetMacEventMonitor::Client* client) {
  702. // Enable the local event monitor if this is the first registered monitor.
  703. if (event_monitors_.empty())
  704. GetNSWindowMojo()->SetLocalEventMonitorEnabled(true);
  705. // Add the new monitor to `event_monitors_`.
  706. auto* monitor = new NativeWidgetMacEventMonitor(client);
  707. event_monitors_.push_back(monitor);
  708. // Set up `monitor`'s remove closure to remove it from `event_monitors_`.
  709. auto remove_lambda = [](base::WeakPtr<NativeWidgetMacNSWindowHost> weak_this,
  710. NativeWidgetMacEventMonitor* monitor) {
  711. if (!weak_this)
  712. return;
  713. auto found = std::find(weak_this->event_monitors_.begin(),
  714. weak_this->event_monitors_.end(), monitor);
  715. CHECK(found != weak_this->event_monitors_.end());
  716. weak_this->event_monitors_.erase(found);
  717. // If this was the last monitor to be removed, disable the local
  718. // event monitor.
  719. if (weak_this->event_monitors_.empty())
  720. weak_this->GetNSWindowMojo()->SetLocalEventMonitorEnabled(false);
  721. };
  722. monitor->remove_closure_runner_.ReplaceClosure(
  723. base::BindOnce(remove_lambda, weak_factory_.GetWeakPtr(), monitor));
  724. return base::WrapUnique<NativeWidgetMacEventMonitor>(monitor);
  725. }
  726. // static
  727. NSView* NativeWidgetMacNSWindowHost::GetGlobalCaptureView() {
  728. // TODO(ccameron): This will not work across process boundaries.
  729. return
  730. [remote_cocoa::CocoaMouseCapture::GetGlobalCaptureWindow() contentView];
  731. }
  732. void NativeWidgetMacNSWindowHost::AddRemoteWindowControlsOverlayView(
  733. remote_cocoa::mojom::WindowControlsOverlayNSViewType overlay_type) {
  734. GetNSWindowMojo()->CreateWindowControlsOverlayNSView(overlay_type);
  735. }
  736. void NativeWidgetMacNSWindowHost::UpdateRemoteWindowControlsOverlayView(
  737. const gfx::Rect& bounds,
  738. remote_cocoa::mojom::WindowControlsOverlayNSViewType overlay_type) {
  739. GetNSWindowMojo()->UpdateWindowControlsOverlayNSView(bounds, overlay_type);
  740. }
  741. void NativeWidgetMacNSWindowHost::RemoveRemoteWindowControlsOverlayView(
  742. remote_cocoa::mojom::WindowControlsOverlayNSViewType overlay_type) {
  743. GetNSWindowMojo()->RemoveWindowControlsOverlayNSView(overlay_type);
  744. }
  745. ////////////////////////////////////////////////////////////////////////////////
  746. // NativeWidgetMacNSWindowHost, remote_cocoa::BridgedNativeWidgetHostHelper:
  747. id NativeWidgetMacNSWindowHost::GetNativeViewAccessible() {
  748. return root_view_ ? root_view_->GetNativeViewAccessible() : nil;
  749. }
  750. void NativeWidgetMacNSWindowHost::DispatchKeyEvent(ui::KeyEvent* event) {
  751. std::ignore =
  752. root_view_->GetWidget()->GetInputMethod()->DispatchKeyEvent(event);
  753. }
  754. bool NativeWidgetMacNSWindowHost::DispatchKeyEventToMenuController(
  755. ui::KeyEvent* event) {
  756. MenuController* menu_controller = MenuController::GetActiveInstance();
  757. if (menu_controller && root_view_ &&
  758. menu_controller->owner() == root_view_->GetWidget()) {
  759. return menu_controller->OnWillDispatchKeyEvent(event) ==
  760. ui::POST_DISPATCH_NONE;
  761. }
  762. return false;
  763. }
  764. remote_cocoa::DragDropClient* NativeWidgetMacNSWindowHost::GetDragDropClient() {
  765. return drag_drop_client_.get();
  766. }
  767. ui::TextInputClient* NativeWidgetMacNSWindowHost::GetTextInputClient() {
  768. return text_input_host_->GetTextInputClient();
  769. }
  770. bool NativeWidgetMacNSWindowHost::MustPostTaskToRunModalSheetAnimation() const {
  771. return false;
  772. }
  773. ////////////////////////////////////////////////////////////////////////////////
  774. // NativeWidgetMacNSWindowHost, remote_cocoa::ApplicationHost::Observer:
  775. void NativeWidgetMacNSWindowHost::OnApplicationHostDestroying(
  776. remote_cocoa::ApplicationHost* host) {
  777. DCHECK_EQ(host, application_host_);
  778. application_host_->RemoveObserver(this);
  779. application_host_ = nullptr;
  780. // Because the process hosting this window has ended, close the window by
  781. // sending the window close messages that the bridge would have sent.
  782. OnWindowWillClose();
  783. // Explicitly propagate this message to all children (they are also observers,
  784. // but may not be destroyed before |this| is destroyed, which would violate
  785. // tear-down assumptions). This would have been done by the bridge, had it
  786. // shut down cleanly.
  787. while (!children_.empty())
  788. children_.front()->OnApplicationHostDestroying(host);
  789. OnWindowHasClosed();
  790. }
  791. ////////////////////////////////////////////////////////////////////////////////
  792. // NativeWidgetMacNSWindowHost,
  793. // remote_cocoa::mojom::NativeWidgetNSWindowHost:
  794. void NativeWidgetMacNSWindowHost::OnVisibilityChanged(bool window_visible) {
  795. is_visible_ = window_visible;
  796. if (compositor_) {
  797. layer()->SetVisible(window_visible);
  798. if (window_visible) {
  799. compositor_->Unsuspend();
  800. layer()->SchedulePaint(layer()->bounds());
  801. } else {
  802. compositor_->Suspend();
  803. }
  804. }
  805. native_widget_mac_->GetWidget()->OnNativeWidgetVisibilityChanged(
  806. window_visible);
  807. }
  808. void NativeWidgetMacNSWindowHost::OnWindowNativeThemeChanged() {
  809. ui::NativeTheme::GetInstanceForNativeUi()->NotifyOnNativeThemeUpdated();
  810. }
  811. void NativeWidgetMacNSWindowHost::OnScrollEvent(
  812. std::unique_ptr<ui::Event> event) {
  813. root_view_->GetWidget()->OnScrollEvent(event->AsScrollEvent());
  814. }
  815. void NativeWidgetMacNSWindowHost::OnMouseEvent(
  816. std::unique_ptr<ui::Event> event) {
  817. ui::MouseEvent* mouse_event = event->AsMouseEvent();
  818. if (scoped_cg_window_id_) {
  819. scoped_cg_window_id_->OnMouseMoved(mouse_event->location_f(),
  820. window_bounds_in_screen_.size());
  821. }
  822. root_view_->GetWidget()->OnMouseEvent(mouse_event);
  823. // Note that |this| may be destroyed by the above call to OnMouseEvent.
  824. // https://crbug.com/1193454
  825. }
  826. void NativeWidgetMacNSWindowHost::OnGestureEvent(
  827. std::unique_ptr<ui::Event> event) {
  828. root_view_->GetWidget()->OnGestureEvent(event->AsGestureEvent());
  829. }
  830. bool NativeWidgetMacNSWindowHost::DispatchKeyEventRemote(
  831. std::unique_ptr<ui::Event> event,
  832. bool* event_handled) {
  833. DispatchKeyEvent(event->AsKeyEvent());
  834. *event_handled = event->handled();
  835. return true;
  836. }
  837. bool NativeWidgetMacNSWindowHost::DispatchKeyEventToMenuControllerRemote(
  838. std::unique_ptr<ui::Event> event,
  839. bool* event_swallowed,
  840. bool* event_handled) {
  841. *event_swallowed = DispatchKeyEventToMenuController(event->AsKeyEvent());
  842. *event_handled = event->handled();
  843. return true;
  844. }
  845. bool NativeWidgetMacNSWindowHost::DispatchMonitorEvent(
  846. std::unique_ptr<ui::Event> event,
  847. bool* event_handled) {
  848. // The calls to NativeWidgetMacEventMonitorOnEvent can add or remove monitors,
  849. // so take a snapshot of `event_monitors_` before making any calls.
  850. auto event_monitors_snapshot = event_monitors_;
  851. // The calls to NativeWidgetMacEventMonitorOnEvent can delete `this`. Use
  852. // `weak_this` to detect that.
  853. auto weak_this = weak_factory_.GetWeakPtr();
  854. *event_handled = false;
  855. for (auto* event_monitor : event_monitors_snapshot) {
  856. // Ensure `event_monitor` was not removed from `event_monitors_` by a
  857. // previous call to NativeWidgetMacEventMonitorOnEvent.
  858. if (!base::Contains(event_monitors_, event_monitor))
  859. continue;
  860. event_monitor->client_->NativeWidgetMacEventMonitorOnEvent(event.get(),
  861. event_handled);
  862. if (!weak_this)
  863. return true;
  864. }
  865. return true;
  866. }
  867. bool NativeWidgetMacNSWindowHost::GetHasMenuController(
  868. bool* has_menu_controller) {
  869. MenuController* menu_controller = MenuController::GetActiveInstance();
  870. *has_menu_controller = menu_controller && root_view_ &&
  871. menu_controller->owner() == root_view_->GetWidget() &&
  872. // The editable combobox menu does not swallow keys.
  873. !menu_controller->IsEditableCombobox();
  874. return true;
  875. }
  876. void NativeWidgetMacNSWindowHost::OnViewSizeChanged(const gfx::Size& new_size) {
  877. root_view_->SetSize(new_size);
  878. }
  879. bool NativeWidgetMacNSWindowHost::GetSheetOffsetY(int32_t* offset_y) {
  880. *offset_y = native_widget_mac_->SheetOffsetY();
  881. return true;
  882. }
  883. void NativeWidgetMacNSWindowHost::SetKeyboardAccessible(bool enabled) {
  884. views::FocusManager* focus_manager =
  885. root_view_->GetWidget()->GetFocusManager();
  886. if (focus_manager)
  887. focus_manager->SetKeyboardAccessible(enabled);
  888. }
  889. void NativeWidgetMacNSWindowHost::OnIsFirstResponderChanged(
  890. bool is_first_responder) {
  891. accessibility_focus_overrider_.SetViewIsFirstResponder(is_first_responder);
  892. FocusManager* focus_manager = root_view_->GetWidget()->GetFocusManager();
  893. if (focus_manager->IsSettingFocusedView()) {
  894. // This first responder change is not initiated by the os,
  895. // but by the focus change within the browser (e.g. tab switch),
  896. // so skip setting the focus.
  897. return;
  898. }
  899. if (is_first_responder) {
  900. focus_manager->RestoreFocusedView();
  901. } else {
  902. // Do not call ClearNativeFocus because that will re-make the
  903. // BridgedNativeWidget first responder (and this is called to indicate that
  904. // it is no longer first responder).
  905. focus_manager->StoreFocusedView(false /* clear_native_focus */);
  906. }
  907. }
  908. void NativeWidgetMacNSWindowHost::OnMouseCaptureActiveChanged(bool is_active) {
  909. DCHECK_NE(is_mouse_capture_active_, is_active);
  910. is_mouse_capture_active_ = is_active;
  911. if (!is_mouse_capture_active_)
  912. native_widget_mac_->GetWidget()->OnMouseCaptureLost();
  913. }
  914. bool NativeWidgetMacNSWindowHost::GetIsDraggableBackgroundAt(
  915. const gfx::Point& location_in_content,
  916. bool* is_draggable_background) {
  917. int component =
  918. root_view_->GetWidget()->GetNonClientComponent(location_in_content);
  919. *is_draggable_background = component == HTCAPTION;
  920. return true;
  921. }
  922. bool NativeWidgetMacNSWindowHost::GetTooltipTextAt(
  923. const gfx::Point& location_in_content,
  924. std::u16string* new_tooltip_text) {
  925. views::View* view =
  926. root_view_->GetTooltipHandlerForPoint(location_in_content);
  927. if (view) {
  928. gfx::Point view_point = location_in_content;
  929. views::View::ConvertPointToScreen(root_view_, &view_point);
  930. views::View::ConvertPointFromScreen(view, &view_point);
  931. *new_tooltip_text = view->GetTooltipText(view_point);
  932. }
  933. return true;
  934. }
  935. void NativeWidgetMacNSWindowHost::GetWordAt(
  936. const gfx::Point& location_in_content,
  937. bool* found_word,
  938. gfx::DecoratedText* decorated_word,
  939. gfx::Point* baseline_point) {
  940. *found_word = false;
  941. views::View* target =
  942. root_view_->GetEventHandlerForPoint(location_in_content);
  943. if (!target)
  944. return;
  945. views::WordLookupClient* word_lookup_client = target->GetWordLookupClient();
  946. if (!word_lookup_client)
  947. return;
  948. gfx::Point location_in_target = location_in_content;
  949. views::View::ConvertPointToTarget(root_view_, target, &location_in_target);
  950. if (!word_lookup_client->GetWordLookupDataAtPoint(
  951. location_in_target, decorated_word, baseline_point)) {
  952. return;
  953. }
  954. // Convert |baselinePoint| to the coordinate system of |root_view_|.
  955. views::View::ConvertPointToTarget(target, root_view_, baseline_point);
  956. *found_word = true;
  957. }
  958. bool NativeWidgetMacNSWindowHost::GetWidgetIsModal(bool* widget_is_modal) {
  959. *widget_is_modal = native_widget_mac_->GetWidget()->IsModal();
  960. return true;
  961. }
  962. bool NativeWidgetMacNSWindowHost::GetIsFocusedViewTextual(bool* is_textual) {
  963. views::FocusManager* focus_manager =
  964. root_view_ ? root_view_->GetWidget()->GetFocusManager() : nullptr;
  965. *is_textual = focus_manager && focus_manager->GetFocusedView() &&
  966. focus_manager->GetFocusedView()->GetClassName() ==
  967. views::Label::kViewClassName;
  968. return true;
  969. }
  970. void NativeWidgetMacNSWindowHost::OnWindowGeometryChanged(
  971. const gfx::Rect& new_window_bounds_in_screen,
  972. const gfx::Rect& new_content_bounds_in_screen) {
  973. UpdateLocalWindowFrame(new_window_bounds_in_screen);
  974. bool window_has_moved =
  975. new_window_bounds_in_screen.origin() != window_bounds_in_screen_.origin();
  976. bool content_has_resized =
  977. new_content_bounds_in_screen.size() != content_bounds_in_screen_.size();
  978. window_bounds_in_screen_ = new_window_bounds_in_screen;
  979. content_bounds_in_screen_ = new_content_bounds_in_screen;
  980. // When a window grows vertically, the AppKit origin changes, but as far as
  981. // tookit-views is concerned, the window hasn't moved. Suppress these.
  982. if (window_has_moved)
  983. native_widget_mac_->GetWidget()->OnNativeWidgetMove();
  984. // Note we can't use new_window_bounds_in_screen.size(), since it includes the
  985. // titlebar for the purposes of detecting a window move.
  986. if (content_has_resized) {
  987. native_widget_mac_->GetWidget()->OnNativeWidgetSizeChanged(
  988. content_bounds_in_screen_.size());
  989. // Update the compositor surface and layer size.
  990. UpdateCompositorProperties();
  991. }
  992. }
  993. void NativeWidgetMacNSWindowHost::OnWindowFullscreenTransitionStart(
  994. bool target_fullscreen_state) {
  995. target_fullscreen_state_ = target_fullscreen_state;
  996. in_fullscreen_transition_ = true;
  997. // If going into fullscreen, store an answer for GetRestoredBounds().
  998. if (target_fullscreen_state)
  999. window_bounds_before_fullscreen_ = window_bounds_in_screen_;
  1000. // Notify that fullscreen state is changing.
  1001. native_widget_mac_->OnWindowFullscreenTransitionStart();
  1002. }
  1003. void NativeWidgetMacNSWindowHost::OnWindowFullscreenTransitionComplete(
  1004. bool actual_fullscreen_state) {
  1005. in_fullscreen_transition_ = false;
  1006. // Notify that fullscreen state has changed.
  1007. native_widget_mac_->OnWindowFullscreenTransitionComplete();
  1008. // Ensure constraints are re-applied when completing a transition.
  1009. native_widget_mac_->OnSizeConstraintsChanged();
  1010. ui::NSWindowFullscreenNotificationWaiter::NotifyFullscreenTransitionComplete(
  1011. native_widget_mac_->GetNativeWindow(), actual_fullscreen_state);
  1012. }
  1013. void NativeWidgetMacNSWindowHost::OnWindowMiniaturizedChanged(
  1014. bool miniaturized) {
  1015. is_miniaturized_ = miniaturized;
  1016. if (native_widget_mac_)
  1017. native_widget_mac_->GetWidget()->OnNativeWidgetWindowShowStateChanged();
  1018. }
  1019. void NativeWidgetMacNSWindowHost::OnWindowDisplayChanged(
  1020. const display::Display& new_display) {
  1021. bool display_id_changed = display_.id() != new_display.id();
  1022. display_ = new_display;
  1023. if (compositor_) {
  1024. // Mac device scale factor is always an integer so the result here is an
  1025. // integer pixel size.
  1026. gfx::Size content_bounds_in_pixels =
  1027. gfx::ToRoundedSize(gfx::ConvertSizeToPixels(
  1028. content_bounds_in_screen_.size(), display_.device_scale_factor()));
  1029. compositor_->UpdateSurface(content_bounds_in_pixels,
  1030. display_.device_scale_factor(),
  1031. display_.color_spaces());
  1032. }
  1033. if (display_id_changed) {
  1034. display_link_ = ui::DisplayLinkMac::GetForDisplay(
  1035. base::checked_cast<CGDirectDisplayID>(display_.id()));
  1036. if (!display_link_) {
  1037. // Note that on some headless systems, the display link will fail to be
  1038. // created, so this should not be a fatal error.
  1039. LOG(ERROR) << "Failed to create display link.";
  1040. }
  1041. }
  1042. }
  1043. void NativeWidgetMacNSWindowHost::OnWindowWillClose() {
  1044. Widget* widget = native_widget_mac_->GetWidget();
  1045. if (DialogDelegate* dialog = widget->widget_delegate()->AsDialogDelegate())
  1046. dialog->RemoveObserver(this);
  1047. native_widget_mac_->WindowDestroying();
  1048. // Remove |this| from the parent's list of children.
  1049. SetParent(nullptr);
  1050. }
  1051. void NativeWidgetMacNSWindowHost::OnWindowHasClosed() {
  1052. // OnWindowHasClosed will be called only after all child windows have had
  1053. // OnWindowWillClose called on them.
  1054. DCHECK(children_.empty());
  1055. native_widget_mac_->WindowDestroyed();
  1056. }
  1057. void NativeWidgetMacNSWindowHost::OnWindowKeyStatusChanged(
  1058. bool is_key,
  1059. bool is_content_first_responder,
  1060. bool full_keyboard_access_enabled) {
  1061. // Explicitly set the keyboard accessibility state on regaining key
  1062. // window status.
  1063. if (is_key && is_content_first_responder)
  1064. SetKeyboardAccessible(full_keyboard_access_enabled);
  1065. accessibility_focus_overrider_.SetWindowIsKey(is_key);
  1066. is_window_key_ = is_key;
  1067. native_widget_mac_->OnWindowKeyStatusChanged(is_key,
  1068. is_content_first_responder);
  1069. }
  1070. void NativeWidgetMacNSWindowHost::OnWindowStateRestorationDataChanged(
  1071. const std::vector<uint8_t>& data) {
  1072. state_restoration_data_ = data;
  1073. native_widget_mac_->GetWidget()->OnNativeWidgetWorkspaceChanged();
  1074. }
  1075. void NativeWidgetMacNSWindowHost::DoDialogButtonAction(
  1076. ui::DialogButton button) {
  1077. views::DialogDelegate* dialog =
  1078. root_view_->GetWidget()->widget_delegate()->AsDialogDelegate();
  1079. DCHECK(dialog);
  1080. if (button == ui::DIALOG_BUTTON_OK) {
  1081. dialog->AcceptDialog();
  1082. } else {
  1083. DCHECK_EQ(button, ui::DIALOG_BUTTON_CANCEL);
  1084. dialog->CancelDialog();
  1085. }
  1086. }
  1087. bool NativeWidgetMacNSWindowHost::GetDialogButtonInfo(
  1088. ui::DialogButton button,
  1089. bool* button_exists,
  1090. std::u16string* button_label,
  1091. bool* is_button_enabled,
  1092. bool* is_button_default) {
  1093. *button_exists = false;
  1094. views::DialogDelegate* dialog =
  1095. root_view_->GetWidget()->widget_delegate()->AsDialogDelegate();
  1096. if (!dialog || !(dialog->GetDialogButtons() & button))
  1097. return true;
  1098. *button_exists = true;
  1099. *button_label = dialog->GetDialogButtonLabel(button);
  1100. *is_button_enabled = dialog->IsDialogButtonEnabled(button);
  1101. *is_button_default = button == dialog->GetDefaultDialogButton();
  1102. return true;
  1103. }
  1104. bool NativeWidgetMacNSWindowHost::GetDoDialogButtonsExist(bool* buttons_exist) {
  1105. views::DialogDelegate* dialog =
  1106. root_view_->GetWidget()->widget_delegate()->AsDialogDelegate();
  1107. *buttons_exist = dialog && dialog->GetDialogButtons();
  1108. return true;
  1109. }
  1110. bool NativeWidgetMacNSWindowHost::GetShouldShowWindowTitle(
  1111. bool* should_show_window_title) {
  1112. *should_show_window_title =
  1113. root_view_
  1114. ? root_view_->GetWidget()->widget_delegate()->ShouldShowWindowTitle()
  1115. : true;
  1116. return true;
  1117. }
  1118. bool NativeWidgetMacNSWindowHost::GetCanWindowBecomeKey(
  1119. bool* can_window_become_key) {
  1120. *can_window_become_key =
  1121. root_view_ ? root_view_->GetWidget()->CanActivate() : false;
  1122. return true;
  1123. }
  1124. bool NativeWidgetMacNSWindowHost::GetAlwaysRenderWindowAsKey(
  1125. bool* always_render_as_key) {
  1126. *always_render_as_key =
  1127. root_view_ ? root_view_->GetWidget()->ShouldPaintAsActive() : false;
  1128. return true;
  1129. }
  1130. bool NativeWidgetMacNSWindowHost::OnWindowCloseRequested(
  1131. bool* can_window_close) {
  1132. *can_window_close = true;
  1133. views::NonClientView* non_client_view =
  1134. root_view_ ? root_view_->GetWidget()->non_client_view() : nullptr;
  1135. if (non_client_view)
  1136. *can_window_close = non_client_view->OnWindowCloseRequested() ==
  1137. CloseRequestResult::kCanClose;
  1138. return true;
  1139. }
  1140. bool NativeWidgetMacNSWindowHost::GetWindowFrameTitlebarHeight(
  1141. bool* override_titlebar_height,
  1142. float* titlebar_height) {
  1143. native_widget_mac_->GetWindowFrameTitlebarHeight(override_titlebar_height,
  1144. titlebar_height);
  1145. return true;
  1146. }
  1147. void NativeWidgetMacNSWindowHost::OnFocusWindowToolbar() {
  1148. native_widget_mac_->OnFocusWindowToolbar();
  1149. }
  1150. void NativeWidgetMacNSWindowHost::SetRemoteAccessibilityTokens(
  1151. const std::vector<uint8_t>& window_token,
  1152. const std::vector<uint8_t>& view_token) {
  1153. remote_window_accessible_ =
  1154. ui::RemoteAccessibility::GetRemoteElementFromToken(window_token);
  1155. remote_view_accessible_ =
  1156. ui::RemoteAccessibility::GetRemoteElementFromToken(view_token);
  1157. [remote_view_accessible_ setWindowUIElement:remote_window_accessible_.get()];
  1158. [remote_view_accessible_
  1159. setTopLevelUIElement:remote_window_accessible_.get()];
  1160. }
  1161. bool NativeWidgetMacNSWindowHost::GetRootViewAccessibilityToken(
  1162. int64_t* pid,
  1163. std::vector<uint8_t>* token) {
  1164. *pid = getpid();
  1165. id element_id = GetNativeViewAccessible();
  1166. *token = ui::RemoteAccessibility::GetTokenForLocalElement(element_id);
  1167. return true;
  1168. }
  1169. bool NativeWidgetMacNSWindowHost::ValidateUserInterfaceItem(
  1170. int32_t command,
  1171. remote_cocoa::mojom::ValidateUserInterfaceItemResultPtr* out_result) {
  1172. *out_result = remote_cocoa::mojom::ValidateUserInterfaceItemResult::New();
  1173. native_widget_mac_->ValidateUserInterfaceItem(command, out_result->get());
  1174. return true;
  1175. }
  1176. bool NativeWidgetMacNSWindowHost::ExecuteCommand(
  1177. int32_t command,
  1178. WindowOpenDisposition window_open_disposition,
  1179. bool is_before_first_responder,
  1180. bool* was_executed) {
  1181. *was_executed = native_widget_mac_->ExecuteCommand(
  1182. command, window_open_disposition, is_before_first_responder);
  1183. return true;
  1184. }
  1185. bool NativeWidgetMacNSWindowHost::HandleAccelerator(
  1186. const ui::Accelerator& accelerator,
  1187. bool require_priority_handler,
  1188. bool* was_handled) {
  1189. *was_handled = false;
  1190. if (Widget* widget = native_widget_mac_->GetWidget()) {
  1191. if (require_priority_handler &&
  1192. !widget->GetFocusManager()->HasPriorityHandler(accelerator)) {
  1193. return true;
  1194. }
  1195. *was_handled = widget->GetFocusManager()->ProcessAccelerator(accelerator);
  1196. }
  1197. return true;
  1198. }
  1199. ////////////////////////////////////////////////////////////////////////////////
  1200. // NativeWidgetMacNSWindowHost,
  1201. // remote_cocoa::mojom::NativeWidgetNSWindowHost synchronous callbacks:
  1202. void NativeWidgetMacNSWindowHost::GetSheetOffsetY(
  1203. GetSheetOffsetYCallback callback) {
  1204. int32_t offset_y = 0;
  1205. GetSheetOffsetY(&offset_y);
  1206. std::move(callback).Run(offset_y);
  1207. }
  1208. void NativeWidgetMacNSWindowHost::DispatchKeyEventRemote(
  1209. std::unique_ptr<ui::Event> event,
  1210. DispatchKeyEventRemoteCallback callback) {
  1211. bool event_handled = false;
  1212. DispatchKeyEventRemote(std::move(event), &event_handled);
  1213. std::move(callback).Run(event_handled);
  1214. }
  1215. void NativeWidgetMacNSWindowHost::DispatchKeyEventToMenuControllerRemote(
  1216. std::unique_ptr<ui::Event> event,
  1217. DispatchKeyEventToMenuControllerRemoteCallback callback) {
  1218. ui::KeyEvent* key_event = event->AsKeyEvent();
  1219. bool event_swallowed = DispatchKeyEventToMenuController(key_event);
  1220. std::move(callback).Run(event_swallowed, key_event->handled());
  1221. }
  1222. void NativeWidgetMacNSWindowHost::DispatchMonitorEvent(
  1223. std::unique_ptr<ui::Event> event,
  1224. DispatchMonitorEventCallback callback) {
  1225. bool event_handled = false;
  1226. DispatchMonitorEvent(std::move(event), &event_handled);
  1227. std::move(callback).Run(event_handled);
  1228. }
  1229. void NativeWidgetMacNSWindowHost::GetHasMenuController(
  1230. GetHasMenuControllerCallback callback) {
  1231. bool has_menu_controller = false;
  1232. GetHasMenuController(&has_menu_controller);
  1233. std::move(callback).Run(has_menu_controller);
  1234. }
  1235. void NativeWidgetMacNSWindowHost::GetIsDraggableBackgroundAt(
  1236. const gfx::Point& location_in_content,
  1237. GetIsDraggableBackgroundAtCallback callback) {
  1238. bool is_draggable_background = false;
  1239. GetIsDraggableBackgroundAt(location_in_content, &is_draggable_background);
  1240. std::move(callback).Run(is_draggable_background);
  1241. }
  1242. void NativeWidgetMacNSWindowHost::GetTooltipTextAt(
  1243. const gfx::Point& location_in_content,
  1244. GetTooltipTextAtCallback callback) {
  1245. std::u16string new_tooltip_text;
  1246. GetTooltipTextAt(location_in_content, &new_tooltip_text);
  1247. std::move(callback).Run(new_tooltip_text);
  1248. }
  1249. void NativeWidgetMacNSWindowHost::GetIsFocusedViewTextual(
  1250. GetIsFocusedViewTextualCallback callback) {
  1251. bool is_textual = false;
  1252. GetIsFocusedViewTextual(&is_textual);
  1253. std::move(callback).Run(is_textual);
  1254. }
  1255. void NativeWidgetMacNSWindowHost::GetWidgetIsModal(
  1256. GetWidgetIsModalCallback callback) {
  1257. bool widget_is_modal = false;
  1258. GetWidgetIsModal(&widget_is_modal);
  1259. std::move(callback).Run(widget_is_modal);
  1260. }
  1261. void NativeWidgetMacNSWindowHost::GetDialogButtonInfo(
  1262. ui::DialogButton button,
  1263. GetDialogButtonInfoCallback callback) {
  1264. bool exists = false;
  1265. std::u16string label;
  1266. bool is_enabled = false;
  1267. bool is_default = false;
  1268. GetDialogButtonInfo(button, &exists, &label, &is_enabled, &is_default);
  1269. std::move(callback).Run(exists, label, is_enabled, is_default);
  1270. }
  1271. void NativeWidgetMacNSWindowHost::GetDoDialogButtonsExist(
  1272. GetDoDialogButtonsExistCallback callback) {
  1273. bool buttons_exist = false;
  1274. GetDoDialogButtonsExist(&buttons_exist);
  1275. std::move(callback).Run(buttons_exist);
  1276. }
  1277. void NativeWidgetMacNSWindowHost::GetShouldShowWindowTitle(
  1278. GetShouldShowWindowTitleCallback callback) {
  1279. bool should_show_window_title = false;
  1280. GetShouldShowWindowTitle(&should_show_window_title);
  1281. std::move(callback).Run(should_show_window_title);
  1282. }
  1283. void NativeWidgetMacNSWindowHost::GetCanWindowBecomeKey(
  1284. GetCanWindowBecomeKeyCallback callback) {
  1285. bool can_window_become_key = false;
  1286. GetCanWindowBecomeKey(&can_window_become_key);
  1287. std::move(callback).Run(can_window_become_key);
  1288. }
  1289. void NativeWidgetMacNSWindowHost::GetAlwaysRenderWindowAsKey(
  1290. GetAlwaysRenderWindowAsKeyCallback callback) {
  1291. bool always_render_as_key = false;
  1292. GetAlwaysRenderWindowAsKey(&always_render_as_key);
  1293. std::move(callback).Run(always_render_as_key);
  1294. }
  1295. void NativeWidgetMacNSWindowHost::OnWindowCloseRequested(
  1296. OnWindowCloseRequestedCallback callback) {
  1297. bool can_window_close = false;
  1298. OnWindowCloseRequested(&can_window_close);
  1299. std::move(callback).Run(can_window_close);
  1300. }
  1301. void NativeWidgetMacNSWindowHost::GetWindowFrameTitlebarHeight(
  1302. GetWindowFrameTitlebarHeightCallback callback) {
  1303. bool override_titlebar_height = false;
  1304. float titlebar_height = 0;
  1305. GetWindowFrameTitlebarHeight(&override_titlebar_height, &titlebar_height);
  1306. std::move(callback).Run(override_titlebar_height, titlebar_height);
  1307. }
  1308. void NativeWidgetMacNSWindowHost::GetRootViewAccessibilityToken(
  1309. GetRootViewAccessibilityTokenCallback callback) {
  1310. std::vector<uint8_t> token;
  1311. int64_t pid;
  1312. GetRootViewAccessibilityToken(&pid, &token);
  1313. std::move(callback).Run(pid, token);
  1314. }
  1315. void NativeWidgetMacNSWindowHost::ValidateUserInterfaceItem(
  1316. int32_t command,
  1317. ValidateUserInterfaceItemCallback callback) {
  1318. remote_cocoa::mojom::ValidateUserInterfaceItemResultPtr result;
  1319. ValidateUserInterfaceItem(command, &result);
  1320. std::move(callback).Run(std::move(result));
  1321. }
  1322. void NativeWidgetMacNSWindowHost::ExecuteCommand(
  1323. int32_t command,
  1324. WindowOpenDisposition window_open_disposition,
  1325. bool is_before_first_responder,
  1326. ExecuteCommandCallback callback) {
  1327. bool was_executed = false;
  1328. ExecuteCommand(command, window_open_disposition, is_before_first_responder,
  1329. &was_executed);
  1330. std::move(callback).Run(was_executed);
  1331. }
  1332. void NativeWidgetMacNSWindowHost::HandleAccelerator(
  1333. const ui::Accelerator& accelerator,
  1334. bool require_priority_handler,
  1335. HandleAcceleratorCallback callback) {
  1336. bool was_handled = false;
  1337. HandleAccelerator(accelerator, require_priority_handler, &was_handled);
  1338. std::move(callback).Run(was_handled);
  1339. }
  1340. ////////////////////////////////////////////////////////////////////////////////
  1341. // NativeWidgetMacNSWindowHost, DialogObserver:
  1342. void NativeWidgetMacNSWindowHost::OnDialogChanged() {
  1343. // Note it's only necessary to clear the TouchBar. If the OS needs it again,
  1344. // a new one will be created.
  1345. GetNSWindowMojo()->ClearTouchBar();
  1346. }
  1347. ////////////////////////////////////////////////////////////////////////////////
  1348. // NativeWidgetMacNSWindowHost, AccessibilityFocusOverrider::Client:
  1349. id NativeWidgetMacNSWindowHost::GetAccessibilityFocusedUIElement() {
  1350. return [GetNativeViewAccessible() accessibilityFocusedUIElement];
  1351. }
  1352. ////////////////////////////////////////////////////////////////////////////////
  1353. // NativeWidgetMacNSWindowHost, LayerDelegate:
  1354. void NativeWidgetMacNSWindowHost::OnPaintLayer(
  1355. const ui::PaintContext& context) {
  1356. native_widget_mac_->GetWidget()->OnNativeWidgetPaint(context);
  1357. }
  1358. void NativeWidgetMacNSWindowHost::OnDeviceScaleFactorChanged(
  1359. float old_device_scale_factor,
  1360. float new_device_scale_factor) {
  1361. native_widget_mac_->GetWidget()->DeviceScaleFactorChanged(
  1362. old_device_scale_factor, new_device_scale_factor);
  1363. }
  1364. void NativeWidgetMacNSWindowHost::UpdateVisualState() {
  1365. native_widget_mac_->GetWidget()->LayoutRootViewIfNecessary();
  1366. }
  1367. ////////////////////////////////////////////////////////////////////////////////
  1368. // NativeWidgetMacNSWindowHost, AcceleratedWidgetMac:
  1369. void NativeWidgetMacNSWindowHost::AcceleratedWidgetCALayerParamsUpdated() {
  1370. if (const auto* ca_layer_params = compositor_->widget()->GetCALayerParams())
  1371. GetNSWindowMojo()->SetCALayerParams(*ca_layer_params);
  1372. // Take this opportunity to update the VSync parameters, if needed.
  1373. if (display_link_) {
  1374. base::TimeTicks timebase;
  1375. base::TimeDelta interval;
  1376. bool register_for_vsync_update = display_link_->IsVSyncPotentiallyStale();
  1377. if (display_link_->GetVSyncParameters(&timebase, &interval)) {
  1378. compositor_->compositor()->SetDisplayVSyncParameters(timebase, interval);
  1379. } else {
  1380. register_for_vsync_update = true;
  1381. }
  1382. if (register_for_vsync_update) {
  1383. if (!weak_factory_for_vsync_update_.HasWeakPtrs()) {
  1384. display_link_->RegisterCallbackForNextVSyncUpdate(base::BindOnce(
  1385. &NativeWidgetMacNSWindowHost::OnVSyncParametersUpdated,
  1386. weak_factory_for_vsync_update_.GetWeakPtr()));
  1387. }
  1388. } else {
  1389. weak_factory_for_vsync_update_.InvalidateWeakPtrs();
  1390. }
  1391. }
  1392. }
  1393. void NativeWidgetMacNSWindowHost::OnVSyncParametersUpdated(
  1394. base::TimeTicks timebase,
  1395. base::TimeDelta interval) {
  1396. compositor_->compositor()->SetDisplayVSyncParameters(timebase, interval);
  1397. }
  1398. } // namespace views