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

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: Extract CocoaWindowMoveLoop, fix review issues. Created 4 years, 9 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 17 matching lines...) Expand all
28 #include "ui/views/cocoa/tooltip_manager_mac.h" 28 #include "ui/views/cocoa/tooltip_manager_mac.h"
29 #import "ui/views/cocoa/views_nswindow_delegate.h" 29 #import "ui/views/cocoa/views_nswindow_delegate.h"
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" {
39
40 typedef int32_t CGSConnection;
41 CGSConnection _CGSDefaultConnection();
42 CGError CGSSetWindowBackgroundBlurRadius(CGSConnection connection,
43 NSInteger windowNumber,
44 int radius);
45
46 }
47
48 // The NSView that hosts the composited CALayer drawing the UI. It fills the 38 // 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 39 // window but is not hittable so that accessibility hit tests always go to the
50 // BridgedContentView. 40 // BridgedContentView.
51 @interface ViewsCompositorSuperview : NSView 41 @interface ViewsCompositorSuperview : NSView
52 @end 42 @end
53 43
54 @implementation ViewsCompositorSuperview 44 @implementation ViewsCompositorSuperview
55 - (NSView*)hitTest:(NSPoint)aPoint { 45 - (NSView*)hitTest:(NSPoint)aPoint {
56 return nil; 46 return nil;
57 } 47 }
(...skipping 29 matching lines...) Expand all
87 const CGFloat kYosemiteMenuOpacity = 194.0 / 255.0; 77 const CGFloat kYosemiteMenuOpacity = 194.0 / 255.0;
88 const int kYosemiteMenuBlur = 80; 78 const int kYosemiteMenuBlur = 80;
89 79
90 // Margin at edge and corners of the window that trigger resizing. These match 80 // Margin at edge and corners of the window that trigger resizing. These match
91 // actual Cocoa resize margins. 81 // actual Cocoa resize margins.
92 const int kResizeAreaEdgeSize = 3; 82 const int kResizeAreaEdgeSize = 3;
93 const int kResizeAreaCornerSize = 12; 83 const int kResizeAreaCornerSize = 12;
94 84
95 int kWindowPropertiesKey; 85 int kWindowPropertiesKey;
96 86
87 bool g_ignore_next_mouse_down_for_draggable_regions = false;
88
97 float GetDeviceScaleFactorFromView(NSView* view) { 89 float GetDeviceScaleFactorFromView(NSView* view) {
98 gfx::Display display = 90 gfx::Display display =
99 gfx::Screen::GetScreen()->GetDisplayNearestWindow(view); 91 gfx::Screen::GetScreen()->GetDisplayNearestWindow(view);
100 DCHECK(display.is_valid()); 92 DCHECK(display.is_valid());
101 return display.device_scale_factor(); 93 return display.device_scale_factor();
102 } 94 }
103 95
104 // Returns true if bounds passed to window in SetBounds should be treated as 96 // Returns true if bounds passed to window in SetBounds should be treated as
105 // though they are in screen coordinates. 97 // though they are in screen coordinates.
106 bool PositionWindowInScreenCoordinates(views::Widget* widget, 98 bool PositionWindowInScreenCoordinates(views::Widget* widget,
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 NSInteger event_number = [ns_event eventNumber]; 176 NSInteger event_number = [ns_event eventNumber];
185 177
186 // The logic here is a bit convoluted because we want to mitigate race 178 // The logic here is a bit convoluted because we want to mitigate race
187 // conditions if somehow a different mouse-down occurs between reposts. 179 // conditions if somehow a different mouse-down occurs between reposts.
188 // Specifically, we want to avoid: 180 // Specifically, we want to avoid:
189 // - BridgedNativeWidget's draggability getting out of sync (e.g. if it is 181 // - BridgedNativeWidget's draggability getting out of sync (e.g. if it is
190 // draggable outside of a repost cycle), 182 // draggable outside of a repost cycle),
191 // - any repost loop. 183 // - any repost loop.
192 184
193 if (repost_state == NONE) { 185 if (repost_state == NONE) {
186 if (g_ignore_next_mouse_down_for_draggable_regions) {
187 g_ignore_next_mouse_down_for_draggable_regions = false;
188 return ns_event;
189 }
190
194 if (WindowWantsMouseDownReposted(ns_event)) { 191 if (WindowWantsMouseDownReposted(ns_event)) {
195 repost_state = EXPECTING_REPOST; 192 repost_state = EXPECTING_REPOST;
196 reposted_event_number = event_number; 193 reposted_event_number = event_number;
197 CGEventPost(kCGSessionEventTap, [ns_event CGEvent]); 194 CGEventPost(kCGSessionEventTap, [ns_event CGEvent]);
198 return nil; 195 return nil;
199 } 196 }
200 197
201 return ns_event; 198 return ns_event;
202 } 199 }
203 200
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 // If the WindowResizeHelper's pumpable task runner is set, it means the GPU 255 // If the WindowResizeHelper's pumpable task runner is set, it means the GPU
259 // process is directing messages there, and the compositor can synchronize 256 // process is directing messages there, and the compositor can synchronize
260 // with it. Otherwise, just use the UI thread. 257 // with it. Otherwise, just use the UI thread.
261 scoped_refptr<base::SingleThreadTaskRunner> task_runner = 258 scoped_refptr<base::SingleThreadTaskRunner> task_runner =
262 ui::WindowResizeHelperMac::Get()->task_runner(); 259 ui::WindowResizeHelperMac::Get()->task_runner();
263 return task_runner ? task_runner : base::ThreadTaskRunnerHandle::Get(); 260 return task_runner ? task_runner : base::ThreadTaskRunnerHandle::Get();
264 } 261 }
265 262
266 } // namespace 263 } // namespace
267 264
265 extern "C" {
266
267 typedef int32_t CGSConnection;
268 CGSConnection _CGSDefaultConnection();
269 CGError CGSSetWindowBackgroundBlurRadius(CGSConnection connection,
270 NSInteger windowNumber,
271 int radius);
272
273 }
274
268 namespace views { 275 namespace views {
269 276
270 // static 277 // static
271 gfx::Size BridgedNativeWidget::GetWindowSizeForClientSize( 278 gfx::Size BridgedNativeWidget::GetWindowSizeForClientSize(
272 NSWindow* window, 279 NSWindow* window,
273 const gfx::Size& content_size) { 280 const gfx::Size& content_size) {
274 NSRect content_rect = 281 NSRect content_rect =
275 NSMakeRect(0, 0, content_size.width(), content_size.height()); 282 NSMakeRect(0, 0, content_size.width(), content_size.height());
276 NSRect frame_rect = [window frameRectForContentRect:content_rect]; 283 NSRect frame_rect = [window frameRectForContentRect:content_rect];
277 return gfx::Size(NSWidth(frame_rect), NSHeight(frame_rect)); 284 return gfx::Size(NSWidth(frame_rect), NSHeight(frame_rect));
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
562 } 569 }
563 570
564 void BridgedNativeWidget::ReleaseCapture() { 571 void BridgedNativeWidget::ReleaseCapture() {
565 mouse_capture_.reset(); 572 mouse_capture_.reset();
566 } 573 }
567 574
568 bool BridgedNativeWidget::HasCapture() { 575 bool BridgedNativeWidget::HasCapture() {
569 return mouse_capture_ && mouse_capture_->IsActive(); 576 return mouse_capture_ && mouse_capture_->IsActive();
570 } 577 }
571 578
579 Widget::MoveLoopResult BridgedNativeWidget::RunMoveLoop(
580 const gfx::Vector2d& drag_offset) {
581 DCHECK(!HasCapture());
582 DCHECK(!window_move_loop_);
583
584 // First, position the window in the right place. The point |drag_offset|
585 // away from the top-left corner needs to be positioned under the mouse.
586 // TODO(tapted): Figure out why the toolkit-views drag controller doesn't get
587 // this right when it first initializes the Widget.
588 NSPoint mouse_in_screen = gfx::ScreenPointToNSPoint(
589 gfx::Screen::GetScreen()->GetCursorScreenPoint());
590 NSRect frame = [window_ frame];
591 frame.origin.x = mouse_in_screen.x - drag_offset.x();
592 frame.origin.y = mouse_in_screen.y - NSHeight(frame) + drag_offset.y();
593
594 // After setting the frame to correct the initial offset, the drag controller
595 // may immediately want to quit when it's notified of the new bounds. So the
596 // MoveLoop must be set up before the call to setFrame.
597 window_move_loop_.reset(new CocoaWindowMoveLoop(this));
598
599 // Animating may provide a less janky UX, but something custom would be
600 // required so that it follows updates to the mouse position.
601 [window_ setFrame:frame display:YES animate:NO];
602
603 // Setting the frame will call OnWidgetBoundsChanged(), which could result in
604 // a call to EndMoveLoop().
605 if (!window_move_loop_)
606 return Widget::MOVE_LOOP_SUCCESSFUL;
607
608 return window_move_loop_->Run();
609
610 // |this| may be destroyed during the RunLoop, causing it to exit early.
611 // Even if that doesn't happen, CocoaWindowMoveLoop will clean itself up by
612 // calling EndMoveLoop(). So window_move_loop_ will always be null before the
613 // function returns. But don't DCHECK since |this| might not be valid.
614 }
615
616 void BridgedNativeWidget::EndMoveLoop() {
617 DCHECK(window_move_loop_);
618 window_move_loop_->End();
619 window_move_loop_.reset();
620 }
621
622 bool BridgedNativeWidget::IsRunMoveLoopActive() const {
623 return window_move_loop_.get();
tapted 2016/03/11 09:38:28 is the .get() needed?
themblsha 2016/04/05 17:20:42 Yes. error: no viable conversion from returned val
624 }
625
572 void BridgedNativeWidget::SetNativeWindowProperty(const char* name, 626 void BridgedNativeWidget::SetNativeWindowProperty(const char* name,
573 void* value) { 627 void* value) {
574 NSString* key = [NSString stringWithUTF8String:name]; 628 NSString* key = [NSString stringWithUTF8String:name];
575 if (value) { 629 if (value) {
576 [GetWindowProperties() setObject:[NSValue valueWithPointer:value] 630 [GetWindowProperties() setObject:[NSValue valueWithPointer:value]
577 forKey:key]; 631 forKey:key];
578 } else { 632 } else {
579 [GetWindowProperties() removeObjectForKey:key]; 633 [GetWindowProperties() removeObjectForKey:key];
580 } 634 }
581 } 635 }
582 636
583 void* BridgedNativeWidget::GetNativeWindowProperty(const char* name) const { 637 void* BridgedNativeWidget::GetNativeWindowProperty(const char* name) const {
584 NSString* key = [NSString stringWithUTF8String:name]; 638 NSString* key = [NSString stringWithUTF8String:name];
585 return [[GetWindowProperties() objectForKey:key] pointerValue]; 639 return [[GetWindowProperties() objectForKey:key] pointerValue];
586 } 640 }
587 641
588 void BridgedNativeWidget::SetCursor(NSCursor* cursor) { 642 void BridgedNativeWidget::SetCursor(NSCursor* cursor) {
589 [window_delegate_ setCursor:cursor]; 643 [window_delegate_ setCursor:cursor];
590 } 644 }
591 645
592 void BridgedNativeWidget::OnWindowWillClose() { 646 void BridgedNativeWidget::OnWindowWillClose() {
647 DCHECK(!drag_run_loop_);
593 if (parent_) { 648 if (parent_) {
594 parent_->RemoveChildWindow(this); 649 parent_->RemoveChildWindow(this);
595 parent_ = nullptr; 650 parent_ = nullptr;
596 } 651 }
597 [window_ setDelegate:nil]; 652 [window_ setDelegate:nil];
598 [[NSNotificationCenter defaultCenter] removeObserver:window_delegate_]; 653 [[NSNotificationCenter defaultCenter] removeObserver:window_delegate_];
599 native_widget_mac_->OnWindowWillClose(); 654 native_widget_mac_->OnWindowWillClose();
600 } 655 }
601 656
602 void BridgedNativeWidget::OnFullscreenTransitionStart( 657 void BridgedNativeWidget::OnFullscreenTransitionStart(
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
685 740
686 // 10.9 is unable to generate a window shadow from the composited CALayer, so 741 // 10.9 is unable to generate a window shadow from the composited CALayer, so
687 // use Quartz. 742 // use Quartz.
688 // We don't update the window mask during a live resize, instead it is done 743 // We don't update the window mask during a live resize, instead it is done
689 // after the resize is completed in viewDidEndLiveResize: in 744 // after the resize is completed in viewDidEndLiveResize: in
690 // BridgedContentView. 745 // BridgedContentView.
691 if (base::mac::IsOSMavericksOrEarlier() && ![window_ inLiveResize]) 746 if (base::mac::IsOSMavericksOrEarlier() && ![window_ inLiveResize])
692 [bridged_view_ updateWindowMask]; 747 [bridged_view_ updateWindowMask];
693 } 748 }
694 749
750 void BridgedNativeWidget::OnPositionChanged() {
751 native_widget_mac_->GetWidget()->OnNativeWidgetMove();
752 }
753
695 void BridgedNativeWidget::OnVisibilityChanged() { 754 void BridgedNativeWidget::OnVisibilityChanged() {
696 OnVisibilityChangedTo([window_ isVisible]); 755 OnVisibilityChangedTo([window_ isVisible]);
697 } 756 }
698 757
699 void BridgedNativeWidget::OnVisibilityChangedTo(bool new_visibility) { 758 void BridgedNativeWidget::OnVisibilityChangedTo(bool new_visibility) {
700 if (window_visible_ == new_visibility) 759 if (window_visible_ == new_visibility)
701 return; 760 return;
702 761
703 window_visible_ = new_visibility; 762 window_visible_ = new_visibility;
704 763
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after
1237 void BridgedNativeWidget::SetDraggable(bool draggable) { 1296 void BridgedNativeWidget::SetDraggable(bool draggable) {
1238 [bridged_view_ setMouseDownCanMoveWindow:draggable]; 1297 [bridged_view_ setMouseDownCanMoveWindow:draggable];
1239 // AppKit will not update its cache of mouseDownCanMoveWindow unless something 1298 // AppKit will not update its cache of mouseDownCanMoveWindow unless something
1240 // changes. Previously we tried adding an NSView and removing it, but for some 1299 // changes. Previously we tried adding an NSView and removing it, but for some
1241 // reason it required reposting the mouse-down event, and didn't always work. 1300 // reason it required reposting the mouse-down event, and didn't always work.
1242 // Calling the below seems to be an effective solution. 1301 // Calling the below seems to be an effective solution.
1243 [window_ setMovableByWindowBackground:NO]; 1302 [window_ setMovableByWindowBackground:NO];
1244 [window_ setMovableByWindowBackground:YES]; 1303 [window_ setMovableByWindowBackground:YES];
1245 } 1304 }
1246 1305
1306 // static
1307 void BridgedNativeWidget::IgnoreNextMouseDownForDraggableRegions() {
1308 g_ignore_next_mouse_down_for_draggable_regions = true;
1309 }
1310
1247 } // namespace views 1311 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698