Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(483)

Side by Side Diff: ui/views/cocoa/bridged_native_widget.mm

Issue 2061693003: MacViews: Suppress visibility changes during an asynchronous close. Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Neater, but Linux, Windows disagree on WidgetTest.DesktopNativeWidgetVisibilityAfterCloseTest Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/views/cocoa/bridged_native_widget.h ('k') | ui/views/cocoa/views_nswindow_close_animator.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "ui/views/cocoa/bridged_native_widget.h" 5 #import "ui/views/cocoa/bridged_native_widget.h"
6 6
7 #import <objc/runtime.h> 7 #import <objc/runtime.h>
8 #include <stddef.h> 8 #include <stddef.h>
9 #include <stdint.h> 9 #include <stdint.h>
10 10
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #import "base/mac/bind_objc_block.h"
12 #import "base/mac/foundation_util.h" 13 #import "base/mac/foundation_util.h"
13 #include "base/mac/mac_util.h" 14 #include "base/mac/mac_util.h"
14 #import "base/mac/sdk_forward_declarations.h" 15 #import "base/mac/sdk_forward_declarations.h"
15 #include "base/threading/thread_task_runner_handle.h" 16 #include "base/threading/thread_task_runner_handle.h"
16 #include "ui/accelerated_widget_mac/window_resize_helper_mac.h" 17 #include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
17 #import "ui/base/cocoa/constrained_window/constrained_window_animation.h" 18 #import "ui/base/cocoa/constrained_window/constrained_window_animation.h"
18 #include "ui/base/hit_test.h" 19 #include "ui/base/hit_test.h"
19 #include "ui/base/ime/input_method.h" 20 #include "ui/base/ime/input_method.h"
20 #include "ui/base/ime/input_method_factory.h" 21 #include "ui/base/ime/input_method_factory.h"
21 #include "ui/display/display.h" 22 #include "ui/display/display.h"
22 #include "ui/display/screen.h" 23 #include "ui/display/screen.h"
23 #include "ui/gfx/geometry/dip_util.h" 24 #include "ui/gfx/geometry/dip_util.h"
24 #import "ui/gfx/mac/coordinate_conversion.h" 25 #import "ui/gfx/mac/coordinate_conversion.h"
25 #import "ui/gfx/mac/nswindow_frame_controls.h" 26 #import "ui/gfx/mac/nswindow_frame_controls.h"
26 #import "ui/views/cocoa/bridged_content_view.h" 27 #import "ui/views/cocoa/bridged_content_view.h"
27 #import "ui/views/cocoa/drag_drop_client_mac.h" 28 #import "ui/views/cocoa/drag_drop_client_mac.h"
28 #import "ui/views/cocoa/cocoa_mouse_capture.h" 29 #import "ui/views/cocoa/cocoa_mouse_capture.h"
29 #import "ui/views/cocoa/cocoa_window_move_loop.h" 30 #import "ui/views/cocoa/cocoa_window_move_loop.h"
30 #include "ui/views/cocoa/tooltip_manager_mac.h" 31 #include "ui/views/cocoa/tooltip_manager_mac.h"
32 #import "ui/views/cocoa/views_nswindow_close_animator.h"
31 #import "ui/views/cocoa/views_nswindow_delegate.h" 33 #import "ui/views/cocoa/views_nswindow_delegate.h"
32 #import "ui/views/cocoa/widget_owner_nswindow_adapter.h" 34 #import "ui/views/cocoa/widget_owner_nswindow_adapter.h"
33 #include "ui/views/view.h" 35 #include "ui/views/view.h"
34 #include "ui/views/views_delegate.h" 36 #include "ui/views/views_delegate.h"
35 #include "ui/views/widget/native_widget_mac.h" 37 #include "ui/views/widget/native_widget_mac.h"
36 #include "ui/views/widget/widget.h" 38 #include "ui/views/widget/widget.h"
37 #include "ui/views/widget/widget_aura_utils.h" 39 #include "ui/views/widget/widget_aura_utils.h"
38 #include "ui/views/widget/widget_delegate.h" 40 #include "ui/views/widget/widget_delegate.h"
39 41
40 extern "C" { 42 extern "C" {
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 BridgedNativeWidget::~BridgedNativeWidget() { 345 BridgedNativeWidget::~BridgedNativeWidget() {
344 bool close_window = false; 346 bool close_window = false;
345 if ([window_ delegate]) { 347 if ([window_ delegate]) {
346 // If the delegate is still set on a modal dialog, it means it was not 348 // If the delegate is still set on a modal dialog, it means it was not
347 // closed via [NSApplication endSheet:]. This is probably OK if the widget 349 // closed via [NSApplication endSheet:]. This is probably OK if the widget
348 // was never shown. But Cocoa ignores close() calls on open sheets. Calling 350 // was never shown. But Cocoa ignores close() calls on open sheets. Calling
349 // endSheet: here would work, but it messes up assumptions elsewhere. E.g. 351 // endSheet: here would work, but it messes up assumptions elsewhere. E.g.
350 // DialogClientView assumes its delegate is alive when closing, which isn't 352 // DialogClientView assumes its delegate is alive when closing, which isn't
351 // true after endSheet: synchronously calls OnNativeWidgetDestroyed(). 353 // true after endSheet: synchronously calls OnNativeWidgetDestroyed().
352 // So ban it. Modal dialogs should be closed via Widget::Close(). 354 // So ban it. Modal dialogs should be closed via Widget::Close().
353 DCHECK(!native_widget_mac_->IsWindowModalSheet()); 355 DCHECK(!IsWindowModalSheet());
354 356
355 // If the delegate is still set, it means OnWindowWillClose() has not been 357 // If the delegate is still set, it means OnWindowWillClose() has not been
356 // called and the window is still open. Usually, -[NSWindow close] would 358 // called and the window is still open. Usually, -[NSWindow close] would
357 // synchronously call OnWindowWillClose() which removes the delegate and 359 // synchronously call OnWindowWillClose() which removes the delegate and
358 // notifies NativeWidgetMac, which then calls this with a nil delegate. 360 // notifies NativeWidgetMac, which then calls this with a nil delegate.
359 // For other teardown flows (e.g. Widget::WIDGET_OWNS_NATIVE_WIDGET or 361 // For other teardown flows (e.g. Widget::WIDGET_OWNS_NATIVE_WIDGET or
360 // Widget::CloseNow()) the delegate must first be cleared to avoid AppKit 362 // Widget::CloseNow()) the delegate must first be cleared to avoid AppKit
361 // calling back into the bridge. This means OnWindowWillClose() needs to be 363 // calling back into the bridge. This means OnWindowWillClose() needs to be
362 // invoked manually, which is done below. 364 // invoked manually, which is done below.
363 // Note that if the window has children it can't be closed until the 365 // Note that if the window has children it can't be closed until the
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
487 // no check for maximum size (consistent with aura::Window::SetBounds()). 489 // no check for maximum size (consistent with aura::Window::SetBounds()).
488 gfx::Size clamped_content_size = 490 gfx::Size clamped_content_size =
489 GetClientSizeForWindowSize(window_, new_bounds.size()); 491 GetClientSizeForWindowSize(window_, new_bounds.size());
490 clamped_content_size.SetToMax(widget->GetMinimumSize()); 492 clamped_content_size.SetToMax(widget->GetMinimumSize());
491 493
492 // A contentRect with zero width or height is a banned practice in ChromeMac, 494 // A contentRect with zero width or height is a banned practice in ChromeMac,
493 // due to unpredictable OSX treatment. 495 // due to unpredictable OSX treatment.
494 DCHECK(!clamped_content_size.IsEmpty()) 496 DCHECK(!clamped_content_size.IsEmpty())
495 << "Zero-sized windows not supported on Mac"; 497 << "Zero-sized windows not supported on Mac";
496 498
497 if (!window_visible_ && native_widget_mac_->IsWindowModalSheet()) { 499 if (!window_visible_ && IsWindowModalSheet()) {
498 // Window-Modal dialogs (i.e. sheets) are positioned by Cocoa when shown for 500 // Window-Modal dialogs (i.e. sheets) are positioned by Cocoa when shown for
499 // the first time. They also have no frame, so just update the content size. 501 // the first time. They also have no frame, so just update the content size.
500 [window_ setContentSize:NSMakeSize(clamped_content_size.width(), 502 [window_ setContentSize:NSMakeSize(clamped_content_size.width(),
501 clamped_content_size.height())]; 503 clamped_content_size.height())];
502 return; 504 return;
503 } 505 }
504 gfx::Rect actual_new_bounds( 506 gfx::Rect actual_new_bounds(
505 new_bounds.origin(), 507 new_bounds.origin(),
506 GetWindowSizeForClientSize(window_, clamped_content_size)); 508 GetWindowSizeForClientSize(window_, clamped_content_size));
507 509
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 DCHECK(!window_visible_); 554 DCHECK(!window_visible_);
553 return; 555 return;
554 } 556 }
555 557
556 DCHECK(wants_to_be_visible_); 558 DCHECK(wants_to_be_visible_);
557 // If the parent (or an ancestor) is hidden, return and wait for it to become 559 // If the parent (or an ancestor) is hidden, return and wait for it to become
558 // visible. 560 // visible.
559 if (parent() && !parent()->IsVisibleParent()) 561 if (parent() && !parent()->IsVisibleParent())
560 return; 562 return;
561 563
562 if (native_widget_mac_->IsWindowModalSheet()) { 564 if (IsWindowModalSheet()) {
563 ShowAsModalSheet(); 565 ShowAsModalSheet();
564 return; 566 return;
565 } 567 }
566 568
567 if (new_state == SHOW_AND_ACTIVATE_WINDOW) { 569 if (new_state == SHOW_AND_ACTIVATE_WINDOW) {
568 [window_ makeKeyAndOrderFront:nil]; 570 [window_ makeKeyAndOrderFront:nil];
569 [NSApp activateIgnoringOtherApps:YES]; 571 [NSApp activateIgnoringOtherApps:YES];
570 } else { 572 } else {
571 // ui::SHOW_STATE_INACTIVE is typically used to avoid stealing focus from a 573 // ui::SHOW_STATE_INACTIVE is typically used to avoid stealing focus from a
572 // parent window. So, if there's a parent, order above that. Otherwise, this 574 // parent window. So, if there's a parent, order above that. Otherwise, this
(...skipping 16 matching lines...) Expand all
589 // duration of the animation, but would keep it smooth. The window also 591 // duration of the animation, but would keep it smooth. The window also
590 // hasn't yet received a frame from the compositor at this stage, so it is 592 // hasn't yet received a frame from the compositor at this stage, so it is
591 // fully transparent until the GPU sends a frame swap IPC. For the blocking 593 // fully transparent until the GPU sends a frame swap IPC. For the blocking
592 // option, the animation needs to wait until AcceleratedWidgetSwapCompleted 594 // option, the animation needs to wait until AcceleratedWidgetSwapCompleted
593 // has been called at least once, otherwise it will animate nothing. 595 // has been called at least once, otherwise it will animate nothing.
594 [show_animation setAnimationBlockingMode:NSAnimationNonblocking]; 596 [show_animation setAnimationBlockingMode:NSAnimationNonblocking];
595 [show_animation startAnimation]; 597 [show_animation startAnimation];
596 } 598 }
597 } 599 }
598 600
601 void BridgedNativeWidget::CloseAsynchronously() {
602 // In a past life, the window would be synchronously hidden for the non-modal
603 // case. AppKit UI could do funny things before an asynchronous close finished
604 // (see http://crbug.com/156101). But that shouldn't be needed with toolkit-
605 // views. But a synchronous hide would have released capture, so do it now.
606 ReleaseCapture();
607
608 if (IsWindowModalSheet()) {
609 // Sheets can't be closed normally. This starts the sheet closing. Once the
610 // sheet has finished animating, it will call sheetDidEnd: on the parent
611 // window's delegate. Note it still needs to be asynchronous, since code
612 // calling Widget::Close() doesn't expect things to be deleted upon return.
613 [NSApp performSelector:@selector(endSheet:)
614 withObject:window_
615 afterDelay:0];
616 return;
617 }
618
619 // For other modal types, animate the close.
620 if (native_widget_mac_->GetWidget()->IsModal()) {
621 CloseNativeWindowWithAnimation(window_);
622 return;
623 }
624
625 // Clear the view early to suppress repaints.
626 SetRootView(nullptr);
627
628 // Widget::Close() ensures [Non]ClientView::CanClose() returns true, so there
629 // is no need to call the NSWindow or its delegate's -windowShouldClose:
630 // implementation in the manner of -[NSWindow performClose:].
631
632 // Many tests assume that base::RunLoop().RunUntilIdle() is always sufficient
633 // to execute a close. However, in rare cases, -performSelector:..afterDelay:0
634 // does not do this. So post a regular task.
635 NSWindow* window = window_; // Ensure the block retains the window.
636 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::BindBlock(^{
637 [window close];
638 }));
639 }
640
599 void BridgedNativeWidget::AcquireCapture() { 641 void BridgedNativeWidget::AcquireCapture() {
600 DCHECK(!HasCapture()); 642 DCHECK(!HasCapture());
601 if (!window_visible_) 643 if (!window_visible_)
602 return; // Capture on hidden windows is disallowed. 644 return; // Capture on hidden windows is disallowed.
603 645
604 mouse_capture_.reset(new CocoaMouseCapture(this)); 646 mouse_capture_.reset(new CocoaMouseCapture(this));
605 647
606 // Initiating global event capture with addGlobalMonitorForEventsMatchingMask: 648 // Initiating global event capture with addGlobalMonitorForEventsMatchingMask:
607 // will reset the mouse cursor to an arrow. Asking the window for an update 649 // will reset the mouse cursor to an arrow. Asking the window for an update
608 // here will restore what we want. However, it can sometimes cause the cursor 650 // here will restore what we want. However, it can sometimes cause the cursor
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
802 } else { 844 } else {
803 ReleaseCapture(); // Capture on hidden windows is not permitted. 845 ReleaseCapture(); // Capture on hidden windows is not permitted.
804 846
805 // When becoming invisible, remove the entry in any parent's childWindow 847 // When becoming invisible, remove the entry in any parent's childWindow
806 // list. Cocoa's childWindow management breaks down when child windows are 848 // list. Cocoa's childWindow management breaks down when child windows are
807 // hidden. 849 // hidden.
808 if (parent_) 850 if (parent_)
809 [parent_->GetNSWindow() removeChildWindow:window_]; 851 [parent_->GetNSWindow() removeChildWindow:window_];
810 } 852 }
811 853
854 NotifyVisibilityChangeDown();
855
856 // Toolkit-views suppresses redraws while not visible. To prevent Cocoa asking
857 // for an "empty" draw, disable auto-display while hidden. For example, this
858 // prevents Cocoa drawing just *after* a minimize, resulting in a blank window
859 // represented in the deminiaturize animation.
860 [window_ setAutodisplay:window_visible_];
861
862 // |bridged_view_| is null when an asynchronous close is pending. Don't
863 // propagate the change further. Note it's not possible to block window
864 // visibility changes coming from native messages, so the bookkeeping above
865 // should still be done.
866 if (!bridged_view_)
867 return;
868
812 // TODO(tapted): Investigate whether we want this for Mac. This is what Aura 869 // TODO(tapted): Investigate whether we want this for Mac. This is what Aura
813 // does, and it is what tests expect. However, because layer drawing is 870 // does, and it is what tests expect. However, because layer drawing is
814 // asynchronous (and things like deminiaturize in AppKit are not), it can 871 // asynchronous (and things like deminiaturize in AppKit are not), it can
815 // result in a CALayer appearing on screen before it has been redrawn in the 872 // result in a CALayer appearing on screen before it has been redrawn in the
816 // GPU process. This is a general problem. In content, a helper class, 873 // GPU process. This is a general problem. In content, a helper class,
817 // RenderWidgetResizeHelper, blocks the UI thread in -[NSView setFrameSize:] 874 // RenderWidgetResizeHelper, blocks the UI thread in -[NSView setFrameSize:]
818 // and RenderWidgetHostView::Show() until a frame is ready. 875 // and RenderWidgetHostView::Show() until a frame is ready.
819 if (layer()) { 876 if (layer()) {
820 layer()->SetVisible(window_visible_); 877 layer()->SetVisible(window_visible_);
821 layer()->SchedulePaint(gfx::Rect(GetClientAreaSize())); 878 layer()->SchedulePaint(gfx::Rect(GetClientAreaSize()));
822 } 879 }
823 880
824 NotifyVisibilityChangeDown();
825
826 native_widget_mac_->GetWidget()->OnNativeWidgetVisibilityChanged( 881 native_widget_mac_->GetWidget()->OnNativeWidgetVisibilityChanged(
827 window_visible_); 882 window_visible_);
828
829 // Toolkit-views suppresses redraws while not visible. To prevent Cocoa asking
830 // for an "empty" draw, disable auto-display while hidden. For example, this
831 // prevents Cocoa drawing just *after* a minimize, resulting in a blank window
832 // represented in the deminiaturize animation.
833 [window_ setAutodisplay:window_visible_];
834 } 883 }
835 884
836 void BridgedNativeWidget::OnBackingPropertiesChanged() { 885 void BridgedNativeWidget::OnBackingPropertiesChanged() {
837 if (layer()) 886 if (layer())
838 UpdateLayerProperties(); 887 UpdateLayerProperties();
839 } 888 }
840 889
841 void BridgedNativeWidget::OnWindowKeyStatusChangedTo(bool is_key) { 890 void BridgedNativeWidget::OnWindowKeyStatusChangedTo(bool is_key) {
842 Widget* widget = native_widget_mac()->GetWidget(); 891 Widget* widget = native_widget_mac()->GetWidget();
843 widget->OnNativeWidgetActivationChanged(is_key); 892 widget->OnNativeWidgetActivationChanged(is_key);
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
955 // Transparent window support. 1004 // Transparent window support.
956 layer()->GetCompositor()->SetHostHasTransparentBackground(translucent); 1005 layer()->GetCompositor()->SetHostHasTransparentBackground(translucent);
957 layer()->SetFillsBoundsOpaquely(!translucent); 1006 layer()->SetFillsBoundsOpaquely(!translucent);
958 1007
959 // Use the regular window background for window modal sheets. The layer() will 1008 // Use the regular window background for window modal sheets. The layer() will
960 // still paint over most of it, but the native -[NSApp beginSheet:] animation 1009 // still paint over most of it, but the native -[NSApp beginSheet:] animation
961 // blocks the UI thread, so there's no way to invalidate the shadow to match 1010 // blocks the UI thread, so there's no way to invalidate the shadow to match
962 // the composited layer. This assumes the native window shape is a good match 1011 // the composited layer. This assumes the native window shape is a good match
963 // for the composited NonClientFrameView, which should be the case since the 1012 // for the composited NonClientFrameView, which should be the case since the
964 // native shape is what's most appropriate for displaying sheets on Mac. 1013 // native shape is what's most appropriate for displaying sheets on Mac.
965 if (translucent && !native_widget_mac_->IsWindowModalSheet()) { 1014 if (translucent && !IsWindowModalSheet()) {
966 [window_ setOpaque:NO]; 1015 [window_ setOpaque:NO];
967 // For Mac OS versions earlier than Yosemite, the Window server isn't able 1016 // For Mac OS versions earlier than Yosemite, the Window server isn't able
968 // to generate a window shadow from the composited CALayer. To get around 1017 // to generate a window shadow from the composited CALayer. To get around
969 // this, let the window background remain opaque and clip the window 1018 // this, let the window background remain opaque and clip the window
970 // boundary in drawRect method of BridgedContentView. See crbug.com/543671. 1019 // boundary in drawRect method of BridgedContentView. See crbug.com/543671.
971 if (base::mac::IsOSYosemiteOrLater()) 1020 if (base::mac::IsOSYosemiteOrLater())
972 [window_ setBackgroundColor:[NSColor clearColor]]; 1021 [window_ setBackgroundColor:[NSColor clearColor]];
973 } 1022 }
974 1023
975 UpdateLayerProperties(); 1024 UpdateLayerProperties();
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
1313 if (!resize_helper->WaitForSingleTaskToRun(timeout_time - now)) 1362 if (!resize_helper->WaitForSingleTaskToRun(timeout_time - now))
1314 return; // Timeout. 1363 return; // Timeout.
1315 1364
1316 // Since the UI thread is blocked, the size shouldn't change. 1365 // Since the UI thread is blocked, the size shouldn't change.
1317 DCHECK(size_in_dip == GetClientAreaSize()); 1366 DCHECK(size_in_dip == GetClientAreaSize());
1318 if (compositor_widget_->HasFrameOfSize(size_in_dip)) 1367 if (compositor_widget_->HasFrameOfSize(size_in_dip))
1319 return; // Frame arrived. 1368 return; // Frame arrived.
1320 } 1369 }
1321 } 1370 }
1322 1371
1372 bool BridgedNativeWidget::IsWindowModalSheet() const {
1373 return native_widget_mac_->GetWidget()->widget_delegate()->GetModalType() ==
1374 ui::MODAL_TYPE_WINDOW;
1375 }
1376
1323 void BridgedNativeWidget::ShowAsModalSheet() { 1377 void BridgedNativeWidget::ShowAsModalSheet() {
1324 // -[NSApp beginSheet:] will block the UI thread while the animation runs. 1378 // -[NSApp beginSheet:] will block the UI thread while the animation runs.
1325 // So that it doesn't animate a fully transparent window, first wait for a 1379 // So that it doesn't animate a fully transparent window, first wait for a
1326 // frame. The first step is to pretend that the window is already visible. 1380 // frame. The first step is to pretend that the window is already visible.
1327 window_visible_ = true; 1381 window_visible_ = true;
1328 layer()->SetVisible(true); 1382 layer()->SetVisible(true);
1329 native_widget_mac_->GetWidget()->OnNativeWidgetVisibilityChanged(true); 1383 native_widget_mac_->GetWidget()->OnNativeWidgetVisibilityChanged(true);
1330 MaybeWaitForFrame(GetClientAreaSize()); 1384 MaybeWaitForFrame(GetClientAreaSize());
1331 1385
1332 NSWindow* parent_window = parent_->GetNSWindow(); 1386 NSWindow* parent_window = parent_->GetNSWindow();
(...skipping 21 matching lines...) Expand all
1354 [bridged_view_ setMouseDownCanMoveWindow:draggable]; 1408 [bridged_view_ setMouseDownCanMoveWindow:draggable];
1355 // AppKit will not update its cache of mouseDownCanMoveWindow unless something 1409 // AppKit will not update its cache of mouseDownCanMoveWindow unless something
1356 // changes. Previously we tried adding an NSView and removing it, but for some 1410 // changes. Previously we tried adding an NSView and removing it, but for some
1357 // reason it required reposting the mouse-down event, and didn't always work. 1411 // reason it required reposting the mouse-down event, and didn't always work.
1358 // Calling the below seems to be an effective solution. 1412 // Calling the below seems to be an effective solution.
1359 [window_ setMovableByWindowBackground:NO]; 1413 [window_ setMovableByWindowBackground:NO];
1360 [window_ setMovableByWindowBackground:YES]; 1414 [window_ setMovableByWindowBackground:YES];
1361 } 1415 }
1362 1416
1363 } // namespace views 1417 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/cocoa/bridged_native_widget.h ('k') | ui/views/cocoa/views_nswindow_close_animator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698