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