OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/ui_controls.h" | 5 #include "chrome/browser/automation/ui_controls.h" |
6 | 6 |
7 #include <gtk/gtk.h> | 7 #include <gtk/gtk.h> |
8 #include <gdk/gdkkeysyms.h> | 8 #include <gdk/gdkkeysyms.h> |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/message_loop.h" | 11 #include "base/message_loop.h" |
12 #include "chrome/test/automation/automation_constants.h" | 12 #include "chrome/test/automation/automation_constants.h" |
13 | 13 |
14 namespace { | 14 namespace { |
15 | 15 |
| 16 guint32 EventTimeNow() { |
| 17 struct timespec ts; |
| 18 clock_gettime(CLOCK_MONOTONIC, &ts); |
| 19 return ts.tv_sec * 1000 + ts.tv_nsec / 1000000; |
| 20 } |
| 21 |
16 class EventWaiter : public MessageLoopForUI::Observer { | 22 class EventWaiter : public MessageLoopForUI::Observer { |
17 public: | 23 public: |
18 EventWaiter(Task* task, GdkEventType type) : task_(task), type_(type) { | 24 EventWaiter(Task* task, GdkEventType type) : task_(task), type_(type) { |
19 MessageLoopForUI::current()->AddObserver(this); | 25 MessageLoopForUI::current()->AddObserver(this); |
20 } | 26 } |
21 | 27 |
22 virtual ~EventWaiter() { | 28 virtual ~EventWaiter() { |
23 MessageLoopForUI::current()->RemoveObserver(this); | 29 MessageLoopForUI::current()->RemoveObserver(this); |
24 } | 30 } |
25 | 31 |
26 // MessageLoop::Observer implementation: | 32 // MessageLoop::Observer implementation: |
27 virtual void WillProcessEvent(GdkEvent* event) { | 33 virtual void WillProcessEvent(GdkEvent* event) { |
28 // No-op. | 34 // No-op. |
29 } | 35 } |
30 | 36 |
31 virtual void DidProcessEvent(GdkEvent* event) { | 37 virtual void DidProcessEvent(GdkEvent* event) { |
32 if (event->any.type == type_) { | 38 if (event->any.type == type_) { |
33 task_->Run(); | 39 task_->Run(); |
34 delete this; | 40 delete this; |
35 } | 41 } |
36 } | 42 } |
37 | 43 |
38 private: | 44 private: |
39 Task* task_; | 45 scoped_ptr<Task> task_; |
40 GdkEventType type_; | 46 GdkEventType type_; |
41 }; | 47 }; |
42 | 48 |
43 } // namespace | 49 } // namespace |
44 | 50 |
45 namespace ui_controls { | 51 namespace ui_controls { |
46 | 52 |
47 bool SendKeyPress(gfx::NativeWindow window, | 53 bool SendKeyPress(gfx::NativeWindow window, |
48 wchar_t key, bool control, bool shift, bool alt) { | 54 wchar_t key, bool control, bool shift, bool alt) { |
49 // TODO(estade): send a release as well? | 55 // TODO(estade): send a release as well? |
50 GdkEvent* event = gdk_event_new(GDK_KEY_PRESS); | 56 GdkEvent* event = gdk_event_new(GDK_KEY_PRESS); |
51 | 57 |
52 event->key.type = GDK_KEY_PRESS; | 58 event->key.type = GDK_KEY_PRESS; |
53 event->key.window = GTK_WIDGET(window)->window; | 59 event->key.window = GTK_WIDGET(window)->window; |
54 g_object_ref(event->key.window); | 60 g_object_ref(event->key.window); |
55 event->key.send_event = false; | 61 event->key.send_event = false; |
56 | 62 event->key.time = EventTimeNow(); |
57 struct timespec ts; | |
58 clock_gettime(CLOCK_MONOTONIC, &ts); | |
59 event->key.time = ts.tv_sec * 1000 + ts.tv_nsec / 1000000; | |
60 | 63 |
61 // TODO(estade): handle other state flags besides control, shift, alt? | 64 // TODO(estade): handle other state flags besides control, shift, alt? |
62 // For example caps lock. | 65 // For example caps lock. |
63 event->key.state = (control ? GDK_CONTROL_MASK : 0) | | 66 event->key.state = (control ? GDK_CONTROL_MASK : 0) | |
64 (shift ? GDK_SHIFT_MASK : 0) | | 67 (shift ? GDK_SHIFT_MASK : 0) | |
65 (alt ? GDK_MOD1_MASK : 0); | 68 (alt ? GDK_MOD1_MASK : 0); |
66 event->key.keyval = key; | 69 event->key.keyval = key; |
67 // TODO(estade): fill in the string? | 70 // TODO(estade): fill in the string? |
68 | 71 |
69 GdkKeymapKey* keys; | 72 GdkKeymapKey* keys; |
(...skipping 13 matching lines...) Expand all Loading... |
83 } | 86 } |
84 | 87 |
85 bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window, wchar_t key, | 88 bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window, wchar_t key, |
86 bool control, bool shift, | 89 bool control, bool shift, |
87 bool alt, Task* task) { | 90 bool alt, Task* task) { |
88 // This object will delete itself after running |task|. | 91 // This object will delete itself after running |task|. |
89 new EventWaiter(task, GDK_KEY_PRESS); | 92 new EventWaiter(task, GDK_KEY_PRESS); |
90 return SendKeyPress(window, key, control, shift, alt); | 93 return SendKeyPress(window, key, control, shift, alt); |
91 } | 94 } |
92 | 95 |
93 // TODO(estade): this appears to be unused on Windows. Can we remove it? | 96 bool SendMouseMove(long x, long y) { |
94 bool SendKeyDown(wchar_t key) { | 97 gdk_display_warp_pointer(gdk_display_get_default(), gdk_screen_get_default(), |
95 NOTIMPLEMENTED(); | 98 x, y); |
| 99 return true; |
| 100 } |
| 101 |
| 102 bool SendMouseMoveNotifyWhenDone(long x, long y, Task* task) { |
| 103 bool rv = SendMouseMove(x, y); |
| 104 // We can't rely on any particular event signalling the completion of the |
| 105 // mouse move. Posting the task to the message loop should gaurantee |
| 106 // the pointer has moved before task is run (although it may not run it as |
| 107 // soon as it could). |
| 108 MessageLoop::current()->PostTask(FROM_HERE, task); |
| 109 return rv; |
| 110 } |
| 111 |
| 112 bool SendMouseClick(const gfx::Point& point, MouseButton type) { |
| 113 GdkEvent* event = gdk_event_new(GDK_BUTTON_PRESS); |
| 114 |
| 115 event->button.window = gdk_window_at_pointer(NULL, NULL); |
| 116 g_object_ref(event->button.window); |
| 117 event->button.send_event = false; |
| 118 event->button.time = EventTimeNow(); |
| 119 |
| 120 event->motion.x_root = point.x(); |
| 121 event->motion.y_root = point.x(); |
| 122 gint origin_x, origin_y; |
| 123 gdk_window_get_origin(event->button.window, &origin_x, &origin_y); |
| 124 event->button.x = point.x() - origin_x; |
| 125 event->button.y = point.y() - origin_y; |
| 126 |
| 127 event->button.axes = NULL; |
| 128 // TODO(estade): as above, we may want to pack this with the actual state. |
| 129 event->button.state = 0; |
| 130 event->button.button = type == LEFT ? 1 : (type == MIDDLE ? 2 : 3); |
| 131 event->button.device = gdk_device_get_core_pointer(); |
| 132 |
| 133 event->button.type = GDK_BUTTON_PRESS; |
| 134 gdk_event_put(event); |
| 135 |
| 136 // Also send a release event. |
| 137 GdkEvent* release_event = gdk_event_copy(event); |
| 138 release_event->button.type = GDK_BUTTON_RELEASE; |
| 139 release_event->button.time++; |
| 140 gdk_event_put(release_event); |
| 141 |
| 142 gdk_event_free(event); |
| 143 gdk_event_free(release_event); |
| 144 |
96 return false; | 145 return false; |
97 } | 146 } |
98 | 147 |
99 // TODO(estade): this appears to be unused on Windows. Can we remove it? | |
100 bool SendKeyUp(wchar_t key) { | |
101 NOTIMPLEMENTED(); | |
102 return false; | |
103 } | |
104 | |
105 bool SendMouseMove(long x, long y) { | |
106 NOTIMPLEMENTED(); | |
107 return false; | |
108 } | |
109 | |
110 void SendMouseMoveNotifyWhenDone(long x, long y, Task* task) { | |
111 NOTIMPLEMENTED(); | |
112 } | |
113 | |
114 bool SendMouseClick(gfx::NativeWindow window, const gfx::Point& point, | |
115 MouseButton type) { | |
116 NOTIMPLEMENTED(); | |
117 return false; | |
118 } | |
119 | |
120 // TODO(estade): need to figure out a better type for this than View. | 148 // TODO(estade): need to figure out a better type for this than View. |
121 void MoveMouseToCenterAndPress(views::View* view, | 149 void MoveMouseToCenterAndPress(views::View* view, |
122 MouseButton button, | 150 MouseButton button, |
123 int state, | 151 int state, |
124 Task* task) { | 152 Task* task) { |
125 NOTIMPLEMENTED(); | 153 NOTIMPLEMENTED(); |
126 } | 154 } |
127 | 155 |
128 } // namespace ui_controls | 156 } // namespace ui_controls |
OLD | NEW |