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

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

Issue 1747803003: MacViews: Implement Tab Dragging (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix include. Created 4 years, 6 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
« no previous file with comments | « ui/views/cocoa/cocoa_window_move_loop.h ('k') | ui/views/cocoa/views_nswindow_delegate.mm » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/views/cocoa/cocoa_window_move_loop.h"
6
7 #include "base/run_loop.h"
8 #include "ui/display/screen.h"
9 #import "ui/gfx/mac/coordinate_conversion.h"
10 #import "ui/views/cocoa/bridged_native_widget.h"
11
12 // When event monitors process the events the full list of monitors is cached,
13 // and if we unregister the event monitor that's at the end of the list while
14 // processing the first monitor's handler -- the callback for the unregistered
15 // monitor will still be called even though it's unregistered. This will result
16 // in dereferencing an invalid pointer.
17 //
18 // WeakCocoaWindowMoveLoop is retained by the event monitor and stores weak
19 // pointer for the CocoaWindowMoveLoop, so there will be no invalid memory
20 // access.
21 @interface WeakCocoaWindowMoveLoop : NSObject {
22 @private
23 base::WeakPtr<views::CocoaWindowMoveLoop> weak_;
24 }
25 @end
26
27 @implementation WeakCocoaWindowMoveLoop
28 - (id)initWithWeakPtr:(const base::WeakPtr<views::CocoaWindowMoveLoop>&)weak {
29 if ((self = [super init])) {
30 weak_ = weak;
31 }
32 return self;
33 }
34
35 - (base::WeakPtr<views::CocoaWindowMoveLoop>&)weak {
36 return weak_;
37 }
38 @end
39
40 namespace views {
41
42 CocoaWindowMoveLoop::CocoaWindowMoveLoop(
43 BridgedNativeWidget* owner,
44 const NSPoint& initial_mouse_in_screen)
45 : owner_(owner),
46 initial_mouse_in_screen_(initial_mouse_in_screen),
47 weak_factory_(this) {
48 }
49
50 CocoaWindowMoveLoop::~CocoaWindowMoveLoop() {
51 // Handle the pathological case, where |this| is destroyed while running.
52 if (exit_reason_ref_) {
53 *exit_reason_ref_ = WINDOW_DESTROYED;
54 quit_closure_.Run();
55 }
56
57 owner_ = nullptr;
58 }
59
60 Widget::MoveLoopResult CocoaWindowMoveLoop::Run() {
61 LoopExitReason exit_reason = ENDED_EXTERNALLY;
62 exit_reason_ref_ = &exit_reason;
63 NSWindow* window = owner_->ns_window();
64 const NSRect initial_frame = [window frame];
65
66 base::RunLoop run_loop;
67 quit_closure_ = run_loop.QuitClosure();
68
69 // Will be retained by the monitor handler block.
70 WeakCocoaWindowMoveLoop* weak_cocoa_window_move_loop =
71 [[[WeakCocoaWindowMoveLoop alloc]
72 initWithWeakPtr:weak_factory_.GetWeakPtr()] autorelease];
73
74 // Esc keypress is handled by EscapeTracker, which is installed by
75 // TabDragController.
76 NSEventMask mask = NSLeftMouseUpMask | NSLeftMouseDraggedMask;
77 auto handler = ^NSEvent*(NSEvent* event) {
78 CocoaWindowMoveLoop* strong = [weak_cocoa_window_move_loop weak].get();
79 if (!strong || !strong->exit_reason_ref_) {
80 // By this point CocoaWindowMoveLoop was deleted while processing this
81 // same event, and this event monitor was not unregistered in time. See
82 // the WeakCocoaWindowMoveLoop comment above.
83 // Continue processing the event.
84 return event;
85 }
86
87 if ([event type] == NSLeftMouseDragged) {
88 const NSPoint mouse_in_screen = [NSEvent mouseLocation];
89
90 const NSRect ns_frame = NSOffsetRect(
91 initial_frame, mouse_in_screen.x - initial_mouse_in_screen_.x,
92 mouse_in_screen.y - initial_mouse_in_screen_.y);
93 [window setFrame:ns_frame display:NO animate:NO];
94
95 return event;
96 }
97
98 DCHECK_EQ([event type], NSLeftMouseUp);
99 *strong->exit_reason_ref_ = MOUSE_UP;
100 strong->quit_closure_.Run();
101 return event; // Process the MouseUp.
102 };
103 id monitor =
104 [NSEvent addLocalMonitorForEventsMatchingMask:mask handler:handler];
105
106 run_loop.Run();
107 [NSEvent removeMonitor:monitor];
108
109 if (exit_reason != WINDOW_DESTROYED && exit_reason != ENDED_EXTERNALLY) {
110 exit_reason_ref_ = nullptr; // Ensure End() doesn't replace the reason.
111 owner_->EndMoveLoop(); // Deletes |this|.
112 }
113
114 return exit_reason != MOUSE_UP ? Widget::MOVE_LOOP_CANCELED
115 : Widget::MOVE_LOOP_SUCCESSFUL;
116 }
117
118 void CocoaWindowMoveLoop::End() {
119 if (exit_reason_ref_) {
120 DCHECK_EQ(*exit_reason_ref_, ENDED_EXTERNALLY);
121 // Ensure the destructor doesn't replace the reason.
122 exit_reason_ref_ = nullptr;
123 quit_closure_.Run();
124 }
125 }
126
127 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/cocoa/cocoa_window_move_loop.h ('k') | ui/views/cocoa/views_nswindow_delegate.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698