提交 3e79cc58 编写于 作者: J James Robinson

Nuke //ui/events, all users are runtime dead

上级 fe9b3446
......@@ -43,9 +43,6 @@ source_set("tests") {
test("mojo_common_unittests") {
deps = [
":tests",
"//mojo/converters/array_string:tests",
"//mojo/converters/base:tests",
"//mojo/converters/url:tests",
"//mojo/data_pipe_utils:tests",
"//mojo/edk/test:run_all_unittests",
"//mojo/environment:chromium",
......
# Copyright 2015 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.
source_set("array_string") {
sources = [
"array_string_type_converters.cc",
"array_string_type_converters.h",
]
deps = [
"//base",
"//mojo/public/cpp/bindings",
]
}
source_set("tests") {
testonly = true
sources = [
"array_string_type_converters_unittest.cc",
]
deps = [
":array_string",
"//base",
"//testing/gtest",
]
}
// Copyright 2013 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 "mojo/converters/array_string/array_string_type_converters.h"
#include <string>
#include "base/strings/utf_string_conversions.h"
namespace mojo {
std::string TypeConverter<std::string, Array<uint8_t>>::Convert(
const Array<uint8_t>& input) {
if (input.is_null())
return std::string();
return std::string(reinterpret_cast<const char*>(&input.front()),
input.size());
}
Array<uint8_t> TypeConverter<Array<uint8_t>, std::string>::Convert(
const std::string& input) {
auto result = Array<uint8_t>::New(input.size());
memcpy(&result.front(), input.c_str(), input.size());
return result;
}
} // namespace mojo
// Copyright 2013 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.
#ifndef MOJO_CONVERTERS_ARRAY_STRING_ARRAY_STRING_TYPE_CONVERTERS_H_
#define MOJO_CONVERTERS_ARRAY_STRING_ARRAY_STRING_TYPE_CONVERTERS_H_
#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
#include "mojo/public/cpp/bindings/array.h"
#include "mojo/public/cpp/bindings/string.h"
#include "mojo/public/cpp/bindings/type_converter.h"
namespace mojo {
// TODO(erg): In the very long term, we will want to remove conversion between
// std::strings and arrays of unsigned bytes. However, there is too much code
// across chrome which uses std::string as a bag of bytes that we probably
// don't want to roll this function at each callsite.
template <>
struct TypeConverter<std::string, Array<uint8_t>> {
static std::string Convert(const Array<uint8_t>& input);
};
template <>
struct TypeConverter<Array<uint8_t>, std::string> {
static Array<uint8_t> Convert(const std::string& input);
};
} // namespace mojo
#endif // MOJO_CONVERTERS_ARRAY_STRING_ARRAY_STRING_TYPE_CONVERTERS_H_
// Copyright 2013 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 "mojo/converters/array_string/array_string_type_converters.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
namespace common {
namespace test {
namespace {
TEST(CommonTypeConvertersTest, ArrayUint8ToStdString) {
auto data = Array<uint8_t>::New(4);
data[0] = 'd';
data[1] = 'a';
data[2] = 't';
data[3] = 'a';
EXPECT_EQ("data", data.To<std::string>());
}
TEST(CommonTypeConvertersTest, StdStringToArrayUint8) {
std::string input("data");
Array<uint8_t> data = Array<uint8_t>::From(input);
ASSERT_EQ(4ul, data.size());
EXPECT_EQ('d', data[0]);
EXPECT_EQ('a', data[1]);
EXPECT_EQ('t', data[2]);
EXPECT_EQ('a', data[3]);
}
} // namespace
} // namespace test
} // namespace common
} // namespace mojo
# Copyright 2015 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.
source_set("base") {
sources = [
"base_type_converters.cc",
"base_type_converters.h",
]
deps = [
"//base",
"//mojo/public/cpp/bindings",
]
}
source_set("tests") {
testonly = true
sources = [
"base_type_converters_unittest.cc",
]
deps = [
":base",
"//base",
"//mojo/public/cpp/bindings",
"//testing/gtest",
]
}
// Copyright 2015 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 "mojo/converters/base/base_type_converters.h"
#include <string>
#include "base/strings/utf_string_conversions.h"
namespace mojo {
// static
String TypeConverter<String, base::StringPiece>::Convert(
const base::StringPiece& input) {
if (input.empty()) {
char c = 0;
return String(&c, 0);
}
return String(input.data(), input.size());
}
// static
base::StringPiece TypeConverter<base::StringPiece, String>::Convert(
const String& input) {
return input.get();
}
// static
String TypeConverter<String, base::string16>::Convert(
const base::string16& input) {
return TypeConverter<String, base::StringPiece>::Convert(
base::UTF16ToUTF8(input));
}
// static
base::string16 TypeConverter<base::string16, String>::Convert(
const String& input) {
return base::UTF8ToUTF16(input.To<base::StringPiece>());
}
} // namespace mojo
// Copyright 2015 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.
#ifndef MOJO_CONVERTERS_BASE_BASE_TYPE_CONVERTERS_H_
#define MOJO_CONVERTERS_BASE_BASE_TYPE_CONVERTERS_H_
#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
#include "mojo/public/cpp/bindings/array.h"
#include "mojo/public/cpp/bindings/string.h"
#include "mojo/public/cpp/bindings/type_converter.h"
namespace mojo {
template <>
struct TypeConverter<String, base::StringPiece> {
static String Convert(const base::StringPiece& input);
};
template <>
struct TypeConverter<base::StringPiece, String> {
static base::StringPiece Convert(const String& input);
};
template <>
struct TypeConverter<String, base::string16> {
static String Convert(const base::string16& input);
};
template <>
struct TypeConverter<base::string16, String> {
static base::string16 Convert(const String& input);
};
} // namespace mojo
#endif // MOJO_CONVERTERS_BASE_BASE_TYPE_CONVERTERS_H_
// Copyright 2013 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 "mojo/converters/base/base_type_converters.h"
#include "base/bind.h"
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
namespace {
void ExpectEqualsStringPiece(const std::string& expected,
const base::StringPiece& str) {
EXPECT_EQ(expected, str.as_string());
}
void ExpectEqualsMojoString(const std::string& expected, const String& str) {
EXPECT_EQ(expected, str.get());
}
void ExpectEqualsString16(const base::string16& expected,
const base::string16& actual) {
EXPECT_EQ(expected, actual);
}
void ExpectEqualsMojoString(const base::string16& expected, const String& str) {
EXPECT_EQ(expected, str.To<base::string16>());
}
TEST(BaseTypeConvertersTest, StringPiece) {
std::string kText("hello world");
base::StringPiece string_piece(kText);
String mojo_string(String::From(string_piece));
ExpectEqualsMojoString(kText, mojo_string);
ExpectEqualsStringPiece(kText, mojo_string.To<base::StringPiece>());
// Test implicit construction and conversion:
ExpectEqualsMojoString(kText, String::From(string_piece));
ExpectEqualsStringPiece(kText, mojo_string.To<base::StringPiece>());
// Test null String:
base::StringPiece empty_string_piece = String().To<base::StringPiece>();
EXPECT_TRUE(empty_string_piece.empty());
}
TEST(BaseTypeConvertersTest, String16) {
const base::string16 string16(base::ASCIIToUTF16("hello world"));
const String mojo_string(String::From(string16));
ExpectEqualsMojoString(string16, mojo_string);
EXPECT_EQ(string16, mojo_string.To<base::string16>());
// Test implicit construction and conversion:
ExpectEqualsMojoString(string16, String::From(string16));
ExpectEqualsString16(string16, mojo_string.To<base::string16>());
// Test empty string conversion.
ExpectEqualsMojoString(base::string16(), String::From(base::string16()));
}
} // namespace
} // namespace mojo
# 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.
# GYP version: mojo/mojo_converters.gypi:mojo_input_events_lib
component("input_events") {
sources = [
"input_events_type_converters.cc",
"input_events_type_converters.h",
"mojo_extended_key_event_data.cc",
"mojo_extended_key_event_data.h",
]
deps = [
"//base",
"//ui/events",
"//ui/gfx/geometry",
"//mojo/converters/geometry",
"//mojo/environment:chromium",
"//mojo/public/c/system",
"//mojo/services/geometry/interfaces",
"//mojo/services/input_events/interfaces",
]
}
// 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 "mojo/converters/input_events/input_events_type_converters.h"
#include <climits>
#if defined(USE_X11)
#include <X11/extensions/XInput2.h>
#include <X11/Xlib.h>
#endif
#include "base/time/time.h"
#include "mojo/converters/geometry/geometry_type_converters.h"
#include "mojo/converters/input_events/mojo_extended_key_event_data.h"
#include "mojo/services/input_events/interfaces/input_events.mojom.h"
#include "ui/events/keycodes/keyboard_codes.h"
namespace mojo {
namespace {
ui::EventType MojoMouseEventTypeToUIEvent(const EventPtr& event) {
DCHECK(!event->pointer_data.is_null());
DCHECK_EQ(PointerKind::MOUSE, event->pointer_data->kind);
switch (event->action) {
case EventType::POINTER_DOWN:
return ui::ET_MOUSE_PRESSED;
case EventType::POINTER_UP:
return ui::ET_MOUSE_RELEASED;
case EventType::POINTER_MOVE:
DCHECK(event->pointer_data);
if (event->pointer_data->horizontal_wheel != 0 ||
event->pointer_data->vertical_wheel != 0) {
return ui::ET_MOUSEWHEEL;
}
if (static_cast<uint32_t>(event->flags) &
(static_cast<uint32_t>(EventFlags::LEFT_MOUSE_BUTTON) |
static_cast<uint32_t>(EventFlags::MIDDLE_MOUSE_BUTTON) |
static_cast<uint32_t>(EventFlags::RIGHT_MOUSE_BUTTON))) {
return ui::ET_MOUSE_DRAGGED;
}
return ui::ET_MOUSE_MOVED;
default:
NOTREACHED();
}
return ui::ET_MOUSE_RELEASED;
}
ui::EventType MojoTouchEventTypeToUIEvent(const EventPtr& event) {
DCHECK(!event->pointer_data.is_null());
DCHECK_EQ(PointerKind::TOUCH, event->pointer_data->kind);
switch (event->action) {
case EventType::POINTER_DOWN:
return ui::ET_TOUCH_PRESSED;
case EventType::POINTER_UP:
return ui::ET_TOUCH_RELEASED;
case EventType::POINTER_MOVE:
return ui::ET_TOUCH_MOVED;
case EventType::POINTER_CANCEL:
return ui::ET_TOUCH_CANCELLED;
default:
NOTREACHED();
}
return ui::ET_TOUCH_CANCELLED;
}
void SetPointerDataLocationFromEvent(const ui::LocatedEvent& located_event,
PointerData* pointer_data) {
pointer_data->x = located_event.location_f().x();
pointer_data->y = located_event.location_f().y();
pointer_data->screen_x = located_event.root_location_f().x();
pointer_data->screen_y = located_event.root_location_f().y();
}
} // namespace
COMPILE_ASSERT(static_cast<int32>(EventFlags::NONE) ==
static_cast<int32>(ui::EF_NONE),
event_flags_should_match);
COMPILE_ASSERT(static_cast<int32>(EventFlags::CAPS_LOCK_DOWN) ==
static_cast<int32>(ui::EF_CAPS_LOCK_DOWN),
event_flags_should_match);
COMPILE_ASSERT(static_cast<int32>(EventFlags::SHIFT_DOWN) ==
static_cast<int32>(ui::EF_SHIFT_DOWN),
event_flags_should_match);
COMPILE_ASSERT(static_cast<int32>(EventFlags::CONTROL_DOWN) ==
static_cast<int32>(ui::EF_CONTROL_DOWN),
event_flags_should_match);
COMPILE_ASSERT(static_cast<int32>(EventFlags::ALT_DOWN) ==
static_cast<int32>(ui::EF_ALT_DOWN),
event_flags_should_match);
COMPILE_ASSERT(static_cast<int32>(EventFlags::LEFT_MOUSE_BUTTON) ==
static_cast<int32>(ui::EF_LEFT_MOUSE_BUTTON),
event_flags_should_match);
COMPILE_ASSERT(static_cast<int32>(EventFlags::MIDDLE_MOUSE_BUTTON) ==
static_cast<int32>(ui::EF_MIDDLE_MOUSE_BUTTON),
event_flags_should_match);
COMPILE_ASSERT(static_cast<int32>(EventFlags::RIGHT_MOUSE_BUTTON) ==
static_cast<int32>(ui::EF_RIGHT_MOUSE_BUTTON),
event_flags_should_match);
COMPILE_ASSERT(static_cast<int32>(EventFlags::COMMAND_DOWN) ==
static_cast<int32>(ui::EF_COMMAND_DOWN),
event_flags_should_match);
COMPILE_ASSERT(static_cast<int32>(EventFlags::EXTENDED) ==
static_cast<int32>(ui::EF_EXTENDED),
event_flags_should_match);
COMPILE_ASSERT(static_cast<int32>(EventFlags::IS_SYNTHESIZED) ==
static_cast<int32>(ui::EF_IS_SYNTHESIZED),
event_flags_should_match);
COMPILE_ASSERT(static_cast<int32>(EventFlags::ALTGR_DOWN) ==
static_cast<int32>(ui::EF_ALTGR_DOWN),
event_flags_should_match);
COMPILE_ASSERT(static_cast<int32>(EventFlags::MOD3_DOWN) ==
static_cast<int32>(ui::EF_MOD3_DOWN),
event_flags_should_match);
// static
EventType TypeConverter<EventType, ui::EventType>::Convert(ui::EventType type) {
switch (type) {
case ui::ET_MOUSE_PRESSED:
case ui::ET_TOUCH_PRESSED:
return EventType::POINTER_DOWN;
case ui::ET_MOUSE_DRAGGED:
case ui::ET_MOUSE_MOVED:
case ui::ET_MOUSE_ENTERED:
case ui::ET_MOUSE_EXITED:
case ui::ET_TOUCH_MOVED:
case ui::ET_MOUSEWHEEL:
return EventType::POINTER_MOVE;
case ui::ET_MOUSE_RELEASED:
case ui::ET_TOUCH_RELEASED:
return EventType::POINTER_UP;
case ui::ET_TOUCH_CANCELLED:
return EventType::POINTER_CANCEL;
case ui::ET_KEY_PRESSED:
return EventType::KEY_PRESSED;
case ui::ET_KEY_RELEASED:
return EventType::KEY_RELEASED;
default:
break;
}
return EventType::UNKNOWN;
}
EventPtr TypeConverter<EventPtr, ui::Event>::Convert(const ui::Event& input) {
const EventType type = ConvertTo<EventType>(input.type());
if (type == EventType::UNKNOWN)
return nullptr;
EventPtr event = Event::New();
event->action = type;
event->flags = EventFlags(input.flags());
event->time_stamp = input.time_stamp().ToInternalValue();
PointerData pointer_data;
if (input.IsMouseEvent()) {
const ui::LocatedEvent* located_event =
static_cast<const ui::LocatedEvent*>(&input);
PointerDataPtr pointer_data(PointerData::New());
// TODO(sky): come up with a better way to handle this.
pointer_data->pointer_id = std::numeric_limits<int32>::max();
pointer_data->kind = PointerKind::MOUSE;
SetPointerDataLocationFromEvent(*located_event, pointer_data.get());
if (input.IsMouseWheelEvent()) {
const ui::MouseWheelEvent* wheel_event =
static_cast<const ui::MouseWheelEvent*>(&input);
// This conversion assumes we're using the mojo meaning of these values:
// [-1 1].
pointer_data->horizontal_wheel =
static_cast<float>(wheel_event->x_offset()) / 100.0f;
pointer_data->vertical_wheel =
static_cast<float>(wheel_event->y_offset()) / 100.0f;
}
event->pointer_data = pointer_data.Pass();
} else if (input.IsTouchEvent()) {
const ui::TouchEvent* touch_event =
static_cast<const ui::TouchEvent*>(&input);
PointerDataPtr pointer_data(PointerData::New());
pointer_data->pointer_id = touch_event->touch_id();
pointer_data->kind = PointerKind::TOUCH;
SetPointerDataLocationFromEvent(*touch_event, pointer_data.get());
pointer_data->radius_major = touch_event->radius_x();
pointer_data->radius_minor = touch_event->radius_y();
pointer_data->pressure = touch_event->force();
pointer_data->orientation = touch_event->rotation_angle();
event->pointer_data = pointer_data.Pass();
} else if (input.IsKeyEvent()) {
const ui::KeyEvent* key_event = static_cast<const ui::KeyEvent*>(&input);
KeyDataPtr key_data(KeyData::New());
key_data->key_code = key_event->GetConflatedWindowsKeyCode();
key_data->native_key_code = key_event->platform_keycode();
key_data->is_char = key_event->is_char();
key_data->character = key_event->GetCharacter();
if (key_event->extended_key_event_data()) {
const MojoExtendedKeyEventData* data =
static_cast<const MojoExtendedKeyEventData*>(
key_event->extended_key_event_data());
key_data->windows_key_code = static_cast<mojo::KeyboardCode>(
data->windows_key_code());
key_data->text = data->text();
key_data->unmodified_text = data->unmodified_text();
} else {
key_data->windows_key_code = static_cast<mojo::KeyboardCode>(
key_event->GetLocatedWindowsKeyboardCode());
key_data->text = key_event->GetText();
key_data->unmodified_text = key_event->GetUnmodifiedText();
}
event->key_data = key_data.Pass();
}
return event;
}
// static
EventPtr TypeConverter<EventPtr, ui::KeyEvent>::Convert(
const ui::KeyEvent& input) {
return Event::From(static_cast<const ui::Event&>(input));
}
// static
scoped_ptr<ui::Event> TypeConverter<scoped_ptr<ui::Event>, EventPtr>::Convert(
const EventPtr& input) {
gfx::PointF location;
gfx::PointF screen_location;
if (!input->pointer_data.is_null()) {
location.SetPoint(input->pointer_data->x, input->pointer_data->y);
screen_location.SetPoint(input->pointer_data->screen_x,
input->pointer_data->screen_y);
}
switch (input->action) {
case EventType::KEY_PRESSED:
case EventType::KEY_RELEASED: {
scoped_ptr<ui::KeyEvent> key_event;
if (input->key_data->is_char) {
// TODO(johngro) : Need to verify that input->flags (a mojom generated
// enum) is a valid set of flags for a ui::KeyEvent
key_event.reset(new ui::KeyEvent(
static_cast<base::char16>(input->key_data->character),
static_cast<ui::KeyboardCode>(
input->key_data->key_code),
static_cast<int32_t>(input->flags)));
} else {
// TODO(johngro) : Need to verify that input->flags (a mojom generated
// enum) is a valid set of flags for a ui::KeyEvent
key_event.reset(new ui::KeyEvent(
input->action == EventType::KEY_PRESSED ? ui::ET_KEY_PRESSED
: ui::ET_KEY_RELEASED,
static_cast<ui::KeyboardCode>(input->key_data->key_code),
static_cast<int32_t>(input->flags)));
}
key_event->SetExtendedKeyEventData(scoped_ptr<ui::ExtendedKeyEventData>(
new MojoExtendedKeyEventData(
static_cast<int32_t>(input->key_data->windows_key_code),
input->key_data->text,
input->key_data->unmodified_text)));
key_event->set_platform_keycode(input->key_data->native_key_code);
return key_event.Pass();
}
case EventType::POINTER_DOWN:
case EventType::POINTER_UP:
case EventType::POINTER_MOVE:
case EventType::POINTER_CANCEL: {
if (input->pointer_data->kind == PointerKind::MOUSE) {
// TODO: last flags isn't right. Need to send changed_flags.
scoped_ptr<ui::MouseEvent> event(new ui::MouseEvent(
MojoMouseEventTypeToUIEvent(input), location, screen_location,
ui::EventFlags(input->flags), ui::EventFlags(input->flags)));
if (event->IsMouseWheelEvent()) {
// This conversion assumes we're using the mojo meaning of these
// values: [-1 1].
scoped_ptr<ui::MouseEvent> wheel_event(new ui::MouseWheelEvent(
*event,
static_cast<int>(input->pointer_data->horizontal_wheel * 100),
static_cast<int>(input->pointer_data->vertical_wheel * 100)));
event = wheel_event.Pass();
}
return event.Pass();
}
scoped_ptr<ui::TouchEvent> touch_event(new ui::TouchEvent(
MojoTouchEventTypeToUIEvent(input), location,
ui::EventFlags(input->flags), input->pointer_data->pointer_id,
base::TimeDelta::FromInternalValue(input->time_stamp),
input->pointer_data->radius_major, input->pointer_data->radius_minor,
input->pointer_data->orientation, input->pointer_data->pressure));
touch_event->set_root_location(screen_location);
return touch_event.Pass();
}
default:
NOTIMPLEMENTED();
}
// TODO: need to support time_stamp.
return nullptr;
}
} // namespace mojo
// 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.
#ifndef MOJO_CONVERTERS_INPUT_EVENTS_INPUT_EVENTS_TYPE_CONVERTERS_H_
#define MOJO_CONVERTERS_INPUT_EVENTS_INPUT_EVENTS_TYPE_CONVERTERS_H_
#include "base/memory/scoped_ptr.h"
#include "mojo/services/input_events/interfaces/input_events.mojom.h"
#include "ui/events/event.h"
namespace mojo {
// NOTE: the mojo input events do not necessarily provide a 1-1 mapping with
// ui::Event types. Be careful in using them!
template <>
struct TypeConverter<EventType, ::ui::EventType> {
static EventType Convert(::ui::EventType type);
};
template <>
struct TypeConverter<EventPtr, ::ui::Event> {
static EventPtr Convert(const ::ui::Event& input);
};
template <>
struct TypeConverter<EventPtr, ::ui::KeyEvent> {
static EventPtr Convert(const ::ui::KeyEvent& input);
};
template <>
struct TypeConverter<EventPtr, ::ui::GestureEvent> {
static EventPtr Convert(const ::ui::GestureEvent& input);
};
template <>
struct TypeConverter<scoped_ptr<::ui::Event>, EventPtr> {
static scoped_ptr<::ui::Event> Convert(const EventPtr& input);
};
} // namespace mojo
#endif // MOJO_CONVERTERS_INPUT_EVENTS_INPUT_EVENTS_TYPE_CONVERTERS_H_
// 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 "mojo/converters/input_events/mojo_extended_key_event_data.h"
namespace mojo {
MojoExtendedKeyEventData::MojoExtendedKeyEventData(int32_t windows_key_code,
uint16_t text,
uint16_t unmodified_text)
: windows_key_code_(windows_key_code),
text_(text),
unmodified_text_(unmodified_text) {
}
MojoExtendedKeyEventData::~MojoExtendedKeyEventData() {}
ui::ExtendedKeyEventData* MojoExtendedKeyEventData::Clone() const {
return new MojoExtendedKeyEventData(windows_key_code_,
text_,
unmodified_text_);
}
} // namespace mojo
// 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.
#ifndef MOJO_CONVERTERS_INPUT_EVENTS_MOJO_EXTENDED_KEY_EVENT_DATA_H_
#define MOJO_CONVERTERS_INPUT_EVENTS_MOJO_EXTENDED_KEY_EVENT_DATA_H_
#include "ui/events/event.h"
namespace mojo {
// A structure to store all mojo specific data on a KeyEvent.
class MojoExtendedKeyEventData : public ui::ExtendedKeyEventData {
public:
MojoExtendedKeyEventData(int32_t windows_key_code,
uint16_t text,
uint16_t unmodified_text);
~MojoExtendedKeyEventData() override;
int32_t windows_key_code() const { return windows_key_code_; }
uint16_t text() const { return text_; }
uint16_t unmodified_text() const { return unmodified_text_; }
// ui::ExtendedKeyEventData:
ui::ExtendedKeyEventData* Clone() const override;
private:
const int32_t windows_key_code_;
const uint16_t text_;
const uint16_t unmodified_text_;
DISALLOW_COPY_AND_ASSIGN(MojoExtendedKeyEventData);
};
} // namespace mojo
#endif // MOJO_CONVERTERS_INPUT_EVENTS_MOJO_EXTENDED_KEY_EVENT_DATA_H_
# Copyright 2015 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.
component("native_viewport") {
sources = [
"surface_configuration_type_converters.cc",
"surface_configuration_type_converters.h",
]
deps = [
"//base",
"//ui/gl",
"//mojo/environment:chromium",
"//mojo/public/c/system",
"//mojo/services/native_viewport/interfaces",
]
}
// Copyright 2015 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 "mojo/converters/native_viewport/surface_configuration_type_converters.h"
namespace mojo {
// static
gfx::SurfaceConfiguration
TypeConverter<gfx::SurfaceConfiguration, SurfaceConfigurationPtr>::Convert(
const SurfaceConfigurationPtr& input) {
auto output = gfx::SurfaceConfiguration();
output.red_bits = input->red_bits;
output.green_bits = input->green_bits;
output.blue_bits = input->blue_bits;
output.alpha_bits = input->alpha_bits;
output.depth_bits = input->depth_bits;
output.stencil_bits = input->stencil_bits;
return output;
}
} // namespace mojo
\ No newline at end of file
// 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.
#ifndef MOJO_CONVERTERS_NATIVE_VIEWPORT_SURFACE_CONFIGURATION_TYPE_CONVERTERS_H_
#define MOJO_CONVERTERS_NATIVE_VIEWPORT_SURFACE_CONFIGURATION_TYPE_CONVERTERS_H_
#include "base/memory/scoped_ptr.h"
#include "mojo/services/native_viewport/interfaces/native_viewport.mojom.h"
#include "ui/gl/gl_surface.h"
namespace mojo {
// Types from native_viewport.mojom
template <>
struct TypeConverter<gfx::SurfaceConfiguration, SurfaceConfigurationPtr> {
static gfx::SurfaceConfiguration Convert(
const SurfaceConfigurationPtr& input);
};
} // namespace mojo
#endif // MOJO_CONVERTERS_NATIVE_VIEWPORT_SURFACE_CONFIGURATION_TYPE_CONVERTERS_H_
# Copyright 2015 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.
source_set("ozone_drm_gpu") {
sources = [
"ozone_drm_gpu_type_converters.cc",
"ozone_drm_gpu_type_converters.h",
]
deps = [
"//base",
"//ui/ozone:ozone_common_message_types",
"//mojo/converters/geometry",
"//mojo/environment:chromium",
"//mojo/public/c/system",
"//mojo/services/ozone_drm_gpu/interfaces",
]
}
// Copyright 2015 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 "mojo/converters/ozone_drm_gpu/ozone_drm_gpu_type_converters.h"
#include "mojo/converters/geometry/geometry_type_converters.h"
namespace mojo {
// static
ui::DisplayMode_Params
TypeConverter<ui::DisplayMode_Params, DisplayModePtr>::Convert(
const DisplayModePtr& in) {
auto out = ui::DisplayMode_Params();
out.size = in->size.To<gfx::Size>();
out.is_interlaced = in->is_interlaced;
out.refresh_rate = in->refresh_rate;
return out;
}
// static
DisplayModePtr TypeConverter<DisplayModePtr, ui::DisplayMode_Params>::Convert(
const ui::DisplayMode_Params& in) {
auto out = DisplayMode::New();
out->size = Size::From<gfx::Size>(in.size);
out->is_interlaced = in.is_interlaced;
out->refresh_rate = in.refresh_rate;
return out;
}
static_assert(static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_NONE) ==
static_cast<int>(mojo::DisplayType::NONE),
"Enum value mismatch");
static_assert(static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_UNKNOWN) ==
static_cast<int>(mojo::DisplayType::UNKNOWN),
"Enum value mismatch");
static_assert(static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_INTERNAL) ==
static_cast<int>(mojo::DisplayType::INTERNAL),
"Enum value mismatch");
static_assert(static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_VGA) ==
static_cast<int>(mojo::DisplayType::VGA),
"Enum value mismatch");
static_assert(static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_HDMI) ==
static_cast<int>(mojo::DisplayType::HDMI),
"Enum value mismatch");
static_assert(static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_DVI) ==
static_cast<int>(mojo::DisplayType::DVI),
"Enum value mismatch");
static_assert(static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_DISPLAYPORT) ==
static_cast<int>(mojo::DisplayType::DISPLAYPORT),
"Enum value mismatch");
static_assert(static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_NETWORK) ==
static_cast<int>(mojo::DisplayType::NETWORK),
"Enum value mismatch");
static_assert(static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_LAST) ==
static_cast<int>(mojo::DisplayType::LAST),
"Enum value mismatch");
// static
ui::DisplaySnapshot_Params
TypeConverter<ui::DisplaySnapshot_Params, DisplaySnapshotPtr>::Convert(
const DisplaySnapshotPtr& in) {
auto out = ui::DisplaySnapshot_Params();
out.display_id = in->display_id;
out.origin = in->origin.To<gfx::Point>();
out.physical_size = in->physical_size.To<gfx::Size>();
out.type = static_cast<ui::DisplayConnectionType>(in->type);
assert(out.type <= ui::DISPLAY_CONNECTION_TYPE_LAST);
for (size_t i = 0; i < in->modes.size(); ++i) {
out.modes.push_back(in->modes[i].To<ui::DisplayMode_Params>());
}
out.has_current_mode = in->has_current_mode;
out.current_mode = in->current_mode.To<ui::DisplayMode_Params>();
out.has_native_mode = in->has_native_mode;
out.native_mode = in->native_mode.To<ui::DisplayMode_Params>();
out.product_id = in->product_id;
out.string_representation = in->string_representation;
return out;
}
// static
DisplaySnapshotPtr
TypeConverter<DisplaySnapshotPtr, ui::DisplaySnapshot_Params>::Convert(
const ui::DisplaySnapshot_Params& in) {
auto out = DisplaySnapshot::New();
out->display_id = in.display_id;
out->origin = Point::From<gfx::Point>(in.origin);
out->physical_size = Size::From<gfx::Size>(in.physical_size);
out->type = static_cast<mojo::DisplayType>(in.type);
assert(out->type <= mojo::DisplayType::LAST);
auto modes = Array<DisplayModePtr>::New(in.modes.size());
for (size_t i = 0; i < in.modes.size(); ++i) {
auto mode = DisplayMode::From<ui::DisplayMode_Params>(in.modes[i]);
modes[i] = mode.Pass();
}
out->modes = modes.Pass();
out->has_current_mode = in.has_current_mode;
out->current_mode =
DisplayMode::From<ui::DisplayMode_Params>(in.current_mode);
out->has_native_mode = in.has_native_mode;
out->native_mode = DisplayMode::From<ui::DisplayMode_Params>(in.native_mode);
out->product_id = in.product_id;
out->string_representation = in.string_representation;
return out;
}
} // namespace mojo
// Copyright 2015 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.
#ifndef MOJO_CONVERTERS_OZONE_DRM_GPU_OZONE_DRM_GPU_TYPE_CONVERTERS_H_
#define MOJO_CONVERTERS_OZONE_DRM_GPU_OZONE_DRM_GPU_TYPE_CONVERTERS_H_
#include "base/memory/scoped_ptr.h"
#include "mojo/services/ozone_drm_gpu/interfaces/ozone_drm_gpu.mojom.h"
#include "ui/ozone/common/gpu/ozone_gpu_message_params.h"
namespace mojo {
// Types from ozone_drm_gpu.mojom
template <>
struct TypeConverter<ui::DisplayMode_Params, DisplayModePtr> {
static ui::DisplayMode_Params Convert(const DisplayModePtr& in);
};
template <>
struct TypeConverter<DisplayModePtr, ui::DisplayMode_Params> {
static DisplayModePtr Convert(const ui::DisplayMode_Params& in);
};
template <>
struct TypeConverter<ui::DisplaySnapshot_Params, DisplaySnapshotPtr> {
static ui::DisplaySnapshot_Params Convert(const DisplaySnapshotPtr& in);
};
template <>
struct TypeConverter<DisplaySnapshotPtr, ui::DisplaySnapshot_Params> {
static DisplaySnapshotPtr Convert(const ui::DisplaySnapshot_Params& in);
};
} // namespace mojo
#endif // MOJO_CONVERTERS_OZONE_DRM_GPU_OZONE_DRM_GPU_TYPE_CONVERTERS_H_
# Copyright 2015 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.
source_set("url") {
sources = [
"url_type_converters.cc",
"url_type_converters.h",
]
deps = [
"//mojo/public/cpp/bindings",
"//url",
]
}
source_set("tests") {
testonly = true
sources = [
"url_type_converters_unittest.cc",
]
deps = [
":url",
"//mojo/public/cpp/bindings",
"//testing/gtest",
"//url",
]
}
// Copyright 2015 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 "mojo/converters/url/url_type_converters.h"
#include "url/gurl.h"
namespace mojo {
String TypeConverter<String, GURL>::Convert(const GURL& input) {
return String(input.spec());
}
GURL TypeConverter<GURL, String>::Convert(const String& input) {
return GURL(input.get());
}
} // namespace mojo
// Copyright 2015 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.
#ifndef MOJO_CONVERTERS_URL_URL_TYPE_CONVERTERS_H_
#define MOJO_CONVERTERS_URL_URL_TYPE_CONVERTERS_H_
#include "mojo/public/cpp/bindings/type_converter.h"
#include "mojo/public/cpp/bindings/string.h"
class GURL;
namespace mojo {
template <>
struct TypeConverter<String, GURL> {
static String Convert(const GURL& input);
};
template <>
struct TypeConverter<GURL, String> {
static GURL Convert(const String& input);
};
} // namespace mojo
#endif // MOJO_CONVERTERS_URL_URL_TYPE_CONVERTERS_H_
// Copyright 2015 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 "mojo/converters/url/url_type_converters.h"
#include "mojo/public/cpp/bindings/string.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace mojo {
namespace {
TEST(UrlTypeConvertersTest, URL) {
GURL url("mojo:foo");
String mojo_string(String::From(url));
ASSERT_EQ(url.spec(), mojo_string);
EXPECT_EQ(url.spec(), mojo_string.To<GURL>().spec());
EXPECT_EQ(url.spec(), String::From(url));
GURL invalid = String().To<GURL>();
ASSERT_TRUE(invalid.spec().empty());
String string_from_invalid = String::From(invalid);
EXPECT_FALSE(string_from_invalid.is_null());
ASSERT_EQ(0U, string_from_invalid.size());
}
} // namespace
} // namespace mojo
......@@ -32,7 +32,6 @@ mojo_native_application("sky") {
"//mojo/application",
"//mojo/common:tracing_impl",
"//mojo/converters/geometry",
"//mojo/converters/input_events",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
"//mojo/public/cpp/utility",
......@@ -54,7 +53,6 @@ mojo_native_application("sky") {
"//sky/engine/web",
"//sky/shell/dart",
"//third_party/icu",
"//ui/events",
"//url",
]
......
......@@ -11,7 +11,6 @@
#include "base/strings/string_util.h"
#include "base/thread_task_runner_handle.h"
#include "mojo/converters/geometry/geometry_type_converters.h"
#include "mojo/converters/input_events/input_events_type_converters.h"
#include "mojo/public/cpp/application/connect.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "mojo/public/interfaces/application/shell.mojom.h"
......
......@@ -20,7 +20,6 @@ mojo_native_application("mojo") {
"//mojo/common",
"//mojo/common:tracing_impl",
"//mojo/converters/geometry",
"//mojo/converters/input_events",
"//mojo/icu",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
......@@ -43,7 +42,6 @@ mojo_native_application("mojo") {
"//sky/engine/web",
"//sky/shell:common",
"//third_party/icu",
"//ui/events",
"//url",
]
}
diff --git a/mojo/common/BUILD.gn b/mojo/common/BUILD.gn
index adac158..25ef0ca 100644
--- a/mojo/common/BUILD.gn
+++ b/mojo/common/BUILD.gn
@@ -43,9 +43,6 @@ source_set("tests") {
test("mojo_common_unittests") {
deps = [
":tests",
- "//mojo/converters/array_string:tests",
- "//mojo/converters/base:tests",
- "//mojo/converters/url:tests",
"//mojo/data_pipe_utils:tests",
"//mojo/edk/test:run_all_unittests",
"//mojo/environment:chromium",
diff --git a/mojo/converters/input_events/input_events_type_converters.cc b/mojo/converters/input_events/input_events_type_converters.cc
index 6f2495f..e7b0f15 100644
--- a/mojo/converters/input_events/input_events_type_converters.cc
+++ b/mojo/converters/input_events/input_events_type_converters.cc
@@ -283,7 +283,6 @@ scoped_ptr<ui::Event> TypeConverter<scoped_ptr<ui::Event>, EventPtr>::Convert(
// TODO: last flags isn't right. Need to send changed_flags.
scoped_ptr<ui::MouseEvent> event(new ui::MouseEvent(
MojoMouseEventTypeToUIEvent(input), location, screen_location,
- base::TimeDelta::FromMilliseconds(input->time_stamp),
ui::EventFlags(input->flags), ui::EventFlags(input->flags)));
if (event->IsMouseWheelEvent()) {
// This conversion assumes we're using the mojo meaning of these
......@@ -73,7 +73,7 @@ dirs_from_mojo = [
'mojo/android',
'mojo/application',
'mojo/common',
'mojo/converters',
'mojo/converters/geometry',
('mojo/dart/embedder', ['embedder.gni']),
'mojo/data_pipe_utils',
'mojo/edk',
......
# 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.
import("//build/config/ui.gni")
import("//testing/test.gni")
static_library("dom4_keycode_converter") {
sources = [
"keycodes/dom4/keycode_converter.cc",
"keycodes/dom4/keycode_converter.h",
"keycodes/dom4/keycode_converter_data.h",
]
deps = [
"//base",
]
}
component("events_base") {
sources = [
"device_data_manager.cc",
"device_data_manager.h",
"device_hotplug_event_observer.h",
"event_constants.h",
"event_switches.cc",
"event_switches.h",
"events_base_export.h",
"gesture_curve.h",
"gesture_event_details.cc",
"gesture_event_details.h",
"gestures/fling_curve.cc",
"gestures/fling_curve.h",
"gestures/gesture_configuration.cc",
"gestures/gesture_configuration.h",
"keycodes/keyboard_code_conversion.cc",
"keycodes/keyboard_code_conversion.h",
"keycodes/keyboard_code_conversion_android.cc",
"keycodes/keyboard_code_conversion_android.h",
"keycodes/keyboard_codes.h",
"latency_info.cc",
"latency_info.h",
"touchscreen_device.cc",
"touchscreen_device.h",
]
defines = [ "EVENTS_BASE_IMPLEMENTATION" ]
deps = [
":dom4_keycode_converter",
"//base/third_party/dynamic_annotations",
"//skia",
]
public_deps = [
"//base",
"//ui/gfx",
"//ui/gfx/geometry",
]
}
component("events") {
sources = [
"event.cc",
"event.h",
"event_dispatcher.cc",
"event_dispatcher.h",
"event_handler.cc",
"event_handler.h",
"event_processor.cc",
"event_processor.h",
"event_rewriter.h",
"event_source.cc",
"event_source.h",
"event_target.cc",
"event_target.h",
"event_target_iterator.h",
"event_targeter.cc",
"event_targeter.h",
"event_utils.cc",
"event_utils.h",
"events_export.h",
"gestures/gesture_provider_impl.cc",
"gestures/gesture_provider_impl.h",
"gestures/gesture_recognizer.h",
"gestures/gesture_recognizer_impl.cc",
"gestures/gesture_recognizer_impl.h",
"gestures/gesture_types.h",
"gestures/motion_event_impl.cc",
"gestures/motion_event_impl.h",
]
defines = [ "EVENTS_IMPLEMENTATION" ]
public_deps = [
":events_base",
]
deps = [
":dom4_keycode_converter",
":gesture_detection",
"//base/third_party/dynamic_annotations",
"//skia",
"//ui/gfx",
"//ui/gfx/geometry",
]
}
component("gesture_detection") {
sources = [
"gesture_detection/bitset_32.h",
"gesture_detection/filtered_gesture_provider.cc",
"gesture_detection/filtered_gesture_provider.h",
"gesture_detection/gesture_config_helper.h",
"gesture_detection/gesture_config_helper_aura.cc",
"gesture_detection/gesture_detection_export.h",
"gesture_detection/gesture_detector.cc",
"gesture_detection/gesture_detector.h",
"gesture_detection/gesture_event_data.cc",
"gesture_detection/gesture_event_data.h",
"gesture_detection/gesture_event_data_packet.cc",
"gesture_detection/gesture_event_data_packet.h",
"gesture_detection/gesture_listeners.cc",
"gesture_detection/gesture_listeners.h",
"gesture_detection/gesture_provider.cc",
"gesture_detection/gesture_provider.h",
"gesture_detection/gesture_touch_uma_histogram.cc",
"gesture_detection/gesture_touch_uma_histogram.h",
"gesture_detection/motion_event.cc",
"gesture_detection/motion_event.h",
"gesture_detection/motion_event_buffer.cc",
"gesture_detection/motion_event_buffer.h",
"gesture_detection/motion_event_generic.cc",
"gesture_detection/motion_event_generic.h",
"gesture_detection/scale_gesture_detector.cc",
"gesture_detection/scale_gesture_detector.h",
"gesture_detection/scale_gesture_listeners.cc",
"gesture_detection/scale_gesture_listeners.h",
"gesture_detection/snap_scroll_controller.cc",
"gesture_detection/snap_scroll_controller.h",
"gesture_detection/touch_disposition_gesture_filter.cc",
"gesture_detection/touch_disposition_gesture_filter.h",
"gesture_detection/velocity_tracker.cc",
"gesture_detection/velocity_tracker.h",
"gesture_detection/velocity_tracker_state.cc",
"gesture_detection/velocity_tracker_state.h",
]
deps = [
":events_base",
"//base",
"//ui/gfx",
"//ui/gfx/geometry",
]
defines = [ "GESTURE_DETECTION_IMPLEMENTATION" ]
}
source_set("test_support") {
sources = [
"test/events_test_utils.cc",
"test/events_test_utils.h",
"test/mock_motion_event.cc",
"test/mock_motion_event.h",
"test/platform_event_waiter.cc",
"test/platform_event_waiter.h",
"test/test_event_handler.cc",
"test/test_event_handler.h",
"test/test_event_processor.cc",
"test/test_event_processor.h",
"test/test_event_target.cc",
"test/test_event_target.h",
]
public_deps = [
":events",
":events_base",
":gesture_detection",
]
deps = [
"//base",
"//skia",
"//ui/events/platform",
"//ui/gfx/geometry",
]
if (use_x11) {
sources += [
"test/events_test_utils_x11.cc",
"test/events_test_utils_x11.h",
]
deps += [ "//ui/gfx/x" ]
}
}
test("events_unittests") {
sources = [
"event_dispatcher_unittest.cc",
"event_processor_unittest.cc",
"event_rewriter_unittest.cc",
"event_unittest.cc",
"gesture_detection/bitset_32_unittest.cc",
"gesture_detection/gesture_event_data_packet_unittest.cc",
"gesture_detection/gesture_provider_unittest.cc",
"gesture_detection/motion_event_buffer_unittest.cc",
"gesture_detection/motion_event_generic_unittest.cc",
"gesture_detection/touch_disposition_gesture_filter_unittest.cc",
"gesture_detection/velocity_tracker_unittest.cc",
"gestures/fling_curve_unittest.cc",
"gestures/gesture_provider_impl_unittest.cc",
"keycodes/dom4/keycode_converter_unittest.cc",
"latency_info_unittest.cc",
"platform/platform_event_builder_x_unittest.cc",
"platform/platform_event_source_unittest.cc",
"platform/x11/platform_event_utils_x_unittest.cc",
]
deps = [
":dom4_keycode_converter",
":events",
":events_base",
":gesture_detection",
":test_support",
"//base",
"//base/test:run_all_unittests",
"//skia",
"//testing/gtest",
"//ui/events/platform",
"//ui/gfx:test_support",
]
if (use_x11) {
configs += [ "//build/config/linux:x11" ]
deps += [ "//ui/gfx/x" ]
} else {
sources -= [
"platform/platform_event_builder_x_unittest.cc",
"platform/x11/platform_event_utils_x_unittest.cc",
]
}
}
sadrul@chromium.org
per-file latency_info*=jbauman@chromium.org
per-file latency_info*=miletus@chromium.org
# If you're doing structural changes get a review from one of the OWNERS.
per-file *.gyp*=*
// 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 "ui/events/device_data_manager.h"
#include "base/at_exit.h"
#include "base/bind.h"
#include "base/logging.h"
#include "ui/events/input_device_event_observer.h"
#include "ui/gfx/display.h"
#include "ui/gfx/geometry/point3_f.h"
namespace ui {
// static
DeviceDataManager* DeviceDataManager::instance_ = NULL;
DeviceDataManager::DeviceDataManager() {
CHECK(!instance_) << "Can not create multiple instances of DeviceDataManager";
instance_ = this;
base::AtExitManager::RegisterTask(
base::Bind(&base::DeletePointer<DeviceDataManager>, this));
for (int i = 0; i < kMaxDeviceNum; ++i) {
touch_device_to_display_map_[i] = gfx::Display::kInvalidDisplayID;
touch_radius_scale_map_[i] = 1.0;
}
}
DeviceDataManager::~DeviceDataManager() {
CHECK_EQ(this, instance_);
instance_ = NULL;
}
// static
DeviceDataManager* DeviceDataManager::instance() { return instance_; }
// static
void DeviceDataManager::CreateInstance() {
if (instance())
return;
new DeviceDataManager();
}
// static
DeviceDataManager* DeviceDataManager::GetInstance() {
CHECK(instance_) << "DeviceDataManager was not created.";
return instance_;
}
// static
bool DeviceDataManager::HasInstance() {
return instance_ != NULL;
}
void DeviceDataManager::ClearTouchTransformerRecord() {
for (int i = 0; i < kMaxDeviceNum; i++) {
touch_device_transformer_map_[i] = gfx::Transform();
touch_device_to_display_map_[i] = gfx::Display::kInvalidDisplayID;
touch_radius_scale_map_[i] = 1.0;
}
}
bool DeviceDataManager::IsTouchDeviceIdValid(int touch_device_id) const {
return (touch_device_id > 0 && touch_device_id < kMaxDeviceNum);
}
void DeviceDataManager::UpdateTouchInfoForDisplay(
int64_t display_id,
int touch_device_id,
const gfx::Transform& touch_transformer) {
if (IsTouchDeviceIdValid(touch_device_id)) {
touch_device_to_display_map_[touch_device_id] = display_id;
touch_device_transformer_map_[touch_device_id] = touch_transformer;
}
}
void DeviceDataManager::UpdateTouchRadiusScale(int touch_device_id,
double scale) {
if (IsTouchDeviceIdValid(touch_device_id))
touch_radius_scale_map_[touch_device_id] = scale;
}
void DeviceDataManager::ApplyTouchRadiusScale(int touch_device_id,
double* radius) {
if (IsTouchDeviceIdValid(touch_device_id))
*radius = (*radius) * touch_radius_scale_map_[touch_device_id];
}
void DeviceDataManager::ApplyTouchTransformer(int touch_device_id,
float* x,
float* y) {
if (IsTouchDeviceIdValid(touch_device_id)) {
gfx::Point3F point(*x, *y, 0.0);
const gfx::Transform& trans =
touch_device_transformer_map_[touch_device_id];
trans.TransformPoint(&point);
*x = point.x();
*y = point.y();
}
}
int64_t DeviceDataManager::GetDisplayForTouchDevice(int touch_device_id) const {
if (IsTouchDeviceIdValid(touch_device_id))
return touch_device_to_display_map_[touch_device_id];
return gfx::Display::kInvalidDisplayID;
}
void DeviceDataManager::OnTouchscreenDevicesUpdated(
const std::vector<TouchscreenDevice>& devices) {
touchscreen_devices_ = devices;
FOR_EACH_OBSERVER(InputDeviceEventObserver,
observers_,
OnInputDeviceConfigurationChanged());
}
void DeviceDataManager::AddObserver(InputDeviceEventObserver* observer) {
observers_.AddObserver(observer);
}
void DeviceDataManager::RemoveObserver(InputDeviceEventObserver* observer) {
observers_.RemoveObserver(observer);
}
} // namespace ui
// 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.
#ifndef UI_EVENTS_DEVICE_DATA_MANAGER_H_
#define UI_EVENTS_DEVICE_DATA_MANAGER_H_
#include <stdint.h>
#include <vector>
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
#include "ui/events/device_hotplug_event_observer.h"
#include "ui/events/events_base_export.h"
#include "ui/events/touchscreen_device.h"
#include "ui/gfx/transform.h"
namespace ui {
class InputDeviceEventObserver;
// Keeps track of device mappings and event transformations.
class EVENTS_BASE_EXPORT DeviceDataManager : public DeviceHotplugEventObserver {
public:
~DeviceDataManager() override;
static void CreateInstance();
static DeviceDataManager* GetInstance();
static bool HasInstance();
void ClearTouchTransformerRecord();
void UpdateTouchInfoForDisplay(int64_t display_id,
int touch_device_id,
const gfx::Transform& touch_transformer);
void ApplyTouchTransformer(int touch_device_id, float* x, float* y);
int64_t GetDisplayForTouchDevice(int touch_device_id) const;
void UpdateTouchRadiusScale(int touch_device_id, double scale);
void ApplyTouchRadiusScale(int touch_device_id, double* radius);
const std::vector<TouchscreenDevice>& touchscreen_devices() const {
return touchscreen_devices_;
}
void AddObserver(InputDeviceEventObserver* observer);
void RemoveObserver(InputDeviceEventObserver* observer);
protected:
DeviceDataManager();
static DeviceDataManager* instance();
static const int kMaxDeviceNum = 128;
private:
static DeviceDataManager* instance_;
bool IsTouchDeviceIdValid(int touch_device_id) const;
// DeviceHotplugEventObserver:
void OnTouchscreenDevicesUpdated(
const std::vector<TouchscreenDevice>& devices) override;
double touch_radius_scale_map_[kMaxDeviceNum];
// Table to keep track of which display id is mapped to which touch device.
int64_t touch_device_to_display_map_[kMaxDeviceNum];
// Index table to find the TouchTransformer for a touch device.
gfx::Transform touch_device_transformer_map_[kMaxDeviceNum];
std::vector<TouchscreenDevice> touchscreen_devices_;
base::ObserverList<InputDeviceEventObserver> observers_;
DISALLOW_COPY_AND_ASSIGN(DeviceDataManager);
};
} // namespace ui
#endif // UI_EVENTS_DEVICE_DATA_MANAGER_H_
// 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.
#ifndef UI_EVENTS_DEVICE_HOTPLUG_EVENT_OBSERVER_H_
#define UI_EVENTS_DEVICE_HOTPLUG_EVENT_OBSERVER_H_
#include "ui/events/events_base_export.h"
#include "ui/events/touchscreen_device.h"
namespace ui {
// Listener for specific input device hotplug events.
class EVENTS_BASE_EXPORT DeviceHotplugEventObserver {
public:
virtual ~DeviceHotplugEventObserver() {}
// On a hotplug event this is called with the list of available devices.
virtual void OnTouchscreenDevicesUpdated(
const std::vector<TouchscreenDevice>& devices) = 0;
};
} // namespace ui
#endif // UI_EVENTS_DEVICE_HOTPLUG_EVENT_OBSERVER_H_
// Copyright (c) 2012 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 "ui/events/event.h"
#if defined(USE_X11)
#include <X11/extensions/XInput2.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
#endif
#include <cmath>
#include <cstring>
#include "base/strings/stringprintf.h"
#include "ui/events/event_utils.h"
#include "ui/events/keycodes/keyboard_code_conversion.h"
#include "ui/gfx/geometry/safe_integer_conversions.h"
#include "ui/gfx/point3_f.h"
#include "ui/gfx/point_conversions.h"
#include "ui/gfx/transform.h"
#include "ui/gfx/transform_util.h"
namespace ui {
////////////////////////////////////////////////////////////////////////////////
// Event
// static
scoped_ptr<Event> Event::Clone(const Event& event) {
if (event.IsKeyEvent()) {
return scoped_ptr<Event>(new KeyEvent(static_cast<const KeyEvent&>(event)));
}
if (event.IsMouseEvent()) {
if (event.IsMouseWheelEvent()) {
return scoped_ptr<Event>(
new MouseWheelEvent(static_cast<const MouseWheelEvent&>(event)));
}
return scoped_ptr<Event>(
new MouseEvent(static_cast<const MouseEvent&>(event)));
}
if (event.IsTouchEvent()) {
return scoped_ptr<Event>(
new TouchEvent(static_cast<const TouchEvent&>(event)));
}
if (event.IsGestureEvent()) {
return scoped_ptr<Event>(
new GestureEvent(static_cast<const GestureEvent&>(event)));
}
if (event.IsScrollEvent()) {
return scoped_ptr<Event>(
new ScrollEvent(static_cast<const ScrollEvent&>(event)));
}
return scoped_ptr<Event>(new Event(event));
}
Event::~Event() {
}
GestureEvent* Event::AsGestureEvent() {
CHECK(IsGestureEvent());
return static_cast<GestureEvent*>(this);
}
const GestureEvent* Event::AsGestureEvent() const {
CHECK(IsGestureEvent());
return static_cast<const GestureEvent*>(this);
}
void Event::StopPropagation() {
// TODO(sad): Re-enable these checks once View uses dispatcher to dispatch
// events.
// CHECK(phase_ != EP_PREDISPATCH && phase_ != EP_POSTDISPATCH);
CHECK(cancelable_);
result_ = static_cast<EventResult>(result_ | ER_CONSUMED);
}
void Event::SetHandled() {
// TODO(sad): Re-enable these checks once View uses dispatcher to dispatch
// events.
// CHECK(phase_ != EP_PREDISPATCH && phase_ != EP_POSTDISPATCH);
CHECK(cancelable_);
result_ = static_cast<EventResult>(result_ | ER_HANDLED);
}
Event::Event()
: type_(ET_UNKNOWN),
time_stamp_(base::TimeDelta()),
flags_(EF_NONE),
cancelable_(true),
target_(NULL),
phase_(EP_PREDISPATCH),
result_(ER_UNHANDLED),
source_device_id_(ED_UNKNOWN_DEVICE) {
}
Event::Event(EventType type, base::TimeDelta time_stamp, int flags)
: type_(type),
time_stamp_(time_stamp),
flags_(flags),
cancelable_(true),
target_(NULL),
phase_(EP_PREDISPATCH),
result_(ER_UNHANDLED),
source_device_id_(ED_UNKNOWN_DEVICE) {
}
Event::Event(const Event& copy)
: type_(copy.type_),
time_stamp_(copy.time_stamp_),
latency_(copy.latency_),
flags_(copy.flags_),
cancelable_(true),
target_(NULL),
phase_(EP_PREDISPATCH),
result_(ER_UNHANDLED),
source_device_id_(copy.source_device_id_) {
}
void Event::SetType(EventType type) {
type_ = type;
}
////////////////////////////////////////////////////////////////////////////////
// CancelModeEvent
CancelModeEvent::CancelModeEvent()
: Event(ET_CANCEL_MODE, base::TimeDelta(), 0) {
set_cancelable(false);
}
CancelModeEvent::~CancelModeEvent() {
}
////////////////////////////////////////////////////////////////////////////////
// LocatedEvent
LocatedEvent::LocatedEvent() : Event() {
}
LocatedEvent::~LocatedEvent() {
}
LocatedEvent::LocatedEvent(EventType type,
const gfx::PointF& location,
const gfx::PointF& root_location,
base::TimeDelta time_stamp,
int flags)
: Event(type, time_stamp, flags),
location_(location),
root_location_(root_location) {
}
void LocatedEvent::UpdateForRootTransform(
const gfx::Transform& reversed_root_transform) {
// Transform has to be done at root level.
gfx::Point3F p(location_);
reversed_root_transform.TransformPoint(&p);
location_ = p.AsPointF();
root_location_ = location_;
}
////////////////////////////////////////////////////////////////////////////////
// MouseEvent
MouseEvent::MouseEvent() : LocatedEvent(), changed_button_flags_(0) {
}
MouseEvent::MouseEvent(EventType type,
const gfx::PointF& location,
const gfx::PointF& root_location,
int flags,
int changed_button_flags)
: LocatedEvent(type, location, root_location, EventTimeForNow(), flags),
changed_button_flags_(changed_button_flags) {
if (this->type() == ET_MOUSE_MOVED && IsAnyButton())
SetType(ET_MOUSE_DRAGGED);
}
// static
bool MouseEvent::IsRepeatedClickEvent(
const MouseEvent& event1,
const MouseEvent& event2) {
// These values match the Windows defaults.
static const int kDoubleClickTimeMS = 500;
static const int kDoubleClickWidth = 4;
static const int kDoubleClickHeight = 4;
if (event1.type() != ET_MOUSE_PRESSED ||
event2.type() != ET_MOUSE_PRESSED)
return false;
// Compare flags, but ignore EF_IS_DOUBLE_CLICK to allow triple clicks.
if ((event1.flags() & ~EF_IS_DOUBLE_CLICK) !=
(event2.flags() & ~EF_IS_DOUBLE_CLICK))
return false;
base::TimeDelta time_difference = event2.time_stamp() - event1.time_stamp();
if (time_difference.InMilliseconds() > kDoubleClickTimeMS)
return false;
if (std::abs(event2.x() - event1.x()) > kDoubleClickWidth / 2)
return false;
if (std::abs(event2.y() - event1.y()) > kDoubleClickHeight / 2)
return false;
return true;
}
int MouseEvent::GetClickCount() const {
if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED)
return 0;
if (flags() & EF_IS_TRIPLE_CLICK)
return 3;
else if (flags() & EF_IS_DOUBLE_CLICK)
return 2;
else
return 1;
}
void MouseEvent::SetClickCount(int click_count) {
if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED)
return;
DCHECK(click_count > 0);
DCHECK(click_count <= 3);
int f = flags();
switch (click_count) {
case 1:
f &= ~EF_IS_DOUBLE_CLICK;
f &= ~EF_IS_TRIPLE_CLICK;
break;
case 2:
f |= EF_IS_DOUBLE_CLICK;
f &= ~EF_IS_TRIPLE_CLICK;
break;
case 3:
f &= ~EF_IS_DOUBLE_CLICK;
f |= EF_IS_TRIPLE_CLICK;
break;
}
set_flags(f);
}
////////////////////////////////////////////////////////////////////////////////
// MouseWheelEvent
MouseWheelEvent::MouseWheelEvent() : MouseEvent(), offset_() {
}
MouseWheelEvent::MouseWheelEvent(const ScrollEvent& scroll_event)
: MouseEvent(scroll_event),
offset_(gfx::ToRoundedInt(scroll_event.x_offset()),
gfx::ToRoundedInt(scroll_event.y_offset())) {
SetType(ET_MOUSEWHEEL);
}
MouseWheelEvent::MouseWheelEvent(const MouseEvent& mouse_event,
int x_offset,
int y_offset)
: MouseEvent(mouse_event), offset_(x_offset, y_offset) {
DCHECK(type() == ET_MOUSEWHEEL);
}
MouseWheelEvent::MouseWheelEvent(const MouseWheelEvent& mouse_wheel_event)
: MouseEvent(mouse_wheel_event),
offset_(mouse_wheel_event.offset()) {
DCHECK(type() == ET_MOUSEWHEEL);
}
MouseWheelEvent::MouseWheelEvent(const gfx::Vector2d& offset,
const gfx::PointF& location,
const gfx::PointF& root_location,
int flags,
int changed_button_flags)
: MouseEvent(ui::ET_MOUSEWHEEL, location, root_location, flags,
changed_button_flags),
offset_(offset) {
}
// This value matches GTK+ wheel scroll amount.
const int MouseWheelEvent::kWheelDelta = 53;
void MouseWheelEvent::UpdateForRootTransform(
const gfx::Transform& inverted_root_transform) {
LocatedEvent::UpdateForRootTransform(inverted_root_transform);
gfx::DecomposedTransform decomp;
bool success = gfx::DecomposeTransform(&decomp, inverted_root_transform);
DCHECK(success);
if (decomp.scale[0]) {
offset_.set_x(
gfx::ToRoundedInt(SkMScalarToFloat(offset_.x() * decomp.scale[0])));
}
if (decomp.scale[1]) {
offset_.set_y(
gfx::ToRoundedInt(SkMScalarToFloat(offset_.y() * decomp.scale[1])));
}
}
////////////////////////////////////////////////////////////////////////////////
// TouchEvent
TouchEvent::TouchEvent()
: LocatedEvent(),
touch_id_(0),
radius_x_(0),
radius_y_(0),
rotation_angle_(0),
force_(0) {
}
TouchEvent::TouchEvent(EventType type,
const gfx::PointF& location,
int touch_id,
base::TimeDelta time_stamp)
: LocatedEvent(type, location, location, time_stamp, 0),
touch_id_(touch_id),
radius_x_(0.0f),
radius_y_(0.0f),
rotation_angle_(0.0f),
force_(0.0f) {
latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
}
TouchEvent::TouchEvent(EventType type,
const gfx::PointF& location,
int flags,
int touch_id,
base::TimeDelta time_stamp,
float radius_x,
float radius_y,
float angle,
float force)
: LocatedEvent(type, location, location, time_stamp, flags),
touch_id_(touch_id),
radius_x_(radius_x),
radius_y_(radius_y),
rotation_angle_(angle),
force_(force) {
latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
}
TouchEvent::~TouchEvent() {
}
void TouchEvent::UpdateForRootTransform(
const gfx::Transform& inverted_root_transform) {
LocatedEvent::UpdateForRootTransform(inverted_root_transform);
gfx::DecomposedTransform decomp;
bool success = gfx::DecomposeTransform(&decomp, inverted_root_transform);
DCHECK(success);
if (decomp.scale[0])
radius_x_ *= decomp.scale[0];
if (decomp.scale[1])
radius_y_ *= decomp.scale[1];
}
////////////////////////////////////////////////////////////////////////////////
// KeyEvent
KeyEvent::KeyEvent()
: Event(),
key_code_(VKEY_UNKNOWN),
code_(),
is_char_(false),
platform_keycode_(0),
character_(0) {
}
KeyEvent::KeyEvent(EventType type,
KeyboardCode key_code,
int flags)
: Event(type, EventTimeForNow(), flags),
key_code_(key_code),
is_char_(false),
platform_keycode_(0),
character_() {
}
KeyEvent::KeyEvent(EventType type,
KeyboardCode key_code,
const std::string& code,
int flags)
: Event(type, EventTimeForNow(), flags),
key_code_(key_code),
code_(code),
is_char_(false),
platform_keycode_(0),
character_(0) {
}
KeyEvent::KeyEvent(base::char16 character, KeyboardCode key_code, int flags)
: Event(ET_KEY_PRESSED, EventTimeForNow(), flags),
key_code_(key_code),
code_(""),
is_char_(true),
platform_keycode_(0),
character_(character) {
}
KeyEvent::KeyEvent(const KeyEvent& rhs)
: Event(rhs),
key_code_(rhs.key_code_),
code_(rhs.code_),
is_char_(rhs.is_char_),
platform_keycode_(rhs.platform_keycode_),
character_(rhs.character_) {
if (rhs.extended_key_event_data_)
extended_key_event_data_.reset(rhs.extended_key_event_data_->Clone());
}
KeyEvent& KeyEvent::operator=(const KeyEvent& rhs) {
if (this != &rhs) {
Event::operator=(rhs);
key_code_ = rhs.key_code_;
code_ = rhs.code_;
is_char_ = rhs.is_char_;
platform_keycode_ = rhs.platform_keycode_;
character_ = rhs.character_;
if (rhs.extended_key_event_data_)
extended_key_event_data_.reset(rhs.extended_key_event_data_->Clone());
}
return *this;
}
KeyEvent::~KeyEvent() {}
void KeyEvent::SetExtendedKeyEventData(scoped_ptr<ExtendedKeyEventData> data) {
extended_key_event_data_ = data.Pass();
}
base::char16 KeyEvent::GetCharacter() const {
if (is_char_ || character_)
return character_;
// TODO(kpschoedel): streamline these cases after settling Ozone
// positional coding.
#if defined(USE_X11)
character_ = GetCharacterFromKeyCode(key_code_, flags());
return character_;
#else
return GetCharacterFromKeyCode(key_code_, flags());
#endif
}
base::char16 KeyEvent::GetText() const {
if ((flags() & EF_CONTROL_DOWN) != 0) {
return GetControlCharacterForKeycode(key_code_,
(flags() & EF_SHIFT_DOWN) != 0);
}
return GetUnmodifiedText();
}
base::char16 KeyEvent::GetUnmodifiedText() const {
if (!is_char_ && (key_code_ == VKEY_RETURN))
return '\r';
return GetCharacter();
}
bool KeyEvent::IsUnicodeKeyCode() const {
return false;
}
void KeyEvent::NormalizeFlags() {
int mask = 0;
switch (key_code()) {
case VKEY_CONTROL:
mask = EF_CONTROL_DOWN;
break;
case VKEY_SHIFT:
mask = EF_SHIFT_DOWN;
break;
case VKEY_MENU:
mask = EF_ALT_DOWN;
break;
case VKEY_CAPITAL:
mask = EF_CAPS_LOCK_DOWN;
break;
default:
return;
}
if (type() == ET_KEY_PRESSED)
set_flags(flags() | mask);
else
set_flags(flags() & ~mask);
}
bool KeyEvent::IsTranslated() const {
switch (type()) {
case ET_KEY_PRESSED:
case ET_KEY_RELEASED:
return false;
case ET_TRANSLATED_KEY_PRESS:
case ET_TRANSLATED_KEY_RELEASE:
return true;
default:
NOTREACHED();
return false;
}
}
void KeyEvent::SetTranslated(bool translated) {
switch (type()) {
case ET_KEY_PRESSED:
case ET_TRANSLATED_KEY_PRESS:
SetType(translated ? ET_TRANSLATED_KEY_PRESS : ET_KEY_PRESSED);
break;
case ET_KEY_RELEASED:
case ET_TRANSLATED_KEY_RELEASE:
SetType(translated ? ET_TRANSLATED_KEY_RELEASE : ET_KEY_RELEASED);
break;
default:
NOTREACHED();
}
}
bool KeyEvent::IsRightSideKey() const {
switch (key_code_) {
case VKEY_CONTROL:
case VKEY_SHIFT:
case VKEY_MENU:
case VKEY_LWIN:
#if defined(USE_X11)
// Under X11, setting code_ requires platform-dependent information, and
// currently assumes that X keycodes are based on Linux evdev keycodes.
// In certain test environments this is not the case, and code_ is not
// set accurately, so we need a different mechanism. Fortunately X11 key
// mapping preserves the left-right distinction, so testing keysyms works
// if the value is available (as it is for all X11 native-based events).
if (platform_keycode_) {
return (platform_keycode_ == XK_Shift_R) ||
(platform_keycode_ == XK_Control_R) ||
(platform_keycode_ == XK_Alt_R) ||
(platform_keycode_ == XK_Meta_R) ||
(platform_keycode_ == XK_Super_R) ||
(platform_keycode_ == XK_Hyper_R);
}
// Fall through to the generic code if we have no platform_keycode_.
// Under X11, this must be a synthetic event, so we can require that
// code_ be set correctly.
#endif
return ((code_.size() > 5) &&
(code_.compare(code_.size() - 5, 5, "Right", 5)) == 0);
default:
return false;
}
}
KeyboardCode KeyEvent::GetLocatedWindowsKeyboardCode() const {
switch (key_code_) {
case VKEY_SHIFT:
return IsRightSideKey() ? VKEY_RSHIFT : VKEY_LSHIFT;
case VKEY_CONTROL:
return IsRightSideKey() ? VKEY_RCONTROL : VKEY_LCONTROL;
case VKEY_MENU:
return IsRightSideKey() ? VKEY_RMENU : VKEY_LMENU;
case VKEY_LWIN:
return IsRightSideKey() ? VKEY_RWIN : VKEY_LWIN;
// TODO(kpschoedel): EF_NUMPAD_KEY is present only on X11. Currently this
// function is only called on X11. Likely the tests here will be replaced
// with a DOM-based code enumeration test in the course of Ozone
// platform-indpendent key event work.
case VKEY_0:
return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD0 : VKEY_0;
case VKEY_1:
return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD1 : VKEY_1;
case VKEY_2:
return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD2 : VKEY_2;
case VKEY_3:
return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD3 : VKEY_3;
case VKEY_4:
return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD4 : VKEY_4;
case VKEY_5:
return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD5 : VKEY_5;
case VKEY_6:
return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD6 : VKEY_6;
case VKEY_7:
return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD7 : VKEY_7;
case VKEY_8:
return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD8 : VKEY_8;
case VKEY_9:
return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD9 : VKEY_9;
default:
return key_code_;
}
}
uint16 KeyEvent::GetConflatedWindowsKeyCode() const {
if (is_char_)
return character_;
return key_code_;
}
////////////////////////////////////////////////////////////////////////////////
// ScrollEvent
ScrollEvent::ScrollEvent() : MouseEvent() {
}
ScrollEvent::ScrollEvent(EventType type,
const gfx::PointF& location,
base::TimeDelta time_stamp,
int flags,
float x_offset,
float y_offset,
float x_offset_ordinal,
float y_offset_ordinal,
int finger_count)
: MouseEvent(type, location, location, flags, 0),
x_offset_(x_offset),
y_offset_(y_offset),
x_offset_ordinal_(x_offset_ordinal),
y_offset_ordinal_(y_offset_ordinal),
finger_count_(finger_count) {
set_time_stamp(time_stamp);
CHECK(IsScrollEvent());
}
void ScrollEvent::Scale(const float factor) {
x_offset_ *= factor;
y_offset_ *= factor;
x_offset_ordinal_ *= factor;
y_offset_ordinal_ *= factor;
}
////////////////////////////////////////////////////////////////////////////////
// GestureEvent
GestureEvent::GestureEvent(float x,
float y,
int flags,
base::TimeDelta time_stamp,
const GestureEventDetails& details)
: LocatedEvent(details.type(),
gfx::PointF(x, y),
gfx::PointF(x, y),
time_stamp,
flags | EF_FROM_TOUCH),
details_(details) {
}
GestureEvent::~GestureEvent() {
}
} // namespace ui
此差异已折叠。
// Copyright (c) 2012 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.
#ifndef UI_EVENTS_EVENT_CONSTANTS_H_
#define UI_EVENTS_EVENT_CONSTANTS_H_
namespace ui {
// Event types. (prefixed because of a conflict with windows headers)
enum EventType {
ET_UNKNOWN = 0,
ET_MOUSE_PRESSED,
ET_MOUSE_DRAGGED,
ET_MOUSE_RELEASED,
ET_MOUSE_MOVED,
ET_MOUSE_ENTERED,
ET_MOUSE_EXITED,
ET_KEY_PRESSED,
ET_KEY_RELEASED,
ET_MOUSEWHEEL,
ET_MOUSE_CAPTURE_CHANGED, // Event has no location.
ET_TOUCH_RELEASED,
ET_TOUCH_PRESSED,
ET_TOUCH_MOVED,
ET_TOUCH_CANCELLED,
ET_DROP_TARGET_EVENT,
ET_TRANSLATED_KEY_PRESS,
ET_TRANSLATED_KEY_RELEASE,
// GestureEvent types
ET_GESTURE_SCROLL_BEGIN,
ET_GESTURE_TYPE_START = ET_GESTURE_SCROLL_BEGIN,
ET_GESTURE_SCROLL_END,
ET_GESTURE_SCROLL_UPDATE,
ET_GESTURE_TAP,
ET_GESTURE_TAP_DOWN,
ET_GESTURE_TAP_CANCEL,
ET_GESTURE_TAP_UNCONFIRMED, // User tapped, but the tap delay hasn't expired.
ET_GESTURE_DOUBLE_TAP,
ET_GESTURE_BEGIN, // The first event sent when each finger is pressed.
ET_GESTURE_END, // Sent for each released finger.
ET_GESTURE_TWO_FINGER_TAP,
ET_GESTURE_PINCH_BEGIN,
ET_GESTURE_PINCH_END,
ET_GESTURE_PINCH_UPDATE,
ET_GESTURE_LONG_PRESS,
ET_GESTURE_LONG_TAP,
// A SWIPE gesture can happen at the end of a touch sequence involving one or
// more fingers if the finger velocity was high enough when the first finger
// was released.
ET_GESTURE_SWIPE,
ET_GESTURE_SHOW_PRESS,
// Sent by Win8+ metro when the user swipes from the bottom or top.
ET_GESTURE_WIN8_EDGE_SWIPE,
// Scroll support.
// TODO[davemoore] we need to unify these events w/ touch and gestures.
ET_SCROLL,
ET_SCROLL_FLING_START,
ET_SCROLL_FLING_CANCEL,
ET_GESTURE_TYPE_END = ET_SCROLL_FLING_CANCEL,
// Sent by the system to indicate any modal type operations, such as drag and
// drop or menus, should stop.
ET_CANCEL_MODE,
// Sent by the CrOS gesture library for interesting patterns that we want
// to track with the UMA system.
ET_UMA_DATA,
// Must always be last. User namespace starts above this value.
// See ui::RegisterCustomEventType().
ET_LAST
};
// Event flags currently supported
enum EventFlags {
EF_NONE = 0, // Used to denote no flags explicitly
EF_CAPS_LOCK_DOWN = 1 << 0,
EF_SHIFT_DOWN = 1 << 1,
EF_CONTROL_DOWN = 1 << 2,
EF_ALT_DOWN = 1 << 3,
EF_LEFT_MOUSE_BUTTON = 1 << 4,
EF_MIDDLE_MOUSE_BUTTON = 1 << 5,
EF_RIGHT_MOUSE_BUTTON = 1 << 6,
EF_COMMAND_DOWN = 1 << 7, // GUI Key (e.g. Command on OS X keyboards,
// Search on Chromebook keyboards,
// Windows on MS-oriented keyboards)
EF_EXTENDED = 1 << 8, // Windows extended key (see WM_KEYDOWN doc)
EF_IS_SYNTHESIZED = 1 << 9,
EF_ALTGR_DOWN = 1 << 10,
EF_MOD3_DOWN = 1 << 11,
};
// Flags specific to key events
enum KeyEventFlags {
EF_NUMPAD_KEY = 1 << 16, // Key originates from number pad (Xkb only)
EF_IME_FABRICATED_KEY = 1 << 17, // Key event fabricated by the underlying
// IME without a user action.
// (Linux X11 only)
EF_IS_REPEAT = 1 << 18,
EF_FUNCTION_KEY = 1 << 19, // Key originates from function key row
EF_FINAL = 1 << 20, // Do not remap; the event was created with
// the desired final values.
};
// Flags specific to mouse events
enum MouseEventFlags {
EF_IS_DOUBLE_CLICK = 1 << 16,
EF_IS_TRIPLE_CLICK = 1 << 17,
EF_IS_NON_CLIENT = 1 << 18,
EF_FROM_TOUCH = 1 << 19, // Indicates this mouse event is generated
// from an unconsumed touch/gesture event.
EF_TOUCH_ACCESSIBILITY = 1 << 20, // Indicates this event was generated from
// touch accessibility mode.
};
// Result of dispatching an event.
enum EventResult {
ER_UNHANDLED = 0, // The event hasn't been handled. The event can be
// propagated to other handlers.
ER_HANDLED = 1 << 0, // The event has already been handled, but it can
// still be propagated to other handlers.
ER_CONSUMED = 1 << 1, // The event has been handled, and it should not be
// propagated to other handlers.
};
// Phase of the event dispatch.
enum EventPhase {
EP_PREDISPATCH,
EP_PRETARGET,
EP_TARGET,
EP_POSTTARGET,
EP_POSTDISPATCH
};
// Device ID for Touch and Key Events.
enum EventDeviceId {
ED_UNKNOWN_DEVICE = -1
};
} // namespace ui
#endif // UI_EVENTS_EVENT_CONSTANTS_H_
// Copyright (c) 2012 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 "ui/events/event_dispatcher.h"
#include <algorithm>
#include "ui/events/event_target.h"
#include "ui/events/event_targeter.h"
namespace ui {
namespace {
class ScopedDispatchHelper : public Event::DispatcherApi {
public:
explicit ScopedDispatchHelper(Event* event)
: Event::DispatcherApi(event) {
set_result(ui::ER_UNHANDLED);
}
virtual ~ScopedDispatchHelper() {
set_phase(EP_POSTDISPATCH);
}
private:
DISALLOW_COPY_AND_ASSIGN(ScopedDispatchHelper);
};
} // namespace
EventDispatcherDelegate::EventDispatcherDelegate()
: dispatcher_(NULL) {
}
EventDispatcherDelegate::~EventDispatcherDelegate() {
if (dispatcher_)
dispatcher_->OnDispatcherDelegateDestroyed();
}
Event* EventDispatcherDelegate::current_event() {
return dispatcher_ ? dispatcher_->current_event() : NULL;
}
EventDispatchDetails EventDispatcherDelegate::DispatchEvent(EventTarget* target,
Event* event) {
CHECK(target);
Event::DispatcherApi dispatch_helper(event);
dispatch_helper.set_phase(EP_PREDISPATCH);
dispatch_helper.set_result(ER_UNHANDLED);
EventDispatchDetails details = PreDispatchEvent(target, event);
if (!event->handled() &&
!details.dispatcher_destroyed &&
!details.target_destroyed) {
details = DispatchEventToTarget(target, event);
}
bool target_destroyed_during_dispatch = details.target_destroyed;
if (!details.dispatcher_destroyed) {
details = PostDispatchEvent(target_destroyed_during_dispatch ?
NULL : target, *event);
}
details.target_destroyed |= target_destroyed_during_dispatch;
return details;
}
EventDispatchDetails EventDispatcherDelegate::PreDispatchEvent(
EventTarget* target, Event* event) {
return EventDispatchDetails();
}
EventDispatchDetails EventDispatcherDelegate::PostDispatchEvent(
EventTarget* target, const Event& event) {
return EventDispatchDetails();
}
EventDispatchDetails EventDispatcherDelegate::DispatchEventToTarget(
EventTarget* target,
Event* event) {
EventDispatcher* old_dispatcher = dispatcher_;
EventDispatcher dispatcher(this);
dispatcher_ = &dispatcher;
dispatcher.ProcessEvent(target, event);
if (!dispatcher.delegate_destroyed())
dispatcher_ = old_dispatcher;
else if (old_dispatcher)
old_dispatcher->OnDispatcherDelegateDestroyed();
EventDispatchDetails details;
details.dispatcher_destroyed = dispatcher.delegate_destroyed();
details.target_destroyed =
(!details.dispatcher_destroyed && !CanDispatchToTarget(target));
return details;
}
////////////////////////////////////////////////////////////////////////////////
// EventDispatcher:
EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate)
: delegate_(delegate),
current_event_(NULL) {
}
EventDispatcher::~EventDispatcher() {
}
void EventDispatcher::OnHandlerDestroyed(EventHandler* handler) {
handler_list_.erase(std::find(handler_list_.begin(),
handler_list_.end(),
handler));
}
void EventDispatcher::ProcessEvent(EventTarget* target, Event* event) {
if (!target || !target->CanAcceptEvent(*event))
return;
ScopedDispatchHelper dispatch_helper(event);
dispatch_helper.set_target(target);
handler_list_.clear();
target->GetPreTargetHandlers(&handler_list_);
dispatch_helper.set_phase(EP_PRETARGET);
DispatchEventToEventHandlers(&handler_list_, event);
if (event->handled())
return;
// If the event hasn't been consumed, trigger the default handler. Note that
// even if the event has already been handled (i.e. return result has
// ER_HANDLED set), that means that the event should still be processed at
// this layer, however it should not be processed in the next layer of
// abstraction.
if (delegate_ && delegate_->CanDispatchToTarget(target)) {
dispatch_helper.set_phase(EP_TARGET);
DispatchEvent(target, event);
if (event->handled())
return;
}
if (!delegate_ || !delegate_->CanDispatchToTarget(target))
return;
handler_list_.clear();
target->GetPostTargetHandlers(&handler_list_);
dispatch_helper.set_phase(EP_POSTTARGET);
DispatchEventToEventHandlers(&handler_list_, event);
}
void EventDispatcher::OnDispatcherDelegateDestroyed() {
delegate_ = NULL;
}
////////////////////////////////////////////////////////////////////////////////
// EventDispatcher, private:
void EventDispatcher::DispatchEventToEventHandlers(EventHandlerList* list,
Event* event) {
for (EventHandlerList::const_iterator it = list->begin(),
end = list->end(); it != end; ++it) {
(*it)->dispatchers_.push(this);
}
while (!list->empty()) {
EventHandler* handler = (*list->begin());
if (delegate_ && !event->stopped_propagation())
DispatchEvent(handler, event);
if (!list->empty() && *list->begin() == handler) {
// The handler has not been destroyed (because if it were, then it would
// have been removed from the list).
CHECK(handler->dispatchers_.top() == this);
handler->dispatchers_.pop();
list->erase(list->begin());
}
}
}
void EventDispatcher::DispatchEvent(EventHandler* handler, Event* event) {
// If the target has been invalidated or deleted, don't dispatch the event.
if (!delegate_->CanDispatchToTarget(event->target())) {
if (event->cancelable())
event->StopPropagation();
return;
}
base::AutoReset<Event*> event_reset(&current_event_, event);
handler->OnEvent(event);
if (!delegate_ && event->cancelable())
event->StopPropagation();
}
} // namespace ui
// Copyright (c) 2012 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.
#ifndef UI_EVENTS_EVENT_DISPATCHER_H_
#define UI_EVENTS_EVENT_DISPATCHER_H_
#include "base/auto_reset.h"
#include "ui/events/event.h"
#include "ui/events/event_constants.h"
#include "ui/events/event_handler.h"
#include "ui/events/events_export.h"
namespace ui {
class EventDispatcher;
class EventTarget;
class EventTargeter;
struct EventDispatchDetails {
EventDispatchDetails()
: dispatcher_destroyed(false),
target_destroyed(false) {}
bool dispatcher_destroyed;
bool target_destroyed;
};
class EVENTS_EXPORT EventDispatcherDelegate {
public:
EventDispatcherDelegate();
virtual ~EventDispatcherDelegate();
// Returns whether an event can still be dispatched to a target. (e.g. during
// event dispatch, one of the handlers may have destroyed the target, in which
// case the event can no longer be dispatched to the target).
virtual bool CanDispatchToTarget(EventTarget* target) = 0;
// Returns the event being dispatched (or NULL if no event is being
// dispatched).
Event* current_event();
// Dispatches |event| to |target|. This calls |PreDispatchEvent()| before
// dispatching the event, and |PostDispatchEvent()| after the event has been
// dispatched.
EventDispatchDetails DispatchEvent(EventTarget* target, Event* event)
WARN_UNUSED_RESULT;
protected:
// This is called once a target has been determined for an event, right before
// the event is dispatched to the target. This function may modify |event| to
// prepare it for dispatch (e.g. update event flags, location etc.).
virtual EventDispatchDetails PreDispatchEvent(
EventTarget* target,
Event* event) WARN_UNUSED_RESULT;
// This is called right after the event dispatch is completed.
// |target| is NULL if the target was deleted during dispatch.
virtual EventDispatchDetails PostDispatchEvent(
EventTarget* target,
const Event& event) WARN_UNUSED_RESULT;
private:
// Dispatches the event to the target.
EventDispatchDetails DispatchEventToTarget(EventTarget* target,
Event* event) WARN_UNUSED_RESULT;
EventDispatcher* dispatcher_;
DISALLOW_COPY_AND_ASSIGN(EventDispatcherDelegate);
};
// Dispatches events to appropriate targets.
class EVENTS_EXPORT EventDispatcher {
public:
explicit EventDispatcher(EventDispatcherDelegate* delegate);
virtual ~EventDispatcher();
void ProcessEvent(EventTarget* target, Event* event);
const Event* current_event() const { return current_event_; }
Event* current_event() { return current_event_; }
bool delegate_destroyed() const { return !delegate_; }
void OnHandlerDestroyed(EventHandler* handler);
void OnDispatcherDelegateDestroyed();
private:
void DispatchEventToEventHandlers(EventHandlerList* list, Event* event);
// Dispatches an event, and makes sure it sets ER_CONSUMED on the
// event-handling result if the dispatcher itself has been destroyed during
// dispatching the event to the event handler.
void DispatchEvent(EventHandler* handler, Event* event);
EventDispatcherDelegate* delegate_;
Event* current_event_;
EventHandlerList handler_list_;
DISALLOW_COPY_AND_ASSIGN(EventDispatcher);
};
} // namespace ui
#endif // UI_EVENTS_EVENT_DISPATCHER_H_
// Copyright (c) 2012 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 "ui/events/event_dispatcher.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/event.h"
#include "ui/events/event_dispatcher.h"
#include "ui/events/event_target.h"
#include "ui/events/event_target_iterator.h"
#include "ui/events/event_utils.h"
namespace ui {
namespace {
class TestTarget : public EventTarget {
public:
TestTarget() : parent_(NULL), valid_(true) {}
~TestTarget() override {}
void set_parent(TestTarget* parent) { parent_ = parent; }
bool valid() const { return valid_; }
void set_valid(bool valid) { valid_ = valid; }
void AddHandlerId(int id) {
handler_list_.push_back(id);
}
const std::vector<int>& handler_list() const { return handler_list_; }
void Reset() {
handler_list_.clear();
valid_ = true;
}
private:
// Overridden from EventTarget:
bool CanAcceptEvent(const ui::Event& event) override {
return true;
}
EventTarget* GetParentTarget() override {
return parent_;
}
scoped_ptr<EventTargetIterator> GetChildIterator() override {
return scoped_ptr<EventTargetIterator>();
}
EventTargeter* GetEventTargeter() override {
return NULL;
}
TestTarget* parent_;
std::vector<int> handler_list_;
bool valid_;
DISALLOW_COPY_AND_ASSIGN(TestTarget);
};
class TestEventHandler : public EventHandler {
public:
TestEventHandler(int id)
: id_(id),
event_result_(ER_UNHANDLED),
expect_pre_target_(false),
expect_post_target_(false),
received_pre_target_(false) {
}
~TestEventHandler() override {}
virtual void ReceivedEvent(Event* event) {
static_cast<TestTarget*>(event->target())->AddHandlerId(id_);
if (event->phase() == ui::EP_POSTTARGET) {
EXPECT_TRUE(expect_post_target_);
if (expect_pre_target_)
EXPECT_TRUE(received_pre_target_);
} else if (event->phase() == ui::EP_PRETARGET) {
EXPECT_TRUE(expect_pre_target_);
received_pre_target_ = true;
} else {
NOTREACHED();
}
}
void set_event_result(EventResult result) { event_result_ = result; }
void set_expect_pre_target(bool expect) { expect_pre_target_ = expect; }
void set_expect_post_target(bool expect) { expect_post_target_ = expect; }
private:
// Overridden from EventHandler:
void OnEvent(Event* event) override {
ui::EventHandler::OnEvent(event);
ReceivedEvent(event);
SetStatusOnEvent(event);
}
void SetStatusOnEvent(Event* event) {
if (event_result_ & ui::ER_CONSUMED)
event->StopPropagation();
if (event_result_ & ui::ER_HANDLED)
event->SetHandled();
}
int id_;
EventResult event_result_;
bool expect_pre_target_;
bool expect_post_target_;
bool received_pre_target_;
DISALLOW_COPY_AND_ASSIGN(TestEventHandler);
};
class NonCancelableEvent : public Event {
public:
NonCancelableEvent()
: Event(ui::ET_CANCEL_MODE, ui::EventTimeForNow(), 0) {
set_cancelable(false);
}
~NonCancelableEvent() override {}
private:
DISALLOW_COPY_AND_ASSIGN(NonCancelableEvent);
};
// Destroys the dispatcher-delegate when it receives any event.
class EventHandlerDestroyDispatcherDelegate : public TestEventHandler {
public:
EventHandlerDestroyDispatcherDelegate(EventDispatcherDelegate* delegate,
int id)
: TestEventHandler(id),
dispatcher_delegate_(delegate) {
}
~EventHandlerDestroyDispatcherDelegate() override {}
private:
void ReceivedEvent(Event* event) override {
TestEventHandler::ReceivedEvent(event);
delete dispatcher_delegate_;
}
EventDispatcherDelegate* dispatcher_delegate_;
DISALLOW_COPY_AND_ASSIGN(EventHandlerDestroyDispatcherDelegate);
};
// Invalidates the target when it receives any event.
class InvalidateTargetEventHandler : public TestEventHandler {
public:
explicit InvalidateTargetEventHandler(int id) : TestEventHandler(id) {}
~InvalidateTargetEventHandler() override {}
private:
void ReceivedEvent(Event* event) override {
TestEventHandler::ReceivedEvent(event);
TestTarget* target = static_cast<TestTarget*>(event->target());
target->set_valid(false);
}
DISALLOW_COPY_AND_ASSIGN(InvalidateTargetEventHandler);
};
// Destroys a second event handler when this handler gets an event.
// Optionally also destroys the dispatcher.
class EventHandlerDestroyer : public TestEventHandler {
public:
EventHandlerDestroyer(int id, EventHandler* destroy)
: TestEventHandler(id),
to_destroy_(destroy),
dispatcher_delegate_(NULL) {
}
~EventHandlerDestroyer() override {
CHECK(!to_destroy_);
}
void set_dispatcher_delegate(EventDispatcherDelegate* dispatcher_delegate) {
dispatcher_delegate_ = dispatcher_delegate;
}
private:
void ReceivedEvent(Event* event) override {
TestEventHandler::ReceivedEvent(event);
delete to_destroy_;
to_destroy_ = NULL;
if (dispatcher_delegate_) {
delete dispatcher_delegate_;
dispatcher_delegate_ = NULL;
}
}
EventHandler* to_destroy_;
EventDispatcherDelegate* dispatcher_delegate_;
DISALLOW_COPY_AND_ASSIGN(EventHandlerDestroyer);
};
class TestEventDispatcher : public EventDispatcherDelegate {
public:
TestEventDispatcher() {}
~TestEventDispatcher() override {}
EventDispatchDetails ProcessEvent(EventTarget* target, Event* event) {
return DispatchEvent(target, event);
}
private:
// Overridden from EventDispatcherDelegate:
bool CanDispatchToTarget(EventTarget* target) override {
TestTarget* test_target = static_cast<TestTarget*>(target);
return test_target->valid();
}
DISALLOW_COPY_AND_ASSIGN(TestEventDispatcher);
};
} // namespace
TEST(EventDispatcherTest, EventDispatchOrder) {
TestEventDispatcher dispatcher;
TestTarget parent, child;
TestEventHandler h1(1), h2(2), h3(3), h4(4);
TestEventHandler h5(5), h6(6), h7(7), h8(8);
child.set_parent(&parent);
parent.AddPreTargetHandler(&h1);
parent.AddPreTargetHandler(&h2);
child.AddPreTargetHandler(&h3);
child.AddPreTargetHandler(&h4);
h1.set_expect_pre_target(true);
h2.set_expect_pre_target(true);
h3.set_expect_pre_target(true);
h4.set_expect_pre_target(true);
child.AddPostTargetHandler(&h5);
child.AddPostTargetHandler(&h6);
parent.AddPostTargetHandler(&h7);
parent.AddPostTargetHandler(&h8);
h5.set_expect_post_target(true);
h6.set_expect_post_target(true);
h7.set_expect_post_target(true);
h8.set_expect_post_target(true);
MouseEvent mouse(ui::ET_MOUSE_MOVED, gfx::Point(3, 4),
gfx::Point(3, 4), 0, 0);
Event::DispatcherApi event_mod(&mouse);
dispatcher.ProcessEvent(&child, &mouse);
EXPECT_FALSE(mouse.stopped_propagation());
EXPECT_FALSE(mouse.handled());
{
int expected[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
EXPECT_EQ(
std::vector<int>(expected, expected + sizeof(expected) / sizeof(int)),
child.handler_list());
}
child.Reset();
event_mod.set_phase(EP_PREDISPATCH);
event_mod.set_result(ER_UNHANDLED);
h1.set_event_result(ER_HANDLED);
dispatcher.ProcessEvent(&child, &mouse);
EXPECT_EQ(EP_POSTDISPATCH, mouse.phase());
EXPECT_FALSE(mouse.stopped_propagation());
EXPECT_TRUE(mouse.handled());
{
// |h1| marks the event as handled. So only the pre-target handlers should
// receive the event.
int expected[] = { 1, 2, 3, 4 };
EXPECT_EQ(
std::vector<int>(expected, expected + sizeof(expected) / sizeof(int)),
child.handler_list());
}
child.Reset();
event_mod.set_phase(EP_PREDISPATCH);
event_mod.set_result(ER_UNHANDLED);
int nexpected[] = { 1, 2, 3, 4, 5 };
h1.set_event_result(ER_UNHANDLED);
h5.set_event_result(ER_CONSUMED);
dispatcher.ProcessEvent(&child, &mouse);
EXPECT_EQ(EP_POSTDISPATCH, mouse.phase());
EXPECT_TRUE(mouse.stopped_propagation());
EXPECT_TRUE(mouse.handled());
EXPECT_EQ(
std::vector<int>(nexpected, nexpected + sizeof(nexpected) / sizeof(int)),
child.handler_list());
child.Reset();
event_mod.set_phase(EP_PREDISPATCH);
event_mod.set_result(ER_UNHANDLED);
int exp[] = { 1 };
h1.set_event_result(ER_CONSUMED);
dispatcher.ProcessEvent(&child, &mouse);
EXPECT_EQ(EP_POSTDISPATCH, mouse.phase());
EXPECT_TRUE(mouse.stopped_propagation());
EXPECT_TRUE(mouse.handled());
EXPECT_EQ(
std::vector<int>(exp, exp + sizeof(exp) / sizeof(int)),
child.handler_list());
}
// Tests that the event-phases are correct.
TEST(EventDispatcherTest, EventDispatchPhase) {
TestEventDispatcher dispatcher;
TestTarget target;
TestEventHandler handler(11);
target.AddPreTargetHandler(&handler);
target.AddPostTargetHandler(&handler);
handler.set_expect_pre_target(true);
handler.set_expect_post_target(true);
MouseEvent mouse(ui::ET_MOUSE_MOVED, gfx::Point(3, 4),
gfx::Point(3, 4), 0, 0);
Event::DispatcherApi event_mod(&mouse);
dispatcher.ProcessEvent(&target, &mouse);
EXPECT_EQ(ER_UNHANDLED, mouse.result());
int handlers[] = { 11, 11 };
EXPECT_EQ(
std::vector<int>(handlers, handlers + sizeof(handlers) / sizeof(int)),
target.handler_list());
}
// Tests that if the dispatcher is destroyed in the middle of pre or post-target
// dispatching events, it doesn't cause a crash.
TEST(EventDispatcherTest, EventDispatcherDestroyedDuringDispatch) {
// Test for pre-target first.
{
TestEventDispatcher* dispatcher = new TestEventDispatcher();
TestTarget target;
EventHandlerDestroyDispatcherDelegate handler(dispatcher, 5);
TestEventHandler h1(1), h2(2);
target.AddPreTargetHandler(&h1);
target.AddPreTargetHandler(&handler);
target.AddPreTargetHandler(&h2);
h1.set_expect_pre_target(true);
handler.set_expect_pre_target(true);
// |h2| should not receive any events at all since |handler| will have
// destroyed the dispatcher.
h2.set_expect_pre_target(false);
MouseEvent mouse(ui::ET_MOUSE_MOVED, gfx::Point(3, 4),
gfx::Point(3, 4), 0, 0);
EventDispatchDetails details = dispatcher->ProcessEvent(&target, &mouse);
EXPECT_TRUE(details.dispatcher_destroyed);
EXPECT_EQ(ER_CONSUMED, mouse.result());
EXPECT_EQ(2U, target.handler_list().size());
EXPECT_EQ(1, target.handler_list()[0]);
EXPECT_EQ(5, target.handler_list()[1]);
}
// Test for non-cancelable event.
{
TestEventDispatcher* dispatcher = new TestEventDispatcher();
TestTarget target;
EventHandlerDestroyDispatcherDelegate handler(dispatcher, 5);
TestEventHandler h1(1), h2(2);
target.AddPreTargetHandler(&h1);
target.AddPreTargetHandler(&handler);
target.AddPreTargetHandler(&h2);
h1.set_expect_pre_target(true);
handler.set_expect_pre_target(true);
// |h2| should not receive any events at all since |handler| will have
// destroyed the dispatcher.
h2.set_expect_pre_target(false);
NonCancelableEvent event;
EventDispatchDetails details = dispatcher->ProcessEvent(&target, &event);
EXPECT_TRUE(details.dispatcher_destroyed);
EXPECT_EQ(2U, target.handler_list().size());
EXPECT_EQ(1, target.handler_list()[0]);
EXPECT_EQ(5, target.handler_list()[1]);
}
// Now test for post-target.
{
TestEventDispatcher* dispatcher = new TestEventDispatcher();
TestTarget target;
EventHandlerDestroyDispatcherDelegate handler(dispatcher, 5);
TestEventHandler h1(1), h2(2);
target.AddPostTargetHandler(&h1);
target.AddPostTargetHandler(&handler);
target.AddPostTargetHandler(&h2);
h1.set_expect_post_target(true);
handler.set_expect_post_target(true);
// |h2| should not receive any events at all since |handler| will have
// destroyed the dispatcher.
h2.set_expect_post_target(false);
MouseEvent mouse(ui::ET_MOUSE_MOVED, gfx::Point(3, 4),
gfx::Point(3, 4), 0, 0);
EventDispatchDetails details = dispatcher->ProcessEvent(&target, &mouse);
EXPECT_TRUE(details.dispatcher_destroyed);
EXPECT_EQ(ER_CONSUMED, mouse.result());
EXPECT_EQ(2U, target.handler_list().size());
EXPECT_EQ(1, target.handler_list()[0]);
EXPECT_EQ(5, target.handler_list()[1]);
}
// Test for non-cancelable event.
{
TestEventDispatcher* dispatcher = new TestEventDispatcher();
TestTarget target;
EventHandlerDestroyDispatcherDelegate handler(dispatcher, 5);
TestEventHandler h1(1), h2(2);
target.AddPostTargetHandler(&h1);
target.AddPostTargetHandler(&handler);
target.AddPostTargetHandler(&h2);
h1.set_expect_post_target(true);
handler.set_expect_post_target(true);
// |h2| should not receive any events at all since |handler| will have
// destroyed the dispatcher.
h2.set_expect_post_target(false);
NonCancelableEvent event;
EventDispatchDetails details = dispatcher->ProcessEvent(&target, &event);
EXPECT_TRUE(details.dispatcher_destroyed);
EXPECT_EQ(2U, target.handler_list().size());
EXPECT_EQ(1, target.handler_list()[0]);
EXPECT_EQ(5, target.handler_list()[1]);
}
}
// Tests that a target becoming invalid in the middle of pre- or post-target
// event processing aborts processing.
TEST(EventDispatcherTest, EventDispatcherInvalidateTarget) {
TestEventDispatcher dispatcher;
TestTarget target;
TestEventHandler h1(1);
InvalidateTargetEventHandler invalidate_handler(2);
TestEventHandler h3(3);
target.AddPreTargetHandler(&h1);
target.AddPreTargetHandler(&invalidate_handler);
target.AddPreTargetHandler(&h3);
h1.set_expect_pre_target(true);
invalidate_handler.set_expect_pre_target(true);
// |h3| should not receive events as the target will be invalidated.
h3.set_expect_pre_target(false);
MouseEvent mouse(ui::ET_MOUSE_MOVED, gfx::Point(3, 4), gfx::Point(3, 4), 0,
0);
EventDispatchDetails details = dispatcher.ProcessEvent(&target, &mouse);
EXPECT_FALSE(details.dispatcher_destroyed);
EXPECT_TRUE(details.target_destroyed);
EXPECT_FALSE(target.valid());
EXPECT_TRUE(mouse.stopped_propagation());
EXPECT_EQ(2U, target.handler_list().size());
EXPECT_EQ(1, target.handler_list()[0]);
EXPECT_EQ(2, target.handler_list()[1]);
// Test for non-cancelable event.
target.Reset();
NonCancelableEvent event;
details = dispatcher.ProcessEvent(&target, &event);
EXPECT_FALSE(details.dispatcher_destroyed);
EXPECT_TRUE(details.target_destroyed);
EXPECT_FALSE(target.valid());
EXPECT_EQ(2U, target.handler_list().size());
EXPECT_EQ(1, target.handler_list()[0]);
EXPECT_EQ(2, target.handler_list()[1]);
}
// Tests that if an event-handler gets destroyed during event-dispatch, it does
// not cause a crash.
TEST(EventDispatcherTest, EventHandlerDestroyedDuringDispatch) {
{
TestEventDispatcher dispatcher;
TestTarget target;
TestEventHandler h1(1);
TestEventHandler* h3 = new TestEventHandler(3);
EventHandlerDestroyer handle_destroyer(2, h3);
target.AddPreTargetHandler(&h1);
target.AddPreTargetHandler(&handle_destroyer);
target.AddPreTargetHandler(h3);
h1.set_expect_pre_target(true);
handle_destroyer.set_expect_pre_target(true);
// |h3| should not receive events since |handle_destroyer| will have
// destroyed it.
h3->set_expect_pre_target(false);
MouseEvent mouse(ui::ET_MOUSE_MOVED, gfx::Point(3, 4), gfx::Point(3, 4), 0,
0);
EventDispatchDetails details = dispatcher.ProcessEvent(&target, &mouse);
EXPECT_FALSE(details.dispatcher_destroyed);
EXPECT_FALSE(details.target_destroyed);
EXPECT_FALSE(mouse.stopped_propagation());
EXPECT_EQ(2U, target.handler_list().size());
EXPECT_EQ(1, target.handler_list()[0]);
EXPECT_EQ(2, target.handler_list()[1]);
}
// Test for non-cancelable events.
{
TestEventDispatcher dispatcher;
TestTarget target;
TestEventHandler h1(1);
TestEventHandler* h3 = new TestEventHandler(3);
EventHandlerDestroyer handle_destroyer(2, h3);
target.AddPreTargetHandler(&h1);
target.AddPreTargetHandler(&handle_destroyer);
target.AddPreTargetHandler(h3);
h1.set_expect_pre_target(true);
handle_destroyer.set_expect_pre_target(true);
h3->set_expect_pre_target(false);
NonCancelableEvent event;
EventDispatchDetails details = dispatcher.ProcessEvent(&target, &event);
EXPECT_FALSE(details.dispatcher_destroyed);
EXPECT_FALSE(details.target_destroyed);
EXPECT_EQ(2U, target.handler_list().size());
EXPECT_EQ(1, target.handler_list()[0]);
EXPECT_EQ(2, target.handler_list()[1]);
}
}
// Tests that things work correctly if an event-handler destroys both the
// dispatcher and a handler.
TEST(EventDispatcherTest, EventHandlerAndDispatcherDestroyedDuringDispatch) {
{
TestEventDispatcher* dispatcher = new TestEventDispatcher();
TestTarget target;
TestEventHandler h1(1);
TestEventHandler* h3 = new TestEventHandler(3);
EventHandlerDestroyer destroyer(2, h3);
target.AddPreTargetHandler(&h1);
target.AddPreTargetHandler(&destroyer);
target.AddPreTargetHandler(h3);
h1.set_expect_pre_target(true);
destroyer.set_expect_pre_target(true);
destroyer.set_dispatcher_delegate(dispatcher);
// |h3| should not receive events since |destroyer| will have destroyed
// it.
h3->set_expect_pre_target(false);
MouseEvent mouse(ui::ET_MOUSE_MOVED, gfx::Point(3, 4), gfx::Point(3, 4), 0,
0);
EventDispatchDetails details = dispatcher->ProcessEvent(&target, &mouse);
EXPECT_TRUE(details.dispatcher_destroyed);
EXPECT_TRUE(mouse.stopped_propagation());
EXPECT_EQ(2U, target.handler_list().size());
EXPECT_EQ(1, target.handler_list()[0]);
EXPECT_EQ(2, target.handler_list()[1]);
}
// Test for non-cancelable events.
{
TestEventDispatcher* dispatcher = new TestEventDispatcher();
TestTarget target;
TestEventHandler h1(1);
TestEventHandler* h3 = new TestEventHandler(3);
EventHandlerDestroyer destroyer(2, h3);
target.AddPreTargetHandler(&h1);
target.AddPreTargetHandler(&destroyer);
target.AddPreTargetHandler(h3);
h1.set_expect_pre_target(true);
destroyer.set_expect_pre_target(true);
destroyer.set_dispatcher_delegate(dispatcher);
// |h3| should not receive events since |destroyer| will have destroyed
// it.
h3->set_expect_pre_target(false);
NonCancelableEvent event;
EventDispatchDetails details = dispatcher->ProcessEvent(&target, &event);
EXPECT_TRUE(details.dispatcher_destroyed);
EXPECT_EQ(2U, target.handler_list().size());
EXPECT_EQ(1, target.handler_list()[0]);
EXPECT_EQ(2, target.handler_list()[1]);
}
}
} // namespace ui
// Copyright (c) 2012 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 "ui/events/event_handler.h"
#include "ui/events/event.h"
#include "ui/events/event_dispatcher.h"
namespace ui {
EventHandler::EventHandler() {
}
EventHandler::~EventHandler() {
while (!dispatchers_.empty()) {
EventDispatcher* dispatcher = dispatchers_.top();
dispatchers_.pop();
dispatcher->OnHandlerDestroyed(this);
}
}
void EventHandler::OnEvent(Event* event) {
// TODO(tdanderson): Encapsulate static_casts in ui::Event for all
// event types.
if (event->IsKeyEvent())
OnKeyEvent(static_cast<KeyEvent*>(event));
else if (event->IsMouseEvent())
OnMouseEvent(static_cast<MouseEvent*>(event));
else if (event->IsScrollEvent())
OnScrollEvent(static_cast<ScrollEvent*>(event));
else if (event->IsTouchEvent())
OnTouchEvent(static_cast<TouchEvent*>(event));
else if (event->IsGestureEvent())
OnGestureEvent(event->AsGestureEvent());
else if (event->type() == ET_CANCEL_MODE)
OnCancelMode(static_cast<CancelModeEvent*>(event));
}
void EventHandler::OnKeyEvent(KeyEvent* event) {
}
void EventHandler::OnMouseEvent(MouseEvent* event) {
}
void EventHandler::OnScrollEvent(ScrollEvent* event) {
}
void EventHandler::OnTouchEvent(TouchEvent* event) {
}
void EventHandler::OnGestureEvent(GestureEvent* event) {
}
void EventHandler::OnCancelMode(CancelModeEvent* event) {
}
} // namespace ui
// Copyright (c) 2012 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.
#ifndef UI_EVENTS_EVENT_HANDLER_H_
#define UI_EVENTS_EVENT_HANDLER_H_
#include <stack>
#include <vector>
#include "base/basictypes.h"
#include "ui/events/event_constants.h"
#include "ui/events/events_export.h"
namespace ui {
class CancelModeEvent;
class Event;
class EventDispatcher;
class EventTarget;
class GestureEvent;
class KeyEvent;
class MouseEvent;
class ScrollEvent;
class TouchEvent;
// Dispatches events to appropriate targets. The default implementations of
// all of the specific handlers (e.g. OnKeyEvent, OnMouseEvent) do nothing.
class EVENTS_EXPORT EventHandler {
public:
EventHandler();
virtual ~EventHandler();
// This is called for all events. The default implementation routes the event
// to one of the event-specific callbacks (OnKeyEvent, OnMouseEvent etc.). If
// this is overridden, then normally, the override should chain into the
// default implementation for un-handled events.
virtual void OnEvent(Event* event);
virtual void OnKeyEvent(KeyEvent* event);
virtual void OnMouseEvent(MouseEvent* event);
virtual void OnScrollEvent(ScrollEvent* event);
virtual void OnTouchEvent(TouchEvent* event);
virtual void OnGestureEvent(GestureEvent* event);
virtual void OnCancelMode(CancelModeEvent* event);
private:
friend class EventDispatcher;
// EventDispatcher pushes itself on the top of this stack while dispatching
// events to this then pops itself off when done.
std::stack<EventDispatcher*> dispatchers_;
DISALLOW_COPY_AND_ASSIGN(EventHandler);
};
typedef std::vector<EventHandler*> EventHandlerList;
} // namespace ui
#endif // UI_EVENTS_EVENT_HANDLER_H_
// Copyright 2013 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 "ui/events/event_processor.h"
#include "ui/events/event_target.h"
#include "ui/events/event_targeter.h"
namespace ui {
EventDispatchDetails EventProcessor::OnEventFromSource(Event* event) {
EventTarget* root = GetRootTarget();
CHECK(root);
EventTargeter* targeter = root->GetEventTargeter();
CHECK(targeter);
// If |event| is in the process of being dispatched or has already been
// dispatched, then dispatch a copy of the event instead.
bool dispatch_original_event = event->phase() == EP_PREDISPATCH;
Event* event_to_dispatch = event;
scoped_ptr<Event> event_copy;
if (!dispatch_original_event) {
event_copy = Event::Clone(*event);
event_to_dispatch = event_copy.get();
}
OnEventProcessingStarted(event_to_dispatch);
EventTarget* target = NULL;
if (!event_to_dispatch->handled())
target = targeter->FindTargetForEvent(root, event_to_dispatch);
EventDispatchDetails details;
while (target) {
details = DispatchEvent(target, event_to_dispatch);
if (!dispatch_original_event) {
if (event_to_dispatch->stopped_propagation())
event->StopPropagation();
else if (event_to_dispatch->handled())
event->SetHandled();
}
if (details.dispatcher_destroyed)
return details;
if (details.target_destroyed || event->handled())
break;
target = targeter->FindNextBestTarget(target, event_to_dispatch);
}
OnEventProcessingFinished(event);
return details;
}
void EventProcessor::OnEventProcessingStarted(Event* event) {
}
void EventProcessor::OnEventProcessingFinished(Event* event) {
}
} // namespace ui
// Copyright 2013 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.
#ifndef UI_EVENTS_EVENT_PROCESSOR_H_
#define UI_EVENTS_EVENT_PROCESSOR_H_
#include "ui/events/event_dispatcher.h"
#include "ui/events/event_source.h"
namespace ui {
// EventProcessor receives an event from an EventSource and dispatches it to a
// tree of EventTargets.
class EVENTS_EXPORT EventProcessor : public EventDispatcherDelegate {
public:
~EventProcessor() override {}
// Returns the root of the tree this event processor owns.
virtual EventTarget* GetRootTarget() = 0;
// Dispatches an event received from the EventSource to the tree of
// EventTargets (whose root is returned by GetRootTarget()). The co-ordinate
// space of the source must be the same as the root target, except that the
// target may have a high-dpi scale applied.
// TODO(tdanderson|sadrul): This is only virtual for testing purposes. It
// should not be virtual at all.
virtual EventDispatchDetails OnEventFromSource(Event* event)
WARN_UNUSED_RESULT;
protected:
// Invoked at the start of processing, before an EventTargeter is used to
// find the target of the event. If processing should not take place, marks
// |event| as handled. Otherwise updates |event| so that the targeter can
// operate correctly (e.g., it can be used to update the location of the
// event when dispatching from an EventSource in high-DPI) and updates any
// members in the event processor as necessary.
virtual void OnEventProcessingStarted(Event* event);
// Invoked when the processing of |event| has finished (i.e., when no further
// dispatching of |event| will be performed by this EventProcessor). Note
// that the last target to which |event| was dispatched may have been
// destroyed.
virtual void OnEventProcessingFinished(Event* event);
};
} // namespace ui
#endif // UI_EVENTS_EVENT_PROCESSOR_H_
此差异已折叠。
// 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.
#ifndef UI_EVENTS_EVENT_REWRITER_H_
#define UI_EVENTS_EVENT_REWRITER_H_
#include "base/memory/scoped_ptr.h"
#include "ui/events/events_export.h"
namespace ui {
class Event;
// Return status of EventRewriter operations; see that class below.
enum EventRewriteStatus {
// Nothing was done; no rewritten event returned. Pass the original
// event to later rewriters, or send it to the EventProcessor if this
// was the final rewriter.
EVENT_REWRITE_CONTINUE,
// The event has been rewritten. Send the rewritten event to the
// EventProcessor instead of the original event (without sending
// either to any later rewriters).
EVENT_REWRITE_REWRITTEN,
// The event should be discarded, neither passing it to any later
// rewriters nor sending it to the EventProcessor.
EVENT_REWRITE_DISCARD,
// The event has been rewritten. As for EVENT_REWRITE_REWRITTEN,
// send the rewritten event to the EventProcessor instead of the
// original event (without sending either to any later rewriters).
// In addition the rewriter has one or more additional new events
// to be retrieved using |NextDispatchEvent()| and sent to the
// EventProcessor.
EVENT_REWRITE_DISPATCH_ANOTHER,
};
// EventRewriter provides a mechanism for Events to be rewritten
// before being dispatched from EventSource to EventProcessor.
class EVENTS_EXPORT EventRewriter {
public:
virtual ~EventRewriter() {}
// Potentially rewrites (replaces) an event, or requests it be discarded.
// or discards an event. If the rewriter wants to rewrite an event, and
// dispatch another event once the rewritten event is dispatched, it should
// return EVENT_REWRITE_DISPATCH_ANOTHER, and return the next event to
// dispatch from |NextDispatchEvent()|.
virtual EventRewriteStatus RewriteEvent(
const Event& event,
scoped_ptr<Event>* rewritten_event) = 0;
// Supplies an additional event to be dispatched. It is only valid to
// call this after the immediately previous call to |RewriteEvent()|
// or |NextDispatchEvent()| has returned EVENT_REWRITE_DISPATCH_ANOTHER.
// Should only return either EVENT_REWRITE_REWRITTEN or
// EVENT_REWRITE_DISPATCH_ANOTHER; otherwise the previous call should not
// have returned EVENT_REWRITE_DISPATCH_ANOTHER.
virtual EventRewriteStatus NextDispatchEvent(
const Event& last_event,
scoped_ptr<Event>* new_event) = 0;
};
} // namespace ui
#endif // UI_EVENTS_EVENT_REWRITER_H_
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
jdduke@chromium.org
tdresser@chromium.org
此差异已折叠。
// 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 "ui/events/gesture_detection/gesture_config_helper.h"
#include "ui/gfx/screen.h"
namespace ui {
GestureProvider::Config DefaultGestureProviderConfig() {
GestureProvider::Config config;
config.display = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
return config;
}
} // namespace ui
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册