• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/automation/automation_provider.h"
6 
7 #include <gtk/gtk.h>
8 
9 #include "base/utf_string_conversions.h"
10 #include "chrome/browser/automation/automation_browser_tracker.h"
11 #include "chrome/browser/automation/automation_window_tracker.h"
12 #include "chrome/browser/automation/ui_controls.h"
13 #include "chrome/browser/ui/browser.h"
14 #include "chrome/browser/ui/gtk/browser_window_gtk.h"
15 #include "chrome/browser/ui/gtk/gtk_util.h"
16 #include "chrome/browser/ui/gtk/view_id_util.h"
17 #include "chrome/common/automation_messages.h"
18 #include "ui/gfx/point.h"
19 #include "ui/gfx/rect.h"
20 
PrintAsync(int tab_handle)21 void AutomationProvider::PrintAsync(int tab_handle) {
22   NOTIMPLEMENTED();
23 }
24 
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:
WindowDragResponseTask(AutomationProvider * provider,IPC::Message * reply_message)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 
~WindowDragResponseTask()39   virtual ~WindowDragResponseTask() {
40   }
41 
Run()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:
MouseEventTask(Task * next_task,ui_controls::MouseButtonState state)57   MouseEventTask(Task* next_task, ui_controls::MouseButtonState state)
58       : next_task_(next_task),
59         state_(state) {}
60 
~MouseEventTask()61   virtual ~MouseEventTask() {
62   }
63 
Run()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:
MouseMoveTask(Task * next_task,int absolute_x,int absolute_y)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 
~MouseMoveTask()88   virtual ~MouseMoveTask() {
89   }
90 
Run()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 
WindowSimulateDrag(int handle,const std::vector<gfx::Point> & drag_path,int flags,bool press_escape_en_route,IPC::Message * reply_message)106 void AutomationProvider::WindowSimulateDrag(
107     int handle,
108     const std::vector<gfx::Point>& drag_path,
109     int flags,
110     bool press_escape_en_route,
111     IPC::Message* reply_message) {
112   // TODO(estade): don't ignore |flags| or |escape_en_route|.
113   gfx::NativeWindow window =
114       browser_tracker_->GetResource(handle)->window()->GetNativeHandle();
115   if (window && (drag_path.size() > 1)) {
116     int x, y;
117     gdk_window_get_position(GTK_WIDGET(window)->window, &x, &y);
118 
119     // Create a nested stack of tasks to run.
120     Task* next_task = new WindowDragResponseTask(this, reply_message);
121     next_task = new MouseEventTask(next_task, ui_controls::UP);
122     next_task = new MouseEventTask(next_task, ui_controls::UP);
123     for (size_t i = drag_path.size() - 1; i > 0; --i) {
124       // Smooth out the mouse movements by adding intermediate points. This
125       // better simulates a real user drag.
126       int dest_x = drag_path[i].x() + x;
127       int dest_y = drag_path[i].y() + y;
128       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;
130 
131       next_task = new MouseMoveTask(next_task, dest_x, dest_y);
132       next_task = new MouseMoveTask(next_task, half_step_x, half_step_y);
133     }
134     next_task = new MouseEventTask(next_task, ui_controls::DOWN);
135 
136     ui_controls::SendMouseMoveNotifyWhenDone(x + drag_path[0].x(),
137                                              y + drag_path[0].y(),
138                                              next_task);
139   } else {
140     AutomationMsg_WindowDrag::WriteReplyParams(reply_message, false);
141     Send(reply_message);
142   }
143 }
144