Add ability for NetLogLogger to gather data from more than just NetLog
[chromium-blink-merge.git] / ui / views / widget / native_widget_mac.mm
blob20db395761ee684482da88635be05860871c89e4
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/widget/native_widget_mac.h"
7 #import <Cocoa/Cocoa.h>
9 #include "base/mac/foundation_util.h"
10 #include "base/mac/scoped_nsobject.h"
11 #include "base/strings/sys_string_conversions.h"
12 #import "ui/base/cocoa/window_size_constants.h"
13 #include "ui/gfx/font_list.h"
14 #import "ui/gfx/mac/coordinate_conversion.h"
15 #include "ui/native_theme/native_theme.h"
16 #import "ui/views/cocoa/bridged_content_view.h"
17 #import "ui/views/cocoa/bridged_native_widget.h"
18 #import "ui/views/cocoa/native_widget_mac_nswindow.h"
19 #import "ui/views/cocoa/views_nswindow_delegate.h"
20 #include "ui/views/window/native_frame_view.h"
22 namespace views {
23 namespace {
25 NSInteger StyleMaskForParams(const Widget::InitParams& params) {
26   // TODO(tapted): Determine better masks when there are use cases for it.
27   if (params.remove_standard_frame)
28     return NSBorderlessWindowMask;
30   if (params.type == Widget::InitParams::TYPE_WINDOW) {
31     return NSTitledWindowMask | NSClosableWindowMask |
32            NSMiniaturizableWindowMask | NSResizableWindowMask;
33   }
34   return NSBorderlessWindowMask;
37 gfx::Size WindowSizeForClientAreaSize(NSWindow* window, const gfx::Size& size) {
38   NSRect content_rect = NSMakeRect(0, 0, size.width(), size.height());
39   NSRect frame_rect = [window frameRectForContentRect:content_rect];
40   return gfx::Size(NSWidth(frame_rect), NSHeight(frame_rect));
43 }  // namespace
45 ////////////////////////////////////////////////////////////////////////////////
46 // NativeWidgetMac, public:
48 NativeWidgetMac::NativeWidgetMac(internal::NativeWidgetDelegate* delegate)
49     : delegate_(delegate),
50       bridge_(new BridgedNativeWidget(this)),
51       ownership_(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET) {
54 NativeWidgetMac::~NativeWidgetMac() {
55   if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET)
56     delete delegate_;
57   else
58     CloseNow();
61 // static
62 BridgedNativeWidget* NativeWidgetMac::GetBridgeForNativeWindow(
63     gfx::NativeWindow window) {
64   id<NSWindowDelegate> window_delegate = [window delegate];
65   if ([window_delegate respondsToSelector:@selector(nativeWidgetMac)]) {
66     ViewsNSWindowDelegate* delegate =
67         base::mac::ObjCCastStrict<ViewsNSWindowDelegate>(window_delegate);
68     return [delegate nativeWidgetMac]->bridge_.get();
69   }
70   return nullptr;  // Not created by NativeWidgetMac.
73 void NativeWidgetMac::OnWindowWillClose() {
74   delegate_->OnNativeWidgetDestroying();
75   // Note: If closed via CloseNow(), |bridge_| will already be reset. If closed
76   // by the user, or via Close() and a RunLoop, this will reset it.
77   bridge_.reset();
78   delegate_->OnNativeWidgetDestroyed();
79   if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET)
80     delete this;
83 ////////////////////////////////////////////////////////////////////////////////
84 // NativeWidgetMac, internal::NativeWidgetPrivate implementation:
86 void NativeWidgetMac::InitNativeWidget(const Widget::InitParams& params) {
87   ownership_ = params.ownership;
89   NSInteger style_mask = StyleMaskForParams(params);
90   base::scoped_nsobject<NSWindow> window([[NativeWidgetMacNSWindow alloc]
91       initWithContentRect:ui::kWindowSizeDeterminedLater
92                 styleMask:style_mask
93                   backing:NSBackingStoreBuffered
94                     defer:YES]);
95   [window setReleasedWhenClosed:NO];  // Owned by scoped_nsobject.
96   bridge_->Init(window, params);
98   delegate_->OnNativeWidgetCreated(true);
100   bridge_->SetFocusManager(GetWidget()->GetFocusManager());
102   DCHECK(GetWidget()->GetRootView());
103   bridge_->SetRootView(GetWidget()->GetRootView());
105   // "Infer" must be handled by ViewsDelegate::OnBeforeWidgetInit().
106   DCHECK_NE(Widget::InitParams::INFER_OPACITY, params.opacity);
107   bool translucent = params.opacity == Widget::InitParams::TRANSLUCENT_WINDOW;
108   switch (params.layer_type) {
109     case aura::WINDOW_LAYER_NONE:
110       break;
111     case aura::WINDOW_LAYER_TEXTURED:
112       bridge_->CreateLayer(ui::LAYER_TEXTURED, translucent);
113       break;
114     case aura::WINDOW_LAYER_NOT_DRAWN:
115       bridge_->CreateLayer(ui::LAYER_NOT_DRAWN, translucent);
116       break;
117     case aura::WINDOW_LAYER_SOLID_COLOR:
118       bridge_->CreateLayer(ui::LAYER_SOLID_COLOR, translucent);
119       break;
120   }
123 NonClientFrameView* NativeWidgetMac::CreateNonClientFrameView() {
124   return new NativeFrameView(GetWidget());
127 bool NativeWidgetMac::ShouldUseNativeFrame() const {
128   return true;
131 bool NativeWidgetMac::ShouldWindowContentsBeTransparent() const {
132   // On Windows, this returns false when DWM is unavailable (e.g. XP, RDP or
133   // classic mode). OSX always has a compositing window manager.
134   return true;
137 void NativeWidgetMac::FrameTypeChanged() {
138   NOTIMPLEMENTED();
141 Widget* NativeWidgetMac::GetWidget() {
142   return delegate_->AsWidget();
145 const Widget* NativeWidgetMac::GetWidget() const {
146   return delegate_->AsWidget();
149 gfx::NativeView NativeWidgetMac::GetNativeView() const {
150   // Returns a BridgedContentView, unless there is no views::RootView set.
151   return [GetNativeWindow() contentView];
154 gfx::NativeWindow NativeWidgetMac::GetNativeWindow() const {
155   return bridge_ ? bridge_->ns_window() : nil;
158 Widget* NativeWidgetMac::GetTopLevelWidget() {
159   NativeWidgetPrivate* native_widget = GetTopLevelNativeWidget(GetNativeView());
160   return native_widget ? native_widget->GetWidget() : NULL;
163 const ui::Compositor* NativeWidgetMac::GetCompositor() const {
164   return bridge_ && bridge_->layer() ? bridge_->layer()->GetCompositor()
165                                      : nullptr;
168 const ui::Layer* NativeWidgetMac::GetLayer() const {
169   return bridge_ ? bridge_->layer() : nullptr;
172 void NativeWidgetMac::ReorderNativeViews() {
173   if (bridge_)
174     bridge_->SetRootView(GetWidget()->GetRootView());
177 void NativeWidgetMac::ViewRemoved(View* view) {
178   NOTIMPLEMENTED();
181 void NativeWidgetMac::SetNativeWindowProperty(const char* name, void* value) {
182   if (bridge_)
183     bridge_->SetNativeWindowProperty(name, value);
186 void* NativeWidgetMac::GetNativeWindowProperty(const char* name) const {
187   if (bridge_)
188     return bridge_->GetNativeWindowProperty(name);
190   return nullptr;
193 TooltipManager* NativeWidgetMac::GetTooltipManager() const {
194   NOTIMPLEMENTED();
195   return NULL;
198 void NativeWidgetMac::SetCapture() {
199   if (bridge_ && !bridge_->HasCapture())
200     bridge_->AcquireCapture();
203 void NativeWidgetMac::ReleaseCapture() {
204   if (bridge_)
205     bridge_->ReleaseCapture();
208 bool NativeWidgetMac::HasCapture() const {
209   return bridge_ && bridge_->HasCapture();
212 InputMethod* NativeWidgetMac::CreateInputMethod() {
213   return bridge_ ? bridge_->CreateInputMethod() : NULL;
216 internal::InputMethodDelegate* NativeWidgetMac::GetInputMethodDelegate() {
217   return bridge_.get();
220 ui::InputMethod* NativeWidgetMac::GetHostInputMethod() {
221   return bridge_ ? bridge_->GetHostInputMethod() : NULL;
224 void NativeWidgetMac::CenterWindow(const gfx::Size& size) {
225   SetSize(WindowSizeForClientAreaSize(GetNativeWindow(), size));
226   // Note that this is not the precise center of screen, but it is the standard
227   // location for windows like dialogs to appear on screen for Mac.
228   // TODO(tapted): If there is a parent window, center in that instead.
229   [GetNativeWindow() center];
232 void NativeWidgetMac::GetWindowPlacement(gfx::Rect* bounds,
233                                          ui::WindowShowState* maximized) const {
234   NOTIMPLEMENTED();
237 bool NativeWidgetMac::SetWindowTitle(const base::string16& title) {
238   NSWindow* window = GetNativeWindow();
239   NSString* current_title = [window title];
240   NSString* new_title = SysUTF16ToNSString(title);
241   if ([current_title isEqualToString:new_title])
242     return false;
244   [window setTitle:new_title];
245   return true;
248 void NativeWidgetMac::SetWindowIcons(const gfx::ImageSkia& window_icon,
249                                      const gfx::ImageSkia& app_icon) {
250   NOTIMPLEMENTED();
253 void NativeWidgetMac::InitModalType(ui::ModalType modal_type) {
254   NOTIMPLEMENTED();
257 gfx::Rect NativeWidgetMac::GetWindowBoundsInScreen() const {
258   return gfx::ScreenRectFromNSRect([GetNativeWindow() frame]);
261 gfx::Rect NativeWidgetMac::GetClientAreaBoundsInScreen() const {
262   NSWindow* window = GetNativeWindow();
263   return gfx::ScreenRectFromNSRect(
264       [window contentRectForFrameRect:[window frame]]);
267 gfx::Rect NativeWidgetMac::GetRestoredBounds() const {
268   return bridge_ ? bridge_->GetRestoredBounds() : gfx::Rect();
271 void NativeWidgetMac::SetBounds(const gfx::Rect& bounds) {
272   if (bridge_)
273     bridge_->SetBounds(bounds);
276 void NativeWidgetMac::SetSize(const gfx::Size& size) {
277   // Ensure the top-left corner stays in-place (rather than the bottom-left,
278   // which -[NSWindow setContentSize:] would do).
279   SetBounds(gfx::Rect(GetWindowBoundsInScreen().origin(), size));
282 void NativeWidgetMac::StackAbove(gfx::NativeView native_view) {
283   NOTIMPLEMENTED();
286 void NativeWidgetMac::StackAtTop() {
287   NOTIMPLEMENTED();
290 void NativeWidgetMac::StackBelow(gfx::NativeView native_view) {
291   NOTIMPLEMENTED();
294 void NativeWidgetMac::SetShape(gfx::NativeRegion shape) {
295   NOTIMPLEMENTED();
298 void NativeWidgetMac::Close() {
299   if (!bridge_)
300     return;
302   // Clear the view early to suppress repaints.
303   bridge_->SetRootView(NULL);
305   NSWindow* window = GetNativeWindow();
306   // Calling performClose: will momentarily highlight the close button, but
307   // AppKit will reject it if there is no close button.
308   SEL close_selector = ([window styleMask] & NSClosableWindowMask)
309                            ? @selector(performClose:)
310                            : @selector(close);
311   [window performSelector:close_selector withObject:nil afterDelay:0];
314 void NativeWidgetMac::CloseNow() {
315   // Reset |bridge_| to NULL before destroying it.
316   scoped_ptr<BridgedNativeWidget> bridge(bridge_.Pass());
319 void NativeWidgetMac::Show() {
320   ShowWithWindowState(ui::SHOW_STATE_NORMAL);
323 void NativeWidgetMac::Hide() {
324   if (!bridge_)
325     return;
327   bridge_->SetVisibilityState(BridgedNativeWidget::HIDE_WINDOW);
330 void NativeWidgetMac::ShowMaximizedWithBounds(
331     const gfx::Rect& restored_bounds) {
332   NOTIMPLEMENTED();
335 void NativeWidgetMac::ShowWithWindowState(ui::WindowShowState state) {
336   if (!bridge_)
337     return;
339   switch (state) {
340     case ui::SHOW_STATE_DEFAULT:
341     case ui::SHOW_STATE_NORMAL:
342     case ui::SHOW_STATE_INACTIVE:
343       break;
344     case ui::SHOW_STATE_MINIMIZED:
345     case ui::SHOW_STATE_MAXIMIZED:
346     case ui::SHOW_STATE_FULLSCREEN:
347       NOTIMPLEMENTED();
348       break;
349     case ui::SHOW_STATE_END:
350       NOTREACHED();
351       break;
352   }
353   bridge_->SetVisibilityState(state == ui::SHOW_STATE_INACTIVE
354       ? BridgedNativeWidget::SHOW_INACTIVE
355       : BridgedNativeWidget::SHOW_AND_ACTIVATE_WINDOW);
358 bool NativeWidgetMac::IsVisible() const {
359   return bridge_ && bridge_->window_visible();
362 void NativeWidgetMac::Activate() {
363   if (!bridge_)
364     return;
366   bridge_->SetVisibilityState(BridgedNativeWidget::SHOW_AND_ACTIVATE_WINDOW);
369 void NativeWidgetMac::Deactivate() {
370   NOTIMPLEMENTED();
373 bool NativeWidgetMac::IsActive() const {
374   return [GetNativeWindow() isKeyWindow];
377 void NativeWidgetMac::SetAlwaysOnTop(bool always_on_top) {
378   NOTIMPLEMENTED();
381 bool NativeWidgetMac::IsAlwaysOnTop() const {
382   NOTIMPLEMENTED();
383   return false;
386 void NativeWidgetMac::SetVisibleOnAllWorkspaces(bool always_visible) {
387   NOTIMPLEMENTED();
390 void NativeWidgetMac::Maximize() {
391   NOTIMPLEMENTED();  // See IsMaximized().
394 void NativeWidgetMac::Minimize() {
395   NSWindow* window = GetNativeWindow();
396   // Calling performMiniaturize: will momentarily highlight the button, but
397   // AppKit will reject it if there is no miniaturize button.
398   if ([window styleMask] & NSMiniaturizableWindowMask)
399     [window performMiniaturize:nil];
400   else
401     [window miniaturize:nil];
404 bool NativeWidgetMac::IsMaximized() const {
405   // The window frame isn't altered on Mac unless going fullscreen. The green
406   // "+" button just makes the window bigger. So, always false.
407   return false;
410 bool NativeWidgetMac::IsMinimized() const {
411   return [GetNativeWindow() isMiniaturized];
414 void NativeWidgetMac::Restore() {
415   [GetNativeWindow() deminiaturize:nil];
418 void NativeWidgetMac::SetFullscreen(bool fullscreen) {
419   if (!bridge_ || fullscreen == IsFullscreen())
420     return;
422   bridge_->ToggleDesiredFullscreenState();
425 bool NativeWidgetMac::IsFullscreen() const {
426   return bridge_ && bridge_->target_fullscreen_state();
429 void NativeWidgetMac::SetOpacity(unsigned char opacity) {
430   NOTIMPLEMENTED();
433 void NativeWidgetMac::SetUseDragFrame(bool use_drag_frame) {
434   NOTIMPLEMENTED();
437 void NativeWidgetMac::FlashFrame(bool flash_frame) {
438   NOTIMPLEMENTED();
441 void NativeWidgetMac::RunShellDrag(View* view,
442                                    const ui::OSExchangeData& data,
443                                    const gfx::Point& location,
444                                    int operation,
445                                    ui::DragDropTypes::DragEventSource source) {
446   NOTIMPLEMENTED();
449 void NativeWidgetMac::SchedulePaintInRect(const gfx::Rect& rect) {
450   // TODO(tapted): This should use setNeedsDisplayInRect:, once the coordinate
451   // system of |rect| has been converted.
452   [GetNativeView() setNeedsDisplay:YES];
453   if (bridge_ && bridge_->layer())
454     bridge_->layer()->SchedulePaint(rect);
457 void NativeWidgetMac::SetCursor(gfx::NativeCursor cursor) {
458   if (bridge_)
459     bridge_->SetCursor(cursor);
462 bool NativeWidgetMac::IsMouseEventsEnabled() const {
463   NOTIMPLEMENTED();
464   return true;
467 void NativeWidgetMac::ClearNativeFocus() {
468   // To quote DesktopWindowTreeHostX11, "This method is weird and misnamed."
469   // The goal is to set focus to the content window, thereby removing focus from
470   // any NSView in the window that doesn't belong to toolkit-views.
471   [GetNativeWindow() makeFirstResponder:GetNativeView()];
474 gfx::Rect NativeWidgetMac::GetWorkAreaBoundsInScreen() const {
475   NOTIMPLEMENTED();
476   return gfx::Rect();
479 Widget::MoveLoopResult NativeWidgetMac::RunMoveLoop(
480     const gfx::Vector2d& drag_offset,
481     Widget::MoveLoopSource source,
482     Widget::MoveLoopEscapeBehavior escape_behavior) {
483   NOTIMPLEMENTED();
484   return Widget::MOVE_LOOP_CANCELED;
487 void NativeWidgetMac::EndMoveLoop() {
488   NOTIMPLEMENTED();
491 void NativeWidgetMac::SetVisibilityChangedAnimationsEnabled(bool value) {
492   NOTIMPLEMENTED();
495 void NativeWidgetMac::SetVisibilityAnimationDuration(
496     const base::TimeDelta& duration) {
497   NOTIMPLEMENTED();
500 void NativeWidgetMac::SetVisibilityAnimationTransition(
501     Widget::VisibilityTransition transition) {
502   NOTIMPLEMENTED();
505 ui::NativeTheme* NativeWidgetMac::GetNativeTheme() const {
506   return ui::NativeTheme::instance();
509 void NativeWidgetMac::OnRootViewLayout() {
510   NOTIMPLEMENTED();
513 bool NativeWidgetMac::IsTranslucentWindowOpacitySupported() const {
514   return false;
517 void NativeWidgetMac::OnSizeConstraintsChanged() {
518   NOTIMPLEMENTED();
521 void NativeWidgetMac::RepostNativeEvent(gfx::NativeEvent native_event) {
522   NOTIMPLEMENTED();
525 ////////////////////////////////////////////////////////////////////////////////
526 // Widget, public:
528 bool Widget::ConvertRect(const Widget* source,
529                          const Widget* target,
530                          gfx::Rect* rect) {
531   return false;
534 namespace internal {
536 ////////////////////////////////////////////////////////////////////////////////
537 // internal::NativeWidgetPrivate, public:
539 // static
540 NativeWidgetPrivate* NativeWidgetPrivate::CreateNativeWidget(
541     internal::NativeWidgetDelegate* delegate) {
542   return new NativeWidgetMac(delegate);
545 // static
546 NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeView(
547     gfx::NativeView native_view) {
548   return GetNativeWidgetForNativeWindow([native_view window]);
551 // static
552 NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeWindow(
553     gfx::NativeWindow native_window) {
554   id<NSWindowDelegate> window_delegate = [native_window delegate];
555   if ([window_delegate respondsToSelector:@selector(nativeWidgetMac)]) {
556     ViewsNSWindowDelegate* delegate =
557         base::mac::ObjCCastStrict<ViewsNSWindowDelegate>(window_delegate);
558     return [delegate nativeWidgetMac];
559   }
560   return NULL;  // Not created by NativeWidgetMac.
563 // static
564 NativeWidgetPrivate* NativeWidgetPrivate::GetTopLevelNativeWidget(
565     gfx::NativeView native_view) {
566   BridgedNativeWidget* bridge =
567       NativeWidgetMac::GetBridgeForNativeWindow([native_view window]);
568   if (!bridge)
569     return NULL;
571   for (BridgedNativeWidget* parent;
572        (parent = bridge->parent());
573        bridge = parent) {
574   }
575   return bridge->native_widget_mac();
578 // static
579 void NativeWidgetPrivate::GetAllChildWidgets(gfx::NativeView native_view,
580                                              Widget::Widgets* children) {
581   BridgedNativeWidget* bridge =
582       NativeWidgetMac::GetBridgeForNativeWindow([native_view window]);
583   if (!bridge)
584     return;
586   // If |native_view| is a subview of the contentView, it will share an
587   // NSWindow, but will itself be a native child of the Widget. That is, adding
588   // bridge->..->GetWidget() to |children| would be adding the _parent_ of
589   // |native_view|, not the Widget for |native_view|. |native_view| doesn't have
590   // a corresponding Widget of its own in this case (and so can't have Widget
591   // children of its own on Mac).
592   if (bridge->ns_view() != native_view)
593     return;
595   // Code expects widget for |native_view| to be added to |children|.
596   if (bridge->native_widget_mac()->GetWidget())
597     children->insert(bridge->native_widget_mac()->GetWidget());
599   for (BridgedNativeWidget* child : bridge->child_windows())
600     GetAllChildWidgets(child->ns_view(), children);
603 // static
604 void NativeWidgetPrivate::GetAllOwnedWidgets(gfx::NativeView native_view,
605                                              Widget::Widgets* owned) {
606   NOTIMPLEMENTED();
609 // static
610 void NativeWidgetPrivate::ReparentNativeView(gfx::NativeView native_view,
611                                              gfx::NativeView new_parent) {
612   NOTIMPLEMENTED();
615 // static
616 bool NativeWidgetPrivate::IsMouseButtonDown() {
617   return [NSEvent pressedMouseButtons] != 0;
620 // static
621 gfx::FontList NativeWidgetPrivate::GetWindowTitleFontList() {
622   NOTIMPLEMENTED();
623   return gfx::FontList();
626 }  // namespace internal
627 }  // namespace views