blob: c77eaba99669ffe28ba1c0fe65c257cfcc6c5095 [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 "content/app_shim_remote_cocoa/web_contents_ns_view_bridge.h"
#include "components/remote_cocoa/app_shim/ns_view_ids.h"
#import "content/app_shim_remote_cocoa/web_contents_view_cocoa.h"
#include "content/browser/web_contents/web_contents_view_mac.h"
#include "ui/gfx/image/image_skia_util_mac.h"
namespace remote_cocoa {
WebContentsNSViewBridge::WebContentsNSViewBridge(
uint64_t view_id,
mojo::PendingAssociatedRemote<mojom::WebContentsNSViewHost> client)
: host_(std::move(client)) {
ns_view_.reset(
[[WebContentsViewCocoa alloc] initWithViewsHostableView:nullptr]);
[ns_view_ setHost:host_.get()];
view_id_ = std::make_unique<remote_cocoa::ScopedNSViewIdMapping>(
view_id, ns_view_.get());
}
WebContentsNSViewBridge::WebContentsNSViewBridge(
uint64_t view_id,
content::WebContentsViewMac* web_contents_view) {
ns_view_.reset([[WebContentsViewCocoa alloc]
initWithViewsHostableView:web_contents_view]);
[ns_view_ setHost:web_contents_view];
view_id_ = std::make_unique<remote_cocoa::ScopedNSViewIdMapping>(
view_id, ns_view_.get());
}
WebContentsNSViewBridge::~WebContentsNSViewBridge() {
// This handles the case where a renderer close call was deferred
// while the user was operating a UI control which resulted in a
// close. In that case, the Cocoa view outlives the
// WebContentsViewMac instance due to Cocoa retain count.
[ns_view_ setHost:nullptr];
[ns_view_ clearViewsHostableView];
[ns_view_ removeFromSuperview];
}
void WebContentsNSViewBridge::SetParentNSView(uint64_t parent_ns_view_id) {
NSView* parent_ns_view = remote_cocoa::GetNSViewFromId(parent_ns_view_id);
// If the browser passed an invalid handle, then there is no recovery.
CHECK(parent_ns_view);
[parent_ns_view addSubview:ns_view_];
}
void WebContentsNSViewBridge::ResetParentNSView() {
[ns_view_ removeFromSuperview];
}
void WebContentsNSViewBridge::SetBounds(const gfx::Rect& bounds_in_window) {
NSWindow* window = [ns_view_ window];
NSRect window_content_rect = [window contentRectForFrameRect:[window frame]];
NSRect ns_bounds_in_window =
NSMakeRect(bounds_in_window.x(),
window_content_rect.size.height - bounds_in_window.y() -
bounds_in_window.height(),
bounds_in_window.width(), bounds_in_window.height());
NSRect ns_bounds_in_superview =
[[ns_view_ superview] convertRect:ns_bounds_in_window fromView:nil];
[ns_view_ setFrame:ns_bounds_in_superview];
}
void WebContentsNSViewBridge::SetVisible(bool visible) {
[ns_view_ setHidden:!visible];
}
void WebContentsNSViewBridge::MakeFirstResponder() {
if ([ns_view_ acceptsFirstResponder])
[[ns_view_ window] makeFirstResponder:ns_view_];
}
void WebContentsNSViewBridge::TakeFocus(bool reverse) {
if (reverse)
[[ns_view_ window] selectPreviousKeyView:ns_view_];
else
[[ns_view_ window] selectNextKeyView:ns_view_];
}
void WebContentsNSViewBridge::StartDrag(const content::DropData& drop_data,
uint32_t operation_mask,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset) {
NSPoint offset = NSPointFromCGPoint(
gfx::PointAtOffsetFromOrigin(image_offset).ToCGPoint());
[ns_view_ startDragWithDropData:drop_data
dragOperationMask:operation_mask
image:gfx::NSImageFromImageSkia(image)
offset:offset];
}
} // namespace remote_cocoa