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

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

Issue 1747803003: MacViews: Implement Tab Dragging (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Removed click simulation, reimplemented CocoaWindowMoveLoop without relying on the WindowServer. Created 4 years, 7 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
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
(...skipping 19 matching lines...) Expand all
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698