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 WindowDragResponse(AutomationProvider* provider, | |
csilv
2011/10/11 21:48:00
maybe 'SendWindowDragResponse' would be a better n
James Hawkins
2011/10/11 21:54:20
Done.
| |
29 IPC::Message* reply_message) { | |
30 AutomationMsg_WindowDrag::WriteReplyParams(reply_message, true); | |
31 provider->Send(reply_message); | |
32 } | |
33 | |
34 // TODO(jhawkins): Get rid of these functions once base::Bind supports functions | |
35 // with non-void return values. | |
36 void SendMouseEventsNotifyWhenDoneWithoutResult( | |
37 ui_controls::MouseButton type, int state, const base::Closure& task) { | |
38 ui_controls::SendMouseEventsNotifyWhenDone(type, state, task); | |
39 } | |
40 | |
41 void SendMouseMoveNotifyWhenDoneWithoutResult( | |
42 long x, long y, const base::Closure& task) { | |
43 ui_controls::SendMouseMoveNotifyWhenDone(x, y, task); | |
44 } | |
45 | |
46 } // namespace | |
47 | |
21 void AutomationProvider::PrintAsync(int tab_handle) { | 48 void AutomationProvider::PrintAsync(int tab_handle) { |
22 NOTIMPLEMENTED(); | 49 NOTIMPLEMENTED(); |
23 } | 50 } |
24 | 51 |
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( | 52 void AutomationProvider::WindowSimulateDrag( |
107 int handle, | 53 int handle, |
108 const std::vector<gfx::Point>& drag_path, | 54 const std::vector<gfx::Point>& drag_path, |
109 int flags, | 55 int flags, |
110 bool press_escape_en_route, | 56 bool press_escape_en_route, |
111 IPC::Message* reply_message) { | 57 IPC::Message* reply_message) { |
112 // TODO(estade): don't ignore |flags| or |escape_en_route|. | 58 // TODO(estade): don't ignore |flags| or |escape_en_route|. |
113 gfx::NativeWindow window = | 59 gfx::NativeWindow window = |
114 browser_tracker_->GetResource(handle)->window()->GetNativeHandle(); | 60 browser_tracker_->GetResource(handle)->window()->GetNativeHandle(); |
115 if (window && (drag_path.size() > 1)) { | 61 if (window && (drag_path.size() > 1)) { |
116 int x, y; | 62 int x, y; |
117 gdk_window_get_position(GTK_WIDGET(window)->window, &x, &y); | 63 gdk_window_get_position(GTK_WIDGET(window)->window, &x, &y); |
118 | 64 |
119 // Create a nested stack of tasks to run. | 65 // Create a nested stack of tasks to run. |
120 Task* next_task = new WindowDragResponseTask(this, reply_message); | 66 base::Closure drag_response_cb = base::Bind( |
121 next_task = new MouseEventTask(next_task, ui_controls::UP); | 67 &WindowDragResponse, make_scoped_refptr(this), reply_message); |
122 next_task = new MouseEventTask(next_task, ui_controls::UP); | 68 base::Closure move_chain_cb = base::IgnoreReturn<bool>( |
69 base::Bind(&ui_controls::SendMouseEventsNotifyWhenDone, | |
70 ui_controls::LEFT, ui_controls::UP, drag_response_cb)); | |
71 move_chain_cb = base::IgnoreReturn<bool>( | |
72 base::Bind(&ui_controls::SendMouseEventsNotifyWhenDone, | |
73 ui_controls::LEFT, ui_controls::UP, move_chain_cb)); | |
123 for (size_t i = drag_path.size() - 1; i > 0; --i) { | 74 for (size_t i = drag_path.size() - 1; i > 0; --i) { |
124 // Smooth out the mouse movements by adding intermediate points. This | 75 // Smooth out the mouse movements by adding intermediate points. This |
125 // better simulates a real user drag. | 76 // better simulates a real user drag. |
126 int dest_x = drag_path[i].x() + x; | 77 int dest_x = drag_path[i].x() + x; |
127 int dest_y = drag_path[i].y() + y; | 78 int dest_y = drag_path[i].y() + y; |
128 int half_step_x = (dest_x + drag_path[i - 1].x() + x) / 2; | 79 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; | 80 int half_step_y = (dest_y + drag_path[i - 1].y() + y) / 2; |
130 | 81 |
131 next_task = new MouseMoveTask(next_task, dest_x, dest_y); | 82 move_chain_cb = base::IgnoreReturn<bool>( |
132 next_task = new MouseMoveTask(next_task, half_step_x, half_step_y); | 83 base::Bind(&ui_controls::SendMouseMoveNotifyWhenDone, dest_x, dest_y, |
84 move_chain_cb)); | |
85 move_chain_cb = base::IgnoreReturn<bool>( | |
86 base::Bind(&ui_controls::SendMouseMoveNotifyWhenDone, half_step_x, | |
87 half_step_y, move_chain_cb)); | |
133 } | 88 } |
134 next_task = new MouseEventTask(next_task, ui_controls::DOWN); | 89 move_chain_cb = base::IgnoreReturn<bool>( |
90 base::Bind(&ui_controls::SendMouseEventsNotifyWhenDone, | |
91 ui_controls::LEFT, ui_controls::DOWN, move_chain_cb)); | |
135 | 92 |
136 ui_controls::SendMouseMoveNotifyWhenDone(x + drag_path[0].x(), | 93 ui_controls::SendMouseMoveNotifyWhenDone(x + drag_path[0].x(), |
137 y + drag_path[0].y(), | 94 y + drag_path[0].y(), |
138 next_task); | 95 move_chain_cb); |
139 } else { | 96 } else { |
140 AutomationMsg_WindowDrag::WriteReplyParams(reply_message, false); | 97 AutomationMsg_WindowDrag::WriteReplyParams(reply_message, false); |
141 Send(reply_message); | 98 Send(reply_message); |
142 } | 99 } |
143 } | 100 } |
OLD | NEW |