Upstream version 10.39.225.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     return SendKeyPressNotifyWhenDone(
60         window, key, control, shift, alt, command, base::Closure());
61   }
62   virtual bool SendKeyPressNotifyWhenDone(
63       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     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     if (command)
95       UnmaskAndSetKeycodeThenSend(&xevent, Mod4Mask, XK_Meta_L);
96     DCHECK(!xevent.xkey.state);
97     RunClosureAfterAllPendingUIEvents(closure);
98     return true;
99   }
100
101   virtual bool SendMouseMove(long screen_x, long screen_y) OVERRIDE {
102     return SendMouseMoveNotifyWhenDone(screen_x, screen_y, base::Closure());
103   }
104   virtual bool SendMouseMoveNotifyWhenDone(
105       long screen_x,
106       long screen_y,
107       const base::Closure& closure) OVERRIDE {
108     gfx::Point root_location(screen_x, screen_y);
109     aura::client::ScreenPositionClient* screen_position_client =
110         aura::client::GetScreenPositionClient(host_->window());
111     if (screen_position_client) {
112       screen_position_client->ConvertPointFromScreen(host_->window(),
113                                                      &root_location);
114     }
115     gfx::Point root_current_location =
116         QueryLatestMousePositionRequestInHost(host_);
117     host_->ConvertPointFromHost(&root_current_location);
118
119     if (root_location != root_current_location && button_down_mask == 0) {
120       // Move the cursor because EnterNotify/LeaveNotify are generated with the
121       // current mouse position as a result of XGrabPointer()
122       host_->window()->MoveCursorTo(root_location);
123     } else {
124       XEvent xevent = {0};
125       XMotionEvent* xmotion = &xevent.xmotion;
126       xmotion->type = MotionNotify;
127       xmotion->x = root_location.x();
128       xmotion->y = root_location.y();
129       xmotion->state = button_down_mask;
130       xmotion->same_screen = True;
131       // WindowTreeHost will take care of other necessary fields.
132       host_->PostNativeEvent(&xevent);
133     }
134     RunClosureAfterAllPendingUIEvents(closure);
135     return true;
136   }
137   virtual bool SendMouseEvents(MouseButton type, int state) OVERRIDE {
138     return SendMouseEventsNotifyWhenDone(type, state, base::Closure());
139   }
140   virtual bool SendMouseEventsNotifyWhenDone(
141       MouseButton type,
142       int state,
143       const base::Closure& closure) OVERRIDE {
144     XEvent xevent = {0};
145     XButtonEvent* xbutton = &xevent.xbutton;
146     gfx::Point mouse_loc = aura::Env::GetInstance()->last_mouse_location();
147     aura::client::ScreenPositionClient* screen_position_client =
148           aura::client::GetScreenPositionClient(host_->window());
149     if (screen_position_client) {
150       screen_position_client->ConvertPointFromScreen(host_->window(),
151                                                      &mouse_loc);
152     }
153     xbutton->x = mouse_loc.x();
154     xbutton->y = mouse_loc.y();
155     xbutton->same_screen = True;
156     switch (type) {
157       case LEFT:
158         xbutton->button = Button1;
159         xbutton->state = Button1Mask;
160         break;
161       case MIDDLE:
162         xbutton->button = Button2;
163         xbutton->state = Button2Mask;
164         break;
165       case RIGHT:
166         xbutton->button = Button3;
167         xbutton->state = Button3Mask;
168         break;
169     }
170     // WindowEventDispatcher will take care of other necessary fields.
171     if (state & DOWN) {
172       xevent.xbutton.type = ButtonPress;
173       host_->PostNativeEvent(&xevent);
174       button_down_mask |= xbutton->state;
175     }
176     if (state & UP) {
177       xevent.xbutton.type = ButtonRelease;
178       host_->PostNativeEvent(&xevent);
179       button_down_mask = (button_down_mask | xbutton->state) ^ xbutton->state;
180     }
181     RunClosureAfterAllPendingUIEvents(closure);
182     return true;
183   }
184   virtual bool SendMouseClick(MouseButton type) OVERRIDE {
185     return SendMouseEvents(type, UP | DOWN);
186   }
187   virtual void RunClosureAfterAllPendingUIEvents(
188       const base::Closure& closure) OVERRIDE {
189     if (closure.is_null())
190       return;
191     static XEvent* marker_event = NULL;
192     if (!marker_event) {
193       marker_event = new XEvent();
194       marker_event->xclient.type = ClientMessage;
195       marker_event->xclient.display = NULL;
196       marker_event->xclient.window = None;
197       marker_event->xclient.format = 8;
198     }
199     marker_event->xclient.message_type = MarkerEventAtom();
200     host_->PostNativeEvent(marker_event);
201     ui::PlatformEventWaiter::Create(closure, base::Bind(&Matcher));
202   }
203  private:
204   void SetKeycodeAndSendThenMask(XEvent* xevent,
205                                  KeySym keysym,
206                                  unsigned int mask) {
207     xevent->xkey.keycode =
208         XKeysymToKeycode(gfx::GetXDisplay(), keysym);
209     host_->PostNativeEvent(xevent);
210     xevent->xkey.state |= mask;
211   }
212
213   void UnmaskAndSetKeycodeThenSend(XEvent* xevent,
214                                    unsigned int mask,
215                                    KeySym keysym) {
216     xevent->xkey.state ^= mask;
217     xevent->xkey.keycode =
218         XKeysymToKeycode(gfx::GetXDisplay(), keysym);
219     host_->PostNativeEvent(xevent);
220   }
221
222   WindowTreeHost* host_;
223
224   DISALLOW_COPY_AND_ASSIGN(UIControlsX11);
225 };
226
227 }  // namespace
228
229 UIControlsAura* CreateUIControlsAura(WindowTreeHost* host) {
230   return new UIControlsX11(host);
231 }
232
233 }  // namespace test
234 }  // namespace aura