blob: 39c39c1585e71e276cbbd073c81eac2b3f0ed655 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/views/cocoa/native_widget_mac_ns_window_host.h"
#include <utility>
#include "base/base64.h"
#include "base/mac/foundation_util.h"
#include "base/strings/sys_string_conversions.h"
#include "components/remote_cocoa/app_shim/mouse_capture.h"
#include "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h"
#include "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h"
#include "components/remote_cocoa/browser/ns_view_ids.h"
#include "components/remote_cocoa/browser/window.h"
#include "mojo/public/cpp/bindings/self_owned_associated_receiver.h"
#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
#include "ui/base/cocoa/animation_utils.h"
#include "ui/base/cocoa/remote_accessibility_api.h"
#include "ui/base/cocoa/remote_layer_api.h"
#include "ui/base/hit_test.h"
#include "ui/base/ime/input_method.h"
#include "ui/compositor/recyclable_compositor_mac.h"
#include "ui/display/screen.h"
#include "ui/events/cocoa/cocoa_event_utils.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/mac/coordinate_conversion.h"
#include "ui/native_theme/native_theme_mac.h"
#include "ui/views/cocoa/text_input_host.h"
#include "ui/views/cocoa/tooltip_manager_mac.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/menu/menu_config.h"
#include "ui/views/controls/menu/menu_controller.h"
#include "ui/views/views_delegate.h"
#include "ui/views/widget/native_widget_mac.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/window/dialog_delegate.h"
#include "ui/views/word_lookup_client.h"
using remote_cocoa::mojom::NativeWidgetNSWindowInitParams;
using remote_cocoa::mojom::WindowVisibilityState;
namespace views {
namespace {
// Dummy implementation of the BridgedNativeWidgetHost interface. This structure
// exists to work around a bug wherein synchronous mojo calls to an associated
// interface can hang if the interface request is unbound. This structure is
// bound to the real host's interface, and then deletes itself only once the
// underlying connection closes.
// https://crbug.com/915572
class BridgedNativeWidgetHostDummy
: public remote_cocoa::mojom::NativeWidgetNSWindowHost {
public:
BridgedNativeWidgetHostDummy() = default;
~BridgedNativeWidgetHostDummy() override = default;
private:
void OnVisibilityChanged(bool visible) override {}
void OnWindowNativeThemeChanged() override {}
void OnViewSizeChanged(const gfx::Size& new_size) override {}
void SetKeyboardAccessible(bool enabled) override {}
void OnIsFirstResponderChanged(bool is_first_responder) override {}
void OnMouseCaptureActiveChanged(bool capture_is_active) override {}
void OnScrollEvent(std::unique_ptr<ui::Event> event) override {}
void OnMouseEvent(std::unique_ptr<ui::Event> event) override {}
void OnGestureEvent(std::unique_ptr<ui::Event> event) override {}
void OnWindowGeometryChanged(
const gfx::Rect& window_bounds_in_screen_dips,
const gfx::Rect& content_bounds_in_screen_dips) override {}
void OnWindowFullscreenTransitionStart(
bool target_fullscreen_state) override {}
void OnWindowFullscreenTransitionComplete(bool is_fullscreen) override {}
void OnWindowMiniaturizedChanged(bool miniaturized) override {}
void OnWindowDisplayChanged(const display::Display& display) override {}
void OnWindowWillClose() override {}
void OnWindowHasClosed() override {}
void OnWindowKeyStatusChanged(bool is_key,
bool is_content_first_responder,
bool full_keyboard_access_enabled) override {}
void OnWindowStateRestorationDataChanged(
const std::vector<uint8_t>& data) override {}
void DoDialogButtonAction(ui::DialogButton button) override {}
void OnFocusWindowToolbar() override {}
void SetRemoteAccessibilityTokens(
const std::vector<uint8_t>& window_token,
const std::vector<uint8_t>& view_token) override {}
void GetSheetOffsetY(GetSheetOffsetYCallback callback) override {
float offset_y = 0;
std::move(callback).Run(offset_y);
}
void DispatchKeyEventRemote(
std::unique_ptr<ui::Event> event,
DispatchKeyEventRemoteCallback callback) override {
bool event_handled = false;
std::move(callback).Run(event_handled);
}
void DispatchKeyEventToMenuControllerRemote(
std::unique_ptr<ui::Event> event,
DispatchKeyEventToMenuControllerRemoteCallback callback) override {
ui::KeyEvent* key_event = event->AsKeyEvent();
bool event_swallowed = false;
std::move(callback).Run(event_swallowed, key_event->handled());
}
void GetHasMenuController(GetHasMenuControllerCallback callback) override {
bool has_menu_controller = false;
std::move(callback).Run(has_menu_controller);
}
void GetIsDraggableBackgroundAt(
const gfx::Point& location_in_content,
GetIsDraggableBackgroundAtCallback callback) override {
bool is_draggable_background = false;
std::move(callback).Run(is_draggable_background);
}
void GetTooltipTextAt(const gfx::Point& location_in_content,
GetTooltipTextAtCallback callback) override {
base::string16 new_tooltip_text;
std::move(callback).Run(new_tooltip_text);
}
void GetIsFocusedViewTextual(
GetIsFocusedViewTextualCallback callback) override {
bool is_textual = false;
std::move(callback).Run(is_textual);
}
void GetWidgetIsModal(GetWidgetIsModalCallback callback) override {
bool widget_is_modal = false;
std::move(callback).Run(widget_is_modal);
}
void GetDialogButtonInfo(ui::DialogButton button,
GetDialogButtonInfoCallback callback) override {
bool exists = false;
base::string16 label;
bool is_enabled = false;
bool is_default = false;
std::move(callback).Run(exists, label, is_enabled, is_default);
}
void GetDoDialogButtonsExist(
GetDoDialogButtonsExistCallback callback) override {
bool buttons_exist = false;
std::move(callback).Run(buttons_exist);
}
void GetShouldShowWindowTitle(
GetShouldShowWindowTitleCallback callback) override {
bool should_show_window_title = false;
std::move(callback).Run(should_show_window_title);
}
void GetCanWindowBecomeKey(GetCanWindowBecomeKeyCallback callback) override {
bool can_window_become_key = false;
std::move(callback).Run(can_window_become_key);
}
void GetAlwaysRenderWindowAsKey(
GetAlwaysRenderWindowAsKeyCallback callback) override {
bool always_render_as_key = false;
std::move(callback).Run(always_render_as_key);
}
void OnWindowCloseRequested(
OnWindowCloseRequestedCallback callback) override {
bool can_window_close = false;
std::move(callback).Run(can_window_close);
}
void GetWindowFrameTitlebarHeight(
GetWindowFrameTitlebarHeightCallback callback) override {
bool override_titlebar_height = false;
float titlebar_height = 0;
std::move(callback).Run(override_titlebar_height, titlebar_height);
}
void GetRootViewAccessibilityToken(
GetRootViewAccessibilityTokenCallback callback) override {
std::vector<uint8_t> token;
int64_t pid = 0;
std::move(callback).Run(pid, token);
}
void ValidateUserInterfaceItem(
int32_t command,
ValidateUserInterfaceItemCallback callback) override {
remote_cocoa::mojom::ValidateUserInterfaceItemResultPtr result;
std::move(callback).Run(std::move(result));
}
void ExecuteCommand(int32_t command,
WindowOpenDisposition window_open_disposition,
bool is_before_first_responder,
ExecuteCommandCallback callback) override {
bool was_executed = false;
std::move(callback).Run(was_executed);
}
void HandleAccelerator(const ui::Accelerator& accelerator,
bool require_priority_handler,
HandleAcceleratorCallback callback) override {
bool was_handled = false;
std::move(callback).Run(was_handled);
}
};
std::map<uint64_t, NativeWidgetMacNSWindowHost*>& GetIdToWidgetHostImplMap() {
static base::NoDestructor<std::map<uint64_t, NativeWidgetMacNSWindowHost*>>
id_map;
return *id_map;
}
uint64_t g_last_bridged_native_widget_id = 0;
} // namespace
// static
NativeWidgetMacNSWindowHost* NativeWidgetMacNSWindowHost::GetFromNativeWindow(
gfx::NativeWindow native_window) {
NSWindow* window = native_window.GetNativeNSWindow();
if (NativeWidgetMacNSWindow* widget_window =
base::mac::ObjCCast<NativeWidgetMacNSWindow>(window)) {
return GetFromId([widget_window bridgedNativeWidgetId]);
}
return nullptr; // Not created by NativeWidgetMac.
}
// static
NativeWidgetMacNSWindowHost* NativeWidgetMacNSWindowHost::GetFromNativeView(
gfx::NativeView native_view) {
return GetFromNativeWindow([native_view.GetNativeNSView() window]);
}
// static
NativeWidgetMacNSWindowHost* NativeWidgetMacNSWindowHost::GetFromId(
uint64_t bridged_native_widget_id) {
auto found = GetIdToWidgetHostImplMap().find(bridged_native_widget_id);
if (found == GetIdToWidgetHostImplMap().end())
return nullptr;
return found->second;
}
NativeWidgetMacNSWindowHost::NativeWidgetMacNSWindowHost(NativeWidgetMac* owner)
: widget_id_(++g_last_bridged_native_widget_id),
native_widget_mac_(owner),
root_view_id_(remote_cocoa::GetNewNSViewId()),
accessibility_focus_overrider_(this),
text_input_host_(new TextInputHost(this)) {
DCHECK(GetIdToWidgetHostImplMap().find(widget_id_) ==
GetIdToWidgetHostImplMap().end());
GetIdToWidgetHostImplMap().emplace(widget_id_, this);
DCHECK(owner);
}
NativeWidgetMacNSWindowHost::~NativeWidgetMacNSWindowHost() {
DCHECK(children_.empty());
native_window_mapping_.reset();
if (application_host_) {
remote_ns_window_remote_.reset();
application_host_->RemoveObserver(this);
application_host_ = nullptr;
}
// Workaround for https://crbug.com/915572
if (remote_ns_window_host_receiver_.is_bound()) {
auto receiver = remote_ns_window_host_receiver_.Unbind();
if (receiver.is_valid()) {
mojo::MakeSelfOwnedAssociatedReceiver(
std::make_unique<BridgedNativeWidgetHostDummy>(),
std::move(receiver));
}
}
// Ensure that |this| cannot be reached by its id while it is being destroyed.
auto found = GetIdToWidgetHostImplMap().find(widget_id_);
DCHECK(found != GetIdToWidgetHostImplMap().end());
DCHECK_EQ(found->second, this);
GetIdToWidgetHostImplMap().erase(found);
// Destroy the bridge first to prevent any calls back into this during
// destruction.
// TODO(ccameron): When all communication from |bridge_| to this goes through
// the BridgedNativeWidgetHost, this can be replaced with closing that pipe.
in_process_ns_window_bridge_.reset();
DestroyCompositor();
}
NativeWidgetMacNSWindow* NativeWidgetMacNSWindowHost::GetInProcessNSWindow()
const {
return in_process_ns_window_.get();
}
gfx::NativeViewAccessible
NativeWidgetMacNSWindowHost::GetNativeViewAccessibleForNSView() const {
if (in_process_ns_window_bridge_)
return in_process_ns_window_bridge_->ns_view();
return remote_view_accessible_.get();
}
gfx::NativeViewAccessible
NativeWidgetMacNSWindowHost::GetNativeViewAccessibleForNSWindow() const {
if (in_process_ns_window_bridge_)
return in_process_ns_window_bridge_->ns_window();
return remote_window_accessible_.get();
}
remote_cocoa::mojom::NativeWidgetNSWindow*
NativeWidgetMacNSWindowHost::GetNSWindowMojo() const {
if (remote_ns_window_remote_)
return remote_ns_window_remote_.get();
if (in_process_ns_window_bridge_)
return in_process_ns_window_bridge_.get();
return nullptr;
}
void NativeWidgetMacNSWindowHost::CreateInProcessNSWindowBridge(
base::scoped_nsobject<NativeWidgetMacNSWindow> window) {
in_process_ns_window_ = window;
in_process_ns_window_bridge_ =
std::make_unique<remote_cocoa::NativeWidgetNSWindowBridge>(
widget_id_, this, this, text_input_host_.get());
in_process_ns_window_bridge_->SetWindow(window);
}
void NativeWidgetMacNSWindowHost::CreateRemoteNSWindow(
remote_cocoa::ApplicationHost* application_host,
remote_cocoa::mojom::CreateWindowParamsPtr window_create_params) {
accessibility_focus_overrider_.SetAppIsRemote(true);
application_host_ = application_host;
application_host_->AddObserver(this);
// Create a local invisible window that will be used as the gfx::NativeWindow
// handle to track this window in this process.
{
auto in_process_ns_window_create_params =
remote_cocoa::mojom::CreateWindowParams::New();
in_process_ns_window_create_params->style_mask = NSBorderlessWindowMask;
in_process_ns_window_ =
remote_cocoa::NativeWidgetNSWindowBridge::CreateNSWindow(
in_process_ns_window_create_params.get());
[in_process_ns_window_ setBridgedNativeWidgetId:widget_id_];
[in_process_ns_window_ setAlphaValue:0.0];
in_process_view_id_mapping_ =
std::make_unique<remote_cocoa::ScopedNSViewIdMapping>(
root_view_id_, [in_process_ns_window_ contentView]);
}
// Initialize |remote_ns_window_remote_| to point to a bridge created by
// |factory|.
mojo::PendingAssociatedRemote<remote_cocoa::mojom::TextInputHost>
text_input_host_remote;
text_input_host_->BindReceiver(
text_input_host_remote.InitWithNewEndpointAndPassReceiver());
application_host_->GetApplication()->CreateNativeWidgetNSWindow(
widget_id_, remote_ns_window_remote_.BindNewEndpointAndPassReceiver(),
remote_ns_window_host_receiver_.BindNewEndpointAndPassRemote(
ui::WindowResizeHelperMac::Get()->task_runner()),
std::move(text_input_host_remote));
// Create the window in its process, and attach it to its parent window.
GetNSWindowMojo()->CreateWindow(std::move(window_create_params));
}
void NativeWidgetMacNSWindowHost::InitWindow(
const Widget::InitParams& params,
const gfx::Rect& initial_bounds_in_screen) {
native_window_mapping_ =
std::make_unique<remote_cocoa::ScopedNativeWindowMapping>(
gfx::NativeWindow(in_process_ns_window_.get()), application_host_,
in_process_ns_window_bridge_.get(), GetNSWindowMojo());
Widget* widget = native_widget_mac_->GetWidget();
// Tooltip Widgets shouldn't have their own tooltip manager, but tooltips are
// native on Mac, so nothing should ever want one in Widget form.
DCHECK_NE(params.type, Widget::InitParams::TYPE_TOOLTIP);
widget_type_ = params.type;
tooltip_manager_ = std::make_unique<TooltipManagerMac>(GetNSWindowMojo());
if (params.workspace.length()) {
std::string restoration_data;
if (base::Base64Decode(params.workspace, &restoration_data)) {
state_restoration_data_ = std::vector<uint8_t>(restoration_data.begin(),
restoration_data.end());
} else {
DLOG(ERROR) << "Failed to decode a window's state restoration data.";
}
}
// Initialize the window.
{
auto window_params = NativeWidgetNSWindowInitParams::New();
window_params->modal_type = widget->widget_delegate()->GetModalType();
window_params->is_translucent =
params.opacity == Widget::InitParams::WindowOpacity::kTranslucent;
// OSX likes to put shadows on most things. However, frameless windows (with
// styleMask = NSBorderlessWindowMask) default to no shadow. So change that.
// ShadowType::kDrop is used for Menus, which get the same shadow style on
// Mac.
switch (params.shadow_type) {
case Widget::InitParams::ShadowType::kNone:
window_params->has_window_server_shadow = false;
break;
case Widget::InitParams::ShadowType::kDefault:
// Controls should get views shadows instead of native shadows.
window_params->has_window_server_shadow =
params.type != Widget::InitParams::TYPE_CONTROL;
break;
case Widget::InitParams::ShadowType::kDrop:
window_params->has_window_server_shadow = true;
break;
} // No default case, to pick up new types.
// Include "regular" windows without the standard frame in the window cycle.
// These use NSBorderlessWindowMask so do not get it by default.
window_params->force_into_collection_cycle =
widget_type_ == Widget::InitParams::TYPE_WINDOW &&
params.remove_standard_frame;
window_params->state_restoration_data = state_restoration_data_;
GetNSWindowMojo()->InitWindow(std::move(window_params));
}
// Set a meaningful initial bounds. Note that except for frameless widgets
// with no WidgetDelegate, the bounds will be set again by Widget after
// initializing the non-client view. In the former case, if bounds were not
// set at all, the creator of the Widget is expected to call SetBounds()
// before calling Widget::Show() to avoid a kWindowSizeDeterminedLater-sized
// (i.e. 1x1) window appearing.
UpdateLocalWindowFrame(initial_bounds_in_screen);
GetNSWindowMojo()->SetInitialBounds(initial_bounds_in_screen,
widget->GetMinimumSize());
// TODO(ccameron): Correctly set these based |in_process_ns_window_|.
window_bounds_in_screen_ = initial_bounds_in_screen;
content_bounds_in_screen_ = initial_bounds_in_screen;
// Widgets for UI controls (usually layered above web contents) start visible.
if (widget_type_ == Widget::InitParams::TYPE_CONTROL)
GetNSWindowMojo()->SetVisibilityState(WindowVisibilityState::kShowInactive);
}
void NativeWidgetMacNSWindowHost::CloseWindowNow() {
bool is_out_of_process = !in_process_ns_window_bridge_;
// Note that CloseWindowNow may delete |this| for in-process windows.
if (GetNSWindowMojo())
GetNSWindowMojo()->CloseWindowNow();
// If it is out-of-process, then simulate the calls that would have been
// during window closure.
if (is_out_of_process) {
OnWindowWillClose();
while (!children_.empty())
children_.front()->CloseWindowNow();
OnWindowHasClosed();
}
}
void NativeWidgetMacNSWindowHost::SetBoundsInScreen(const gfx::Rect& bounds) {
UpdateLocalWindowFrame(bounds);
GetNSWindowMojo()->SetBounds(
bounds, native_widget_mac_->GetWidget()->GetMinimumSize());
if (remote_ns_window_remote_) {
gfx::Rect window_in_screen =
gfx::ScreenRectFromNSRect([in_process_ns_window_ frame]);
gfx::Rect content_in_screen =
gfx::ScreenRectFromNSRect([in_process_ns_window_
contentRectForFrameRect:[in_process_ns_window_ frame]]);
OnWindowGeometryChanged(window_in_screen, content_in_screen);
}
}
void NativeWidgetMacNSWindowHost::SetFullscreen(bool fullscreen) {
// Note that when the NSWindow begins a fullscreen transition, the value of
// |target_fullscreen_state_| updates via OnWindowFullscreenTransitionStart.
// The update here is necessary for the case where we are currently in
// transition (and therefore OnWindowFullscreenTransitionStart will not be
// called until the current transition completes).
target_fullscreen_state_ = fullscreen;
GetNSWindowMojo()->SetFullscreen(target_fullscreen_state_);
}
void NativeWidgetMacNSWindowHost::SetRootView(views::View* root_view) {
root_view_ = root_view;
if (root_view_) {
// TODO(ccameron): Drag-drop functionality does not yet run over mojo.
if (in_process_ns_window_bridge_) {
drag_drop_client_ = std::make_unique<DragDropClientMac>(
in_process_ns_window_bridge_.get(), root_view_);
}
} else {
drag_drop_client_.reset();
}
}
void NativeWidgetMacNSWindowHost::CreateCompositor(
const Widget::InitParams& params) {
DCHECK(!compositor_);
DCHECK(!layer());
DCHECK(ViewsDelegate::GetInstance());
// "Infer" must be handled by ViewsDelegate::OnBeforeWidgetInit().
DCHECK_NE(Widget::InitParams::WindowOpacity::kInferred, params.opacity);
bool translucent =
params.opacity == Widget::InitParams::WindowOpacity::kTranslucent;
// Create the layer.
SetLayer(std::make_unique<ui::Layer>(params.layer_type));
layer()->set_delegate(this);
layer()->SetFillsBoundsOpaquely(!translucent);
// Create the compositor and attach the layer to it.
ui::ContextFactory* context_factory =
ViewsDelegate::GetInstance()->GetContextFactory();
DCHECK(context_factory);
compositor_ = ui::RecyclableCompositorMacFactory::Get()->CreateCompositor(
context_factory);
compositor_->widget()->SetNSView(this);
compositor_->compositor()->SetBackgroundColor(
translucent ? SK_ColorTRANSPARENT : SK_ColorWHITE);
compositor_->compositor()->SetRootLayer(layer());
// The compositor is locked (prevented from producing frames) until the widget
// is made visible.
UpdateCompositorProperties();
layer()->SetVisible(is_visible_);
if (is_visible_)
compositor_->Unsuspend();
GetNSWindowMojo()->InitCompositorView();
}
void NativeWidgetMacNSWindowHost::UpdateCompositorProperties() {
if (!compositor_)
return;
gfx::Size surface_size_in_dip = content_bounds_in_screen_.size();
layer()->SetBounds(gfx::Rect(surface_size_in_dip));
compositor_->UpdateSurface(
ConvertSizeToPixel(display_.device_scale_factor(), surface_size_in_dip),
display_.device_scale_factor(), display_.color_spaces());
}
void NativeWidgetMacNSWindowHost::DestroyCompositor() {
if (layer()) {
// LayerOwner supports a change in ownership, e.g., to animate a closing
// window, but that won't work as expected for the root layer in
// NativeWidgetNSWindowBridge.
DCHECK_EQ(this, layer()->owner());
layer()->CompleteAllAnimations();
}
DestroyLayer();
if (!compositor_)
return;
compositor_->widget()->ResetNSView();
compositor_->compositor()->SetRootLayer(nullptr);
ui::RecyclableCompositorMacFactory::Get()->RecycleCompositor(
std::move(compositor_));
}
bool NativeWidgetMacNSWindowHost::SetWindowTitle(const base::string16& title) {
if (window_title_ == title)
return false;
window_title_ = title;
GetNSWindowMojo()->SetWindowTitle(window_title_);
return true;
}
void NativeWidgetMacNSWindowHost::OnWidgetInitDone() {
Widget* widget = native_widget_mac_->GetWidget();
if (DialogDelegate* dialog = widget->widget_delegate()->AsDialogDelegate())
dialog->AddObserver(this);
}
bool NativeWidgetMacNSWindowHost::RedispatchKeyEvent(NSEvent* event) {
// If the target window is in-process, then redispatch the event directly,
// and give an accurate return value.
if (in_process_ns_window_bridge_)
return in_process_ns_window_bridge_->RedispatchKeyEvent(event);
// If the target window is out of process then always report the event as
// handled (because it should never be handled in this process).
GetNSWindowMojo()->RedispatchKeyEvent(ui::EventToData(event));
return true;
}
gfx::Rect NativeWidgetMacNSWindowHost::GetRestoredBounds() const {
if (target_fullscreen_state_ || in_fullscreen_transition_)
return window_bounds_before_fullscreen_;
return window_bounds_in_screen_;
}
const std::vector<uint8_t>&
NativeWidgetMacNSWindowHost::GetWindowStateRestorationData() const {
return state_restoration_data_;
}
void NativeWidgetMacNSWindowHost::SetNativeWindowProperty(const char* name,
void* value) {
if (value)
native_window_properties_[name] = value;
else
native_window_properties_.erase(name);
}
void* NativeWidgetMacNSWindowHost::GetNativeWindowProperty(
const char* name) const {
auto found = native_window_properties_.find(name);
if (found == native_window_properties_.end())
return nullptr;
return found->second;
}
void NativeWidgetMacNSWindowHost::SetParent(
NativeWidgetMacNSWindowHost* new_parent) {
if (new_parent == parent_)
return;
if (parent_) {
auto found =
std::find(parent_->children_.begin(), parent_->children_.end(), this);
DCHECK(found != parent_->children_.end());
parent_->children_.erase(found);
parent_ = nullptr;
}
// We can only re-parent to another Widget if that Widget is hosted in the
// same process that we were already hosted by. If this is not the case, just
// close the Widget.
// https://crbug.com/957927
remote_cocoa::ApplicationHost* new_application_host =
new_parent ? new_parent->application_host() : application_host_;
if (new_application_host != application_host_) {
DLOG(ERROR) << "Cannot migrate views::NativeWidget to another process, "
"closing it instead.";
GetNSWindowMojo()->CloseWindow();
return;
}
parent_ = new_parent;
if (parent_) {
parent_->children_.push_back(this);
GetNSWindowMojo()->SetParent(parent_->bridged_native_widget_id());
} else {
GetNSWindowMojo()->SetParent(0);
}
}
void NativeWidgetMacNSWindowHost::OnNativeViewHostAttach(const View* view,
NSView* native_view) {
DCHECK_EQ(0u, attached_native_view_host_views_.count(view));
attached_native_view_host_views_[view] = native_view;
native_widget_mac_->GetWidget()->ReorderNativeViews();
}
void NativeWidgetMacNSWindowHost::OnNativeViewHostDetach(const View* view) {
auto it = attached_native_view_host_views_.find(view);
DCHECK(it != attached_native_view_host_views_.end());
attached_native_view_host_views_.erase(it);
}
void NativeWidgetMacNSWindowHost::ReorderChildViews() {
Widget* widget = native_widget_mac_->GetWidget();
if (!widget->GetRootView())
return;
// Get the ordering for the NSViews in |attached_native_view_host_views_|.
std::vector<NSView*> attached_subviews;
GetAttachedNativeViewHostViewsRecursive(widget->GetRootView(),
&attached_subviews);
// Convert to NSView ids that can go over mojo. If need be, create temporary
// NSView ids.
std::vector<uint64_t> attached_subview_ids;
std::list<remote_cocoa::ScopedNSViewIdMapping> temp_ids;
for (NSView* subview : attached_subviews) {
uint64_t ns_view_id = remote_cocoa::GetIdFromNSView(subview);
if (!ns_view_id) {
// Subviews that do not already have an id will not work if the target is
// in a different process.
DCHECK(in_process_ns_window_bridge_);
ns_view_id = remote_cocoa::GetNewNSViewId();
temp_ids.emplace_back(ns_view_id, subview);
}
attached_subview_ids.push_back(ns_view_id);
}
GetNSWindowMojo()->SortSubviews(attached_subview_ids);
}
void NativeWidgetMacNSWindowHost::GetAttachedNativeViewHostViewsRecursive(
View* view,
std::vector<NSView*>* order) const {
auto found = attached_native_view_host_views_.find(view);
if (found != attached_native_view_host_views_.end())
order->push_back(found->second);
for (View* child : view->children())
GetAttachedNativeViewHostViewsRecursive(child, order);
}
void NativeWidgetMacNSWindowHost::UpdateLocalWindowFrame(
const gfx::Rect& frame) {
if (!remote_ns_window_remote_)
return;
[in_process_ns_window_ setFrame:gfx::ScreenRectToNSRect(frame)
display:NO
animate:NO];
}
// static
NSView* NativeWidgetMacNSWindowHost::GetGlobalCaptureView() {
// TODO(ccameron): This will not work across process boundaries.
return
[remote_cocoa::CocoaMouseCapture::GetGlobalCaptureWindow() contentView];
}
////////////////////////////////////////////////////////////////////////////////
// NativeWidgetMacNSWindowHost, remote_cocoa::BridgedNativeWidgetHostHelper:
id NativeWidgetMacNSWindowHost::GetNativeViewAccessible() {
return root_view_ ? root_view_->GetNativeViewAccessible() : nil;
}
void NativeWidgetMacNSWindowHost::DispatchKeyEvent(ui::KeyEvent* event) {
ignore_result(
root_view_->GetWidget()->GetInputMethod()->DispatchKeyEvent(event));
}
bool NativeWidgetMacNSWindowHost::DispatchKeyEventToMenuController(
ui::KeyEvent* event) {
MenuController* menu_controller = MenuController::GetActiveInstance();
if (menu_controller && root_view_ &&
menu_controller->owner() == root_view_->GetWidget()) {
return menu_controller->OnWillDispatchKeyEvent(event) ==
ui::POST_DISPATCH_NONE;
}
return false;
}
remote_cocoa::DragDropClient* NativeWidgetMacNSWindowHost::GetDragDropClient() {
return drag_drop_client_.get();
}
ui::TextInputClient* NativeWidgetMacNSWindowHost::GetTextInputClient() {
return text_input_host_->GetTextInputClient();
}
////////////////////////////////////////////////////////////////////////////////
// NativeWidgetMacNSWindowHost, remote_cocoa::ApplicationHost::Observer:
void NativeWidgetMacNSWindowHost::OnApplicationHostDestroying(
remote_cocoa::ApplicationHost* host) {
DCHECK_EQ(host, application_host_);
application_host_->RemoveObserver(this);
application_host_ = nullptr;
// Because the process hosting this window has ended, close the window by
// sending the window close messages that the bridge would have sent.
OnWindowWillClose();
// Explicitly propagate this message to all children (they are also observers,
// but may not be destroyed before |this| is destroyed, which would violate
// tear-down assumptions). This would have been done by the bridge, had it
// shut down cleanly.
while (!children_.empty())
children_.front()->OnApplicationHostDestroying(host);
OnWindowHasClosed();
}
////////////////////////////////////////////////////////////////////////////////
// NativeWidgetMacNSWindowHost,
// remote_cocoa::mojom::NativeWidgetNSWindowHost:
void NativeWidgetMacNSWindowHost::OnVisibilityChanged(bool window_visible) {
is_visible_ = window_visible;
if (compositor_) {
layer()->SetVisible(window_visible);
if (window_visible) {
compositor_->Unsuspend();
layer()->SchedulePaint(layer()->bounds());
} else {
compositor_->Suspend();
}
}
native_widget_mac_->GetWidget()->OnNativeWidgetVisibilityChanged(
window_visible);
}
void NativeWidgetMacNSWindowHost::OnWindowNativeThemeChanged() {
ui::NativeTheme::GetInstanceForNativeUi()->NotifyObservers();
}
void NativeWidgetMacNSWindowHost::OnScrollEvent(
std::unique_ptr<ui::Event> event) {
root_view_->GetWidget()->OnScrollEvent(event->AsScrollEvent());
}
void NativeWidgetMacNSWindowHost::OnMouseEvent(
std::unique_ptr<ui::Event> event) {
root_view_->GetWidget()->OnMouseEvent(event->AsMouseEvent());
}
void NativeWidgetMacNSWindowHost::OnGestureEvent(
std::unique_ptr<ui::Event> event) {
root_view_->GetWidget()->OnGestureEvent(event->AsGestureEvent());
}
bool NativeWidgetMacNSWindowHost::DispatchKeyEventRemote(
std::unique_ptr<ui::Event> event,
bool* event_handled) {
DispatchKeyEvent(event->AsKeyEvent());
*event_handled = event->handled();
return true;
}
bool NativeWidgetMacNSWindowHost::DispatchKeyEventToMenuControllerRemote(
std::unique_ptr<ui::Event> event,
bool* event_swallowed,
bool* event_handled) {
*event_swallowed = DispatchKeyEventToMenuController(event->AsKeyEvent());
*event_handled = event->handled();
return true;
}
bool NativeWidgetMacNSWindowHost::GetHasMenuController(
bool* has_menu_controller) {
MenuController* menu_controller = MenuController::GetActiveInstance();
*has_menu_controller = menu_controller && root_view_ &&
menu_controller->owner() == root_view_->GetWidget() &&
// The editable combobox menu does not swallow keys.
!menu_controller->IsEditableCombobox();
return true;
}
void NativeWidgetMacNSWindowHost::OnViewSizeChanged(const gfx::Size& new_size) {
root_view_->SetSize(new_size);
}
bool NativeWidgetMacNSWindowHost::GetSheetOffsetY(int32_t* offset_y) {
*offset_y = native_widget_mac_->SheetOffsetY();
return true;
}
void NativeWidgetMacNSWindowHost::SetKeyboardAccessible(bool enabled) {
views::FocusManager* focus_manager =
root_view_->GetWidget()->GetFocusManager();
if (focus_manager)
focus_manager->SetKeyboardAccessible(enabled);
}
void NativeWidgetMacNSWindowHost::OnIsFirstResponderChanged(
bool is_first_responder) {
accessibility_focus_overrider_.SetViewIsFirstResponder(is_first_responder);
if (is_first_responder) {
root_view_->GetWidget()->GetFocusManager()->RestoreFocusedView();
} else {
// Do not call ClearNativeFocus because that will re-make the
// BridgedNativeWidget first responder (and this is called to indicate that
// it is no longer first responder).
root_view_->GetWidget()->GetFocusManager()->StoreFocusedView(
false /* clear_native_focus */);
}
}
void NativeWidgetMacNSWindowHost::OnMouseCaptureActiveChanged(bool is_active) {
DCHECK_NE(is_mouse_capture_active_, is_active);
is_mouse_capture_active_ = is_active;
if (!is_mouse_capture_active_)
native_widget_mac_->GetWidget()->OnMouseCaptureLost();
}
bool NativeWidgetMacNSWindowHost::GetIsDraggableBackgroundAt(
const gfx::Point& location_in_content,
bool* is_draggable_background) {
int component =
root_view_->GetWidget()->GetNonClientComponent(location_in_content);
*is_draggable_background = component == HTCAPTION;
return true;
}
bool NativeWidgetMacNSWindowHost::GetTooltipTextAt(
const gfx::Point& location_in_content,
base::string16* new_tooltip_text) {
views::View* view =
root_view_->GetTooltipHandlerForPoint(location_in_content);
if (view) {
gfx::Point view_point = location_in_content;
views::View::ConvertPointToScreen(root_view_, &view_point);
views::View::ConvertPointFromScreen(view, &view_point);
*new_tooltip_text = view->GetTooltipText(view_point);
}
return true;
}
void NativeWidgetMacNSWindowHost::GetWordAt(
const gfx::Point& location_in_content,
bool* found_word,
gfx::DecoratedText* decorated_word,
gfx::Point* baseline_point) {
*found_word = false;
views::View* target =
root_view_->GetEventHandlerForPoint(location_in_content);
if (!target)
return;
views::WordLookupClient* word_lookup_client = target->GetWordLookupClient();
if (!word_lookup_client)
return;
gfx::Point location_in_target = location_in_content;
views::View::ConvertPointToTarget(root_view_, target, &location_in_target);
if (!word_lookup_client->GetWordLookupDataAtPoint(
location_in_target, decorated_word, baseline_point)) {
return;
}
// Convert |baselinePoint| to the coordinate system of |root_view_|.
views::View::ConvertPointToTarget(target, root_view_, baseline_point);
*found_word = true;
}
bool NativeWidgetMacNSWindowHost::GetWidgetIsModal(bool* widget_is_modal) {
*widget_is_modal = native_widget_mac_->GetWidget()->IsModal();
return true;
}
bool NativeWidgetMacNSWindowHost::GetIsFocusedViewTextual(bool* is_textual) {
views::FocusManager* focus_manager =
root_view_ ? root_view_->GetWidget()->GetFocusManager() : nullptr;
*is_textual = focus_manager && focus_manager->GetFocusedView() &&
focus_manager->GetFocusedView()->GetClassName() ==
views::Label::kViewClassName;
return true;
}
void NativeWidgetMacNSWindowHost::OnWindowGeometryChanged(
const gfx::Rect& new_window_bounds_in_screen,
const gfx::Rect& new_content_bounds_in_screen) {
UpdateLocalWindowFrame(new_window_bounds_in_screen);
bool window_has_moved =
new_window_bounds_in_screen.origin() != window_bounds_in_screen_.origin();
bool content_has_resized =
new_content_bounds_in_screen.size() != content_bounds_in_screen_.size();
window_bounds_in_screen_ = new_window_bounds_in_screen;
content_bounds_in_screen_ = new_content_bounds_in_screen;
// When a window grows vertically, the AppKit origin changes, but as far as
// tookit-views is concerned, the window hasn't moved. Suppress these.
if (window_has_moved)
native_widget_mac_->GetWidget()->OnNativeWidgetMove();
// Note we can't use new_window_bounds_in_screen.size(), since it includes the
// titlebar for the purposes of detecting a window move.
if (content_has_resized) {
native_widget_mac_->GetWidget()->OnNativeWidgetSizeChanged(
content_bounds_in_screen_.size());
// Update the compositor surface and layer size.
UpdateCompositorProperties();
}
}
void NativeWidgetMacNSWindowHost::OnWindowFullscreenTransitionStart(
bool target_fullscreen_state) {
target_fullscreen_state_ = target_fullscreen_state;
in_fullscreen_transition_ = true;
// If going into fullscreen, store an answer for GetRestoredBounds().
if (target_fullscreen_state)
window_bounds_before_fullscreen_ = window_bounds_in_screen_;
// Notify that fullscreen state changed.
native_widget_mac_->OnWindowFullscreenStateChange();
}
void NativeWidgetMacNSWindowHost::OnWindowFullscreenTransitionComplete(
bool actual_fullscreen_state) {
in_fullscreen_transition_ = false;
// Ensure constraints are re-applied when completing a transition.
native_widget_mac_->OnSizeConstraintsChanged();
}
void NativeWidgetMacNSWindowHost::OnWindowMiniaturizedChanged(
bool miniaturized) {
is_miniaturized_ = miniaturized;
if (native_widget_mac_)
native_widget_mac_->GetWidget()->OnNativeWidgetWindowShowStateChanged();
}
void NativeWidgetMacNSWindowHost::OnWindowDisplayChanged(
const display::Display& new_display) {
bool display_id_changed = display_.id() != new_display.id();
display_ = new_display;
if (compositor_) {
compositor_->UpdateSurface(
ConvertSizeToPixel(display_.device_scale_factor(),
content_bounds_in_screen_.size()),
display_.device_scale_factor(), display_.color_spaces());
}
if (display_id_changed) {
display_link_ = ui::DisplayLinkMac::GetForDisplay(display_.id());
if (!display_link_) {
// Note that on some headless systems, the display link will fail to be
// created, so this should not be a fatal error.
LOG(ERROR) << "Failed to create display link.";
}
}
}
void NativeWidgetMacNSWindowHost::OnWindowWillClose() {
Widget* widget = native_widget_mac_->GetWidget();
if (DialogDelegate* dialog = widget->widget_delegate()->AsDialogDelegate())
dialog->RemoveObserver(this);
native_widget_mac_->WindowDestroying();
// Remove |this| from the parent's list of children.
SetParent(nullptr);
}
void NativeWidgetMacNSWindowHost::OnWindowHasClosed() {
// OnWindowHasClosed will be called only after all child windows have had
// OnWindowWillClose called on them.
DCHECK(children_.empty());
native_widget_mac_->WindowDestroyed();
}
void NativeWidgetMacNSWindowHost::OnWindowKeyStatusChanged(
bool is_key,
bool is_content_first_responder,
bool full_keyboard_access_enabled) {
// Explicitly set the keyboard accessibility state on regaining key
// window status.
if (is_key && is_content_first_responder)
SetKeyboardAccessible(full_keyboard_access_enabled);
accessibility_focus_overrider_.SetWindowIsKey(is_key);
is_window_key_ = is_key;
native_widget_mac_->OnWindowKeyStatusChanged(is_key,
is_content_first_responder);
}
void NativeWidgetMacNSWindowHost::OnWindowStateRestorationDataChanged(
const std::vector<uint8_t>& data) {
state_restoration_data_ = data;
native_widget_mac_->GetWidget()->OnNativeWidgetWorkspaceChanged();
}
void NativeWidgetMacNSWindowHost::DoDialogButtonAction(
ui::DialogButton button) {
views::DialogDelegate* dialog =
root_view_->GetWidget()->widget_delegate()->AsDialogDelegate();
DCHECK(dialog);
if (button == ui::DIALOG_BUTTON_OK) {
dialog->AcceptDialog();
} else {
DCHECK_EQ(button, ui::DIALOG_BUTTON_CANCEL);
dialog->CancelDialog();
}
}
bool NativeWidgetMacNSWindowHost::GetDialogButtonInfo(
ui::DialogButton button,
bool* button_exists,
base::string16* button_label,
bool* is_button_enabled,
bool* is_button_default) {
*button_exists = false;
views::DialogDelegate* dialog =
root_view_->GetWidget()->widget_delegate()->AsDialogDelegate();
if (!dialog || !(dialog->GetDialogButtons() & button))
return true;
*button_exists = true;
*button_label = dialog->GetDialogButtonLabel(button);
*is_button_enabled = dialog->IsDialogButtonEnabled(button);
*is_button_default = button == dialog->GetDefaultDialogButton();
return true;
}
bool NativeWidgetMacNSWindowHost::GetDoDialogButtonsExist(bool* buttons_exist) {
views::DialogDelegate* dialog =
root_view_->GetWidget()->widget_delegate()->AsDialogDelegate();
*buttons_exist = dialog && dialog->GetDialogButtons();
return true;
}
bool NativeWidgetMacNSWindowHost::GetShouldShowWindowTitle(
bool* should_show_window_title) {
*should_show_window_title =
root_view_
? root_view_->GetWidget()->widget_delegate()->ShouldShowWindowTitle()
: true;
return true;
}
bool NativeWidgetMacNSWindowHost::GetCanWindowBecomeKey(
bool* can_window_become_key) {
*can_window_become_key =
root_view_ ? root_view_->GetWidget()->CanActivate() : false;
return true;
}
bool NativeWidgetMacNSWindowHost::GetAlwaysRenderWindowAsKey(
bool* always_render_as_key) {
*always_render_as_key =
root_view_ ? root_view_->GetWidget()->ShouldPaintAsActive() : false;
return true;
}
bool NativeWidgetMacNSWindowHost::OnWindowCloseRequested(
bool* can_window_close) {
*can_window_close = true;
views::NonClientView* non_client_view =
root_view_ ? root_view_->GetWidget()->non_client_view() : nullptr;
if (non_client_view)
*can_window_close = non_client_view->OnWindowCloseRequested() ==
CloseRequestResult::kCanClose;
return true;
}
bool NativeWidgetMacNSWindowHost::GetWindowFrameTitlebarHeight(
bool* override_titlebar_height,
float* titlebar_height) {
native_widget_mac_->GetWindowFrameTitlebarHeight(override_titlebar_height,
titlebar_height);
return true;
}
void NativeWidgetMacNSWindowHost::OnFocusWindowToolbar() {
native_widget_mac_->OnFocusWindowToolbar();
}
void NativeWidgetMacNSWindowHost::SetRemoteAccessibilityTokens(
const std::vector<uint8_t>& window_token,
const std::vector<uint8_t>& view_token) {
remote_window_accessible_ =
ui::RemoteAccessibility::GetRemoteElementFromToken(window_token);
remote_view_accessible_ =
ui::RemoteAccessibility::GetRemoteElementFromToken(view_token);
[remote_view_accessible_ setWindowUIElement:remote_window_accessible_.get()];
[remote_view_accessible_
setTopLevelUIElement:remote_window_accessible_.get()];
}
bool NativeWidgetMacNSWindowHost::GetRootViewAccessibilityToken(
int64_t* pid,
std::vector<uint8_t>* token) {
*pid = getpid();
id element_id = GetNativeViewAccessible();
*token = ui::RemoteAccessibility::GetTokenForLocalElement(element_id);
return true;
}
bool NativeWidgetMacNSWindowHost::ValidateUserInterfaceItem(
int32_t command,
remote_cocoa::mojom::ValidateUserInterfaceItemResultPtr* out_result) {
*out_result = remote_cocoa::mojom::ValidateUserInterfaceItemResult::New();
native_widget_mac_->ValidateUserInterfaceItem(command, out_result->get());
return true;
}
bool NativeWidgetMacNSWindowHost::ExecuteCommand(
int32_t command,
WindowOpenDisposition window_open_disposition,
bool is_before_first_responder,
bool* was_executed) {
*was_executed = native_widget_mac_->ExecuteCommand(
command, window_open_disposition, is_before_first_responder);
return true;
}
bool NativeWidgetMacNSWindowHost::HandleAccelerator(
const ui::Accelerator& accelerator,
bool require_priority_handler,
bool* was_handled) {
*was_handled = false;
if (Widget* widget = native_widget_mac_->GetWidget()) {
if (require_priority_handler &&
!widget->GetFocusManager()->HasPriorityHandler(accelerator)) {
return true;
}
*was_handled = widget->GetFocusManager()->ProcessAccelerator(accelerator);
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// NativeWidgetMacNSWindowHost,
// remote_cocoa::mojom::NativeWidgetNSWindowHost synchronous callbacks:
void NativeWidgetMacNSWindowHost::GetSheetOffsetY(
GetSheetOffsetYCallback callback) {
int32_t offset_y = 0;
GetSheetOffsetY(&offset_y);
std::move(callback).Run(offset_y);
}
void NativeWidgetMacNSWindowHost::DispatchKeyEventRemote(
std::unique_ptr<ui::Event> event,
DispatchKeyEventRemoteCallback callback) {
bool event_handled = false;
DispatchKeyEventRemote(std::move(event), &event_handled);
std::move(callback).Run(event_handled);
}
void NativeWidgetMacNSWindowHost::DispatchKeyEventToMenuControllerRemote(
std::unique_ptr<ui::Event> event,
DispatchKeyEventToMenuControllerRemoteCallback callback) {
ui::KeyEvent* key_event = event->AsKeyEvent();
bool event_swallowed = DispatchKeyEventToMenuController(key_event);
std::move(callback).Run(event_swallowed, key_event->handled());
}
void NativeWidgetMacNSWindowHost::GetHasMenuController(
GetHasMenuControllerCallback callback) {
bool has_menu_controller = false;
GetHasMenuController(&has_menu_controller);
std::move(callback).Run(has_menu_controller);
}
void NativeWidgetMacNSWindowHost::GetIsDraggableBackgroundAt(
const gfx::Point& location_in_content,
GetIsDraggableBackgroundAtCallback callback) {
bool is_draggable_background = false;
GetIsDraggableBackgroundAt(location_in_content, &is_draggable_background);
std::move(callback).Run(is_draggable_background);
}
void NativeWidgetMacNSWindowHost::GetTooltipTextAt(
const gfx::Point& location_in_content,
GetTooltipTextAtCallback callback) {
base::string16 new_tooltip_text;
GetTooltipTextAt(location_in_content, &new_tooltip_text);
std::move(callback).Run(new_tooltip_text);
}
void NativeWidgetMacNSWindowHost::GetIsFocusedViewTextual(
GetIsFocusedViewTextualCallback callback) {
bool is_textual = false;
GetIsFocusedViewTextual(&is_textual);
std::move(callback).Run(is_textual);
}
void NativeWidgetMacNSWindowHost::GetWidgetIsModal(
GetWidgetIsModalCallback callback) {
bool widget_is_modal = false;
GetWidgetIsModal(&widget_is_modal);
std::move(callback).Run(widget_is_modal);
}
void NativeWidgetMacNSWindowHost::GetDialogButtonInfo(
ui::DialogButton button,
GetDialogButtonInfoCallback callback) {
bool exists = false;
base::string16 label;
bool is_enabled = false;
bool is_default = false;
GetDialogButtonInfo(button, &exists, &label, &is_enabled, &is_default);
std::move(callback).Run(exists, label, is_enabled, is_default);
}
void NativeWidgetMacNSWindowHost::GetDoDialogButtonsExist(
GetDoDialogButtonsExistCallback callback) {
bool buttons_exist = false;
GetDoDialogButtonsExist(&buttons_exist);
std::move(callback).Run(buttons_exist);
}
void NativeWidgetMacNSWindowHost::GetShouldShowWindowTitle(
GetShouldShowWindowTitleCallback callback) {
bool should_show_window_title = false;
GetShouldShowWindowTitle(&should_show_window_title);
std::move(callback).Run(should_show_window_title);
}
void NativeWidgetMacNSWindowHost::GetCanWindowBecomeKey(
GetCanWindowBecomeKeyCallback callback) {
bool can_window_become_key = false;
GetCanWindowBecomeKey(&can_window_become_key);
std::move(callback).Run(can_window_become_key);
}
void NativeWidgetMacNSWindowHost::GetAlwaysRenderWindowAsKey(
GetAlwaysRenderWindowAsKeyCallback callback) {
bool always_render_as_key = false;
GetAlwaysRenderWindowAsKey(&always_render_as_key);
std::move(callback).Run(always_render_as_key);
}
void NativeWidgetMacNSWindowHost::OnWindowCloseRequested(
OnWindowCloseRequestedCallback callback) {
bool can_window_close = false;
OnWindowCloseRequested(&can_window_close);
std::move(callback).Run(can_window_close);
}
void NativeWidgetMacNSWindowHost::GetWindowFrameTitlebarHeight(
GetWindowFrameTitlebarHeightCallback callback) {
bool override_titlebar_height = false;
float titlebar_height = 0;
GetWindowFrameTitlebarHeight(&override_titlebar_height, &titlebar_height);
std::move(callback).Run(override_titlebar_height, titlebar_height);
}
void NativeWidgetMacNSWindowHost::GetRootViewAccessibilityToken(
GetRootViewAccessibilityTokenCallback callback) {
std::vector<uint8_t> token;
int64_t pid;
GetRootViewAccessibilityToken(&pid, &token);
std::move(callback).Run(pid, token);
}
void NativeWidgetMacNSWindowHost::ValidateUserInterfaceItem(
int32_t command,
ValidateUserInterfaceItemCallback callback) {
remote_cocoa::mojom::ValidateUserInterfaceItemResultPtr result;
ValidateUserInterfaceItem(command, &result);
std::move(callback).Run(std::move(result));
}
void NativeWidgetMacNSWindowHost::ExecuteCommand(
int32_t command,
WindowOpenDisposition window_open_disposition,
bool is_before_first_responder,
ExecuteCommandCallback callback) {
bool was_executed = false;
ExecuteCommand(command, window_open_disposition, is_before_first_responder,
&was_executed);
std::move(callback).Run(was_executed);
}
void NativeWidgetMacNSWindowHost::HandleAccelerator(
const ui::Accelerator& accelerator,
bool require_priority_handler,
HandleAcceleratorCallback callback) {
bool was_handled = false;
HandleAccelerator(accelerator, require_priority_handler, &was_handled);
std::move(callback).Run(was_handled);
}
////////////////////////////////////////////////////////////////////////////////
// NativeWidgetMacNSWindowHost, DialogObserver:
void NativeWidgetMacNSWindowHost::OnDialogChanged() {
// Note it's only necessary to clear the TouchBar. If the OS needs it again,
// a new one will be created.
GetNSWindowMojo()->ClearTouchBar();
}
////////////////////////////////////////////////////////////////////////////////
// NativeWidgetMacNSWindowHost, AccessibilityFocusOverrider::Client:
id NativeWidgetMacNSWindowHost::GetAccessibilityFocusedUIElement() {
return [GetNativeViewAccessible() accessibilityFocusedUIElement];
}
////////////////////////////////////////////////////////////////////////////////
// NativeWidgetMacNSWindowHost, LayerDelegate:
void NativeWidgetMacNSWindowHost::OnPaintLayer(
const ui::PaintContext& context) {
native_widget_mac_->GetWidget()->OnNativeWidgetPaint(context);
}
void NativeWidgetMacNSWindowHost::OnDeviceScaleFactorChanged(
float old_device_scale_factor,
float new_device_scale_factor) {
native_widget_mac_->GetWidget()->DeviceScaleFactorChanged(
old_device_scale_factor, new_device_scale_factor);
}
void NativeWidgetMacNSWindowHost::UpdateVisualState() {
native_widget_mac_->GetWidget()->LayoutRootViewIfNecessary();
}
////////////////////////////////////////////////////////////////////////////////
// NativeWidgetMacNSWindowHost, AcceleratedWidgetMac:
void NativeWidgetMacNSWindowHost::AcceleratedWidgetCALayerParamsUpdated() {
if (const auto* ca_layer_params = compositor_->widget()->GetCALayerParams())
GetNSWindowMojo()->SetCALayerParams(*ca_layer_params);
// Take this opportunity to update the VSync parameters, if needed.
if (display_link_) {
base::TimeTicks timebase;
base::TimeDelta interval;
if (display_link_->GetVSyncParameters(&timebase, &interval))
compositor_->compositor()->SetDisplayVSyncParameters(timebase, interval);
}
}
} // namespace views