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 |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #import "base/mac/foundation_util.h" | 12 #import "base/mac/foundation_util.h" |
13 #include "base/mac/mac_util.h" | 13 #include "base/mac/mac_util.h" |
14 #import "base/mac/sdk_forward_declarations.h" | 14 #import "base/mac/sdk_forward_declarations.h" |
15 #include "base/run_loop.h" | |
15 #include "base/thread_task_runner_handle.h" | 16 #include "base/thread_task_runner_handle.h" |
16 #include "ui/accelerated_widget_mac/window_resize_helper_mac.h" | 17 #include "ui/accelerated_widget_mac/window_resize_helper_mac.h" |
17 #import "ui/base/cocoa/constrained_window/constrained_window_animation.h" | 18 #import "ui/base/cocoa/constrained_window/constrained_window_animation.h" |
18 #include "ui/base/hit_test.h" | 19 #include "ui/base/hit_test.h" |
19 #include "ui/base/ime/input_method.h" | 20 #include "ui/base/ime/input_method.h" |
20 #include "ui/base/ime/input_method_factory.h" | 21 #include "ui/base/ime/input_method_factory.h" |
21 #include "ui/gfx/display.h" | 22 #include "ui/gfx/display.h" |
22 #include "ui/gfx/geometry/dip_util.h" | 23 #include "ui/gfx/geometry/dip_util.h" |
23 #import "ui/gfx/mac/coordinate_conversion.h" | 24 #import "ui/gfx/mac/coordinate_conversion.h" |
24 #import "ui/gfx/mac/nswindow_frame_controls.h" | 25 #import "ui/gfx/mac/nswindow_frame_controls.h" |
25 #include "ui/gfx/screen.h" | 26 #include "ui/gfx/screen.h" |
26 #import "ui/views/cocoa/bridged_content_view.h" | 27 #import "ui/views/cocoa/bridged_content_view.h" |
27 #import "ui/views/cocoa/cocoa_mouse_capture.h" | 28 #import "ui/views/cocoa/cocoa_mouse_capture.h" |
28 #include "ui/views/cocoa/tooltip_manager_mac.h" | 29 #include "ui/views/cocoa/tooltip_manager_mac.h" |
29 #import "ui/views/cocoa/views_nswindow_delegate.h" | 30 #import "ui/views/cocoa/views_nswindow_delegate.h" |
30 #import "ui/views/cocoa/widget_owner_nswindow_adapter.h" | 31 #import "ui/views/cocoa/widget_owner_nswindow_adapter.h" |
31 #include "ui/views/view.h" | 32 #include "ui/views/view.h" |
32 #include "ui/views/views_delegate.h" | 33 #include "ui/views/views_delegate.h" |
33 #include "ui/views/widget/native_widget_mac.h" | 34 #include "ui/views/widget/native_widget_mac.h" |
34 #include "ui/views/widget/widget.h" | 35 #include "ui/views/widget/widget.h" |
35 #include "ui/views/widget/widget_aura_utils.h" | 36 #include "ui/views/widget/widget_aura_utils.h" |
36 #include "ui/views/widget/widget_delegate.h" | 37 #include "ui/views/widget/widget_delegate.h" |
37 | 38 |
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 | 39 // 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 | 40 // window but is not hittable so that accessibility hit tests always go to the |
50 // BridgedContentView. | 41 // BridgedContentView. |
51 @interface ViewsCompositorSuperview : NSView | 42 @interface ViewsCompositorSuperview : NSView |
52 @end | 43 @end |
53 | 44 |
54 @implementation ViewsCompositorSuperview | 45 @implementation ViewsCompositorSuperview |
55 - (NSView*)hitTest:(NSPoint)aPoint { | 46 - (NSView*)hitTest:(NSPoint)aPoint { |
56 return nil; | 47 return nil; |
57 } | 48 } |
(...skipping 29 matching lines...) Expand all Loading... | |
87 const CGFloat kYosemiteMenuOpacity = 194.0 / 255.0; | 78 const CGFloat kYosemiteMenuOpacity = 194.0 / 255.0; |
88 const int kYosemiteMenuBlur = 80; | 79 const int kYosemiteMenuBlur = 80; |
89 | 80 |
90 // Margin at edge and corners of the window that trigger resizing. These match | 81 // Margin at edge and corners of the window that trigger resizing. These match |
91 // actual Cocoa resize margins. | 82 // actual Cocoa resize margins. |
92 const int kResizeAreaEdgeSize = 3; | 83 const int kResizeAreaEdgeSize = 3; |
93 const int kResizeAreaCornerSize = 12; | 84 const int kResizeAreaCornerSize = 12; |
94 | 85 |
95 int kWindowPropertiesKey; | 86 int kWindowPropertiesKey; |
96 | 87 |
88 bool g_ignore_next_mouse_down_for_draggable_regions = false; | |
89 | |
97 float GetDeviceScaleFactorFromView(NSView* view) { | 90 float GetDeviceScaleFactorFromView(NSView* view) { |
98 gfx::Display display = | 91 gfx::Display display = |
99 gfx::Screen::GetScreen()->GetDisplayNearestWindow(view); | 92 gfx::Screen::GetScreen()->GetDisplayNearestWindow(view); |
100 DCHECK(display.is_valid()); | 93 DCHECK(display.is_valid()); |
101 return display.device_scale_factor(); | 94 return display.device_scale_factor(); |
102 } | 95 } |
103 | 96 |
104 // Returns true if bounds passed to window in SetBounds should be treated as | 97 // Returns true if bounds passed to window in SetBounds should be treated as |
105 // though they are in screen coordinates. | 98 // though they are in screen coordinates. |
106 bool PositionWindowInScreenCoordinates(views::Widget* widget, | 99 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]; | 177 NSInteger event_number = [ns_event eventNumber]; |
185 | 178 |
186 // The logic here is a bit convoluted because we want to mitigate race | 179 // The logic here is a bit convoluted because we want to mitigate race |
187 // conditions if somehow a different mouse-down occurs between reposts. | 180 // conditions if somehow a different mouse-down occurs between reposts. |
188 // Specifically, we want to avoid: | 181 // Specifically, we want to avoid: |
189 // - BridgedNativeWidget's draggability getting out of sync (e.g. if it is | 182 // - BridgedNativeWidget's draggability getting out of sync (e.g. if it is |
190 // draggable outside of a repost cycle), | 183 // draggable outside of a repost cycle), |
191 // - any repost loop. | 184 // - any repost loop. |
192 | 185 |
193 if (repost_state == NONE) { | 186 if (repost_state == NONE) { |
187 if (g_ignore_next_mouse_down_for_draggable_regions) { | |
188 g_ignore_next_mouse_down_for_draggable_regions = false; | |
189 return ns_event; | |
190 } | |
191 | |
194 if (WindowWantsMouseDownReposted(ns_event)) { | 192 if (WindowWantsMouseDownReposted(ns_event)) { |
195 repost_state = EXPECTING_REPOST; | 193 repost_state = EXPECTING_REPOST; |
196 reposted_event_number = event_number; | 194 reposted_event_number = event_number; |
197 CGEventPost(kCGSessionEventTap, [ns_event CGEvent]); | 195 CGEventPost(kCGSessionEventTap, [ns_event CGEvent]); |
198 return nil; | 196 return nil; |
199 } | 197 } |
200 | 198 |
201 return ns_event; | 199 return ns_event; |
202 } | 200 } |
203 | 201 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
256 // resize operations to coordinate with frames provided by the GPU process. | 254 // resize operations to coordinate with frames provided by the GPU process. |
257 scoped_refptr<base::SingleThreadTaskRunner> GetCompositorTaskRunner() { | 255 scoped_refptr<base::SingleThreadTaskRunner> GetCompositorTaskRunner() { |
258 // If the WindowResizeHelper's pumpable task runner is set, it means the GPU | 256 // If the WindowResizeHelper's pumpable task runner is set, it means the GPU |
259 // process is directing messages there, and the compositor can synchronize | 257 // process is directing messages there, and the compositor can synchronize |
260 // with it. Otherwise, just use the UI thread. | 258 // with it. Otherwise, just use the UI thread. |
261 scoped_refptr<base::SingleThreadTaskRunner> task_runner = | 259 scoped_refptr<base::SingleThreadTaskRunner> task_runner = |
262 ui::WindowResizeHelperMac::Get()->task_runner(); | 260 ui::WindowResizeHelperMac::Get()->task_runner(); |
263 return task_runner ? task_runner : base::ThreadTaskRunnerHandle::Get(); | 261 return task_runner ? task_runner : base::ThreadTaskRunnerHandle::Get(); |
264 } | 262 } |
265 | 263 |
264 CGPoint GetCGMousePosition() { | |
265 return CGEventGetLocation( | |
266 base::ScopedCFTypeRef<CGEventRef>(CGEventCreate(nullptr))); | |
267 } | |
268 | |
269 void SendCustomLeftMouseEvent(CGEventType type) { | |
270 base::ScopedCFTypeRef<CGEventRef> event( | |
271 CGEventCreateMouseEvent( | |
272 nullptr, type, GetCGMousePosition(), | |
273 kCGMouseButtonLeft)); | |
274 CGEventSetIntegerValueField(event, kCGEventSourceUserData, 1); | |
275 CGEventPost(kCGSessionEventTap, event); | |
276 } | |
277 | |
266 } // namespace | 278 } // namespace |
267 | 279 |
280 extern "C" { | |
281 | |
282 typedef int32_t CGSConnection; | |
283 CGSConnection _CGSDefaultConnection(); | |
284 CGError CGSSetWindowBackgroundBlurRadius(CGSConnection connection, | |
285 NSInteger windowNumber, | |
286 int radius); | |
287 | |
288 } | |
289 | |
290 // CocoaWindowMoveLoop can be deleted just before its local event monitor is | |
291 // processed and in that case it's too late to call removeMonitor: and we have a | |
292 // dangling this pointer. Use a proxy Obj-C class to store the weakptr. | |
293 @interface WeakCocoaWindowMoveLoop : NSObject { | |
294 @private | |
295 base::WeakPtr<views::CocoaWindowMoveLoop> weak_; | |
296 } | |
297 @end | |
298 | |
299 @implementation WeakCocoaWindowMoveLoop | |
300 - (id)initWithWeakPtr:(const base::WeakPtr<views::CocoaWindowMoveLoop>&)weak { | |
301 if (self = [super init]) { | |
302 weak_ = weak; | |
303 } | |
304 return self; | |
305 } | |
306 | |
307 - (base::WeakPtr<views::CocoaWindowMoveLoop>&)weak { | |
308 return weak_; | |
309 } | |
310 @end | |
311 | |
268 namespace views { | 312 namespace views { |
269 | 313 |
314 class CocoaWindowMoveLoop { | |
tapted
2016/03/10 11:51:19
Move this to its own file (with WeakCocoaMoveLoop?
themblsha
2016/03/10 17:18:58
Oh, right, you told me about that and it seems tha
| |
315 public: | |
316 explicit CocoaWindowMoveLoop(BridgedNativeWidget* owner) | |
317 : owner_(owner), | |
318 run_loop_(new base::RunLoop), | |
319 quit_closure_(run_loop_->QuitClosure()), | |
320 weak_factory_(this) { | |
321 // AppKit continues to send mouse events to the window, but toolkit-views | |
322 // goes berserk if it gets them during RunMoveLoop(). | |
tapted
2016/03/10 11:51:19
hehe - I remember writing `berserk`... Perhaps "bu
themblsha
2016/03/10 17:18:58
Done.
| |
323 [owner_->ns_view() setIgnoreMouseEvents:YES]; | |
324 owner_->SetDraggable(true); | |
325 } | |
326 | |
327 ~CocoaWindowMoveLoop() { | |
328 owner_->SetDraggable(false); | |
329 // Note the crafted events in Run() should not make their way through to | |
330 // toolkit-views, but regular events after that should be. So stop ignoring. | |
331 [owner_->ns_view() setIgnoreMouseEvents:NO]; | |
332 | |
333 // Handle the pathological case, where |this| is destroyed while running. | |
334 if (exit_reason_ref_) { | |
335 *exit_reason_ref_ = WINDOW_DESTROYED; | |
336 quit_closure_.Run(); | |
337 } | |
338 | |
339 // Handle Run() never being called. | |
340 if (monitor_) { | |
341 [NSEvent removeMonitor:monitor_]; | |
342 monitor_ = nil; | |
343 } | |
344 owner_ = nullptr; | |
345 } | |
346 | |
347 Widget::MoveLoopResult Run() { | |
348 LoopExitReason exit_reason = ENDED_EXTERNALLY; | |
349 exit_reason_ref_ = &exit_reason; | |
350 | |
351 // Move the RunLoop to the stack so our destructor can be called while it is | |
352 // running. | |
353 scoped_ptr<base::RunLoop> run_loop(std::move(run_loop_)); | |
354 | |
355 // A new window may have just been created, so post an event at the session | |
356 // tap level to initiate a window drag. | |
357 // TODO(tapted): Move this "inside" the window or stuff breaks when dragging | |
358 // the last tab/s off a browser. | |
359 SendCustomLeftMouseEvent(kCGEventLeftMouseDown); | |
360 | |
361 WeakCocoaWindowMoveLoop* proxy_quit_closure = | |
362 [[[WeakCocoaWindowMoveLoop alloc] | |
363 initWithWeakPtr:weak_factory_.GetWeakPtr()] autorelease]; | |
364 | |
365 NSEventMask mask = | |
366 NSLeftMouseUpMask | NSKeyDownMask | NSLeftMouseDraggedMask; | |
367 monitor_ = [NSEvent addLocalMonitorForEventsMatchingMask:mask | |
368 handler:^NSEvent*(NSEvent* event) { | |
369 if ([event type] == NSLeftMouseDragged) { | |
370 // AppKit doesn't supply position updates during a drag, so post a | |
371 // task to notify observers once AppKit has moved the window. | |
372 base::MessageLoop::current()->PostTask( | |
373 FROM_HERE, base::Bind(&BridgedNativeWidget::OnPositionChanged, | |
374 base::Unretained(owner_))); | |
375 return event; | |
376 } | |
377 | |
378 CocoaWindowMoveLoop* thiss = [proxy_quit_closure weak].get(); | |
379 if (!thiss) | |
380 return nil; | |
381 | |
382 thiss->quit_closure_.Run(); | |
383 if ([event type] == NSLeftMouseUp) { | |
384 *thiss->exit_reason_ref_ = MOUSE_UP; | |
385 return event; // Process the MouseUp. | |
386 } | |
387 *thiss->exit_reason_ref_ = ESCAPE_PRESSED; | |
388 return nil; // Swallow the keypress. | |
389 }]; | |
390 | |
391 // NSKeyDownMask doesn't work inside addLocalMonitorForEventsMatchingMask: | |
392 // the event is swallowed by the window move loop before it gets to -[NSApp | |
393 // sendEvent:]. To see an escape keypress, hook in an event tap lower. | |
394 | |
395 run_loop->Run(); | |
396 | |
397 if (exit_reason != WINDOW_DESTROYED && exit_reason != ENDED_EXTERNALLY) { | |
398 exit_reason_ref_ = nullptr; // Ensure End() doesn't replace the reason. | |
399 owner_->EndMoveLoop(); // Deletes |this|. | |
400 } | |
401 | |
402 if (exit_reason != MOUSE_UP) { | |
403 // Tell AppKit to stop moving the window. Otherwise, AppKit will refuse to | |
404 // start a new window drag. Note the window being dragged is going away in | |
405 // this case, so it doesn't really matter where the event is located. | |
406 SendCustomLeftMouseEvent(kCGEventLeftMouseUp); | |
407 | |
408 if (exit_reason == ENDED_EXTERNALLY) { | |
409 // When not canceled, the non-moving drag in the original window must | |
410 // resume. To do this, AppKit needs to see a mouseDown so that it sends | |
411 // the correct events. Ideally, it also needs to be at the original | |
412 // offset, so that it hits a non-draggable region of the original | |
413 // window: The tab being dragged may move some distance from the cursor | |
414 // when it "snaps in", so the cursor may not be over a tab. Sadly, this | |
415 // method doesn't know which window that is. But all that really needs | |
416 // to be done is to prevent a custom-dragging area from starting a | |
417 // window-drag. So hook into the logic in RepostEventIfHandledByWindow() | |
418 // by setting a flag here. Note this assumes the custom mouseDown event | |
419 // is guaranteed to hit another BridgedNativeWidget when it gets to the | |
420 // front of the event queue. | |
421 // TODO(tapted): A better fix would be to keep the temporary window | |
422 // around and never call EndMoveLoop() on Mac, making this block of code | |
423 // obsolete. | |
424 g_ignore_next_mouse_down_for_draggable_regions = true; | |
425 SendCustomLeftMouseEvent(kCGEventLeftMouseDown); | |
426 } | |
427 } | |
428 | |
429 return exit_reason == ESCAPE_PRESSED | |
430 ? Widget::MOVE_LOOP_CANCELED : Widget::MOVE_LOOP_SUCCESSFUL; | |
431 } | |
432 | |
433 void End() { | |
434 if (exit_reason_ref_) { | |
435 DCHECK_EQ(*exit_reason_ref_, ENDED_EXTERNALLY); | |
436 // Ensure the destructor doesn't replace the reason. | |
437 exit_reason_ref_ = nullptr; | |
438 quit_closure_.Run(); | |
439 } | |
440 } | |
441 | |
442 static CGEventRef EscapeKeypressMonitor(CGEventTapProxy proxy, | |
443 CGEventType type, | |
444 CGEventRef event, | |
445 void* refcon) { | |
446 CocoaWindowMoveLoop* self = static_cast<CocoaWindowMoveLoop*>(refcon); | |
447 (void)self; | |
448 return event; | |
449 } | |
450 | |
451 private: | |
452 enum LoopExitReason { | |
453 ENDED_EXTERNALLY, | |
454 ESCAPE_PRESSED, | |
455 MOUSE_UP, | |
456 WINDOW_DESTROYED, | |
457 }; | |
458 | |
459 BridgedNativeWidget* owner_; // Weak. Owns this. | |
460 scoped_ptr<base::RunLoop> run_loop_; | |
461 id monitor_ = nil; | |
462 | |
463 // Pointer to a stack variable holding the exit reason. | |
464 LoopExitReason* exit_reason_ref_ = nullptr; | |
465 base::Closure quit_closure_; | |
466 | |
467 // WeakPtrFactory for event monitor safety. | |
468 base::WeakPtrFactory<CocoaWindowMoveLoop> weak_factory_; | |
469 | |
470 DISALLOW_COPY_AND_ASSIGN(CocoaWindowMoveLoop); | |
471 }; | |
472 | |
270 // static | 473 // static |
271 gfx::Size BridgedNativeWidget::GetWindowSizeForClientSize( | 474 gfx::Size BridgedNativeWidget::GetWindowSizeForClientSize( |
272 NSWindow* window, | 475 NSWindow* window, |
273 const gfx::Size& content_size) { | 476 const gfx::Size& content_size) { |
274 NSRect content_rect = | 477 NSRect content_rect = |
275 NSMakeRect(0, 0, content_size.width(), content_size.height()); | 478 NSMakeRect(0, 0, content_size.width(), content_size.height()); |
276 NSRect frame_rect = [window frameRectForContentRect:content_rect]; | 479 NSRect frame_rect = [window frameRectForContentRect:content_rect]; |
277 return gfx::Size(NSWidth(frame_rect), NSHeight(frame_rect)); | 480 return gfx::Size(NSWidth(frame_rect), NSHeight(frame_rect)); |
278 } | 481 } |
279 | 482 |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
562 } | 765 } |
563 | 766 |
564 void BridgedNativeWidget::ReleaseCapture() { | 767 void BridgedNativeWidget::ReleaseCapture() { |
565 mouse_capture_.reset(); | 768 mouse_capture_.reset(); |
566 } | 769 } |
567 | 770 |
568 bool BridgedNativeWidget::HasCapture() { | 771 bool BridgedNativeWidget::HasCapture() { |
569 return mouse_capture_ && mouse_capture_->IsActive(); | 772 return mouse_capture_ && mouse_capture_->IsActive(); |
570 } | 773 } |
571 | 774 |
775 Widget::MoveLoopResult BridgedNativeWidget::RunMoveLoop( | |
776 const gfx::Vector2d& drag_offset) { | |
777 DCHECK(!HasCapture()); | |
778 DCHECK(!window_move_loop_); | |
779 | |
780 // First, position the window in the right place. The point |drag_offset| | |
781 // away from the top-left corner needs to be positioned under the mouse. | |
782 // TODO(tapted): Figure out why the toolkit-views drag controller doesn't get | |
783 // this right when it first initializes the Widget. | |
784 NSPoint mouse_in_screen = gfx::ScreenPointToNSPoint( | |
785 gfx::Screen::GetScreen()->GetCursorScreenPoint()); | |
786 NSRect frame = [window_ frame]; | |
787 frame.origin.x = mouse_in_screen.x - drag_offset.x(); | |
788 frame.origin.y = mouse_in_screen.y - NSHeight(frame) + drag_offset.y(); | |
789 | |
790 // After setting the frame to correct the initial offset, the drag controller | |
791 // may immediately want to quit when it's notified of the new bounds. So the | |
792 // MoveLoop must be set up before the call to setFrame. | |
793 window_move_loop_.reset(new CocoaWindowMoveLoop(this)); | |
794 | |
795 // Animating may provide a less janky UX, but something custom would be | |
796 // required so that it follows updates to the mouse position. | |
797 [window_ setFrame:frame display:YES animate:NO]; | |
798 | |
799 // Setting the frame will call OnWidgetBoundsChanged(), which could result in | |
800 // a call to EndMoveLoop(). | |
801 if (!window_move_loop_) | |
802 return Widget::MOVE_LOOP_SUCCESSFUL; | |
803 | |
804 return window_move_loop_->Run(); | |
805 | |
806 // |this| may be destroyed during the RunLoop, causing it to exit early. | |
807 // Even if that doesn't happen, CocoaWindowMoveLoop will clean itself up by | |
808 // calling EndMoveLoop(). So window_move_loop_ will always be null before the | |
809 // function returns. But don't DCHECK since |this| might not be valid. | |
810 } | |
811 | |
812 void BridgedNativeWidget::EndMoveLoop() { | |
813 DCHECK(window_move_loop_); | |
814 window_move_loop_->End(); | |
815 window_move_loop_.reset(); | |
816 } | |
817 | |
572 void BridgedNativeWidget::SetNativeWindowProperty(const char* name, | 818 void BridgedNativeWidget::SetNativeWindowProperty(const char* name, |
573 void* value) { | 819 void* value) { |
574 NSString* key = [NSString stringWithUTF8String:name]; | 820 NSString* key = [NSString stringWithUTF8String:name]; |
575 if (value) { | 821 if (value) { |
576 [GetWindowProperties() setObject:[NSValue valueWithPointer:value] | 822 [GetWindowProperties() setObject:[NSValue valueWithPointer:value] |
577 forKey:key]; | 823 forKey:key]; |
578 } else { | 824 } else { |
579 [GetWindowProperties() removeObjectForKey:key]; | 825 [GetWindowProperties() removeObjectForKey:key]; |
580 } | 826 } |
581 } | 827 } |
582 | 828 |
583 void* BridgedNativeWidget::GetNativeWindowProperty(const char* name) const { | 829 void* BridgedNativeWidget::GetNativeWindowProperty(const char* name) const { |
584 NSString* key = [NSString stringWithUTF8String:name]; | 830 NSString* key = [NSString stringWithUTF8String:name]; |
585 return [[GetWindowProperties() objectForKey:key] pointerValue]; | 831 return [[GetWindowProperties() objectForKey:key] pointerValue]; |
586 } | 832 } |
587 | 833 |
588 void BridgedNativeWidget::SetCursor(NSCursor* cursor) { | 834 void BridgedNativeWidget::SetCursor(NSCursor* cursor) { |
589 [window_delegate_ setCursor:cursor]; | 835 [window_delegate_ setCursor:cursor]; |
590 } | 836 } |
591 | 837 |
592 void BridgedNativeWidget::OnWindowWillClose() { | 838 void BridgedNativeWidget::OnWindowWillClose() { |
839 DCHECK(!drag_run_loop_); | |
593 if (parent_) { | 840 if (parent_) { |
594 parent_->RemoveChildWindow(this); | 841 parent_->RemoveChildWindow(this); |
595 parent_ = nullptr; | 842 parent_ = nullptr; |
596 } | 843 } |
597 [window_ setDelegate:nil]; | 844 [window_ setDelegate:nil]; |
598 [[NSNotificationCenter defaultCenter] removeObserver:window_delegate_]; | 845 [[NSNotificationCenter defaultCenter] removeObserver:window_delegate_]; |
599 native_widget_mac_->OnWindowWillClose(); | 846 native_widget_mac_->OnWindowWillClose(); |
600 } | 847 } |
601 | 848 |
602 void BridgedNativeWidget::OnFullscreenTransitionStart( | 849 void BridgedNativeWidget::OnFullscreenTransitionStart( |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
685 | 932 |
686 // 10.9 is unable to generate a window shadow from the composited CALayer, so | 933 // 10.9 is unable to generate a window shadow from the composited CALayer, so |
687 // use Quartz. | 934 // use Quartz. |
688 // We don't update the window mask during a live resize, instead it is done | 935 // We don't update the window mask during a live resize, instead it is done |
689 // after the resize is completed in viewDidEndLiveResize: in | 936 // after the resize is completed in viewDidEndLiveResize: in |
690 // BridgedContentView. | 937 // BridgedContentView. |
691 if (base::mac::IsOSMavericksOrEarlier() && ![window_ inLiveResize]) | 938 if (base::mac::IsOSMavericksOrEarlier() && ![window_ inLiveResize]) |
692 [bridged_view_ updateWindowMask]; | 939 [bridged_view_ updateWindowMask]; |
693 } | 940 } |
694 | 941 |
942 void BridgedNativeWidget::OnPositionChanged() { | |
943 native_widget_mac_->GetWidget()->OnNativeWidgetMove(); | |
944 } | |
945 | |
695 void BridgedNativeWidget::OnVisibilityChanged() { | 946 void BridgedNativeWidget::OnVisibilityChanged() { |
696 OnVisibilityChangedTo([window_ isVisible]); | 947 OnVisibilityChangedTo([window_ isVisible]); |
697 } | 948 } |
698 | 949 |
699 void BridgedNativeWidget::OnVisibilityChangedTo(bool new_visibility) { | 950 void BridgedNativeWidget::OnVisibilityChangedTo(bool new_visibility) { |
700 if (window_visible_ == new_visibility) | 951 if (window_visible_ == new_visibility) |
701 return; | 952 return; |
702 | 953 |
703 window_visible_ = new_visibility; | 954 window_visible_ = new_visibility; |
704 | 955 |
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1238 [bridged_view_ setMouseDownCanMoveWindow:draggable]; | 1489 [bridged_view_ setMouseDownCanMoveWindow:draggable]; |
1239 // AppKit will not update its cache of mouseDownCanMoveWindow unless something | 1490 // AppKit will not update its cache of mouseDownCanMoveWindow unless something |
1240 // changes. Previously we tried adding an NSView and removing it, but for some | 1491 // 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. | 1492 // reason it required reposting the mouse-down event, and didn't always work. |
1242 // Calling the below seems to be an effective solution. | 1493 // Calling the below seems to be an effective solution. |
1243 [window_ setMovableByWindowBackground:NO]; | 1494 [window_ setMovableByWindowBackground:NO]; |
1244 [window_ setMovableByWindowBackground:YES]; | 1495 [window_ setMovableByWindowBackground:YES]; |
1245 } | 1496 } |
1246 | 1497 |
1247 } // namespace views | 1498 } // namespace views |
OLD | NEW |