Home | History | Annotate | Download | only in test
      1 // Copyright 2014 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 "base/bind.h"
      6 #include "base/logging.h"
      7 #include "ui/aura/client/screen_position_client.h"
      8 #include "ui/aura/env.h"
      9 #include "ui/aura/test/aura_test_utils.h"
     10 #include "ui/aura/test/ui_controls_factory_aura.h"
     11 #include "ui/aura/window_tree_host.h"
     12 #include "ui/base/test/ui_controls_aura.h"
     13 
     14 namespace aura {
     15 namespace test {
     16 namespace {
     17 
     18 class UIControlsOzone : public ui_controls::UIControlsAura {
     19  public:
     20   UIControlsOzone(WindowTreeHost* host) : host_(host) {}
     21 
     22   virtual bool SendKeyPress(gfx::NativeWindow window,
     23                             ui::KeyboardCode key,
     24                             bool control,
     25                             bool shift,
     26                             bool alt,
     27                             bool command) OVERRIDE {
     28     return SendKeyPressNotifyWhenDone(
     29         window, key, control, shift, alt, command, base::Closure());
     30   }
     31   virtual bool SendKeyPressNotifyWhenDone(
     32       gfx::NativeWindow window,
     33       ui::KeyboardCode key,
     34       bool control,
     35       bool shift,
     36       bool alt,
     37       bool command,
     38       const base::Closure& closure) OVERRIDE {
     39     int flags = button_down_mask_;
     40 
     41     if (control) {
     42       flags |= ui::EF_CONTROL_DOWN;
     43       PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, flags);
     44     }
     45 
     46     if (shift) {
     47       flags |= ui::EF_SHIFT_DOWN;
     48       PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SHIFT, flags);
     49     }
     50 
     51     if (alt) {
     52       flags |= ui::EF_ALT_DOWN;
     53       PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_MENU, flags);
     54     }
     55 
     56     if (command) {
     57       flags |= ui::EF_COMMAND_DOWN;
     58       PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_LWIN, flags);
     59     }
     60 
     61     PostKeyEvent(ui::ET_KEY_PRESSED, key, flags);
     62     PostKeyEvent(ui::ET_KEY_RELEASED, key, flags);
     63 
     64     if (alt) {
     65       flags &= ~ui::EF_ALT_DOWN;
     66       PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_MENU, flags);
     67     }
     68 
     69     if (shift) {
     70       flags &= ~ui::EF_SHIFT_DOWN;
     71       PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_SHIFT, flags);
     72     }
     73 
     74     if (control) {
     75       flags &= ~ui::EF_CONTROL_DOWN;
     76       PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL, flags);
     77     }
     78 
     79     if (command) {
     80       flags &= ~ui::EF_COMMAND_DOWN;
     81       PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_LWIN, flags);
     82     }
     83 
     84     RunClosureAfterAllPendingUIEvents(closure);
     85     return true;
     86   }
     87 
     88   virtual bool SendMouseMove(long screen_x, long screen_y) OVERRIDE {
     89     return SendMouseMoveNotifyWhenDone(screen_x, screen_y, base::Closure());
     90   }
     91   virtual bool SendMouseMoveNotifyWhenDone(
     92       long screen_x,
     93       long screen_y,
     94       const base::Closure& closure) OVERRIDE {
     95     gfx::Point root_location(screen_x, screen_y);
     96     aura::client::ScreenPositionClient* screen_position_client =
     97         aura::client::GetScreenPositionClient(host_->window());
     98     if (screen_position_client) {
     99       screen_position_client->ConvertPointFromScreen(host_->window(),
    100                                                      &root_location);
    101     }
    102     gfx::Point root_current_location =
    103         QueryLatestMousePositionRequestInHost(host_);
    104     host_->ConvertPointFromHost(&root_current_location);
    105 
    106     if (button_down_mask_)
    107       PostMouseEvent(ui::ET_MOUSE_DRAGGED, root_location, 0, 0);
    108     else
    109       PostMouseEvent(ui::ET_MOUSE_MOVED, root_location, 0, 0);
    110 
    111     RunClosureAfterAllPendingUIEvents(closure);
    112     return true;
    113   }
    114   virtual bool SendMouseEvents(ui_controls::MouseButton type,
    115                                int state) OVERRIDE {
    116     return SendMouseEventsNotifyWhenDone(type, state, base::Closure());
    117   }
    118   virtual bool SendMouseEventsNotifyWhenDone(
    119       ui_controls::MouseButton type,
    120       int state,
    121       const base::Closure& closure) OVERRIDE {
    122     gfx::Point loc = aura::Env::GetInstance()->last_mouse_location();
    123     aura::client::ScreenPositionClient* screen_position_client =
    124         aura::client::GetScreenPositionClient(host_->window());
    125     if (screen_position_client) {
    126       screen_position_client->ConvertPointFromScreen(host_->window(), &loc);
    127     }
    128     int flag = 0;
    129 
    130     switch (type) {
    131       case ui_controls::LEFT:
    132         flag = ui::EF_LEFT_MOUSE_BUTTON;
    133         break;
    134       case ui_controls::MIDDLE:
    135         flag = ui::EF_MIDDLE_MOUSE_BUTTON;
    136         break;
    137       case ui_controls::RIGHT:
    138         flag = ui::EF_RIGHT_MOUSE_BUTTON;
    139         break;
    140       default:
    141         NOTREACHED();
    142         break;
    143     }
    144 
    145     if (state & ui_controls::DOWN) {
    146       button_down_mask_ |= flag;
    147       PostMouseEvent(ui::ET_MOUSE_PRESSED, loc, button_down_mask_ | flag, flag);
    148     }
    149     if (state & ui_controls::UP) {
    150       button_down_mask_ &= ~flag;
    151       PostMouseEvent(
    152           ui::ET_MOUSE_RELEASED, loc, button_down_mask_ | flag, flag);
    153     }
    154 
    155     RunClosureAfterAllPendingUIEvents(closure);
    156     return true;
    157   }
    158   virtual bool SendMouseClick(ui_controls::MouseButton type) OVERRIDE {
    159     return SendMouseEvents(type, ui_controls::UP | ui_controls::DOWN);
    160   }
    161   virtual void RunClosureAfterAllPendingUIEvents(
    162       const base::Closure& closure) OVERRIDE {
    163     if (!closure.is_null())
    164       base::MessageLoop::current()->PostTask(FROM_HERE, closure);
    165   }
    166 
    167  private:
    168   void PostKeyEvent(ui::EventType type, ui::KeyboardCode key_code, int flags) {
    169     base::MessageLoop::current()->PostTask(
    170         FROM_HERE,
    171         base::Bind(&UIControlsOzone::PostKeyEventTask,
    172                    base::Unretained(this),
    173                    type,
    174                    key_code,
    175                    flags));
    176   }
    177 
    178   void PostKeyEventTask(ui::EventType type,
    179                         ui::KeyboardCode key_code,
    180                         int flags) {
    181     // Do not rewrite injected events. See crbug.com/136465.
    182     flags |= ui::EF_FINAL;
    183 
    184     ui::KeyEvent key_event(type, key_code, flags);
    185     host_->PostNativeEvent(&key_event);
    186   }
    187 
    188   void PostMouseEvent(ui::EventType type,
    189                       const gfx::PointF& location,
    190                       int flags,
    191                       int changed_button_flags) {
    192     base::MessageLoop::current()->PostTask(
    193         FROM_HERE,
    194         base::Bind(&UIControlsOzone::PostMouseEventTask,
    195                    base::Unretained(this),
    196                    type,
    197                    location,
    198                    flags,
    199                    changed_button_flags));
    200   }
    201 
    202   void PostMouseEventTask(ui::EventType type,
    203                           const gfx::PointF& location,
    204                           int flags,
    205                           int changed_button_flags) {
    206     ui::MouseEvent mouse_event(
    207         type, location, location, flags, changed_button_flags);
    208 
    209     // This hack is necessary to set the repeat count for clicks.
    210     ui::MouseEvent mouse_event2(&mouse_event);
    211 
    212     host_->PostNativeEvent(&mouse_event2);
    213   }
    214 
    215   WindowTreeHost* host_;
    216 
    217   // Mask of the mouse buttons currently down.
    218   unsigned button_down_mask_ = 0;
    219 
    220   DISALLOW_COPY_AND_ASSIGN(UIControlsOzone);
    221 };
    222 
    223 }  // namespace
    224 
    225 ui_controls::UIControlsAura* CreateUIControlsAura(WindowTreeHost* host) {
    226   return new UIControlsOzone(host);
    227 }
    228 
    229 }  // namespace test
    230 }  // namespace aura
    231