diff options
author | rjkroege@chromium.org <rjkroege@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-10 22:11:17 +0000 |
---|---|---|
committer | rjkroege@chromium.org <rjkroege@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-10 22:11:17 +0000 |
commit | ce83ede3e7f5176deca43bb2d83d07f77944ad02 (patch) | |
tree | 2b2b789f00e14d648d182ef77e2a94cf6edc9b91 /ui | |
parent | 374806bbff3c92885a11afc6520e3118faecff47 (diff) | |
download | chromium_src-ce83ede3e7f5176deca43bb2d83d07f77944ad02.zip chromium_src-ce83ede3e7f5176deca43bb2d83d07f77944ad02.tar.gz chromium_src-ce83ede3e7f5176deca43bb2d83d07f77944ad02.tar.bz2 |
Event handling support for ozone.
Basic framework for handling events in ozone. Touch events are
recognized and dispatched. Some button events are supported.
BUG=178543
R=sadrul@chromium.org, sky@chromium.org
Review URL: https://codereview.chromium.org/16466003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@205324 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r-- | ui/aura/root_window_host_ozone.cc | 7 | ||||
-rw-r--r-- | ui/aura/root_window_host_ozone.h | 3 | ||||
-rw-r--r-- | ui/base/ozone/event_converter_ozone.cc | 33 | ||||
-rw-r--r-- | ui/base/ozone/event_converter_ozone.h | 38 | ||||
-rw-r--r-- | ui/base/ozone/event_factory_ozone.cc | 66 | ||||
-rw-r--r-- | ui/base/ozone/event_factory_ozone.h | 35 | ||||
-rw-r--r-- | ui/base/ozone/events_ozone.cc | 84 | ||||
-rw-r--r-- | ui/base/ozone/key_event_converter_ozone.cc | 64 | ||||
-rw-r--r-- | ui/base/ozone/key_event_converter_ozone.h | 27 | ||||
-rw-r--r-- | ui/base/ozone/surface_factory_ozone.h | 7 | ||||
-rw-r--r-- | ui/base/ozone/touch_event_converter_ozone.cc | 181 | ||||
-rw-r--r-- | ui/base/ozone/touch_event_converter_ozone.h | 77 | ||||
-rw-r--r-- | ui/base/ozone/touch_event_converter_ozone_unittest.cc | 397 | ||||
-rw-r--r-- | ui/gl/gl_implementation_ozone.cc | 10 | ||||
-rw-r--r-- | ui/ui.gyp | 9 | ||||
-rw-r--r-- | ui/ui_unittests.gypi | 1 |
16 files changed, 1010 insertions, 29 deletions
diff --git a/ui/aura/root_window_host_ozone.cc b/ui/aura/root_window_host_ozone.cc index b822a84..2e046bc 100644 --- a/ui/aura/root_window_host_ozone.cc +++ b/ui/aura/root_window_host_ozone.cc @@ -105,13 +105,6 @@ bool RootWindowHostOzone::CopyAreaToSkCanvas(const gfx::Rect& source_bounds, return false; } -bool RootWindowHostOzone::GrabSnapshot( - const gfx::Rect& snapshot_bounds, - std::vector<unsigned char>* png_representation) { - NOTIMPLEMENTED(); - return false; -} - void RootWindowHostOzone::PostNativeEvent( const base::NativeEvent& native_event) { NOTIMPLEMENTED(); diff --git a/ui/aura/root_window_host_ozone.h b/ui/aura/root_window_host_ozone.h index 857d8c5..107f2bf 100644 --- a/ui/aura/root_window_host_ozone.h +++ b/ui/aura/root_window_host_ozone.h @@ -49,9 +49,6 @@ class RootWindowHostOzone : public RootWindowHost, virtual bool CopyAreaToSkCanvas(const gfx::Rect& source_bounds, const gfx::Point& dest_offset, SkCanvas* canvas) OVERRIDE; - virtual bool GrabSnapshot(const gfx::Rect& snapshot_bounds, - std::vector<unsigned char>* png_representation) - OVERRIDE; virtual void PostNativeEvent(const base::NativeEvent& event) OVERRIDE; virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE; virtual void PrepareForShutdown() OVERRIDE; diff --git a/ui/base/ozone/event_converter_ozone.cc b/ui/base/ozone/event_converter_ozone.cc new file mode 100644 index 0000000..0be5036 --- /dev/null +++ b/ui/base/ozone/event_converter_ozone.cc @@ -0,0 +1,33 @@ +// Copyright (c) 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/base/ozone/event_converter_ozone.h" + +#include "base/bind.h" +#include "base/message_loop.h" +#include "base/message_pump_ozone.h" +#include "ui/base/events/event.h" + +namespace { + +void DispatchEventHelper(scoped_ptr<ui::Event> key) { + base::MessagePumpOzone::Current()->Dispatch(key.get()); +} + +} // namespace + +namespace ui { + +EventConverterOzone::EventConverterOzone() { +} + +EventConverterOzone::~EventConverterOzone() { +} + +void EventConverterOzone::DispatchEvent(scoped_ptr<ui::Event> event) { + base::MessageLoop::current()->PostTask( + FROM_HERE, base::Bind(&DispatchEventHelper, base::Passed(&event))); +} + +} // namespace ui diff --git a/ui/base/ozone/event_converter_ozone.h b/ui/base/ozone/event_converter_ozone.h new file mode 100644 index 0000000..766b1df --- /dev/null +++ b/ui/base/ozone/event_converter_ozone.h @@ -0,0 +1,38 @@ +// Copyright (c) 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_BASE_OZONE_EVENT_CONVERTER_OZONE_H_ +#define UI_BASE_OZONE_EVENT_CONVERTER_OZONE_H_ + +#include "base/memory/scoped_ptr.h" +#include "base/message_pump_libevent.h" + +namespace ui { +class Event; + +// In ozone, Chrome reads events from file descriptors created from Linux device +// drivers. The |MessagePumpLibevent::Watcher| parent class provides the +// functionality to watch a file descriptor for the arrival of new data and +// notify its subclasses. Device-specific event converters turn bytes read from +// the file descriptor into |ui::Event| instances. This class provides the +// functionality needed in common across all converters: dispatching the +// |ui::Event| to aura. +class EventConverterOzone : public base::MessagePumpLibevent::Watcher { + public: + EventConverterOzone(); + virtual ~EventConverterOzone(); + + protected: + // Subclasses should use this method to post a task that will dispatch + // |event| from the UI message loop. This method takes ownership of + // |event|. |event| will be deleted at the end of the posted task. + void DispatchEvent(scoped_ptr<ui::Event> event); + + private: + DISALLOW_COPY_AND_ASSIGN(EventConverterOzone); +}; + +} // namespace ui + +#endif // UI_BASE_OZONE_EVENT_CONVERTER_OZONE_H_ diff --git a/ui/base/ozone/event_factory_ozone.cc b/ui/base/ozone/event_factory_ozone.cc new file mode 100644 index 0000000..3189f1d --- /dev/null +++ b/ui/base/ozone/event_factory_ozone.cc @@ -0,0 +1,66 @@ +// Copyright (c) 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/base/ozone/event_factory_ozone.h" + +#include <fcntl.h> +#include <linux/input.h> +#include <poll.h> +#include <unistd.h> + +#include "base/message_pump_ozone.h" +#include "base/stringprintf.h" +#include "ui/base/ozone/key_event_converter_ozone.h" +#include "ui/base/ozone/touch_event_converter_ozone.h" + +namespace ui { + +EventFactoryOzone::EventFactoryOzone() {} + +EventFactoryOzone::~EventFactoryOzone() { + for (unsigned i = 0; i < fd_controllers_.size(); i++) { + fd_controllers_[i]->StopWatchingFileDescriptor(); + } +} + +void EventFactoryOzone::CreateEvdevWatchers() { + // The number of devices in the directory is unknown without reading + // the contents of the directory. Further, with hot-plugging, the entries + // might decrease during the execution of this loop. So exciting from the + // loop on the first failure of open below is both cheaper and more + // reliable. + for (int id = 0; true; id++) { + std::string path = base::StringPrintf("/dev/input/event%d", id); + int fd = open(path.c_str(), O_RDONLY | O_NONBLOCK); + if (fd < 0) + break; + size_t evtype = 0; + COMPILE_ASSERT(sizeof(evtype) * 8 >= EV_MAX, evtype_wide_enough); + if (ioctl(fd, EVIOCGBIT(0, sizeof(evtype)), &evtype) == -1) { + DLOG(ERROR) << "failed ioctl EVIOCGBIT 0" << path; + close(fd); + continue; + } + + EventConverterOzone* watcher = NULL; + // TODO(rjkroege) Add more device types. Support hot-plugging. + if (evtype & (1 << EV_ABS)) + watcher = new TouchEventConverterOzone(fd, id); + else if (evtype & (1 << EV_KEY)) + watcher = new KeyEventConverterOzone(); + + if (watcher) { + base::MessagePumpLibevent::FileDescriptorWatcher* controller = + new base::MessagePumpLibevent::FileDescriptorWatcher(); + base::MessagePumpOzone::Current()->WatchFileDescriptor( + fd, true, base::MessagePumpLibevent::WATCH_READ, controller, watcher); + evdev_watchers_.push_back(watcher); + fd_controllers_.push_back(controller); + } else { + close(fd); + } + } +} + +} // namespace ui diff --git a/ui/base/ozone/event_factory_ozone.h b/ui/base/ozone/event_factory_ozone.h new file mode 100644 index 0000000..adf5b81 --- /dev/null +++ b/ui/base/ozone/event_factory_ozone.h @@ -0,0 +1,35 @@ +// Copyright (c) 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_BASE_OZONE_EVENT_FACTORY_OZONE_H_ +#define UI_BASE_OZONE_EVENT_FACTORY_OZONE_H_ + +#include "base/memory/scoped_vector.h" +#include "base/message_pump_libevent.h" +#include "ui/base/ozone/event_converter_ozone.h" +#include "ui/base/ui_export.h" + +namespace ui { + +// Sets up and manages watcher instances for event sources in /dev/input/*. +class UI_EXPORT EventFactoryOzone { + public: + EventFactoryOzone(); + virtual ~EventFactoryOzone(); + + // Opens /dev/input/* event sources as appropriate and set up watchers. + void CreateEvdevWatchers(); + + private: + // FileDescriptorWatcher instances for each watched source of events. + ScopedVector<EventConverterOzone> evdev_watchers_; + ScopedVector<base::MessagePumpLibevent::FileDescriptorWatcher> + fd_controllers_; + + DISALLOW_COPY_AND_ASSIGN(EventFactoryOzone); +}; + +} // namespace ui + +#endif // UI_BASE_OZONE_EVENT_FACTORY_OZONE_H_ diff --git a/ui/base/ozone/events_ozone.cc b/ui/base/ozone/events_ozone.cc index 8732ddb..f5481ce 100644 --- a/ui/base/ozone/events_ozone.cc +++ b/ui/base/ozone/events_ozone.cc @@ -1,4 +1,4 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright (c) 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. @@ -8,73 +8,93 @@ namespace ui { +void UpdateDeviceList() { NOTIMPLEMENTED(); } + base::TimeDelta EventTimeFromNative(const base::NativeEvent& native_event) { - ui::Event* event = static_cast<ui::Event*>(native_event); + const ui::Event* event = static_cast<const ui::Event*>(native_event); return event->time_stamp(); } int EventFlagsFromNative(const base::NativeEvent& native_event) { - ui::Event* event = static_cast<ui::Event*>(native_event); + const ui::Event* event = static_cast<const ui::Event*>(native_event); return event->flags(); } EventType EventTypeFromNative(const base::NativeEvent& native_event) { - ui::Event* event = static_cast<ui::Event*>(native_event); + const ui::Event* event = static_cast<const ui::Event*>(native_event); return event->type(); } +gfx::Point EventSystemLocationFromNative( + const base::NativeEvent& native_event) { + const ui::LocatedEvent* e = + static_cast<const ui::LocatedEvent*>(native_event); + DCHECK(e->IsMouseEvent() || e->IsTouchEvent() || e->IsGestureEvent() || + e->IsScrollEvent()); + return e->location(); +} + gfx::Point EventLocationFromNative(const base::NativeEvent& native_event) { - ui::LocatedEvent* event = static_cast<ui::LocatedEvent*>(native_event); - DCHECK(event->IsMouseEvent() || event->IsTouchEvent() || - event->IsGestureEvent() || event->IsScrollEvent()); - return event->location(); + return EventSystemLocationFromNative(native_event); } int GetChangedMouseButtonFlagsFromNative( const base::NativeEvent& native_event) { - ui::MouseEvent* event = static_cast<ui::MouseEvent*>(native_event); + const ui::MouseEvent* event = + static_cast<const ui::MouseEvent*>(native_event); DCHECK(event->IsMouseEvent()); return event->changed_button_flags(); } KeyboardCode KeyboardCodeFromNative(const base::NativeEvent& native_event) { - ui::KeyEvent* event = static_cast<ui::KeyEvent*>(native_event); + const ui::KeyEvent* event = static_cast<const ui::KeyEvent*>(native_event); DCHECK(event->IsKeyEvent()); return event->key_code(); } +bool IsMouseEvent(const base::NativeEvent& native_event) { + const ui::Event* e = static_cast<const ui::Event*>(native_event); + return e->IsMouseEvent(); +} + gfx::Vector2d GetMouseWheelOffset(const base::NativeEvent& native_event) { - ui::MouseWheelEvent* event = static_cast<ui::MouseWheelEvent*>(native_event); + const ui::MouseWheelEvent* event = + static_cast<const ui::MouseWheelEvent*>(native_event); DCHECK(event->type() == ET_MOUSEWHEEL); return event->offset(); } int GetTouchId(const base::NativeEvent& native_event) { - ui::TouchEvent* event = static_cast<ui::TouchEvent*>(native_event); + const ui::TouchEvent* event = + static_cast<const ui::TouchEvent*>(native_event); DCHECK(event->IsTouchEvent()); return event->touch_id(); } float GetTouchRadiusX(const base::NativeEvent& native_event) { - ui::TouchEvent* event = static_cast<ui::TouchEvent*>(native_event); + const ui::TouchEvent* event = + static_cast<const ui::TouchEvent*>(native_event); DCHECK(event->IsTouchEvent()); return event->radius_x(); } float GetTouchRadiusY(const base::NativeEvent& native_event) { - ui::TouchEvent* event = static_cast<ui::TouchEvent*>(native_event); + const ui::TouchEvent* event = + static_cast<const ui::TouchEvent*>(native_event); DCHECK(event->IsTouchEvent()); return event->radius_y(); } float GetTouchAngle(const base::NativeEvent& native_event) { - ui::TouchEvent* event = static_cast<ui::TouchEvent*>(native_event); + const ui::TouchEvent* event = + static_cast<const ui::TouchEvent*>(native_event); DCHECK(event->IsTouchEvent()); return event->rotation_angle(); } float GetTouchForce(const base::NativeEvent& native_event) { - ui::TouchEvent* event = static_cast<ui::TouchEvent*>(native_event); + const ui::TouchEvent* event = + static_cast<const ui::TouchEvent*>(native_event); DCHECK(event->IsTouchEvent()); return event->force(); } @@ -99,4 +119,36 @@ bool GetFlingData(const base::NativeEvent& native_event, return false; } +bool GetGestureTimes(const base::NativeEvent& native_event, + double* start_time, + double* end_time) { + *start_time = 0; + *end_time = 0; + return false; +} + +void SetNaturalScroll(bool /* enabled */) { NOTIMPLEMENTED(); } + +bool IsNaturalScrollEnabled() { return false; } + +bool IsTouchpadEvent(const base::NativeEvent& event) { + NOTIMPLEMENTED(); + return false; +} + +bool IsNoopEvent(const base::NativeEvent& event) { + NOTIMPLEMENTED(); + return false; +} + +base::NativeEvent CreateNoopEvent() { + NOTIMPLEMENTED(); + return NULL; +} + +int GetModifiersFromKeyState() { + NOTIMPLEMENTED(); + return 0; +} + } // namespace ui diff --git a/ui/base/ozone/key_event_converter_ozone.cc b/ui/base/ozone/key_event_converter_ozone.cc new file mode 100644 index 0000000..f4ff3db --- /dev/null +++ b/ui/base/ozone/key_event_converter_ozone.cc @@ -0,0 +1,64 @@ +// Copyright (c) 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/base/ozone/key_event_converter_ozone.h" + +#include <linux/input.h> + +#include "ui/base/events/event.h" +#include "ui/base/keycodes/keyboard_codes.h" + +namespace { + +ui::KeyboardCode KeyboardCodeFromButton(int code) { + switch (code) { + case KEY_VOLUMEDOWN: + return ui::VKEY_VOLUME_DOWN; + + case KEY_VOLUMEUP: + return ui::VKEY_VOLUME_UP; + + case KEY_POWER: + return ui::VKEY_POWER; + } + + LOG(ERROR) << "Unknown key code: " << code; + return static_cast<ui::KeyboardCode>(0); +} + +} // namespace + +namespace ui { + +// TODO(rjkroege): Stop leaking file descriptor. +KeyEventConverterOzone::KeyEventConverterOzone() {} +KeyEventConverterOzone::~KeyEventConverterOzone() {} + +void KeyEventConverterOzone::OnFileCanReadWithoutBlocking(int fd) { + input_event inputs[4]; + ssize_t read_size = read(fd, inputs, sizeof(inputs)); + if (read_size <= 0) + return; + + CHECK_EQ(read_size % sizeof(*inputs), 0u); + for (unsigned i = 0; i < read_size / sizeof(*inputs); ++i) { + const input_event& input = inputs[i]; + if (input.type == EV_KEY) { + scoped_ptr<KeyEvent> key( + new KeyEvent(input.value == 1 ? ET_KEY_PRESSED : ET_KEY_RELEASED, + KeyboardCodeFromButton(input.code), + 0, + true)); + DispatchEvent(key.PassAs<ui::Event>()); + } else if (input.type == EV_SYN) { + // TODO(sadrul): Handle this case appropriately. + } + } +} + +void KeyEventConverterOzone::OnFileCanWriteWithoutBlocking(int fd) { + NOTREACHED(); +} + +} // namespace ui diff --git a/ui/base/ozone/key_event_converter_ozone.h b/ui/base/ozone/key_event_converter_ozone.h new file mode 100644 index 0000000..29ea26a --- /dev/null +++ b/ui/base/ozone/key_event_converter_ozone.h @@ -0,0 +1,27 @@ +// Copyright (c) 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_BASE_OZONE_KEY_EVENT_CONVERTER_OZONE_H_ +#define UI_BASE_OZONE_KEY_EVENT_CONVERTER_OZONE_H_ + +#include "ui/base/ozone/event_converter_ozone.h" + +namespace ui { + +class KeyEventConverterOzone : public EventConverterOzone { + public: + KeyEventConverterOzone(); + virtual ~KeyEventConverterOzone(); + + private: + // Overidden from base::MessagePumpLibevent::Watcher. + virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE; + virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE; + + DISALLOW_COPY_AND_ASSIGN(KeyEventConverterOzone); +}; + +} // namspace ui + +#endif // UI_BASE_OZONE_KEY_EVENT_CONVERTER_OZONE_H_ diff --git a/ui/base/ozone/surface_factory_ozone.h b/ui/base/ozone/surface_factory_ozone.h index c9c3351..bd22d35 100644 --- a/ui/base/ozone/surface_factory_ozone.h +++ b/ui/base/ozone/surface_factory_ozone.h @@ -5,7 +5,8 @@ #ifndef UI_BASE_OZONE_SURFACE_LNUX_FACTORY_OZONE_H_ #define UI_BASE_OZONE_SURFACE_LNUX_FACTORY_OZONE_H_ -#include "ui/gfx/native_widget_types.h" +#include "ui/base/ui_export.h" +#include "ui/gfx/native_widget_types.h" namespace gfx { class VSyncProvider; @@ -19,14 +20,14 @@ class SurfaceFactoryOzone { virtual ~SurfaceFactoryOzone(); // Returns the instance - static SurfaceFactoryOzone* GetInstance(); + UI_EXPORT static SurfaceFactoryOzone* GetInstance(); // Returns a display spec as in |CreateDisplayFromSpec| for the default // native surface. virtual const char* DefaultDisplaySpec(); // Sets the implementation delegate. - static void SetInstance(SurfaceFactoryOzone* impl); + UI_EXPORT static void SetInstance(SurfaceFactoryOzone* impl); // TODO(rjkroege): Add a status code if necessary. // Configures the display hardware. Must be called from within the GPU diff --git a/ui/base/ozone/touch_event_converter_ozone.cc b/ui/base/ozone/touch_event_converter_ozone.cc new file mode 100644 index 0000000..0784fb4 --- /dev/null +++ b/ui/base/ozone/touch_event_converter_ozone.cc @@ -0,0 +1,181 @@ +// Copyright (c) 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/base/ozone/touch_event_converter_ozone.h" + +#include <fcntl.h> +#include <linux/input.h> +#include <poll.h> +#include <stdio.h> +#include <unistd.h> + +#include <cmath> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/logging.h" +#include "base/message_loop.h" +#include "base/message_pump_ozone.h" +#include "ui/base/events/event.h" +#include "ui/base/events/event_constants.h" +#include "ui/base/ozone/surface_factory_ozone.h" + +namespace { + +// Number is determined empirically. +// TODO(rjkroege): Configure this per device. +const float kFingerWidth = 25.f; + +} // namespace + +namespace ui { + +TouchEventConverterOzone::TouchEventConverterOzone(int fd, int id) + : pressure_min_(0), + pressure_max_(0), + x_scale_(1.), + y_scale_(1.), + current_slot_(0), + fd_(fd), + id_(id) { + Init(); +} + +TouchEventConverterOzone::~TouchEventConverterOzone() { + if (close(fd_) < 0) + DLOG(WARNING) << "failed close on /dev/input/event" << id_; +} + +void TouchEventConverterOzone::Init() { + input_absinfo abs = {}; + if (ioctl(fd_, EVIOCGABS(ABS_MT_SLOT), &abs) != -1) { + CHECK_GE(abs.maximum, abs.minimum); + CHECK_GE(abs.minimum, 0); + } else { + DLOG(WARNING) << "failed ioctl EVIOCGABS ABS_MT_SLOT event" << id_; + } + if (ioctl(fd_, EVIOCGABS(ABS_MT_PRESSURE), &abs) != -1) { + pressure_min_ = abs.minimum; + pressure_max_ = abs.maximum; + } else { + DLOG(WARNING) << "failed ioctl EVIOCGABS ABS_MT_PRESSURE event" << id_; + } + int x_min = 0, x_max = 0; + if (ioctl(fd_, EVIOCGABS(ABS_MT_POSITION_X), &abs) != -1) { + x_min = abs.minimum; + x_max = abs.maximum; + } else { + LOG(WARNING) << "failed ioctl EVIOCGABS ABS_X event" << id_; + } + int y_min = 0, y_max = 0; + if (ioctl(fd_, EVIOCGABS(ABS_MT_POSITION_Y), &abs) != -1) { + y_min = abs.minimum; + y_max = abs.maximum; + } else { + LOG(WARNING) << "failed ioctl EVIOCGABS ABS_Y event" << id_; + } + if (x_max && y_max && SurfaceFactoryOzone::GetInstance()) { + const char* display = + SurfaceFactoryOzone::GetInstance()->DefaultDisplaySpec(); + int screen_width, screen_height; + int sc = sscanf(display, "%dx%d", &screen_width, &screen_height); + if (sc == 2) { + x_scale_ = (double)screen_width / (x_max - x_min); + y_scale_ = (double)screen_height / (y_max - y_min); + LOG(INFO) << "touch input x_scale=" << x_scale_ + << " y_scale=" << y_scale_; + } else { + LOG(WARNING) << "malformed display spec from " + << "SurfaceFactoryOzone::DefaultDisplaySpec"; + } + } +} + +void TouchEventConverterOzone::OnFileCanWriteWithoutBlocking(int /* fd */) { + // Read-only file-descriptors. + NOTREACHED(); +} + +void TouchEventConverterOzone::OnFileCanReadWithoutBlocking(int fd) { + input_event inputs[MAX_FINGERS * 6 + 1]; + ssize_t read_size = read(fd, inputs, sizeof(inputs)); + if (read_size <= 0) + return; + + for (unsigned i = 0; i < read_size / sizeof(*inputs); i++) { + const input_event& input = inputs[i]; + if (input.type == EV_ABS) { + switch (input.code) { + case ABS_MT_TOUCH_MAJOR: + altered_slots_.set(current_slot_); + events_[current_slot_].major_ = input.value; + break; + case ABS_X: + case ABS_MT_POSITION_X: + altered_slots_.set(current_slot_); + events_[current_slot_].x_ = roundf(input.value * x_scale_); + break; + case ABS_Y: + case ABS_MT_POSITION_Y: + altered_slots_.set(current_slot_); + events_[current_slot_].y_ = roundf(input.value * y_scale_); + break; + case ABS_MT_TRACKING_ID: + altered_slots_.set(current_slot_); + if (input.value < 0) { + events_[current_slot_].type_ = ET_TOUCH_RELEASED; + } else { + events_[current_slot_].finger_ = input.value; + events_[current_slot_].type_ = ET_TOUCH_PRESSED; + } + break; + case ABS_MT_PRESSURE: + case ABS_PRESSURE: + altered_slots_.set(current_slot_); + events_[current_slot_].pressure_ = input.value - pressure_min_; + events_[current_slot_].pressure_ /= pressure_max_ - pressure_min_; + break; + case ABS_MT_SLOT: + current_slot_ = input.value; + altered_slots_.set(current_slot_); + break; + default: + NOTREACHED(); + } + } else if (input.type == EV_SYN) { + switch (input.code) { + case SYN_REPORT: + for (int j = 0; j < MAX_FINGERS; j++) { + if (altered_slots_[j]) { + // TODO(rjkroege): Support elliptical finger regions. + scoped_ptr<TouchEvent> tev(new TouchEvent( + events_[j].type_, + gfx::Point(events_[j].x_, events_[j].y_), + /* flags */ 0, + /* touch_id */ j, + base::TimeDelta::FromMicroseconds( + input.time.tv_sec * 1000000 + input.time.tv_usec), + events_[j].pressure_ * kFingerWidth, + events_[j].pressure_ * kFingerWidth, + /* angle */ 0., + events_[j].pressure_)); + events_[j].type_ = ET_TOUCH_MOVED; + DispatchEvent(tev.PassAs<ui::Event>()); + } + } + altered_slots_.reset(); + break; + case SYN_MT_REPORT: + case SYN_CONFIG: + case SYN_DROPPED: + NOTREACHED() << "SYN_MT events not supported."; + break; + } + } else { + NOTREACHED(); + } + } +} + +} // namespace ui diff --git a/ui/base/ozone/touch_event_converter_ozone.h b/ui/base/ozone/touch_event_converter_ozone.h new file mode 100644 index 0000000..f246b5c --- /dev/null +++ b/ui/base/ozone/touch_event_converter_ozone.h @@ -0,0 +1,77 @@ +// Copyright (c) 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_BASE_OZONE_TOUCH_EVENT_CONVERTER_OZONE_H_ +#define UI_BASE_OZONE_TOUCH_EVENT_CONVERTER_OZONE_H_ + +#include <bitset> + +#include "base/compiler_specific.h" +#include "ui/base/events/event_constants.h" +#include "ui/base/ozone/event_converter_ozone.h" +#include "ui/base/ui_export.h" + +namespace ui { + +class TouchEvent; + +class UI_EXPORT TouchEventConverterOzone : public EventConverterOzone { + public: + enum { + MAX_FINGERS = 11 + }; + TouchEventConverterOzone(int fd, int id); + virtual ~TouchEventConverterOzone(); + + private: + friend class MockTouchEventConverterOzone; + + // Unsafe part of initialization. + void Init(); + + // Overidden from base::MessagePumpLibevent::Watcher. + virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE; + virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE; + + // Pressure values. + int pressure_min_; + int pressure_max_; // Used to normalize pressure values. + + // Touch scaling. + float x_scale_; + float y_scale_; + + // Touch point currently being updated from the /dev/input/event* stream. + int current_slot_; + + // File descriptor for the /dev/input/event* instance. + int fd_; + + // Number corresponding to * in the source evdev device: /dev/input/event* + int id_; + + // Bit field tracking which in-progress touch points have been modified + // without a syn event. + std::bitset<MAX_FINGERS> altered_slots_; + + struct InProgressEvents { + int x_; + int y_; + int id_; // Device reported "unique" touch point id; -1 means not active + int finger_; // "Finger" id starting from 0; -1 means not active + + EventType type_; + int major_; + float pressure_; + }; + + // In-progress touch points. + InProgressEvents events_[MAX_FINGERS]; + + DISALLOW_COPY_AND_ASSIGN(TouchEventConverterOzone); +}; + +} // namespace ui + +#endif // UI_BASE_OZONE_TOUCH_EVENT_CONVERTER_OZONE_H_ diff --git a/ui/base/ozone/touch_event_converter_ozone_unittest.cc b/ui/base/ozone/touch_event_converter_ozone_unittest.cc new file mode 100644 index 0000000..88194df --- /dev/null +++ b/ui/base/ozone/touch_event_converter_ozone_unittest.cc @@ -0,0 +1,397 @@ +// Copyright (c) 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 <errno.h> +#include <fcntl.h> +#include <linux/input.h> +#include <unistd.h> + +#include <vector> + +#include "base/memory/scoped_ptr.h" +#include "base/memory/scoped_vector.h" +#include "base/message_loop.h" +#include "base/posix/eintr_wrapper.h" +#include "base/run_loop.h" +#include "base/time.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/events/event.h" +#include "ui/base/ozone/touch_event_converter_ozone.h" + + +namespace { + +static int SetNonBlocking(int fd) { + int flags = fcntl(fd, F_GETFL, 0); + if (flags == -1) + flags = 0; + return fcntl(fd, F_SETFL, flags | O_NONBLOCK); +} + +} // namespace + +namespace ui { + +class MockTouchEventConverterOzone : public TouchEventConverterOzone, + public base::MessageLoop::Dispatcher { + public: + MockTouchEventConverterOzone(int a, int b); + virtual ~MockTouchEventConverterOzone() {}; + + void ConfigureReadMock(struct input_event* queue, + long read_this_many, + long queue_index); + + unsigned size() { return dispatched_events_.size(); } + TouchEvent* event(unsigned index) { return dispatched_events_[index]; } + + // Actually dispatch the event reader code. + void ReadNow() { + OnFileCanReadWithoutBlocking(read_pipe_); + base::RunLoop().RunUntilIdle(); + } + + virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE; + + private: + int read_pipe_; + int write_pipe_; + + ScopedVector<TouchEvent> dispatched_events_; + + DISALLOW_COPY_AND_ASSIGN(MockTouchEventConverterOzone); +}; + +MockTouchEventConverterOzone::MockTouchEventConverterOzone(int a, int b) + : TouchEventConverterOzone(a, b) { + pressure_min_ = 30; + pressure_max_ = 60; + + int fds[2]; + + DCHECK(pipe(fds) >= 0) << "pipe() failed, errno: " << errno; + DCHECK(SetNonBlocking(fds[0]) == 0) + << "SetNonBlocking for pipe fd[0] failed, errno: " << errno; + DCHECK(SetNonBlocking(fds[1]) == 0) + << "SetNonBlocking for pipe fd[0] failed, errno: " << errno; + read_pipe_ = fds[0]; + write_pipe_ = fds[1]; +} + +bool MockTouchEventConverterOzone::Dispatch(const base::NativeEvent& event) { + ui::TouchEvent* ev = new ui::TouchEvent(event); + dispatched_events_.push_back(ev); + return true; +} + +void MockTouchEventConverterOzone::ConfigureReadMock(struct input_event* queue, + long read_this_many, + long queue_index) { + int nwrite = HANDLE_EINTR(write(write_pipe_, + queue + queue_index, + sizeof(struct input_event) * read_this_many)); + DCHECK(nwrite == + static_cast<int>(sizeof(struct input_event) * read_this_many)) + << "write() failed, errno: " << errno; +} + +} // namespace ui + +// Test fixture. +class TouchEventConverterOzoneTest : public testing::Test { + public: + TouchEventConverterOzoneTest() {} + + // Overridden from testing::Test: + virtual void SetUp() OVERRIDE { + loop_ = new base::MessageLoop(base::MessageLoop::TYPE_UI); + device_ = new ui::MockTouchEventConverterOzone(-1, 2); + base::MessagePumpOzone::Current()->AddDispatcherForRootWindow(device_); + } + virtual void TearDown() OVERRIDE { + delete device_; + delete loop_; + } + + ui::MockTouchEventConverterOzone* device() { return device_; } + + private: + base::MessageLoop* loop_; + ui::MockTouchEventConverterOzone* device_; + DISALLOW_COPY_AND_ASSIGN(TouchEventConverterOzoneTest); +}; + +// TODO(rjkroege): Test for valid handling of time stamps. +TEST_F(TouchEventConverterOzoneTest, TouchDown) { + ui::MockTouchEventConverterOzone* dev = device(); + + struct input_event mock_kernel_queue[] = { + {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684}, + {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3}, + {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45}, + {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42}, + {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0} + }; + + dev->ConfigureReadMock(mock_kernel_queue, 1, 0); + dev->ReadNow(); + EXPECT_EQ(0u, dev->size()); + + dev->ConfigureReadMock(mock_kernel_queue, 2, 1); + dev->ReadNow(); + EXPECT_EQ(0u, dev->size()); + + dev->ConfigureReadMock(mock_kernel_queue, 3, 3); + dev->ReadNow(); + EXPECT_EQ(1u, dev->size()); + + ui::TouchEvent* event = dev->event(0); + EXPECT_FALSE(event == NULL); + + EXPECT_EQ(ui::ET_TOUCH_PRESSED, event->type()); + EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp()); + EXPECT_EQ(42, event->x()); + EXPECT_EQ(51, event->y()); + EXPECT_EQ(0, event->touch_id()); + EXPECT_FLOAT_EQ(.5f, event->force()); + EXPECT_FLOAT_EQ(0.f, event->rotation_angle()); +} + +TEST_F(TouchEventConverterOzoneTest, NoEvents) { + ui::MockTouchEventConverterOzone* dev = device(); + dev->ConfigureReadMock(NULL, 0, 0); + EXPECT_EQ(0u, dev->size()); +} + +TEST_F(TouchEventConverterOzoneTest, TouchMove) { + ui::MockTouchEventConverterOzone* dev = device(); + + struct input_event mock_kernel_queue_press[] = { + {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684}, + {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3}, + {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45}, + {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42}, + {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0} + }; + + struct input_event mock_kernel_queue_move1[] = { + {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 50}, + {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42}, + {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 43}, {{0, 0}, EV_SYN, SYN_REPORT, 0} + }; + + struct input_event mock_kernel_queue_move2[] = { + {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 42}, {{0, 0}, EV_SYN, SYN_REPORT, 0} + }; + + // Setup and discard a press. + dev->ConfigureReadMock(mock_kernel_queue_press, 6, 0); + dev->ReadNow(); + EXPECT_EQ(1u, dev->size()); + + dev->ConfigureReadMock(mock_kernel_queue_move1, 4, 0); + dev->ReadNow(); + EXPECT_EQ(2u, dev->size()); + ui::TouchEvent* event = dev->event(1); + EXPECT_FALSE(event == NULL); + + EXPECT_EQ(ui::ET_TOUCH_MOVED, event->type()); + EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp()); + EXPECT_EQ(42, event->x()); + EXPECT_EQ(43, event->y()); + EXPECT_EQ(0, event->touch_id()); + EXPECT_FLOAT_EQ(2.f / 3.f, event->force()); + EXPECT_FLOAT_EQ(0.f, event->rotation_angle()); + + dev->ConfigureReadMock(mock_kernel_queue_move2, 2, 0); + dev->ReadNow(); + EXPECT_EQ(3u, dev->size()); + event = dev->event(2); + EXPECT_FALSE(event == NULL); + + EXPECT_EQ(ui::ET_TOUCH_MOVED, event->type()); + EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp()); + EXPECT_EQ(42, event->x()); + EXPECT_EQ(42, event->y()); + EXPECT_EQ(0, event->touch_id()); + EXPECT_FLOAT_EQ(2.f / 3.f, event->force()); + EXPECT_FLOAT_EQ(0.f, event->rotation_angle()); +} + +TEST_F(TouchEventConverterOzoneTest, TouchRelease) { + ui::MockTouchEventConverterOzone* dev = device(); + + struct input_event mock_kernel_queue_press[] = { + {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684}, + {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3}, + {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45}, + {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42}, + {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0} + }; + + struct input_event mock_kernel_queue_release[] = { + {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, -1}, {{0, 0}, EV_SYN, SYN_REPORT, 0} + }; + + // Setup and discard a press. + dev->ConfigureReadMock(mock_kernel_queue_press, 6, 0); + dev->ReadNow(); + EXPECT_EQ(1u, dev->size()); + ui::TouchEvent* event = dev->event(0); + EXPECT_FALSE(event == NULL); + + dev->ConfigureReadMock(mock_kernel_queue_release, 2, 0); + dev->ReadNow(); + EXPECT_EQ(2u, dev->size()); + event = dev->event(1); + EXPECT_FALSE(event == NULL); + + EXPECT_EQ(ui::ET_TOUCH_RELEASED, event->type()); + EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp()); + EXPECT_EQ(42, event->x()); + EXPECT_EQ(51, event->y()); + EXPECT_EQ(0, event->touch_id()); + EXPECT_FLOAT_EQ(.5f, event->force()); + EXPECT_FLOAT_EQ(0.f, event->rotation_angle()); +} + +TEST_F(TouchEventConverterOzoneTest, TwoFingerGesture) { + ui::MockTouchEventConverterOzone* dev = device(); + + ui::TouchEvent* ev0; + ui::TouchEvent* ev1; + + struct input_event mock_kernel_queue_press0[] = { + {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684}, + {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3}, + {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45}, + {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 42}, + {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51}, {{0, 0}, EV_SYN, SYN_REPORT, 0} + }; + // Setup and discard a press. + dev->ConfigureReadMock(mock_kernel_queue_press0, 6, 0); + dev->ReadNow(); + EXPECT_EQ(1u, dev->size()); + + struct input_event mock_kernel_queue_move0[] = { + {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 40}, {{0, 0}, EV_SYN, SYN_REPORT, 0} + }; + // Setup and discard a move. + dev->ConfigureReadMock(mock_kernel_queue_move0, 2, 0); + dev->ReadNow(); + EXPECT_EQ(2u, dev->size()); + + struct input_event mock_kernel_queue_move0press1[] = { + {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 40}, {{0, 0}, EV_SYN, SYN_REPORT, 0}, + {{0, 0}, EV_ABS, ABS_MT_SLOT, 1}, {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 686}, + {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3}, + {{0, 0}, EV_ABS, ABS_MT_PRESSURE, 45}, + {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 101}, + {{0, 0}, EV_ABS, ABS_MT_POSITION_Y, 102}, {{0, 0}, EV_SYN, SYN_REPORT, 0} + }; + // Move on 0, press on 1. + dev->ConfigureReadMock(mock_kernel_queue_move0press1, 9, 0); + dev->ReadNow(); + EXPECT_EQ(4u, dev->size()); + ev0 = dev->event(2); + ev1 = dev->event(3); + + // Move + EXPECT_EQ(ui::ET_TOUCH_MOVED, ev0->type()); + EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0->time_stamp()); + EXPECT_EQ(40, ev0->x()); + EXPECT_EQ(51, ev0->y()); + EXPECT_EQ(0, ev0->touch_id()); + EXPECT_FLOAT_EQ(.5f, ev0->force()); + EXPECT_FLOAT_EQ(0.f, ev0->rotation_angle()); + + // Press + EXPECT_EQ(ui::ET_TOUCH_PRESSED, ev1->type()); + EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp()); + EXPECT_EQ(101, ev1->x()); + EXPECT_EQ(102, ev1->y()); + EXPECT_EQ(1, ev1->touch_id()); + EXPECT_FLOAT_EQ(.5f, ev1->force()); + EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle()); + + // Stationary 0, Moves 1. + struct input_event mock_kernel_queue_stationary0_move1[] = { + {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 40}, {{0, 0}, EV_SYN, SYN_REPORT, 0} + }; + dev->ConfigureReadMock(mock_kernel_queue_stationary0_move1, 2, 0); + dev->ReadNow(); + EXPECT_EQ(5u, dev->size()); + ev1 = dev->event(4); + + EXPECT_EQ(ui::ET_TOUCH_MOVED, ev1->type()); + EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp()); + EXPECT_EQ(40, ev1->x()); + EXPECT_EQ(102, ev1->y()); + EXPECT_EQ(1, ev1->touch_id()); + + EXPECT_FLOAT_EQ(.5f, ev1->force()); + EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle()); + + // Move 0, stationary 1. + struct input_event mock_kernel_queue_move0_stationary1[] = { + {{0, 0}, EV_ABS, ABS_MT_SLOT, 0}, {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 39}, + {{0, 0}, EV_SYN, SYN_REPORT, 0} + }; + dev->ConfigureReadMock(mock_kernel_queue_move0_stationary1, 3, 0); + dev->ReadNow(); + EXPECT_EQ(6u, dev->size()); + ev0 = dev->event(5); + + EXPECT_EQ(ui::ET_TOUCH_MOVED, ev0->type()); + EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0->time_stamp()); + EXPECT_EQ(39, ev0->x()); + EXPECT_EQ(51, ev0->y()); + EXPECT_EQ(0, ev0->touch_id()); + EXPECT_FLOAT_EQ(.5f, ev0->force()); + EXPECT_FLOAT_EQ(0.f, ev0->rotation_angle()); + + // Release 0, move 1. + struct input_event mock_kernel_queue_release0_move1[] = { + {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, -1}, {{0, 0}, EV_ABS, ABS_MT_SLOT, 1}, + {{0, 0}, EV_ABS, ABS_MT_POSITION_X, 38}, {{0, 0}, EV_SYN, SYN_REPORT, 0} + }; + dev->ConfigureReadMock(mock_kernel_queue_release0_move1, 4, 0); + dev->ReadNow(); + EXPECT_EQ(8u, dev->size()); + ev0 = dev->event(6); + ev1 = dev->event(7); + + EXPECT_EQ(ui::ET_TOUCH_RELEASED, ev0->type()); + EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0->time_stamp()); + EXPECT_EQ(39, ev0->x()); + EXPECT_EQ(51, ev0->y()); + EXPECT_EQ(0, ev0->touch_id()); + EXPECT_FLOAT_EQ(.5f, ev0->force()); + EXPECT_FLOAT_EQ(0.f, ev0->rotation_angle()); + + EXPECT_EQ(ui::ET_TOUCH_MOVED, ev1->type()); + EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp()); + EXPECT_EQ(38, ev1->x()); + EXPECT_EQ(102, ev1->y()); + EXPECT_EQ(1, ev1->touch_id()); + EXPECT_FLOAT_EQ(.5f, ev1->force()); + EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle()); + + // Release 1. + struct input_event mock_kernel_queue_release1[] = { + {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, -1}, {{0, 0}, EV_SYN, SYN_REPORT, 0}, + }; + dev->ConfigureReadMock(mock_kernel_queue_release1, 2, 0); + dev->ReadNow(); + EXPECT_EQ(9u, dev->size()); + ev1 = dev->event(8); + + EXPECT_EQ(ui::ET_TOUCH_RELEASED, ev1->type()); + EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp()); + EXPECT_EQ(38, ev1->x()); + EXPECT_EQ(102, ev1->y()); + EXPECT_EQ(1, ev1->touch_id()); + EXPECT_FLOAT_EQ(.5f, ev1->force()); + EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle()); +} diff --git a/ui/gl/gl_implementation_ozone.cc b/ui/gl/gl_implementation_ozone.cc index b3bdfc9..481a309 100644 --- a/ui/gl/gl_implementation_ozone.cc +++ b/ui/gl/gl_implementation_ozone.cc @@ -96,4 +96,14 @@ void ClearGLBindings() { UnloadGLNativeLibraries(); } +bool GetGLWindowSystemBindingInfo(GLWindowSystemBindingInfo* info) { + switch (GetGLImplementation()) { + case kGLImplementationEGLGLES2: + return GetGLWindowSystemBindingInfoEGL(info); + default: + return false; + } + return false; +} + } // namespace gfx @@ -279,8 +279,17 @@ 'base/models/tree_node_iterator.h', 'base/models/tree_node_model.h', 'base/ozone/events_ozone.cc', + 'base/ozone/event_factory_ozone.cc', + 'base/ozone/event_factory_ozone.h', + 'base/ozone/event_converter_ozone.cc', + 'base/ozone/event_converter_ozone.h', + 'base/ozone/events_ozone.cc', + 'base/ozone/key_event_converter_ozone.cc', + 'base/ozone/key_event_converter_ozone.h', 'base/ozone/surface_factory_ozone.cc', 'base/ozone/surface_factory_ozone.h', + 'base/ozone/touch_event_converter_ozone.cc', + 'base/ozone/touch_event_converter_ozone.h', 'base/range/range.cc', 'base/range/range.h', 'base/range/range_mac.mm', diff --git a/ui/ui_unittests.gypi b/ui/ui_unittests.gypi index 30a16dc..2d1e78c 100644 --- a/ui/ui_unittests.gypi +++ b/ui/ui_unittests.gypi @@ -152,6 +152,7 @@ 'base/models/list_model_unittest.cc', 'base/models/list_selection_model_unittest.cc', 'base/models/tree_node_model_unittest.cc', + 'base/ozone/touch_event_converter_ozone_unittest.cc', 'base/test/data/resource.h', 'base/text/bytes_formatting_unittest.cc', 'base/text/utf16_indexing_unittest.cc', |