| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2012 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 // X macro fail. |
| 9 #if defined(RootWindow) |
| 10 #undef RootWindow |
| 11 #endif |
| 12 |
| 13 #include "base/logging.h" |
| 14 #include "base/message_pump_x.h" |
| 15 #include "ui/aura/root_window.h" |
| 16 #include "ui/aura/ui_controls_aura.h" |
| 17 #include "ui/base/keycodes/keyboard_code_conversion_x.h" |
| 18 #include "ui/ui_controls/ui_controls_aura.h" |
| 19 |
| 20 namespace aura { |
| 21 namespace { |
| 22 |
| 23 // Mask of the buttons currently down. |
| 24 unsigned button_down_mask = 0; |
| 25 |
| 26 // Event waiter executes the specified closure|when a matching event |
| 27 // is found. |
| 28 // TODO(oshima): Move this to base. |
| 29 class EventWaiter : public MessageLoopForUI::Observer { |
| 30 public: |
| 31 typedef bool (*EventWaiterMatcher)(const base::NativeEvent& event); |
| 32 |
| 33 EventWaiter(const base::Closure& closure, EventWaiterMatcher matcher) |
| 34 : closure_(closure), |
| 35 matcher_(matcher) { |
| 36 MessageLoopForUI::current()->AddObserver(this); |
| 37 } |
| 38 |
| 39 virtual ~EventWaiter() { |
| 40 MessageLoopForUI::current()->RemoveObserver(this); |
| 41 } |
| 42 |
| 43 // MessageLoop::Observer implementation: |
| 44 virtual base::EventStatus WillProcessEvent( |
| 45 const base::NativeEvent& event) OVERRIDE { |
| 46 if ((*matcher_)(event)) { |
| 47 MessageLoop::current()->PostTask(FROM_HERE, closure_); |
| 48 delete this; |
| 49 } |
| 50 return base::EVENT_CONTINUE; |
| 51 } |
| 52 |
| 53 virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE { |
| 54 } |
| 55 |
| 56 private: |
| 57 base::Closure closure_; |
| 58 EventWaiterMatcher matcher_; |
| 59 DISALLOW_COPY_AND_ASSIGN(EventWaiter); |
| 60 }; |
| 61 |
| 62 // Latest mouse pointer location set by SendMouseMoveNotifyWhenDone. |
| 63 int g_current_x = -1000; |
| 64 int g_current_y = -1000; |
| 65 |
| 66 // Returns atom that indidates that the XEvent is marker event. |
| 67 Atom MarkerEventAtom() { |
| 68 return XInternAtom(base::MessagePumpX::GetDefaultXDisplay(), |
| 69 "marker_event", |
| 70 False); |
| 71 } |
| 72 |
| 73 // Returns true when the event is a marker event. |
| 74 bool Matcher(const base::NativeEvent& event) { |
| 75 return event->xany.type == ClientMessage && |
| 76 event->xclient.message_type == MarkerEventAtom(); |
| 77 } |
| 78 |
| 79 class UIControlsX11 : public ui_controls::UIControlsAura { |
| 80 public: |
| 81 UIControlsX11(RootWindow* root_window) : root_window_(root_window) { |
| 82 } |
| 83 |
| 84 virtual bool SendKeyPress(gfx::NativeWindow window, |
| 85 ui::KeyboardCode key, |
| 86 bool control, |
| 87 bool shift, |
| 88 bool alt, |
| 89 bool command) { |
| 90 DCHECK(!command); // No command key on Aura |
| 91 return SendKeyPressNotifyWhenDone( |
| 92 window, key, control, shift, alt, command, base::Closure()); |
| 93 } |
| 94 virtual bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window, |
| 95 ui::KeyboardCode key, |
| 96 bool control, |
| 97 bool shift, |
| 98 bool alt, |
| 99 bool command, |
| 100 const base::Closure& closure) { |
| 101 DCHECK(!command); // No command key on Aura |
| 102 XEvent xevent = {0}; |
| 103 xevent.xkey.type = KeyPress; |
| 104 if (control) |
| 105 SetKeycodeAndSendThenMask(&xevent, XK_Control_L, ControlMask); |
| 106 if (shift) |
| 107 SetKeycodeAndSendThenMask(&xevent, XK_Shift_L, ShiftMask); |
| 108 if (alt) |
| 109 SetKeycodeAndSendThenMask(&xevent, XK_Alt_L, Mod1Mask); |
| 110 xevent.xkey.keycode = |
| 111 XKeysymToKeycode(base::MessagePumpX::GetDefaultXDisplay(), |
| 112 ui::XKeysymForWindowsKeyCode(key, shift)); |
| 113 root_window_->PostNativeEvent(&xevent); |
| 114 |
| 115 // Send key release events. |
| 116 xevent.xkey.type = KeyRelease; |
| 117 root_window_->PostNativeEvent(&xevent); |
| 118 if (alt) |
| 119 UnmaskAndSetKeycodeThenSend(&xevent, Mod1Mask, XK_Alt_L); |
| 120 if (shift) |
| 121 UnmaskAndSetKeycodeThenSend(&xevent, ShiftMask, XK_Shift_L); |
| 122 if (control) |
| 123 UnmaskAndSetKeycodeThenSend(&xevent, ControlMask, XK_Control_L); |
| 124 DCHECK(!xevent.xkey.state); |
| 125 RunClosureAfterAllPendingUIEvents(closure); |
| 126 return true; |
| 127 } |
| 128 |
| 129 // Simulate a mouse move. (x,y) are absolute screen coordinates. |
| 130 virtual bool SendMouseMove(long x, long y) { |
| 131 return SendMouseMoveNotifyWhenDone(x, y, base::Closure()); |
| 132 } |
| 133 virtual bool SendMouseMoveNotifyWhenDone(long x, |
| 134 long y, |
| 135 const base::Closure& closure) { |
| 136 XEvent xevent = {0}; |
| 137 XMotionEvent* xmotion = &xevent.xmotion; |
| 138 xmotion->type = MotionNotify; |
| 139 g_current_x = xmotion->x = x; |
| 140 g_current_y = xmotion->y = y; |
| 141 xmotion->state = button_down_mask; |
| 142 xmotion->same_screen = True; |
| 143 // RootWindow will take care of other necessary fields. |
| 144 root_window_->PostNativeEvent(&xevent); |
| 145 RunClosureAfterAllPendingUIEvents(closure); |
| 146 return true; |
| 147 } |
| 148 virtual bool SendMouseEvents(ui_controls::MouseButton type, int state) { |
| 149 return SendMouseEventsNotifyWhenDone(type, state, base::Closure()); |
| 150 } |
| 151 virtual bool SendMouseEventsNotifyWhenDone(ui_controls::MouseButton type, |
| 152 int state, |
| 153 const base::Closure& closure) { |
| 154 XEvent xevent = {0}; |
| 155 XButtonEvent* xbutton = &xevent.xbutton; |
| 156 DCHECK_NE(g_current_x, -1000); |
| 157 DCHECK_NE(g_current_y, -1000); |
| 158 xbutton->x = g_current_x; |
| 159 xbutton->y = g_current_y; |
| 160 xbutton->same_screen = True; |
| 161 switch (type) { |
| 162 case ui_controls::LEFT: |
| 163 xbutton->button = Button1; |
| 164 xbutton->state = Button1Mask; |
| 165 break; |
| 166 case ui_controls::MIDDLE: |
| 167 xbutton->button = Button2; |
| 168 xbutton->state = Button2Mask; |
| 169 break; |
| 170 case ui_controls::RIGHT: |
| 171 xbutton->button = Button3; |
| 172 xbutton->state = Button3Mask; |
| 173 break; |
| 174 } |
| 175 // RootWindow will take care of other necessary fields. |
| 176 if (state & ui_controls::DOWN) { |
| 177 xevent.xbutton.type = ButtonPress; |
| 178 root_window_->PostNativeEvent(&xevent); |
| 179 button_down_mask |= xbutton->state; |
| 180 } |
| 181 if (state & ui_controls::UP) { |
| 182 xevent.xbutton.type = ButtonRelease; |
| 183 root_window_->PostNativeEvent(&xevent); |
| 184 button_down_mask = (button_down_mask | xbutton->state) ^ xbutton->state; |
| 185 } |
| 186 RunClosureAfterAllPendingUIEvents(closure); |
| 187 return true; |
| 188 } |
| 189 virtual bool SendMouseClick(ui_controls::MouseButton type) { |
| 190 return SendMouseEvents(type, ui_controls::UP | ui_controls::DOWN); |
| 191 } |
| 192 virtual void RunClosureAfterAllPendingUIEvents(const base::Closure& closure) { |
| 193 if (closure.is_null()) |
| 194 return; |
| 195 static XEvent* marker_event = NULL; |
| 196 if (!marker_event) { |
| 197 marker_event = new XEvent(); |
| 198 marker_event->xclient.type = ClientMessage; |
| 199 marker_event->xclient.display = NULL; |
| 200 marker_event->xclient.window = None; |
| 201 marker_event->xclient.format = 8; |
| 202 } |
| 203 marker_event->xclient.message_type = MarkerEventAtom(); |
| 204 root_window_->PostNativeEvent(marker_event); |
| 205 new EventWaiter(closure, &Matcher); |
| 206 } |
| 207 private: |
| 208 void SetKeycodeAndSendThenMask(XEvent* xevent, |
| 209 KeySym keysym, |
| 210 unsigned int mask) { |
| 211 xevent->xkey.keycode = |
| 212 XKeysymToKeycode(base::MessagePumpX::GetDefaultXDisplay(), |
| 213 keysym); |
| 214 root_window_->PostNativeEvent(xevent); |
| 215 xevent->xkey.state |= mask; |
| 216 } |
| 217 |
| 218 void UnmaskAndSetKeycodeThenSend(XEvent* xevent, |
| 219 unsigned int mask, |
| 220 KeySym keysym) { |
| 221 xevent->xkey.state ^= mask; |
| 222 xevent->xkey.keycode = |
| 223 XKeysymToKeycode(base::MessagePumpX::GetDefaultXDisplay(), |
| 224 keysym); |
| 225 root_window_->PostNativeEvent(xevent); |
| 226 } |
| 227 |
| 228 RootWindow* root_window_; |
| 229 DISALLOW_COPY_AND_ASSIGN(UIControlsX11); |
| 230 }; |
| 231 |
| 232 } // namespace |
| 233 |
| 234 ui_controls::UIControlsAura* CreateUIControlsAura(RootWindow* root_window) { |
| 235 return new UIControlsX11(root_window); |
| 236 } |
| 237 |
| 238 } // namespace aura |
| OLD | NEW |