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 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 |