Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / ui / aura / test / ui_controls_factory_aurax11.cc
blob8999aa6b1b10af7deed6099aa11f7cea0a3a3699
1 // Copyright 2013 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.
5 #include <X11/keysym.h>
6 #include <X11/Xlib.h>
8 #include "base/bind.h"
9 #include "base/logging.h"
10 #include "ui/aura/client/screen_position_client.h"
11 #include "ui/aura/env.h"
12 #include "ui/aura/test/aura_test_utils.h"
13 #include "ui/aura/test/ui_controls_factory_aura.h"
14 #include "ui/aura/test/x11_event_sender.h"
15 #include "ui/aura/window.h"
16 #include "ui/aura/window_tree_host.h"
17 #include "ui/base/test/ui_controls_aura.h"
18 #include "ui/base/x/x11_util.h"
19 #include "ui/compositor/dip_util.h"
20 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
21 #include "ui/events/test/platform_event_waiter.h"
23 namespace aura {
24 namespace test {
25 namespace {
27 using ui_controls::DOWN;
28 using ui_controls::LEFT;
29 using ui_controls::MIDDLE;
30 using ui_controls::MouseButton;
31 using ui_controls::RIGHT;
32 using ui_controls::UIControlsAura;
33 using ui_controls::UP;
35 // Mask of the buttons currently down.
36 unsigned button_down_mask = 0;
38 // Returns atom that indidates that the XEvent is marker event.
39 Atom MarkerEventAtom() {
40 return XInternAtom(gfx::GetXDisplay(), "marker_event", False);
43 // Returns true when the event is a marker event.
44 bool Matcher(const base::NativeEvent& event) {
45 return event->xany.type == ClientMessage &&
46 event->xclient.message_type == MarkerEventAtom();
49 class UIControlsX11 : public UIControlsAura {
50 public:
51 UIControlsX11(WindowTreeHost* host) : host_(host) {
54 bool SendKeyPress(gfx::NativeWindow window,
55 ui::KeyboardCode key,
56 bool control,
57 bool shift,
58 bool alt,
59 bool command) override {
60 return SendKeyPressNotifyWhenDone(
61 window, key, control, shift, alt, command, base::Closure());
63 bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
64 ui::KeyboardCode key,
65 bool control,
66 bool shift,
67 bool alt,
68 bool command,
69 const base::Closure& closure) override {
70 XEvent xevent = {0};
71 xevent.xkey.type = KeyPress;
72 if (control)
73 SetKeycodeAndSendThenMask(&xevent, XK_Control_L, ControlMask);
74 if (shift)
75 SetKeycodeAndSendThenMask(&xevent, XK_Shift_L, ShiftMask);
76 if (alt)
77 SetKeycodeAndSendThenMask(&xevent, XK_Alt_L, Mod1Mask);
78 if (command)
79 SetKeycodeAndSendThenMask(&xevent, XK_Meta_L, Mod4Mask);
80 xevent.xkey.keycode =
81 XKeysymToKeycode(gfx::GetXDisplay(),
82 ui::XKeysymForWindowsKeyCode(key, shift));
83 PostEventToWindowTreeHost(xevent, host_);
85 // Send key release events.
86 xevent.xkey.type = KeyRelease;
87 PostEventToWindowTreeHost(xevent, host_);
88 if (alt)
89 UnmaskAndSetKeycodeThenSend(&xevent, Mod1Mask, XK_Alt_L);
90 if (shift)
91 UnmaskAndSetKeycodeThenSend(&xevent, ShiftMask, XK_Shift_L);
92 if (control)
93 UnmaskAndSetKeycodeThenSend(&xevent, ControlMask, XK_Control_L);
94 if (command)
95 UnmaskAndSetKeycodeThenSend(&xevent, Mod4Mask, XK_Meta_L);
96 DCHECK(!xevent.xkey.state);
97 RunClosureAfterAllPendingUIEvents(closure);
98 return true;
101 bool SendMouseMove(long screen_x, long screen_y) override {
102 return SendMouseMoveNotifyWhenDone(screen_x, screen_y, base::Closure());
104 bool SendMouseMoveNotifyWhenDone(long screen_x,
105 long screen_y,
106 const base::Closure& closure) override {
107 gfx::Point root_location(screen_x, screen_y);
108 aura::client::ScreenPositionClient* screen_position_client =
109 aura::client::GetScreenPositionClient(host_->window());
110 if (screen_position_client) {
111 screen_position_client->ConvertPointFromScreen(host_->window(),
112 &root_location);
114 gfx::Point root_current_location =
115 QueryLatestMousePositionRequestInHost(host_);
116 host_->ConvertPointFromHost(&root_current_location);
118 if (root_location != root_current_location && button_down_mask == 0) {
119 // Move the cursor because EnterNotify/LeaveNotify are generated with the
120 // current mouse position as a result of XGrabPointer()
121 host_->window()->MoveCursorTo(root_location);
122 } else {
123 XEvent xevent = {0};
124 XMotionEvent* xmotion = &xevent.xmotion;
125 xmotion->type = MotionNotify;
126 xmotion->x = root_location.x();
127 xmotion->y = root_location.y();
128 xmotion->state = button_down_mask;
129 xmotion->same_screen = True;
130 // WindowTreeHost will take care of other necessary fields.
131 PostEventToWindowTreeHost(xevent, host_);
133 RunClosureAfterAllPendingUIEvents(closure);
134 return true;
136 bool SendMouseEvents(MouseButton type, int state) override {
137 return SendMouseEventsNotifyWhenDone(type, state, base::Closure());
139 bool SendMouseEventsNotifyWhenDone(MouseButton type,
140 int state,
141 const base::Closure& closure) override {
142 XEvent xevent = {0};
143 XButtonEvent* xbutton = &xevent.xbutton;
144 gfx::Point mouse_loc = aura::Env::GetInstance()->last_mouse_location();
145 aura::client::ScreenPositionClient* screen_position_client =
146 aura::client::GetScreenPositionClient(host_->window());
147 if (screen_position_client) {
148 screen_position_client->ConvertPointFromScreen(host_->window(),
149 &mouse_loc);
151 xbutton->x = mouse_loc.x();
152 xbutton->y = mouse_loc.y();
153 xbutton->same_screen = True;
154 switch (type) {
155 case LEFT:
156 xbutton->button = Button1;
157 xbutton->state = Button1Mask;
158 break;
159 case MIDDLE:
160 xbutton->button = Button2;
161 xbutton->state = Button2Mask;
162 break;
163 case RIGHT:
164 xbutton->button = Button3;
165 xbutton->state = Button3Mask;
166 break;
168 // WindowEventDispatcher will take care of other necessary fields.
169 if (state & DOWN) {
170 xevent.xbutton.type = ButtonPress;
171 PostEventToWindowTreeHost(xevent, host_);
172 button_down_mask |= xbutton->state;
174 if (state & UP) {
175 xevent.xbutton.type = ButtonRelease;
176 PostEventToWindowTreeHost(xevent, host_);
177 button_down_mask = (button_down_mask | xbutton->state) ^ xbutton->state;
179 RunClosureAfterAllPendingUIEvents(closure);
180 return true;
182 bool SendMouseClick(MouseButton type) override {
183 return SendMouseEvents(type, UP | DOWN);
185 void RunClosureAfterAllPendingUIEvents(
186 const base::Closure& closure) override {
187 if (closure.is_null())
188 return;
189 static XEvent* marker_event = NULL;
190 if (!marker_event) {
191 marker_event = new XEvent();
192 marker_event->xclient.type = ClientMessage;
193 marker_event->xclient.display = NULL;
194 marker_event->xclient.window = None;
195 marker_event->xclient.format = 8;
197 marker_event->xclient.message_type = MarkerEventAtom();
198 PostEventToWindowTreeHost(*marker_event, host_);
199 ui::PlatformEventWaiter::Create(closure, base::Bind(&Matcher));
201 private:
202 void SetKeycodeAndSendThenMask(XEvent* xevent,
203 KeySym keysym,
204 unsigned int mask) {
205 xevent->xkey.keycode =
206 XKeysymToKeycode(gfx::GetXDisplay(), keysym);
207 PostEventToWindowTreeHost(*xevent, host_);
208 xevent->xkey.state |= mask;
211 void UnmaskAndSetKeycodeThenSend(XEvent* xevent,
212 unsigned int mask,
213 KeySym keysym) {
214 xevent->xkey.state ^= mask;
215 xevent->xkey.keycode =
216 XKeysymToKeycode(gfx::GetXDisplay(), keysym);
217 PostEventToWindowTreeHost(*xevent, host_);
220 WindowTreeHost* host_;
222 DISALLOW_COPY_AND_ASSIGN(UIControlsX11);
225 } // namespace
227 UIControlsAura* CreateUIControlsAura(WindowTreeHost* host) {
228 return new UIControlsX11(host);
231 } // namespace test
232 } // namespace aura