| OLD | NEW |
| (Empty) |
| 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 | |
| OLD | NEW |