Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: chrome/browser/automation/ui_controls_aurax11.cc

Issue 9390038: Move automation/ui_controls to ui/ui_controls (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: win_aura fix, sync Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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/ui_controls.h"
6
7 #include <X11/keysym.h>
8 #include <X11/Xlib.h>
9
10 // X macro fail.
11 #if defined(RootWindow)
12 #undef RootWindow
13 #endif
14
15 #include "ash/shell.h"
16 #include "base/callback.h"
17 #include "base/logging.h"
18 #include "base/message_pump_x.h"
19 #include "chrome/browser/automation/ui_controls_internal.h"
20 #include "ui/aura/root_window.h"
21 #include "ui/base/keycodes/keyboard_code_conversion_x.h"
22 #include "ui/views/view.h"
23
24 namespace {
25
26 // Mask of the buttons currently down.
27 unsigned button_down_mask = 0;
28
29 // Event waiter executes the specified closure|when a matching event
30 // is found.
31 // TODO(oshima): Move this to base.
32 class EventWaiter : public MessageLoopForUI::Observer {
33 public:
34 typedef bool (*EventWaiterMatcher)(const base::NativeEvent& event);
35
36 EventWaiter(const base::Closure& closure, EventWaiterMatcher matcher)
37 : closure_(closure),
38 matcher_(matcher) {
39 MessageLoopForUI::current()->AddObserver(this);
40 }
41
42 virtual ~EventWaiter() {
43 MessageLoopForUI::current()->RemoveObserver(this);
44 }
45
46 // MessageLoop::Observer implementation:
47 virtual base::EventStatus WillProcessEvent(
48 const base::NativeEvent& event) OVERRIDE {
49 if ((*matcher_)(event)) {
50 MessageLoop::current()->PostTask(FROM_HERE, closure_);
51 delete this;
52 }
53 return base::EVENT_CONTINUE;
54 }
55
56 virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE {
57 }
58
59 private:
60 base::Closure closure_;
61 EventWaiterMatcher matcher_;
62 DISALLOW_COPY_AND_ASSIGN(EventWaiter);
63 };
64
65 // Latest mouse pointer location set by SendMouseMoveNotifyWhenDone.
66 int g_current_x = -1000;
67 int g_current_y = -1000;
68
69 // Returns atom that indidates that the XEvent is marker event.
70 Atom MarkerEventAtom() {
71 return XInternAtom(base::MessagePumpX::GetDefaultXDisplay(),
72 "marker_event",
73 False);
74 }
75
76 // Returns true when the event is a marker event.
77 bool Matcher(const base::NativeEvent& event) {
78 return event->xany.type == ClientMessage &&
79 event->xclient.message_type == MarkerEventAtom();
80 }
81
82 } // namespace
83
84 namespace ui_controls {
85
86 bool SendKeyPress(gfx::NativeWindow window,
87 ui::KeyboardCode key,
88 bool control,
89 bool shift,
90 bool alt,
91 bool command) {
92 DCHECK(!command); // No command key on Aura
93 return SendKeyPressNotifyWhenDone(
94 window, key, control, shift, alt, command, base::Closure());
95 }
96
97 void SetKeycodeAndSendThenMask(XEvent* xevent,
98 KeySym keysym,
99 unsigned int mask) {
100 xevent->xkey.keycode =
101 XKeysymToKeycode(base::MessagePumpX::GetDefaultXDisplay(),
102 keysym);
103 ash::Shell::GetRootWindow()->PostNativeEvent(xevent);
104 xevent->xkey.state |= mask;
105 }
106
107 void UnmaskAndSetKeycodeThenSend(XEvent* xevent,
108 unsigned int mask,
109 KeySym keysym) {
110 xevent->xkey.state ^= mask;
111 xevent->xkey.keycode =
112 XKeysymToKeycode(base::MessagePumpX::GetDefaultXDisplay(),
113 keysym);
114 ash::Shell::GetRootWindow()->PostNativeEvent(xevent);
115 }
116
117 bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
118 ui::KeyboardCode key,
119 bool control,
120 bool shift,
121 bool alt,
122 bool command,
123 const base::Closure& closure) {
124 DCHECK(!command); // No command key on Aura
125 XEvent xevent = {0};
126 xevent.xkey.type = KeyPress;
127 if (control)
128 SetKeycodeAndSendThenMask(&xevent, XK_Control_L, ControlMask);
129 if (shift)
130 SetKeycodeAndSendThenMask(&xevent, XK_Shift_L, ShiftMask);
131 if (alt)
132 SetKeycodeAndSendThenMask(&xevent, XK_Alt_L, Mod1Mask);
133 xevent.xkey.keycode =
134 XKeysymToKeycode(base::MessagePumpX::GetDefaultXDisplay(),
135 ui::XKeysymForWindowsKeyCode(key, shift));
136 ash::Shell::GetRootWindow()->PostNativeEvent(&xevent);
137
138 // Send key release events.
139 xevent.xkey.type = KeyRelease;
140 ash::Shell::GetRootWindow()->PostNativeEvent(&xevent);
141 if (alt)
142 UnmaskAndSetKeycodeThenSend(&xevent, Mod1Mask, XK_Alt_L);
143 if (shift)
144 UnmaskAndSetKeycodeThenSend(&xevent, ShiftMask, XK_Shift_L);
145 if (control)
146 UnmaskAndSetKeycodeThenSend(&xevent, ControlMask, XK_Control_L);
147 DCHECK(!xevent.xkey.state);
148 RunClosureAfterAllPendingUIEvents(closure);
149 return true;
150 }
151
152 bool SendMouseMove(long x, long y) {
153 return SendMouseMoveNotifyWhenDone(x, y, base::Closure());
154 }
155
156 bool SendMouseMoveNotifyWhenDone(long x, long y, const base::Closure& closure) {
157 XEvent xevent = {0};
158 XMotionEvent* xmotion = &xevent.xmotion;
159 xmotion->type = MotionNotify;
160 g_current_x = xmotion->x = x;
161 g_current_y = xmotion->y = y;
162 xmotion->state = button_down_mask;
163 xmotion->same_screen = True;
164 // RootWindow will take care of other necessary fields.
165 ash::Shell::GetRootWindow()->PostNativeEvent(&xevent);
166 RunClosureAfterAllPendingUIEvents(closure);
167 return true;
168 }
169
170 bool SendMouseEvents(MouseButton type, int state) {
171 return SendMouseEventsNotifyWhenDone(type, state, base::Closure());
172 }
173
174 bool SendMouseEventsNotifyWhenDone(MouseButton type,
175 int state,
176 const base::Closure& closure) {
177 XEvent xevent = {0};
178 XButtonEvent* xbutton = &xevent.xbutton;
179 DCHECK_NE(g_current_x, -1000);
180 DCHECK_NE(g_current_y, -1000);
181 xbutton->x = g_current_x;
182 xbutton->y = g_current_y;
183 xbutton->same_screen = True;
184 switch (type) {
185 case LEFT:
186 xbutton->button = Button1;
187 xbutton->state = Button1Mask;
188 break;
189 case MIDDLE:
190 xbutton->button = Button2;
191 xbutton->state = Button2Mask;
192 break;
193 case RIGHT:
194 xbutton->button = Button3;
195 xbutton->state = Button3Mask;
196 break;
197 }
198 // RootWindow will take care of other necessary fields.
199
200 aura::RootWindow* root_window = ash::Shell::GetRootWindow();
201 if (state & DOWN) {
202 xevent.xbutton.type = ButtonPress;
203 root_window->PostNativeEvent(&xevent);
204 button_down_mask |= xbutton->state;
205 }
206 if (state & UP) {
207 xevent.xbutton.type = ButtonRelease;
208 root_window->PostNativeEvent(&xevent);
209 button_down_mask = (button_down_mask | xbutton->state) ^ xbutton->state;
210 }
211 RunClosureAfterAllPendingUIEvents(closure);
212 return true;
213 }
214
215 bool SendMouseClick(MouseButton type) {
216 return SendMouseEvents(type, UP | DOWN);
217 }
218
219 void MoveMouseToCenterAndPress(views::View* view, MouseButton button,
220 int state, const base::Closure& closure) {
221 DCHECK(view);
222 DCHECK(view->GetWidget());
223 gfx::Point view_center(view->width() / 2, view->height() / 2);
224 views::View::ConvertPointToScreen(view, &view_center);
225 SendMouseMove(view_center.x(), view_center.y());
226 SendMouseEventsNotifyWhenDone(button, state, closure);
227 }
228
229 void RunClosureAfterAllPendingUIEvents(const base::Closure& closure) {
230 if (closure.is_null())
231 return;
232 static XEvent* marker_event = NULL;
233 if (!marker_event) {
234 marker_event = new XEvent();
235 marker_event->xclient.type = ClientMessage;
236 marker_event->xclient.display = NULL;
237 marker_event->xclient.window = None;
238 marker_event->xclient.format = 8;
239 }
240 marker_event->xclient.message_type = MarkerEventAtom();
241 ash::Shell::GetRootWindow()->PostNativeEvent(marker_event);
242 new EventWaiter(closure, &Matcher);
243 }
244
245 } // namespace ui_controls
OLDNEW
« no previous file with comments | « chrome/browser/automation/ui_controls_aurawin.cc ('k') | chrome/browser/automation/ui_controls_gtk.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698