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

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

Issue 8585015: Implement ui_controls for aura (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: " Created 9 years, 1 month 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 #include "base/callback.h"
11 #include "base/logging.h"
12 #include "base/message_pump_x.h"
13 #include "chrome/browser/automation/ui_controls_internal.h"
14 #include "ui/aura/desktop.h"
15 #include "ui/base/keycodes/keyboard_code_conversion_x.h"
16 #include "views/view.h"
17
18 namespace {
19
20 // Event waiter executes the given |closure| when an event that
21 // matches condition implemented by |matcher|.
sky 2011/11/22 00:28:33 Event waiter executes the specified closure when a
oshima 2011/11/22 01:36:10 Done.
22 // TODO(oshima): Move this to base.
23 class EventWaiter : public MessageLoopForUI::Observer {
24 public:
25 typedef bool (*EventWaiterMatcher)(const base::NativeEvent& event);
26
27 EventWaiter(const base::Closure& closure, EventWaiterMatcher matcher)
28 : closure_(closure),
29 matcher_(matcher) {
30 MessageLoopForUI::current()->AddObserver(this);
31 }
32
33 virtual ~EventWaiter() {
34 MessageLoopForUI::current()->RemoveObserver(this);
35 }
36
37 // MessageLoop::Observer implementation:
38 virtual base::EventStatus WillProcessEvent(const base::NativeEvent& event) {
sky 2011/11/22 00:28:33 OVERRIDE here and on DidProcessEvent.
oshima 2011/11/22 01:36:10 Done.
39 if ((*matcher_)(event)) {
40 MessageLoop::current()->PostTask(FROM_HERE, closure_);
41 delete this;
42 }
43 return base::EVENT_CONTINUE;
44 }
45
46 virtual void DidProcessEvent(const base::NativeEvent& event) {
47
sky 2011/11/22 00:28:33 nit: remove empty line.
oshima 2011/11/22 01:36:10 Done.
48 }
49 private:
sky 2011/11/22 00:28:33 nit: newline between 48 and 49.
oshima 2011/11/22 01:36:10 Done.
50 base::Closure closure_;
51 EventWaiterMatcher matcher_;
52 DISALLOW_COPY_AND_ASSIGN(EventWaiter);
53 };
54
55 // Latest mouse pointer location set by SendMouseMoveNotifyWhenDone.
56 int g_current_x = -1000;
57 int g_current_y = -1000;
58
59 // Returns atom that indidates that the XEvent is marker event.
60 Atom MarkerEventAtom() {
61 return XInternAtom(base::MessagePumpX::GetDefaultXDisplay(),
62 "marker_event",
63 False);
64 }
65
66 // Returns true when the event is a marker event.
67 bool Matcher(const base::NativeEvent& event) {
68 return event->xany.type == ClientMessage &&
69 event->xclient.message_type == MarkerEventAtom();
70 }
71
72 void RunClosureAfterEvents(const base::Closure closure) {
73 if (closure.is_null())
74 return;
75 static XEvent* marker_event = NULL;
76 if (!marker_event) {
77 marker_event = new XEvent();
78 marker_event->xclient.type = ClientMessage;
79 marker_event->xclient.display = NULL;
80 marker_event->xclient.window = None;
81 marker_event->xclient.format = 8;
82 }
83 marker_event->xclient.message_type = MarkerEventAtom();
84 aura::Desktop::GetInstance()->PostNativeEvent(marker_event);
85 new EventWaiter(closure, &Matcher);
86 }
87
88 } // namespace
89
90 namespace ui_controls {
91
92 bool SendKeyPress(gfx::NativeWindow window,
93 ui::KeyboardCode key,
94 bool control,
95 bool shift,
96 bool alt,
97 bool command) {
98 DCHECK(!command); // No command key on Aura
99 return SendKeyPressNotifyWhenDone(
100 window, key, control, shift, alt, command, base::Closure());
101 }
102
103 void SetMaskAndKeycodeThenSend(XEvent* xevent,
104 unsigned int mask,
105 unsigned int keycode) {
106 xevent->xkey.state |= mask;
107 xevent->xkey.keycode = keycode;
108 aura::Desktop::GetInstance()->PostNativeEvent(xevent);
109 }
110
111 void SetKeycodeAndSendThenUnmask(XEvent* xevent,
112 unsigned int mask,
113 unsigned int keycode) {
114 xevent->xkey.keycode = keycode;
115 aura::Desktop::GetInstance()->PostNativeEvent(xevent);
116 xevent->xkey.state ^= mask;
117 }
118
119 bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
120 ui::KeyboardCode key,
121 bool control,
122 bool shift,
123 bool alt,
124 bool command,
125 const base::Closure& closure) {
126 DCHECK(!command); // No command key on Aura
127 XEvent xevent = {0};
128 xevent.xkey.type = KeyPress;
129 if (control)
130 SetMaskAndKeycodeThenSend(&xevent, ControlMask, XK_Control_L);
131 if (shift)
132 SetMaskAndKeycodeThenSend(&xevent, ShiftMask, XK_Shift_L);
133 if (alt)
134 SetMaskAndKeycodeThenSend(&xevent, Mod1Mask, XK_Alt_L);
135 xevent.xkey.keycode = ui::XKeysymForWindowsKeyCode(key, shift);
136 aura::Desktop::GetInstance()->PostNativeEvent(&xevent);
137
138 // Send key release events.
139 xevent.xkey.type = KeyRelease;
140 aura::Desktop::GetInstance()->PostNativeEvent(&xevent);
141 if (alt)
142 SetKeycodeAndSendThenUnmask(&xevent, Mod1Mask, XK_Alt_L);
143 if (shift)
144 SetKeycodeAndSendThenUnmask(&xevent, ShiftMask, XK_Shift_L);
145 if (control)
146 SetKeycodeAndSendThenUnmask(&xevent, ControlMask, XK_Control_L);
147 DCHECK(!xevent.xkey.state);
148 RunClosureAfterEvents(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->same_screen = True;
163 // Desktop will take care of other necessary fields.
164 aura::Desktop::GetInstance()->PostNativeEvent(&xevent);
165 RunClosureAfterEvents(closure);
166 return false;
167 }
168
169 bool SendMouseEvents(MouseButton type, int state) {
170 return SendMouseEventsNotifyWhenDone(type, state, base::Closure());
171 }
172
173 bool SendMouseEventsNotifyWhenDone(MouseButton type,
174 int state,
175 const base::Closure& closure) {
176 XEvent xevent = {0};
177 XButtonEvent* xbutton = &xevent.xbutton;
178 DCHECK_NE(g_current_x, -1000);
179 DCHECK_NE(g_current_y, -1000);
180 xbutton->x = g_current_x;
181 xbutton->y = g_current_y;
182 xbutton->same_screen = True;
183 switch (type) {
184 case LEFT:
185 xbutton->button = Button1;
186 xbutton->state = Button1Mask;
187 break;
188 case MIDDLE:
189 xbutton->button = Button2;
190 xbutton->state = Button2Mask;
191 break;
192 case RIGHT:
193 xbutton->button = Button3;
194 xbutton->state = Button3Mask;
195 break;
196 }
197 // Desktop will take care of other necessary fields.
198
199 aura::Desktop* desktop = aura::Desktop::GetInstance();
200 if (state & DOWN) {
201 xevent.xbutton.type = ButtonPress;
202 desktop->PostNativeEvent(&xevent);
203 }
204 if (state & UP) {
205 xevent.xbutton.type = ButtonRelease;
206 desktop->PostNativeEvent(&xevent);
207 }
208 RunClosureAfterEvents(closure);
209 return false;
210 }
211
212 bool SendMouseClick(MouseButton type) {
213 return SendMouseEvents(type, UP | DOWN);
214 }
215
216 void MoveMouseToCenterAndPress(views::View* view, MouseButton button,
217 int state, const base::Closure& closure) {
218 DCHECK(view);
219 DCHECK(view->GetWidget());
220 gfx::Point view_center(view->width() / 2, view->height() / 2);
221 views::View::ConvertPointToScreen(view, &view_center);
222 SendMouseMove(view_center.x(), view_center.y());
223 SendMouseEventsNotifyWhenDone(button, state, closure);
224 }
225
226 } // namespace ui_controls
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698