1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/keysym.h>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/Xlib.h>
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/bind.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/client/screen_position_client.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/env.h"
125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/aura/test/aura_test_utils.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/aura/test/ui_controls_factory_aura.h"
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/aura/window.h"
1523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ui/aura/window_tree_host.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/base/test/ui_controls_aura.h"
17d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/base/x/x11_util.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/dip_util.h"
19d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/keycodes/keyboard_code_conversion_x.h"
20c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/events/test/platform_event_waiter.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace aura {
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace test {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using ui_controls::DOWN;
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using ui_controls::LEFT;
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using ui_controls::MIDDLE;
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using ui_controls::MouseButton;
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using ui_controls::RIGHT;
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using ui_controls::UIControlsAura;
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using ui_controls::UP;
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Mask of the buttons currently down.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned button_down_mask = 0;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns atom that indidates that the XEvent is marker event.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Atom MarkerEventAtom() {
3968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return XInternAtom(gfx::GetXDisplay(), "marker_event", False);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true when the event is a marker event.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Matcher(const base::NativeEvent& event) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return event->xany.type == ClientMessage &&
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event->xclient.message_type == MarkerEventAtom();
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class UIControlsX11 : public UIControlsAura {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
5023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  UIControlsX11(WindowTreeHost* host) : host_(host) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool SendKeyPress(gfx::NativeWindow window,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            ui::KeyboardCode key,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            bool control,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            bool shift,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            bool alt,
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            bool command) OVERRIDE {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SendKeyPressNotifyWhenDone(
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        window, key, control, shift, alt, command, base::Closure());
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool SendKeyPressNotifyWhenDone(
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::NativeWindow window,
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ui::KeyboardCode key,
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool control,
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool shift,
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool alt,
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool command,
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::Closure& closure) OVERRIDE {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XEvent xevent = {0};
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xevent.xkey.type = KeyPress;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (control)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SetKeycodeAndSendThenMask(&xevent, XK_Control_L, ControlMask);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (shift)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SetKeycodeAndSendThenMask(&xevent, XK_Shift_L, ShiftMask);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (alt)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SetKeycodeAndSendThenMask(&xevent, XK_Alt_L, Mod1Mask);
7803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (command)
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      SetKeycodeAndSendThenMask(&xevent, XK_Meta_L, Mod4Mask);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xevent.xkey.keycode =
8168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        XKeysymToKeycode(gfx::GetXDisplay(),
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         ui::XKeysymForWindowsKeyCode(key, shift));
8323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    host_->PostNativeEvent(&xevent);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Send key release events.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xevent.xkey.type = KeyRelease;
8723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    host_->PostNativeEvent(&xevent);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (alt)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UnmaskAndSetKeycodeThenSend(&xevent, Mod1Mask, XK_Alt_L);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (shift)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UnmaskAndSetKeycodeThenSend(&xevent, ShiftMask, XK_Shift_L);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (control)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UnmaskAndSetKeycodeThenSend(&xevent, ControlMask, XK_Control_L);
9403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (command)
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      UnmaskAndSetKeycodeThenSend(&xevent, Mod4Mask, XK_Meta_L);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!xevent.xkey.state);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RunClosureAfterAllPendingUIEvents(closure);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual bool SendMouseMove(long screen_x, long screen_y) OVERRIDE {
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return SendMouseMoveNotifyWhenDone(screen_x, screen_y, base::Closure());
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool SendMouseMoveNotifyWhenDone(
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      long screen_x,
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      long screen_y,
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::Closure& closure) OVERRIDE {
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    gfx::Point root_location(screen_x, screen_y);
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    aura::client::ScreenPositionClient* screen_position_client =
11023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        aura::client::GetScreenPositionClient(host_->window());
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (screen_position_client) {
11223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      screen_position_client->ConvertPointFromScreen(host_->window(),
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                     &root_location);
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    gfx::Point root_current_location =
1165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        QueryLatestMousePositionRequestInHost(host_);
11723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    host_->ConvertPointFromHost(&root_current_location);
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (root_location != root_current_location && button_down_mask == 0) {
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // Move the cursor because EnterNotify/LeaveNotify are generated with the
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // current mouse position as a result of XGrabPointer()
12223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      host_->window()->MoveCursorTo(root_location);
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    } else {
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      XEvent xevent = {0};
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      XMotionEvent* xmotion = &xevent.xmotion;
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      xmotion->type = MotionNotify;
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      xmotion->x = root_location.x();
128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      xmotion->y = root_location.y();
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      xmotion->state = button_down_mask;
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      xmotion->same_screen = True;
13123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      // WindowTreeHost will take care of other necessary fields.
13223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      host_->PostNativeEvent(&xevent);
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RunClosureAfterAllPendingUIEvents(closure);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool SendMouseEvents(MouseButton type, int state) OVERRIDE {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SendMouseEventsNotifyWhenDone(type, state, base::Closure());
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool SendMouseEventsNotifyWhenDone(
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MouseButton type,
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int state,
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::Closure& closure) OVERRIDE {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XEvent xevent = {0};
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XButtonEvent* xbutton = &xevent.xbutton;
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gfx::Point mouse_loc = aura::Env::GetInstance()->last_mouse_location();
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    aura::client::ScreenPositionClient* screen_position_client =
14823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          aura::client::GetScreenPositionClient(host_->window());
149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (screen_position_client) {
15023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      screen_position_client->ConvertPointFromScreen(host_->window(),
151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                     &mouse_loc);
152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    xbutton->x = mouse_loc.x();
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    xbutton->y = mouse_loc.y();
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xbutton->same_screen = True;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (type) {
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case LEFT:
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xbutton->button = Button1;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xbutton->state = Button1Mask;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case MIDDLE:
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xbutton->button = Button2;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xbutton->state = Button2Mask;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case RIGHT:
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xbutton->button = Button3;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xbutton->state = Button3Mask;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // WindowEventDispatcher will take care of other necessary fields.
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (state & DOWN) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      xevent.xbutton.type = ButtonPress;
17323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      host_->PostNativeEvent(&xevent);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      button_down_mask |= xbutton->state;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (state & UP) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      xevent.xbutton.type = ButtonRelease;
17823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      host_->PostNativeEvent(&xevent);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      button_down_mask = (button_down_mask | xbutton->state) ^ xbutton->state;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RunClosureAfterAllPendingUIEvents(closure);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool SendMouseClick(MouseButton type) OVERRIDE {
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return SendMouseEvents(type, UP | DOWN);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void RunClosureAfterAllPendingUIEvents(
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::Closure& closure) OVERRIDE {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (closure.is_null())
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static XEvent* marker_event = NULL;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!marker_event) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      marker_event = new XEvent();
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      marker_event->xclient.type = ClientMessage;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      marker_event->xclient.display = NULL;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      marker_event->xclient.window = None;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      marker_event->xclient.format = 8;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    marker_event->xclient.message_type = MarkerEventAtom();
20023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    host_->PostNativeEvent(marker_event);
201c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ui::PlatformEventWaiter::Create(closure, base::Bind(&Matcher));
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetKeycodeAndSendThenMask(XEvent* xevent,
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 KeySym keysym,
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 unsigned int mask) {
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xevent->xkey.keycode =
20868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        XKeysymToKeycode(gfx::GetXDisplay(), keysym);
20923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    host_->PostNativeEvent(xevent);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xevent->xkey.state |= mask;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void UnmaskAndSetKeycodeThenSend(XEvent* xevent,
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   unsigned int mask,
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   KeySym keysym) {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xevent->xkey.state ^= mask;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xevent->xkey.keycode =
21868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        XKeysymToKeycode(gfx::GetXDisplay(), keysym);
21923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    host_->PostNativeEvent(xevent);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  WindowTreeHost* host_;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(UIControlsX11);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)UIControlsAura* CreateUIControlsAura(WindowTreeHost* host) {
23023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return new UIControlsX11(host);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace test
234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace aura
235