Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / ui / aura / test / ui_controls_factory_aurax11.cc
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.
4
5 #include <X11/keysym.h>
6 #include <X11/Xlib.h>
7
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/window.h"
15 #include "ui/aura/window_tree_host.h"
16 #include "ui/base/test/ui_controls_aura.h"
17 #include "ui/base/x/x11_util.h"
18 #include "ui/compositor/dip_util.h"
19 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
20 #include "ui/events/test/platform_event_waiter.h"
21
22 namespace aura {
23 namespace test {
24 namespace {
25
26 using ui_controls::DOWN;
27 using ui_controls::LEFT;
28 using ui_controls::MIDDLE;
29 using ui_controls::MouseButton;
30 using ui_controls::RIGHT;
31 using ui_controls::UIControlsAura;
32 using ui_controls::UP;
33
34 // Mask of the buttons currently down.
35 unsigned button_down_mask = 0;
36
37 // Returns atom that indidates that the XEvent is marker event.
38 Atom MarkerEventAtom() {
39   return XInternAtom(gfx::GetXDisplay(), "marker_event", False);
40 }
41
42 // Returns true when the event is a marker event.
43 bool Matcher(const base::NativeEvent& event) {
44   return event->xany.type == ClientMessage &&
45       event->xclient.message_type == MarkerEventAtom();
46 }
47
48 class UIControlsX11 : public UIControlsAura {
49  public:
50   UIControlsX11(WindowTreeHost* host) : host_(host) {
51   }
52
53   virtual bool SendKeyPress(gfx::NativeWindow window,
54                             ui::KeyboardCode key,
55                             bool control,
56                             bool shift,
57                             bool alt,
58                             bool command) OVERRIDE {
59     DCHECK(!command);  // No command key on Aura
60     return SendKeyPressNotifyWhenDone(
61         window, key, control, shift, alt, command, base::Closure());
62   }
63   virtual bool SendKeyPressNotifyWhenDone(
64       gfx::NativeWindow window,
65       ui::KeyboardCode key,
66       bool control,
67       bool shift,
68       bool alt,
69       bool command,
70       const base::Closure& closure) OVERRIDE {
71     DCHECK(!command);  // No command key on Aura
72     XEvent xevent = {0};
73     xevent.xkey.type = KeyPress;
74     if (control)
75       SetKeycodeAndSendThenMask(&xevent, XK_Control_L, ControlMask);
76     if (shift)
77       SetKeycodeAndSendThenMask(&xevent, XK_Shift_L, ShiftMask);
78     if (alt)
79       SetKeycodeAndSendThenMask(&xevent, XK_Alt_L, Mod1Mask);
80     xevent.xkey.keycode =
81         XKeysymToKeycode(gfx::GetXDisplay(),
82                          ui::XKeysymForWindowsKeyCode(key, shift));
83     host_->PostNativeEvent(&xevent);
84
85     // Send key release events.
86     xevent.xkey.type = KeyRelease;
87     host_->PostNativeEvent(&xevent);
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     DCHECK(!xevent.xkey.state);
95     RunClosureAfterAllPendingUIEvents(closure);
96     return true;
97   }
98
99   virtual bool SendMouseMove(long screen_x, long screen_y) OVERRIDE {
100     return SendMouseMoveNotifyWhenDone(screen_x, screen_y, base::Closure());
101   }
102   virtual bool SendMouseMoveNotifyWhenDone(
103       long screen_x,
104       long screen_y,
105       const base::Closure& closure) OVERRIDE {
106     gfx::Point root_location(screen_x, screen_y);
107     aura::client::ScreenPositionClient* screen_position_client =
108         aura::client::GetScreenPositionClient(host_->window());
109     if (screen_position_client) {
110       screen_position_client->ConvertPointFromScreen(host_->window(),
111                                                      &root_location);
112     }
113     gfx::Point root_current_location =
114         QueryLatestMousePositionRequestInHost(host_);
115     host_->ConvertPointFromHost(&root_current_location);
116
117     if (root_location != root_current_location && button_down_mask == 0) {
118       // Move the cursor because EnterNotify/LeaveNotify are generated with the
119       // current mouse position as a result of XGrabPointer()
120       host_->window()->MoveCursorTo(root_location);
121     } else {
122       XEvent xevent = {0};
123       XMotionEvent* xmotion = &xevent.xmotion;
124       xmotion->type = MotionNotify;
125       xmotion->x = root_location.x();
126       xmotion->y = root_location.y();
127       xmotion->state = button_down_mask;
128       xmotion->same_screen = True;
129       // WindowTreeHost will take care of other necessary fields.
130       host_->PostNativeEvent(&xevent);
131     }
132     RunClosureAfterAllPendingUIEvents(closure);
133     return true;
134   }
135   virtual bool SendMouseEvents(MouseButton type, int state) OVERRIDE {
136     return SendMouseEventsNotifyWhenDone(type, state, base::Closure());
137   }
138   virtual bool SendMouseEventsNotifyWhenDone(
139       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);
150     }
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;
167     }
168     // WindowEventDispatcher will take care of other necessary fields.
169     if (state & DOWN) {
170       xevent.xbutton.type = ButtonPress;
171       host_->PostNativeEvent(&xevent);
172       button_down_mask |= xbutton->state;
173     }
174     if (state & UP) {
175       xevent.xbutton.type = ButtonRelease;
176       host_->PostNativeEvent(&xevent);
177       button_down_mask = (button_down_mask | xbutton->state) ^ xbutton->state;
178     }
179     RunClosureAfterAllPendingUIEvents(closure);
180     return true;
181   }
182   virtual bool SendMouseClick(MouseButton type) OVERRIDE {
183     return SendMouseEvents(type, UP | DOWN);
184   }
185   virtual 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;
196     }
197     marker_event->xclient.message_type = MarkerEventAtom();
198     host_->PostNativeEvent(marker_event);
199     ui::PlatformEventWaiter::Create(closure, base::Bind(&Matcher));
200   }
201  private:
202   void SetKeycodeAndSendThenMask(XEvent* xevent,
203                                  KeySym keysym,
204                                  unsigned int mask) {
205     xevent->xkey.keycode =
206         XKeysymToKeycode(gfx::GetXDisplay(), keysym);
207     host_->PostNativeEvent(xevent);
208     xevent->xkey.state |= mask;
209   }
210
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     host_->PostNativeEvent(xevent);
218   }
219
220   WindowTreeHost* host_;
221
222   DISALLOW_COPY_AND_ASSIGN(UIControlsX11);
223 };
224
225 }  // namespace
226
227 UIControlsAura* CreateUIControlsAura(WindowTreeHost* host) {
228   return new UIControlsX11(host);
229 }
230
231 }  // namespace test
232 }  // namespace aura