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

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: no mask for xsendevent 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 specified closure|when a matching event
21 // is found.
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(
39 const base::NativeEvent& event) OVERRIDE {
40 if ((*matcher_)(event)) {
41 MessageLoop::current()->PostTask(FROM_HERE, closure_);
42 delete this;
43 }
44 return base::EVENT_CONTINUE;
45 }
46
47 virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE {
48 }
49
50 private:
51 base::Closure closure_;
52 EventWaiterMatcher matcher_;
53 DISALLOW_COPY_AND_ASSIGN(EventWaiter);
54 };
55
56 // Latest mouse pointer location set by SendMouseMoveNotifyWhenDone.
57 int g_current_x = -1000;
58 int g_current_y = -1000;
59
60 // Returns atom that indidates that the XEvent is marker event.
61 Atom MarkerEventAtom() {
62 return XInternAtom(base::MessagePumpX::GetDefaultXDisplay(),
63 "marker_event",
64 False);
65 }
66
67 // Returns true when the event is a marker event.
68 bool Matcher(const base::NativeEvent& event) {
69 return event->xany.type == ClientMessage &&
70 event->xclient.message_type == MarkerEventAtom();
71 }
72
73 void RunClosureAfterEvents(const base::Closure closure) {
74 if (closure.is_null())
75 return;
76 static XEvent* marker_event = NULL;
77 if (!marker_event) {
78 marker_event = new XEvent();
79 marker_event->xclient.type = ClientMessage;
80 marker_event->xclient.display = NULL;
81 marker_event->xclient.window = None;
82 marker_event->xclient.format = 8;
83 }
84 marker_event->xclient.message_type = MarkerEventAtom();
85 aura::Desktop::GetInstance()->PostNativeEvent(marker_event);
86 new EventWaiter(closure, &Matcher);
87 }
88
89 } // namespace
90
91 namespace ui_controls {
92
93 bool SendKeyPress(gfx::NativeWindow window,
94 ui::KeyboardCode key,
95 bool control,
96 bool shift,
97 bool alt,
98 bool command) {
99 DCHECK(!command); // No command key on Aura
100 return SendKeyPressNotifyWhenDone(
101 window, key, control, shift, alt, command, base::Closure());
102 }
103
104 void SetMaskAndKeycodeThenSend(XEvent* xevent,
105 unsigned int mask,
106 unsigned int keycode) {
107 xevent->xkey.state |= mask;
108 xevent->xkey.keycode = keycode;
109 aura::Desktop::GetInstance()->PostNativeEvent(xevent);
110 }
111
112 void SetKeycodeAndSendThenUnmask(XEvent* xevent,
113 unsigned int mask,
114 unsigned int keycode) {
115 xevent->xkey.keycode = keycode;
116 aura::Desktop::GetInstance()->PostNativeEvent(xevent);
117 xevent->xkey.state ^= mask;
118 }
119
120 bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
121 ui::KeyboardCode key,
122 bool control,
123 bool shift,
124 bool alt,
125 bool command,
126 const base::Closure& closure) {
127 DCHECK(!command); // No command key on Aura
128 XEvent xevent = {0};
129 xevent.xkey.type = KeyPress;
130 if (control)
131 SetMaskAndKeycodeThenSend(&xevent, ControlMask, XK_Control_L);
132 if (shift)
133 SetMaskAndKeycodeThenSend(&xevent, ShiftMask, XK_Shift_L);
134 if (alt)
135 SetMaskAndKeycodeThenSend(&xevent, Mod1Mask, XK_Alt_L);
136 xevent.xkey.keycode = ui::XKeysymForWindowsKeyCode(key, shift);
137 aura::Desktop::GetInstance()->PostNativeEvent(&xevent);
138
139 // Send key release events.
140 xevent.xkey.type = KeyRelease;
141 aura::Desktop::GetInstance()->PostNativeEvent(&xevent);
142 if (alt)
143 SetKeycodeAndSendThenUnmask(&xevent, Mod1Mask, XK_Alt_L);
144 if (shift)
145 SetKeycodeAndSendThenUnmask(&xevent, ShiftMask, XK_Shift_L);
146 if (control)
147 SetKeycodeAndSendThenUnmask(&xevent, ControlMask, XK_Control_L);
148 DCHECK(!xevent.xkey.state);
149 RunClosureAfterEvents(closure);
150 return true;
151 }
152
153 bool SendMouseMove(long x, long y) {
154 return SendMouseMoveNotifyWhenDone(x, y, base::Closure());
155 }
156
157 bool SendMouseMoveNotifyWhenDone(long x, long y, const base::Closure& closure) {
158 XEvent xevent = {0};
159 XMotionEvent* xmotion = &xevent.xmotion;
160 xmotion->type = MotionNotify;
161 g_current_x = xmotion->x = x;
162 g_current_y = xmotion->y = y;
163 xmotion->same_screen = True;
164 // Desktop will take care of other necessary fields.
165 aura::Desktop::GetInstance()->PostNativeEvent(&xevent);
166 RunClosureAfterEvents(closure);
167 return false;
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 // Desktop will take care of other necessary fields.
199
200 aura::Desktop* desktop = aura::Desktop::GetInstance();
201 if (state & DOWN) {
202 xevent.xbutton.type = ButtonPress;
203 desktop->PostNativeEvent(&xevent);
204 }
205 if (state & UP) {
206 xevent.xbutton.type = ButtonRelease;
207 desktop->PostNativeEvent(&xevent);
208 }
209 RunClosureAfterEvents(closure);
210 return false;
211 }
212
213 bool SendMouseClick(MouseButton type) {
214 return SendMouseEvents(type, UP | DOWN);
215 }
216
217 void MoveMouseToCenterAndPress(views::View* view, MouseButton button,
218 int state, const base::Closure& closure) {
219 DCHECK(view);
220 DCHECK(view->GetWidget());
221 gfx::Point view_center(view->width() / 2, view->height() / 2);
222 views::View::ConvertPointToScreen(view, &view_center);
223 SendMouseMove(view_center.x(), view_center.y());
224 SendMouseEventsNotifyWhenDone(button, state, closure);
225 }
226
227 } // 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