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

Side by Side Diff: chrome/test/base/interactive_test_utils_mac.mm

Issue 1747803003: MacViews: Implement Tab Dragging (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Extract DragsWindowUsingCocoaMoveLoop test, cleanup code. 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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 #include "chrome/test/base/interactive_test_utils.h" 5 #include "chrome/test/base/interactive_test_utils.h"
6 6
7 #include <Carbon/Carbon.h> 7 #include <Carbon/Carbon.h>
8 #import <Cocoa/Cocoa.h> 8 #import <Cocoa/Cocoa.h>
9 9
10 #include "base/message_loop/message_loop.h" 10 #include "base/message_loop/message_loop.h"
11 #include "chrome/app/chrome_command_ids.h" 11 #include "chrome/app/chrome_command_ids.h"
12 #include "chrome/browser/ui/views/tabs/window_finder.h"
13 #include "content/public/test/test_utils.h"
12 #import "ui/base/test/windowed_nsnotification_observer.h" 14 #import "ui/base/test/windowed_nsnotification_observer.h"
15 #include "ui/gfx/animation/tween.h"
16 #include "ui/gfx/mac/coordinate_conversion.h"
17 #include "ui/views/cocoa/bridged_native_widget.h"
18 #include "ui/views/event_monitor.h"
19 #include "ui/views/widget/native_widget_mac.h"
20
21 namespace views {
22 namespace test {
23 class BridgedNativeWidgetTestApi {
tapted 2016/03/10 11:51:19 ooh interesting - there's already a BridgedNativeW
themblsha 2016/03/10 17:18:58 I've added BridgedNativeWidget::IsRunMoveLoopActiv
tapted 2016/03/11 09:38:28 nice - I like IsRunMoveLoopActive But did you see
24 public:
25 explicit BridgedNativeWidgetTestApi(NSWindow* window) {
26 bridge_ = NativeWidgetMac::GetBridgeForNativeWindow(window);
27 DCHECK(bridge_);
28 }
29
30 bool WindowIsMoving() const {
31 return bridge_->window_move_loop_.get();
32 }
33
34 private:
35 BridgedNativeWidget* bridge_;
36
37 DISALLOW_COPY_AND_ASSIGN(BridgedNativeWidgetTestApi);
38 };
39 } // namespace test
40 } // namespace views
41
42 namespace {
43
44 bool WaitForEvent(
45 bool (^dispatch_event_block)(const base::Closure& quit_closure)) {
46 scoped_refptr<content::MessageLoopRunner> runner =
47 new content::MessageLoopRunner;
48 bool result = dispatch_event_block(runner->QuitClosure());
49 runner->Run();
50 return result;
51 }
52
53 bool MouseMove(const gfx::Point& p) {
54 return WaitForEvent(^(const base::Closure& quit_closure) {
55 return ui_controls::SendMouseMoveNotifyWhenDone(p.x(), p.y(), quit_closure);
56 });
57 }
58
59 bool MouseDown() {
60 return WaitForEvent(^(const base::Closure& quit_closure) {
61 return ui_controls::SendMouseEventsNotifyWhenDone(
62 ui_controls::LEFT, ui_controls::DOWN, quit_closure);
63 });
64 }
65
66 bool MouseUp() {
67 return WaitForEvent(^(const base::Closure& quit_closure) {
68 return ui_controls::SendMouseEventsNotifyWhenDone(
69 ui_controls::LEFT, ui_controls::UP, quit_closure);
70 });
71 }
72
73 class ScopedCGEventsEnabler {
74 public:
75 ScopedCGEventsEnabler()
76 : enable_cgevents_(ui_controls::SendMouseEventsAsCGEvents()) {
77 ui_controls::SetSendMouseEventsAsCGEvents(true);
78 }
79
80 ~ScopedCGEventsEnabler() {
81 ui_controls::SetSendMouseEventsAsCGEvents(enable_cgevents_);
82 }
83
84 private:
85 bool enable_cgevents_;
86 };
87
88 void RunAtBackgroundQueue(void (^block)()) {
89 auto queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
90 scoped_refptr<content::MessageLoopRunner> runner =
91 new content::MessageLoopRunner;
92
93 dispatch_async(queue, ^{
94 scoped_ptr<base::MessageLoop> loop(
95 new base::MessageLoop(base::MessageLoop::TYPE_DEFAULT));
96
97 block();
98
99 dispatch_async(dispatch_get_main_queue(), ^{
100 runner->Quit();
101 });
102 });
103
104 // We need to run the loop on the main thread, so the mouse events will be
105 // actually processed.
106 runner->Run();
107 }
108
109 void WaitForSystemWindowMoveToStop() {
110 // NOTE: This is a potentially troublesome part, currently it only works
111 // with MacViewsBrowser when the moved window entered RunMoveLoop.
112 // On non-MacViewsBrowser builds or when the window was moved using the
113 // caption we would be unable to detect that the window was moved using the
114 // WindowServer and would not wait for the final NSWindowMovedEventType
115 // notification.
116 //
117 // As a possible solution it would be possible to add an
118 // additional argument to the function
119 // |force_wait_for_system_window_move_to_finish|, and force waiting for
120 // notification if this ever becomes a problem.
121 NSWindow* window =
122 GetLocalProcessWindowAtPoint(views::EventMonitor::GetLastMouseLocation(),
123 std::set<gfx::NativeWindow>());
124 const bool window_is_moving_by_system =
125 window &&
126 views::test::BridgedNativeWidgetTestApi(window).WindowIsMoving();
127
128 if (window_is_moving_by_system) {
129 // Wait for a final NSWindowMovedEventType notification, otherwise
130 // the window won't be in the final position. It arrives asynchronously
131 // after the mouse move events.
132 NSEvent* window_move_event =
133 [NSEvent otherEventWithType:NSAppKitDefined
134 location:NSZeroPoint
135 modifierFlags:0
136 timestamp:0
137 windowNumber:0
138 context:0
139 subtype:NSWindowMovedEventType
140 data1:0
141 data2:0];
142 scoped_refptr<content::MessageLoopRunner> no_window_move_runner =
143 new content::MessageLoopRunner;
144 ui_controls::NotifyWhenEventIsProcessed(
145 window_move_event, no_window_move_runner->QuitClosure());
146 no_window_move_runner->Run();
147 }
148 }
149
150 } // namespace
13 151
14 namespace ui_test_utils { 152 namespace ui_test_utils {
15 153
16 void HideNativeWindow(gfx::NativeWindow window) { 154 void HideNativeWindow(gfx::NativeWindow window) {
17 [window orderOut:nil]; 155 [window orderOut:nil];
18 } 156 }
19 157
20 bool ShowAndFocusNativeWindow(gfx::NativeWindow window) { 158 bool ShowAndFocusNativeWindow(gfx::NativeWindow window) {
21 // Make sure an unbundled program can get the input focus. 159 // Make sure an unbundled program can get the input focus.
22 ProcessSerialNumber psn = { 0, kCurrentProcess }; 160 ProcessSerialNumber psn = { 0, kCurrentProcess };
(...skipping 14 matching lines...) Expand all
37 // This is because normal AppKit menu updating does not get invoked when 175 // This is because normal AppKit menu updating does not get invoked when
38 // events are sent via ui_test_utils::SendKeyPressSync. 176 // events are sent via ui_test_utils::SendKeyPressSync.
39 BOOL notification_observed = [async_waiter wait]; 177 BOOL notification_observed = [async_waiter wait];
40 base::RunLoop().RunUntilIdle(); // There may be other events queued. Flush. 178 base::RunLoop().RunUntilIdle(); // There may be other events queued. Flush.
41 NSMenu* file_menu = [[[NSApp mainMenu] itemWithTag:IDC_FILE_MENU] submenu]; 179 NSMenu* file_menu = [[[NSApp mainMenu] itemWithTag:IDC_FILE_MENU] submenu];
42 [[file_menu delegate] menuNeedsUpdate:file_menu]; 180 [[file_menu delegate] menuNeedsUpdate:file_menu];
43 181
44 return !async_waiter || notification_observed; 182 return !async_waiter || notification_observed;
45 } 183 }
46 184
185 void DragAndDrop(const gfx::Point& from,
186 const gfx::Point& to,
187 base::TimeDelta delay,
188 unsigned int steps) {
189 DCHECK_GE(steps, 1u);
190
191 ScopedCGEventsEnabler cgevents_enabler;
192
193 RunAtBackgroundQueue(^() {
194 MouseMove(from);
195 MouseDown();
196
197 // If steps is greater than 1, then we need to use CGEvents, otherwise
198 // the CocoaWindowMoveLoop won't actually work, as the window dragging works
199 // on the WindowServer level.
200 for (unsigned int i = 1; i <= steps; ++i) {
tapted 2016/03/10 11:51:19 nit: just int
themblsha 2016/03/10 17:18:58 Done.
201 const double progress = double(i) / steps;
tapted 2016/03/10 11:51:19 we tend to use static_cast instead of this style -
themblsha 2016/03/10 17:18:58 Done.
202 const gfx::Point p(
203 gfx::Tween::IntValueBetween(progress, from.x(), to.x()),
204 gfx::Tween::IntValueBetween(progress, from.y(), to.y()));
205 MouseMove(p);
206 }
207
208 // Specify a delay if there's a non-zero drag'n'drop delay, like
209 // kTearDuration in tab_strip_drag_controller.mm
210 usleep(delay.InMicroseconds());
tapted 2016/03/10 11:51:19 yeah - I think we can remove this for now? - `usle
themblsha 2016/03/10 17:18:58 Okay :-)
211
212 WaitForSystemWindowMoveToStop();
213 MouseUp();
214 });
215 }
216
47 } // namespace ui_test_utils 217 } // namespace ui_test_utils
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698