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 17 matching lines...) Expand all Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |