blob: 10cb38c18802f93aa2005e37b431b4be874e55ef [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/bind.h"
#include "base/logging.h"
#include "base/macros.h"
#include "ui/aura/client/screen_position_client.h"
#include "ui/aura/env.h"
#include "ui/aura/test/aura_test_utils.h"
#include "ui/aura/test/ui_controls_factory_aura.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/test/ui_controls_aura.h"
#include "ui/events/event_utils.h"
#include "ui/events/test/events_test_utils.h"
namespace aura {
namespace test {
namespace {
class UIControlsOzone : public ui_controls::UIControlsAura {
public:
UIControlsOzone(WindowTreeHost* host) : host_(host) {}
bool SendKeyPress(gfx::NativeWindow window,
ui::KeyboardCode key,
bool control,
bool shift,
bool alt,
bool command) override {
return SendKeyPressNotifyWhenDone(
window, key, control, shift, alt, command, base::Closure());
}
bool SendKeyPressNotifyWhenDone(
gfx::NativeWindow window,
ui::KeyboardCode key,
bool control,
bool shift,
bool alt,
bool command,
const base::Closure& closure) override {
int flags = button_down_mask_;
if (control) {
flags |= ui::EF_CONTROL_DOWN;
PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, flags);
}
if (shift) {
flags |= ui::EF_SHIFT_DOWN;
PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SHIFT, flags);
}
if (alt) {
flags |= ui::EF_ALT_DOWN;
PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_MENU, flags);
}
if (command) {
flags |= ui::EF_COMMAND_DOWN;
PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_LWIN, flags);
}
PostKeyEvent(ui::ET_KEY_PRESSED, key, flags);
PostKeyEvent(ui::ET_KEY_RELEASED, key, flags);
if (alt) {
flags &= ~ui::EF_ALT_DOWN;
PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_MENU, flags);
}
if (shift) {
flags &= ~ui::EF_SHIFT_DOWN;
PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_SHIFT, flags);
}
if (control) {
flags &= ~ui::EF_CONTROL_DOWN;
PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL, flags);
}
if (command) {
flags &= ~ui::EF_COMMAND_DOWN;
PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_LWIN, flags);
}
RunClosureAfterAllPendingUIEvents(closure);
return true;
}
bool SendMouseMove(long screen_x, long screen_y) override {
return SendMouseMoveNotifyWhenDone(screen_x, screen_y, base::Closure());
}
bool SendMouseMoveNotifyWhenDone(
long screen_x,
long screen_y,
const base::Closure& closure) override {
gfx::Point root_location(screen_x, screen_y);
aura::client::ScreenPositionClient* screen_position_client =
aura::client::GetScreenPositionClient(host_->window());
if (screen_position_client) {
screen_position_client->ConvertPointFromScreen(host_->window(),
&root_location);
}
gfx::Point host_location = root_location;
host_->ConvertPointToHost(&host_location);
ui::EventType event_type;
if (button_down_mask_)
event_type = ui::ET_MOUSE_DRAGGED;
else
event_type = ui::ET_MOUSE_MOVED;
PostMouseEvent(event_type, host_location, 0, 0);
RunClosureAfterAllPendingUIEvents(closure);
return true;
}
bool SendMouseEvents(ui_controls::MouseButton type, int state) override {
return SendMouseEventsNotifyWhenDone(type, state, base::Closure());
}
bool SendMouseEventsNotifyWhenDone(
ui_controls::MouseButton type,
int state,
const base::Closure& closure) override {
gfx::Point root_location = aura::Env::GetInstance()->last_mouse_location();
aura::client::ScreenPositionClient* screen_position_client =
aura::client::GetScreenPositionClient(host_->window());
if (screen_position_client) {
screen_position_client->ConvertPointFromScreen(host_->window(),
&root_location);
}
gfx::Point host_location = root_location;
host_->ConvertPointToHost(&host_location);
int flag = 0;
switch (type) {
case ui_controls::LEFT:
flag = ui::EF_LEFT_MOUSE_BUTTON;
break;
case ui_controls::MIDDLE:
flag = ui::EF_MIDDLE_MOUSE_BUTTON;
break;
case ui_controls::RIGHT:
flag = ui::EF_RIGHT_MOUSE_BUTTON;
break;
default:
NOTREACHED();
break;
}
if (state & ui_controls::DOWN) {
button_down_mask_ |= flag;
PostMouseEvent(ui::ET_MOUSE_PRESSED, host_location,
button_down_mask_ | flag, flag);
}
if (state & ui_controls::UP) {
button_down_mask_ &= ~flag;
PostMouseEvent(ui::ET_MOUSE_RELEASED, host_location,
button_down_mask_ | flag, flag);
}
RunClosureAfterAllPendingUIEvents(closure);
return true;
}
bool SendMouseClick(ui_controls::MouseButton type) override {
return SendMouseEvents(type, ui_controls::UP | ui_controls::DOWN);
}
void RunClosureAfterAllPendingUIEvents(
const base::Closure& closure) override {
if (!closure.is_null())
base::MessageLoop::current()->PostTask(FROM_HERE, closure);
}
private:
void SendEventToProcessor(ui::Event* event) {
ui::EventSourceTestApi event_source_test(host_->GetEventSource());
ui::EventDispatchDetails details =
event_source_test.SendEventToProcessor(event);
if (details.dispatcher_destroyed)
return;
}
void PostKeyEvent(ui::EventType type, ui::KeyboardCode key_code, int flags) {
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&UIControlsOzone::PostKeyEventTask,
base::Unretained(this),
type,
key_code,
flags));
}
void PostKeyEventTask(ui::EventType type,
ui::KeyboardCode key_code,
int flags) {
// Do not rewrite injected events. See crbug.com/136465.
flags |= ui::EF_FINAL;
ui::KeyEvent key_event(type, key_code, flags);
SendEventToProcessor(&key_event);
}
void PostMouseEvent(ui::EventType type,
const gfx::Point& host_location,
int flags,
int changed_button_flags) {
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&UIControlsOzone::PostMouseEventTask, base::Unretained(this),
type, host_location, flags, changed_button_flags));
}
void PostMouseEventTask(ui::EventType type,
const gfx::Point& host_location,
int flags,
int changed_button_flags) {
ui::MouseEvent mouse_event(type, host_location, host_location,
ui::EventTimeForNow(), flags,
changed_button_flags);
// This hack is necessary to set the repeat count for clicks.
ui::MouseEvent mouse_event2(&mouse_event);
SendEventToProcessor(&mouse_event2);
}
WindowTreeHost* host_;
// Mask of the mouse buttons currently down.
unsigned button_down_mask_ = 0;
DISALLOW_COPY_AND_ASSIGN(UIControlsOzone);
};
} // namespace
ui_controls::UIControlsAura* CreateUIControlsAura(WindowTreeHost* host) {
return new UIControlsOzone(host);
}
} // namespace test
} // namespace aura