Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 30 #import "ui/views/cocoa/widget_owner_nswindow_adapter.h" | 30 #import "ui/views/cocoa/widget_owner_nswindow_adapter.h" |
| 31 #include "ui/views/view.h" | 31 #include "ui/views/view.h" |
| 32 #include "ui/views/views_delegate.h" | 32 #include "ui/views/views_delegate.h" |
| 33 #include "ui/views/widget/native_widget_mac.h" | 33 #include "ui/views/widget/native_widget_mac.h" |
| 34 #include "ui/views/widget/widget.h" | 34 #include "ui/views/widget/widget.h" |
| 35 #include "ui/views/widget/widget_aura_utils.h" | 35 #include "ui/views/widget/widget_aura_utils.h" |
| 36 #include "ui/views/widget/widget_delegate.h" | 36 #include "ui/views/widget/widget_delegate.h" |
| 37 | 37 |
| 38 extern "C" { | 38 extern "C" { |
| 39 | 39 |
| 40 typedef int32_t CGSWindow; | |
| 40 typedef int32_t CGSConnection; | 41 typedef int32_t CGSConnection; |
| 41 CGSConnection _CGSDefaultConnection(); | 42 CGSConnection _CGSDefaultConnection(); |
| 43 OSStatus CGSGetWindowBounds(CGSConnection connection, | |
| 44 CGSWindow window, | |
| 45 CGRect* bounds); | |
| 42 CGError CGSSetWindowBackgroundBlurRadius(CGSConnection connection, | 46 CGError CGSSetWindowBackgroundBlurRadius(CGSConnection connection, |
| 43 NSInteger windowNumber, | 47 NSInteger windowNumber, |
| 44 int radius); | 48 int radius); |
| 45 | 49 |
| 46 } | 50 } |
| 47 | 51 |
| 48 // The NSView that hosts the composited CALayer drawing the UI. It fills the | 52 // The NSView that hosts the composited CALayer drawing the UI. It fills the |
| 49 // window but is not hittable so that accessibility hit tests always go to the | 53 // window but is not hittable so that accessibility hit tests always go to the |
| 50 // BridgedContentView. | 54 // BridgedContentView. |
| 51 @interface ViewsCompositorSuperview : NSView | 55 @interface ViewsCompositorSuperview : NSView |
| (...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 608 } | 612 } |
| 609 | 613 |
| 610 void BridgedNativeWidget::ReleaseCapture() { | 614 void BridgedNativeWidget::ReleaseCapture() { |
| 611 mouse_capture_.reset(); | 615 mouse_capture_.reset(); |
| 612 } | 616 } |
| 613 | 617 |
| 614 bool BridgedNativeWidget::HasCapture() { | 618 bool BridgedNativeWidget::HasCapture() { |
| 615 return mouse_capture_ && mouse_capture_->IsActive(); | 619 return mouse_capture_ && mouse_capture_->IsActive(); |
| 616 } | 620 } |
| 617 | 621 |
| 622 Widget::MoveLoopResult BridgedNativeWidget::RunMoveLoop( | |
| 623 const gfx::Vector2d& drag_offset) { | |
| 624 DCHECK(!HasCapture()); | |
| 625 DCHECK(!window_move_loop_); | |
| 626 | |
| 627 // First, position the window in the right place. The point |drag_offset| | |
| 628 // away from the top-left corner needs to be positioned under the mouse. | |
| 629 // TODO(tapted): Figure out why the toolkit-views drag controller doesn't get | |
| 630 // this right when it first initializes the Widget. | |
| 631 gfx::Point mouse_in_screen = | |
| 632 display::Screen::GetScreen()->GetCursorScreenPoint(); | |
| 633 | |
| 634 // A window can't be moved vertically up out of the work area. Treat this case | |
| 635 // as if the mouse location is at the point it would be when the window first | |
| 636 // stopped moving. That is, vertically down such that the top edge of the | |
| 637 // window touches the menubar (or top of the screen in a dual-screen setup). | |
| 638 // Note on Mac we can assume that the y-coordinate of the work area origin is | |
| 639 // the bottom of the menu bar and not the Dock which doesn't affect window | |
| 640 // movement, but can reduce the work area on the bottom, left and right. | |
| 641 const display::Display display = | |
| 642 display::Screen::GetScreen()->GetDisplayNearestPoint(mouse_in_screen); | |
| 643 const int min_y = display.work_area().y() + drag_offset.y(); | |
| 644 if (mouse_in_screen.y() < min_y) | |
| 645 mouse_in_screen.set_y(min_y); | |
| 646 | |
| 647 gfx::Rect frame = gfx::ScreenRectFromNSRect([window_ frame]); | |
| 648 frame.set_x(mouse_in_screen.x() - drag_offset.x()); | |
| 649 frame.set_y(mouse_in_screen.y() - drag_offset.y()); | |
| 650 DCHECK_GE(frame.y(), display.work_area().y()); | |
| 651 | |
| 652 // After setting the frame to correct the initial offset, the drag controller | |
| 653 // may immediately want to quit when it's notified of the new bounds. So the | |
| 654 // MoveLoop must be set up before the call to setFrame. | |
| 655 window_move_loop_.reset(new CocoaWindowMoveLoop(this, mouse_in_screen)); | |
| 656 | |
| 657 const NSRect ns_frame = gfx::ScreenRectToNSRect(frame); | |
| 658 [window_ setFrame:ns_frame display:YES animate:NO]; | |
| 659 | |
| 660 // Setting the frame will call OnWidgetBoundsChanged(), which could result in | |
| 661 // a call to EndMoveLoop(). | |
| 662 if (!window_move_loop_) | |
| 663 return Widget::MOVE_LOOP_SUCCESSFUL; | |
| 664 | |
| 665 // Make sure WindowServer has caught up with moving the window, this is | |
| 666 // required in order to send the MouseDown click to the intended position. | |
| 667 // El Capitan would always replicate the old window coordinates when calling | |
| 668 // CGSGetWindowBounds(). | |
| 669 // DetachToBrowserTabDragControllerTest.MacDetachesAndReattachesSecondTab will | |
| 670 // fail without the following NSRunLoop pass. | |
| 671 [[NSRunLoop currentRunLoop] | |
|
tapted
2016/05/23 07:29:28
is this still needed?
themblsha
2016/05/26 15:13:25
Nope, removed.
| |
| 672 runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0]]; | |
| 673 DCHECK(NSEqualRects(ns_frame, WindowServerFrame())); | |
| 674 | |
| 675 return window_move_loop_->Run(); | |
| 676 | |
| 677 // |this| may be destroyed during the RunLoop, causing it to exit early. | |
| 678 // Even if that doesn't happen, CocoaWindowMoveLoop will clean itself up by | |
| 679 // calling EndMoveLoop(). So window_move_loop_ will always be null before the | |
| 680 // function returns. But don't DCHECK since |this| might not be valid. | |
| 681 } | |
| 682 | |
| 683 void BridgedNativeWidget::EndMoveLoop() { | |
| 684 DCHECK(window_move_loop_); | |
| 685 window_move_loop_->End(); | |
| 686 window_move_loop_.reset(); | |
| 687 } | |
| 688 | |
| 689 bool BridgedNativeWidget::IsRunMoveLoopActive() const { | |
| 690 return window_move_loop_.get(); | |
| 691 } | |
| 692 | |
| 618 void BridgedNativeWidget::SetNativeWindowProperty(const char* name, | 693 void BridgedNativeWidget::SetNativeWindowProperty(const char* name, |
| 619 void* value) { | 694 void* value) { |
| 620 NSString* key = [NSString stringWithUTF8String:name]; | 695 NSString* key = [NSString stringWithUTF8String:name]; |
| 621 if (value) { | 696 if (value) { |
| 622 [GetWindowProperties() setObject:[NSValue valueWithPointer:value] | 697 [GetWindowProperties() setObject:[NSValue valueWithPointer:value] |
| 623 forKey:key]; | 698 forKey:key]; |
| 624 } else { | 699 } else { |
| 625 [GetWindowProperties() removeObjectForKey:key]; | 700 [GetWindowProperties() removeObjectForKey:key]; |
| 626 } | 701 } |
| 627 } | 702 } |
| 628 | 703 |
| 629 void* BridgedNativeWidget::GetNativeWindowProperty(const char* name) const { | 704 void* BridgedNativeWidget::GetNativeWindowProperty(const char* name) const { |
| 630 NSString* key = [NSString stringWithUTF8String:name]; | 705 NSString* key = [NSString stringWithUTF8String:name]; |
| 631 return [[GetWindowProperties() objectForKey:key] pointerValue]; | 706 return [[GetWindowProperties() objectForKey:key] pointerValue]; |
| 632 } | 707 } |
| 633 | 708 |
| 634 void BridgedNativeWidget::SetCursor(NSCursor* cursor) { | 709 void BridgedNativeWidget::SetCursor(NSCursor* cursor) { |
| 635 [window_delegate_ setCursor:cursor]; | 710 [window_delegate_ setCursor:cursor]; |
| 636 } | 711 } |
| 637 | 712 |
| 638 void BridgedNativeWidget::OnWindowWillClose() { | 713 void BridgedNativeWidget::OnWindowWillClose() { |
| 714 DCHECK(!drag_run_loop_); | |
| 639 if (parent_) { | 715 if (parent_) { |
| 640 parent_->RemoveChildWindow(this); | 716 parent_->RemoveChildWindow(this); |
| 641 parent_ = nullptr; | 717 parent_ = nullptr; |
| 642 } | 718 } |
| 643 [window_ setDelegate:nil]; | 719 [window_ setDelegate:nil]; |
| 644 [[NSNotificationCenter defaultCenter] removeObserver:window_delegate_]; | 720 [[NSNotificationCenter defaultCenter] removeObserver:window_delegate_]; |
| 645 native_widget_mac_->OnWindowWillClose(); | 721 native_widget_mac_->OnWindowWillClose(); |
| 646 } | 722 } |
| 647 | 723 |
| 648 void BridgedNativeWidget::OnFullscreenTransitionStart( | 724 void BridgedNativeWidget::OnFullscreenTransitionStart( |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 726 | 802 |
| 727 // 10.9 is unable to generate a window shadow from the composited CALayer, so | 803 // 10.9 is unable to generate a window shadow from the composited CALayer, so |
| 728 // use Quartz. | 804 // use Quartz. |
| 729 // We don't update the window mask during a live resize, instead it is done | 805 // We don't update the window mask during a live resize, instead it is done |
| 730 // after the resize is completed in viewDidEndLiveResize: in | 806 // after the resize is completed in viewDidEndLiveResize: in |
| 731 // BridgedContentView. | 807 // BridgedContentView. |
| 732 if (base::mac::IsOSMavericksOrEarlier() && ![window_ inLiveResize]) | 808 if (base::mac::IsOSMavericksOrEarlier() && ![window_ inLiveResize]) |
| 733 [bridged_view_ updateWindowMask]; | 809 [bridged_view_ updateWindowMask]; |
| 734 } | 810 } |
| 735 | 811 |
| 812 void BridgedNativeWidget::OnPositionChanged() { | |
| 813 native_widget_mac_->GetWidget()->OnNativeWidgetMove(); | |
| 814 } | |
| 815 | |
| 736 void BridgedNativeWidget::OnVisibilityChanged() { | 816 void BridgedNativeWidget::OnVisibilityChanged() { |
| 737 OnVisibilityChangedTo([window_ isVisible]); | 817 OnVisibilityChangedTo([window_ isVisible]); |
| 738 } | 818 } |
| 739 | 819 |
| 740 void BridgedNativeWidget::OnVisibilityChangedTo(bool new_visibility) { | 820 void BridgedNativeWidget::OnVisibilityChangedTo(bool new_visibility) { |
| 741 if (window_visible_ == new_visibility) | 821 if (window_visible_ == new_visibility) |
| 742 return; | 822 return; |
| 743 | 823 |
| 744 window_visible_ = new_visibility; | 824 window_visible_ = new_visibility; |
| 745 | 825 |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 882 return input_method_.get(); | 962 return input_method_.get(); |
| 883 } | 963 } |
| 884 | 964 |
| 885 gfx::Rect BridgedNativeWidget::GetRestoredBounds() const { | 965 gfx::Rect BridgedNativeWidget::GetRestoredBounds() const { |
| 886 if (target_fullscreen_state_ || in_fullscreen_transition_) | 966 if (target_fullscreen_state_ || in_fullscreen_transition_) |
| 887 return bounds_before_fullscreen_; | 967 return bounds_before_fullscreen_; |
| 888 | 968 |
| 889 return gfx::ScreenRectFromNSRect([window_ frame]); | 969 return gfx::ScreenRectFromNSRect([window_ frame]); |
| 890 } | 970 } |
| 891 | 971 |
| 972 NSRect BridgedNativeWidget::WindowServerFrame() const { | |
| 973 CGRect bounds = NSZeroRect; | |
| 974 CGSGetWindowBounds(_CGSDefaultConnection(), [window_ windowNumber], | |
| 975 &bounds); | |
| 976 NSRect rect = ScreenRectToNSRect(gfx::Rect(bounds)); | |
| 977 rect.size = [window_ frame].size; | |
| 978 return rect; | |
| 979 } | |
| 980 | |
| 892 void BridgedNativeWidget::CreateLayer(ui::LayerType layer_type, | 981 void BridgedNativeWidget::CreateLayer(ui::LayerType layer_type, |
| 893 bool translucent) { | 982 bool translucent) { |
| 894 DCHECK(bridged_view_); | 983 DCHECK(bridged_view_); |
| 895 DCHECK(!layer()); | 984 DCHECK(!layer()); |
| 896 | 985 |
| 897 CreateCompositor(); | 986 CreateCompositor(); |
| 898 DCHECK(compositor_); | 987 DCHECK(compositor_); |
| 899 | 988 |
| 900 SetLayer(new ui::Layer(layer_type)); | 989 SetLayer(new ui::Layer(layer_type)); |
| 901 // Note, except for controls, this will set the layer to be hidden, since it | 990 // Note, except for controls, this will set the layer to be hidden, since it |
| (...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1303 [bridged_view_ setMouseDownCanMoveWindow:draggable]; | 1392 [bridged_view_ setMouseDownCanMoveWindow:draggable]; |
| 1304 // AppKit will not update its cache of mouseDownCanMoveWindow unless something | 1393 // AppKit will not update its cache of mouseDownCanMoveWindow unless something |
| 1305 // changes. Previously we tried adding an NSView and removing it, but for some | 1394 // changes. Previously we tried adding an NSView and removing it, but for some |
| 1306 // reason it required reposting the mouse-down event, and didn't always work. | 1395 // reason it required reposting the mouse-down event, and didn't always work. |
| 1307 // Calling the below seems to be an effective solution. | 1396 // Calling the below seems to be an effective solution. |
| 1308 [window_ setMovableByWindowBackground:NO]; | 1397 [window_ setMovableByWindowBackground:NO]; |
| 1309 [window_ setMovableByWindowBackground:YES]; | 1398 [window_ setMovableByWindowBackground:YES]; |
| 1310 } | 1399 } |
| 1311 | 1400 |
| 1312 } // namespace views | 1401 } // namespace views |
| OLD | NEW |