Chromium Code Reviews| 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/callback.h" | |
| 9 #include "base/utf_string_conversions.h" | 11 #include "base/utf_string_conversions.h" |
| 10 #include "chrome/browser/automation/automation_browser_tracker.h" | 12 #include "chrome/browser/automation/automation_browser_tracker.h" |
| 11 #include "chrome/browser/automation/automation_window_tracker.h" | 13 #include "chrome/browser/automation/automation_window_tracker.h" |
| 12 #include "chrome/browser/automation/ui_controls.h" | 14 #include "chrome/browser/automation/ui_controls.h" |
| 13 #include "chrome/browser/ui/browser.h" | 15 #include "chrome/browser/ui/browser.h" |
| 14 #include "chrome/browser/ui/gtk/browser_window_gtk.h" | 16 #include "chrome/browser/ui/gtk/browser_window_gtk.h" |
| 15 #include "chrome/browser/ui/gtk/gtk_util.h" | 17 #include "chrome/browser/ui/gtk/gtk_util.h" |
| 16 #include "chrome/browser/ui/gtk/view_id_util.h" | 18 #include "chrome/browser/ui/gtk/view_id_util.h" |
| 17 #include "chrome/common/automation_messages.h" | 19 #include "chrome/common/automation_messages.h" |
| 18 #include "ui/gfx/point.h" | 20 #include "ui/gfx/point.h" |
| 19 #include "ui/gfx/rect.h" | 21 #include "ui/gfx/rect.h" |
| 20 | 22 |
| 23 namespace { | |
| 24 | |
| 25 // This function sends a WindowDragResponse message with the appropriate routing | |
| 26 // ID to the automation proxy. | |
| 27 void WindowDragResponse(AutomationProvider* provider, | |
| 28 IPC::Message* reply_message) { | |
| 29 AutomationMsg_WindowDrag::WriteReplyParams(reply_message, true); | |
| 30 provider->Send(reply_message); | |
| 31 } | |
| 32 | |
| 33 // TODO(jhawkins): Get rid of these functions once base::Bind supports functions | |
| 34 // with non-void return values. | |
| 35 void SendMouseEventsNotifyWhenDoneWithoutResult( | |
| 36 ui_controls::MouseButton type, int state, const base::Closure& task) { | |
| 37 ui_controls::SendMouseEventsNotifyWhenDone(type, state, task); | |
| 38 } | |
| 39 | |
| 40 void SendMouseMoveNotifyWhenDoneWithoutResult( | |
| 41 long x, long y, const base::Closure& task) { | |
| 42 ui_controls::SendMouseMoveNotifyWhenDone(x, y, task); | |
| 43 } | |
| 44 | |
| 45 } // namespace | |
| 46 | |
| 21 void AutomationProvider::PrintAsync(int tab_handle) { | 47 void AutomationProvider::PrintAsync(int tab_handle) { |
| 22 NOTIMPLEMENTED(); | 48 NOTIMPLEMENTED(); |
| 23 } | 49 } |
| 24 | 50 |
| 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( | 51 void AutomationProvider::WindowSimulateDrag( |
| 107 int handle, | 52 int handle, |
| 108 const std::vector<gfx::Point>& drag_path, | 53 const std::vector<gfx::Point>& drag_path, |
| 109 int flags, | 54 int flags, |
| 110 bool press_escape_en_route, | 55 bool press_escape_en_route, |
| 111 IPC::Message* reply_message) { | 56 IPC::Message* reply_message) { |
| 112 // TODO(estade): don't ignore |flags| or |escape_en_route|. | 57 // TODO(estade): don't ignore |flags| or |escape_en_route|. |
| 113 gfx::NativeWindow window = | 58 gfx::NativeWindow window = |
| 114 browser_tracker_->GetResource(handle)->window()->GetNativeHandle(); | 59 browser_tracker_->GetResource(handle)->window()->GetNativeHandle(); |
| 115 if (window && (drag_path.size() > 1)) { | 60 if (window && (drag_path.size() > 1)) { |
| 116 int x, y; | 61 int x, y; |
| 117 gdk_window_get_position(GTK_WIDGET(window)->window, &x, &y); | 62 gdk_window_get_position(GTK_WIDGET(window)->window, &x, &y); |
| 118 | 63 |
| 119 // Create a nested stack of tasks to run. | 64 // Create a nested stack of tasks to run. |
| 120 Task* next_task = new WindowDragResponseTask(this, reply_message); | 65 base::Closure task1 = base::Bind(&WindowDragResponse, |
| 121 next_task = new MouseEventTask(next_task, ui_controls::UP); | 66 make_scoped_refptr(this), reply_message); |
| 122 next_task = new MouseEventTask(next_task, ui_controls::UP); | 67 base::Closure task2 = |
| 68 base::Bind(&SendMouseEventsNotifyWhenDoneWithoutResult, | |
| 69 ui_controls::LEFT, ui_controls::UP, task1); | |
| 70 base::Closure task3 = | |
| 71 base::Bind(&SendMouseEventsNotifyWhenDoneWithoutResult, | |
| 72 ui_controls::LEFT, ui_controls::UP, task2); | |
| 73 base::Closure task4, task5; | |
| 74 base::Closure* task = &task3; | |
| 123 for (size_t i = drag_path.size() - 1; i > 0; --i) { | 75 for (size_t i = drag_path.size() - 1; i > 0; --i) { |
| 124 // Smooth out the mouse movements by adding intermediate points. This | 76 // Smooth out the mouse movements by adding intermediate points. This |
| 125 // better simulates a real user drag. | 77 // better simulates a real user drag. |
| 126 int dest_x = drag_path[i].x() + x; | 78 int dest_x = drag_path[i].x() + x; |
| 127 int dest_y = drag_path[i].y() + y; | 79 int dest_y = drag_path[i].y() + y; |
| 128 int half_step_x = (dest_x + drag_path[i - 1].x() + x) / 2; | 80 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; | 81 int half_step_y = (dest_y + drag_path[i - 1].y() + y) / 2; |
| 130 | 82 |
| 131 next_task = new MouseMoveTask(next_task, dest_x, dest_y); | 83 task4 = base::Bind(&SendMouseMoveNotifyWhenDoneWithoutResult, dest_x, |
| 132 next_task = new MouseMoveTask(next_task, half_step_x, half_step_y); | 84 dest_y, *task); |
| 85 task5 = base::Bind(&SendMouseMoveNotifyWhenDoneWithoutResult, half_step_x, | |
| 86 half_step_y, task4); | |
| 87 task = &task5; | |
|
awong
2011/10/11 01:18:04
Why bother with a task* at all? Just copy?
In fa
James Hawkins
2011/10/11 21:11:22
Done.
| |
| 133 } | 88 } |
| 134 next_task = new MouseEventTask(next_task, ui_controls::DOWN); | 89 base::Closure task6 = |
| 90 base::Bind(&SendMouseEventsNotifyWhenDoneWithoutResult, | |
| 91 ui_controls::LEFT, ui_controls::DOWN, *task); | |
| 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 task6); |
| 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 |