OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/browser/automation/automation_provider.h" | 5 #include "chrome/browser/automation/automation_provider.h" |
6 | 6 |
7 #include <gtk/gtk.h> | 7 #include <gtk/gtk.h> |
8 | 8 |
| 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" |
| 11 #include "base/callback.h" |
9 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
10 #include "chrome/browser/automation/automation_browser_tracker.h" | 13 #include "chrome/browser/automation/automation_browser_tracker.h" |
11 #include "chrome/browser/automation/automation_window_tracker.h" | 14 #include "chrome/browser/automation/automation_window_tracker.h" |
12 #include "chrome/browser/automation/ui_controls.h" | 15 #include "chrome/browser/automation/ui_controls.h" |
13 #include "chrome/browser/ui/browser.h" | 16 #include "chrome/browser/ui/browser.h" |
14 #include "chrome/browser/ui/gtk/browser_window_gtk.h" | 17 #include "chrome/browser/ui/gtk/browser_window_gtk.h" |
15 #include "chrome/browser/ui/gtk/gtk_util.h" | 18 #include "chrome/browser/ui/gtk/gtk_util.h" |
16 #include "chrome/browser/ui/gtk/view_id_util.h" | 19 #include "chrome/browser/ui/gtk/view_id_util.h" |
17 #include "chrome/common/automation_messages.h" | 20 #include "chrome/common/automation_messages.h" |
18 #include "ui/gfx/point.h" | 21 #include "ui/gfx/point.h" |
19 #include "ui/gfx/rect.h" | 22 #include "ui/gfx/rect.h" |
20 | 23 |
| 24 namespace { |
| 25 |
| 26 // This function sends a WindowDragResponse message with the appropriate routing |
| 27 // ID to the automation proxy. |
| 28 void SendWindowDragResponse(AutomationProvider* provider, |
| 29 IPC::Message* reply_message) { |
| 30 AutomationMsg_WindowDrag::WriteReplyParams(reply_message, true); |
| 31 provider->Send(reply_message); |
| 32 } |
| 33 |
| 34 } // namespace |
| 35 |
21 void AutomationProvider::PrintAsync(int tab_handle) { | 36 void AutomationProvider::PrintAsync(int tab_handle) { |
22 NOTIMPLEMENTED(); | 37 NOTIMPLEMENTED(); |
23 } | 38 } |
24 | 39 |
25 // This task sends a WindowDragResponse message with the appropriate | |
26 // routing ID to the automation proxy. This is implemented as a task so that | |
27 // we know that the mouse events (and any tasks that they spawn on the message | |
28 // loop) have been processed by the time this is sent. | |
29 class WindowDragResponseTask : public Task { | |
30 public: | |
31 WindowDragResponseTask(AutomationProvider* provider, | |
32 IPC::Message* reply_message) | |
33 : provider_(provider), | |
34 reply_message_(reply_message) { | |
35 DCHECK(provider_); | |
36 DCHECK(reply_message_); | |
37 } | |
38 | |
39 virtual ~WindowDragResponseTask() { | |
40 } | |
41 | |
42 virtual void Run() { | |
43 AutomationMsg_WindowDrag::WriteReplyParams(reply_message_, true); | |
44 provider_->Send(reply_message_); | |
45 } | |
46 | |
47 private: | |
48 AutomationProvider* provider_; | |
49 IPC::Message* reply_message_; | |
50 | |
51 DISALLOW_COPY_AND_ASSIGN(WindowDragResponseTask); | |
52 }; | |
53 | |
54 // A task that just runs a SendMouseEvent and performs another task when done. | |
55 class MouseEventTask : public Task { | |
56 public: | |
57 MouseEventTask(Task* next_task, ui_controls::MouseButtonState state) | |
58 : next_task_(next_task), | |
59 state_(state) {} | |
60 | |
61 virtual ~MouseEventTask() { | |
62 } | |
63 | |
64 virtual void Run() { | |
65 ui_controls::SendMouseEventsNotifyWhenDone(ui_controls::LEFT, state_, | |
66 next_task_); | |
67 } | |
68 | |
69 private: | |
70 // The task to execute when we are done. | |
71 Task* next_task_; | |
72 | |
73 // Mouse press or mouse release. | |
74 ui_controls::MouseButtonState state_; | |
75 | |
76 DISALLOW_COPY_AND_ASSIGN(MouseEventTask); | |
77 }; | |
78 | |
79 // A task that just runs a SendMouseMove and performs another task when done. | |
80 class MouseMoveTask : public Task { | |
81 public: | |
82 MouseMoveTask(Task* next_task, int absolute_x, int absolute_y) | |
83 : next_task_(next_task), | |
84 x_(absolute_x), | |
85 y_(absolute_y) { | |
86 } | |
87 | |
88 virtual ~MouseMoveTask() { | |
89 } | |
90 | |
91 virtual void Run() { | |
92 ui_controls::SendMouseMoveNotifyWhenDone(x_, y_, next_task_); | |
93 } | |
94 | |
95 private: | |
96 // The task to execute when we are done. | |
97 Task* next_task_; | |
98 | |
99 // Coordinates of the press. | |
100 int x_; | |
101 int y_; | |
102 | |
103 DISALLOW_COPY_AND_ASSIGN(MouseMoveTask); | |
104 }; | |
105 | |
106 void AutomationProvider::WindowSimulateDrag( | 40 void AutomationProvider::WindowSimulateDrag( |
107 int handle, | 41 int handle, |
108 const std::vector<gfx::Point>& drag_path, | 42 const std::vector<gfx::Point>& drag_path, |
109 int flags, | 43 int flags, |
110 bool press_escape_en_route, | 44 bool press_escape_en_route, |
111 IPC::Message* reply_message) { | 45 IPC::Message* reply_message) { |
112 // TODO(estade): don't ignore |flags| or |escape_en_route|. | 46 // TODO(estade): don't ignore |flags| or |escape_en_route|. |
113 gfx::NativeWindow window = | 47 gfx::NativeWindow window = |
114 browser_tracker_->GetResource(handle)->window()->GetNativeHandle(); | 48 browser_tracker_->GetResource(handle)->window()->GetNativeHandle(); |
115 if (window && (drag_path.size() > 1)) { | 49 if (window && (drag_path.size() > 1)) { |
116 int x, y; | 50 int x, y; |
117 gdk_window_get_position(GTK_WIDGET(window)->window, &x, &y); | 51 gdk_window_get_position(GTK_WIDGET(window)->window, &x, &y); |
118 | 52 |
119 // Create a nested stack of tasks to run. | 53 // Create a nested stack of tasks to run. |
120 Task* next_task = new WindowDragResponseTask(this, reply_message); | 54 base::Closure drag_response_cb = base::Bind( |
121 next_task = new MouseEventTask(next_task, ui_controls::UP); | 55 &SendWindowDragResponse, make_scoped_refptr(this), reply_message); |
122 next_task = new MouseEventTask(next_task, ui_controls::UP); | 56 base::Closure move_chain_cb = base::IgnoreReturn<bool>( |
| 57 base::Bind(&ui_controls::SendMouseEventsNotifyWhenDone, |
| 58 ui_controls::LEFT, ui_controls::UP, drag_response_cb)); |
| 59 move_chain_cb = base::IgnoreReturn<bool>( |
| 60 base::Bind(&ui_controls::SendMouseEventsNotifyWhenDone, |
| 61 ui_controls::LEFT, ui_controls::UP, move_chain_cb)); |
123 for (size_t i = drag_path.size() - 1; i > 0; --i) { | 62 for (size_t i = drag_path.size() - 1; i > 0; --i) { |
124 // Smooth out the mouse movements by adding intermediate points. This | 63 // Smooth out the mouse movements by adding intermediate points. This |
125 // better simulates a real user drag. | 64 // better simulates a real user drag. |
126 int dest_x = drag_path[i].x() + x; | 65 int dest_x = drag_path[i].x() + x; |
127 int dest_y = drag_path[i].y() + y; | 66 int dest_y = drag_path[i].y() + y; |
128 int half_step_x = (dest_x + drag_path[i - 1].x() + x) / 2; | 67 int half_step_x = (dest_x + drag_path[i - 1].x() + x) / 2; |
129 int half_step_y = (dest_y + drag_path[i - 1].y() + y) / 2; | 68 int half_step_y = (dest_y + drag_path[i - 1].y() + y) / 2; |
130 | 69 |
131 next_task = new MouseMoveTask(next_task, dest_x, dest_y); | 70 move_chain_cb = base::IgnoreReturn<bool>( |
132 next_task = new MouseMoveTask(next_task, half_step_x, half_step_y); | 71 base::Bind(&ui_controls::SendMouseMoveNotifyWhenDone, dest_x, dest_y, |
| 72 move_chain_cb)); |
| 73 move_chain_cb = base::IgnoreReturn<bool>( |
| 74 base::Bind(&ui_controls::SendMouseMoveNotifyWhenDone, half_step_x, |
| 75 half_step_y, move_chain_cb)); |
133 } | 76 } |
134 next_task = new MouseEventTask(next_task, ui_controls::DOWN); | 77 move_chain_cb = base::IgnoreReturn<bool>( |
| 78 base::Bind(&ui_controls::SendMouseEventsNotifyWhenDone, |
| 79 ui_controls::LEFT, ui_controls::DOWN, move_chain_cb)); |
135 | 80 |
136 ui_controls::SendMouseMoveNotifyWhenDone(x + drag_path[0].x(), | 81 ui_controls::SendMouseMoveNotifyWhenDone(x + drag_path[0].x(), |
137 y + drag_path[0].y(), | 82 y + drag_path[0].y(), |
138 next_task); | 83 move_chain_cb); |
139 } else { | 84 } else { |
140 AutomationMsg_WindowDrag::WriteReplyParams(reply_message, false); | 85 AutomationMsg_WindowDrag::WriteReplyParams(reply_message, false); |
141 Send(reply_message); | 86 Send(reply_message); |
142 } | 87 } |
143 } | 88 } |
OLD | NEW |