1 // Copyright 2014 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.
5 #include "ui/views/controls/native/native_view_host_mac.h"
7 #import <Cocoa/Cocoa.h>
9 #include "base/logging.h"
10 #include "base/mac/foundation_util.h"
11 #import "ui/views/cocoa/bridged_content_view.h"
12 #include "ui/views/controls/native/native_view_host.h"
13 #include "ui/views/widget/widget.h"
18 // Reparents |native_view| to be a child of the native content view of
20 void ReparentNSView(NSView* native_view, Widget* new_parent) {
22 // Mac's NativeViewHost has no support for hosting its own child widgets.
23 // This check is probably overly restrictive, since the Widget containing the
24 // NativeViewHost _is_ allowed child Widgets. However, we don't know yet
25 // whether those child Widgets need to be distinguished from Widgets that code
26 // might want to associate with the hosted NSView instead.
28 Widget::Widgets child_widgets;
29 Widget::GetAllChildWidgets(native_view, &child_widgets);
30 CHECK_GE(1u, child_widgets.size()); // 1 (itself) or 0 if detached.
34 [native_view removeFromSuperview];
38 BridgedContentView* new_superview =
39 base::mac::ObjCCastStrict<BridgedContentView>(
40 new_parent->GetNativeView());
41 DCHECK(new_superview);
42 [new_superview addSubview:native_view];
47 NativeViewHostMac::NativeViewHostMac(NativeViewHost* host) : host_(host) {
50 NativeViewHostMac::~NativeViewHostMac() {
53 ////////////////////////////////////////////////////////////////////////////////
54 // NativeViewHostMac, NativeViewHostWrapper implementation:
56 void NativeViewHostMac::AttachNativeView() {
57 DCHECK(host_->native_view());
58 ReparentNSView(host_->native_view(), host_->GetWidget());
61 void NativeViewHostMac::NativeViewDetaching(bool destroyed) {
62 // |destroyed| is only true if this class calls host_->NativeViewDestroyed().
63 // TODO(tapted): See if that's needed on Mac, since views are hard to destroy
66 [host_->native_view() setHidden:YES];
67 ReparentNSView(host_->native_view(), NULL);
70 void NativeViewHostMac::AddedToWidget() {
71 if (!host_->native_view())
78 void NativeViewHostMac::RemovedFromWidget() {
79 if (!host_->native_view())
82 NativeViewDetaching(false);
85 void NativeViewHostMac::InstallClip(int x, int y, int w, int h) {
89 bool NativeViewHostMac::HasInstalledClip() {
93 void NativeViewHostMac::UninstallClip() {
97 void NativeViewHostMac::ShowWidget(int x, int y, int w, int h) {
98 if (host_->fast_resize())
101 // Coordinates will be from the top left of the parent Widget. The NativeView
102 // is already in the same NSWindow, so just flip to get Cooca coordinates and
103 // then convert to the containing view.
104 NSRect window_rect = NSMakeRect(
106 host_->GetWidget()->GetClientAreaBoundsInScreen().height() - y - h,
110 // Convert window coordinates to the hosted view's superview, since that's how
111 // coordinates of the hosted view's frame is based.
112 NSRect container_rect =
113 [[host_->native_view() superview] convertRect:window_rect fromView:nil];
114 [host_->native_view() setFrame:container_rect];
115 [host_->native_view() setHidden:NO];
118 void NativeViewHostMac::HideWidget() {
119 [host_->native_view() setHidden:YES];
122 void NativeViewHostMac::SetFocus() {
123 if ([host_->native_view() acceptsFirstResponder])
124 [[host_->native_view() window] makeFirstResponder:host_->native_view()];
127 gfx::NativeViewAccessible NativeViewHostMac::GetNativeViewAccessible() {
131 gfx::NativeCursor NativeViewHostMac::GetCursor(int x, int y) {
133 return gfx::kNullCursor;
137 NativeViewHostWrapper* NativeViewHostWrapper::CreateWrapper(
138 NativeViewHost* host) {
139 return new NativeViewHostMac(host);