diff options
author | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-17 16:06:35 +0000 |
---|---|---|
committer | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-17 16:06:35 +0000 |
commit | 5951806fdc9a6d3063014b0479307dba66767f97 (patch) | |
tree | 1b52d819db6119600bcaeab8f51ccc3a3d48c925 | |
parent | b5ad6bd0e8eda70dc4f3b1dbd6229f9d82cdb17b (diff) | |
download | chromium_src-5951806fdc9a6d3063014b0479307dba66767f97.zip chromium_src-5951806fdc9a6d3063014b0479307dba66767f97.tar.gz chromium_src-5951806fdc9a6d3063014b0479307dba66767f97.tar.bz2 |
aura: Add support for touch events.
Among the changes:
. Add touch event handling in EventFilter. Be default, activates a window on TOUCH_START (like for MOUSE_PRESSED).
. Move TouchEvent details functions into ui/. Moved the X11 implementations from views/ to ui/. NOTIMPLEMENTED on windows.
. Disable RWHVAura et. al. for touchui for now (they are still compiled in, but not used).
BUG=100269
TEST=none
Review URL: http://codereview.chromium.org/8274025
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@105816 0039d316-1c4b-4281-b951-d872f2087c98
31 files changed, 460 insertions, 82 deletions
diff --git a/chrome/browser/ui/views/tab_contents/native_tab_contents_view_aura.cc b/chrome/browser/ui/views/tab_contents/native_tab_contents_view_aura.cc index 1b9cd54..b7dd70b 100644 --- a/chrome/browser/ui/views/tab_contents/native_tab_contents_view_aura.cc +++ b/chrome/browser/ui/views/tab_contents/native_tab_contents_view_aura.cc @@ -132,6 +132,7 @@ bool NativeTabContentsViewAura::OnMouseEvent(aura::MouseEvent* event) { return views::NativeWidgetAura::OnMouseEvent(event); } +#if !defined(TOUCH_UI) //////////////////////////////////////////////////////////////////////////////// // NativeTabContentsView, public: @@ -142,3 +143,4 @@ NativeTabContentsView* NativeTabContentsView::CreateNativeTabContentsView( // TODO(beng): switch over to this. // return new NativeTabContentsViewAura(delegate); } +#endif diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index fd06e23..e6b422e 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc @@ -363,7 +363,13 @@ bool RenderWidgetHostViewAura::OnMouseEvent(aura::MouseEvent* event) { return true; } -bool RenderWidgetHostViewAura::ShouldActivate(aura::MouseEvent* event) { +ui::TouchStatus RenderWidgetHostViewAura::OnTouchEvent( + aura::TouchEvent* event) { + NOTIMPLEMENTED(); + return ui::TOUCH_STATUS_UNKNOWN; +} + +bool RenderWidgetHostViewAura::ShouldActivate(aura::Event* event) { return false; } @@ -399,6 +405,7 @@ void RenderWidgetHostViewAura::OnWindowDestroyed() { void RenderWidgetHostViewAura::OnWindowVisibilityChanged(bool visible) { } +#if !defined(TOUCH_UI) //////////////////////////////////////////////////////////////////////////////// // RenderWidgetHostViewAura, private: @@ -406,3 +413,4 @@ void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() { //NOTIMPLEMENTED(); // TODO(beng): See RenderWidgetHostViewWin. } +#endif diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h index 87185fe..b596cb5 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h @@ -96,7 +96,8 @@ class RenderWidgetHostViewAura : public RenderWidgetHostView, virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE; virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE; virtual bool OnMouseEvent(aura::MouseEvent* event) OVERRIDE; - virtual bool ShouldActivate(aura::MouseEvent* event) OVERRIDE; + virtual ui::TouchStatus OnTouchEvent(aura::TouchEvent* event) OVERRIDE; + virtual bool ShouldActivate(aura::Event* event) OVERRIDE; virtual void OnActivated() OVERRIDE; virtual void OnLostActive() OVERRIDE; virtual void OnCaptureLost() OVERRIDE; diff --git a/ui/aura/demo/demo_main.cc b/ui/aura/demo/demo_main.cc index cbbdd69..335b298 100644 --- a/ui/aura/demo/demo_main.cc +++ b/ui/aura/demo/demo_main.cc @@ -46,7 +46,10 @@ class DemoWindowDelegate : public aura::WindowDelegate { virtual bool OnMouseEvent(aura::MouseEvent* event) OVERRIDE { return true; } - virtual bool ShouldActivate(aura::MouseEvent* event) OVERRIDE { return true; } + virtual ui::TouchStatus OnTouchEvent(aura::TouchEvent* event) OVERRIDE { + return ui::TOUCH_STATUS_END; + } + virtual bool ShouldActivate(aura::Event* event) OVERRIDE { return true; } virtual void OnActivated() OVERRIDE {} virtual void OnLostActive() OVERRIDE {} virtual void OnCaptureLost() OVERRIDE {} diff --git a/ui/aura/desktop.cc b/ui/aura/desktop.cc index 243fffd9..6e6a07d 100644 --- a/ui/aura/desktop.cc +++ b/ui/aura/desktop.cc @@ -98,6 +98,10 @@ bool Desktop::OnKeyEvent(const KeyEvent& event) { return window_->HandleKeyEvent(event); } +bool Desktop::OnTouchEvent(const TouchEvent& event) { + return window_->HandleTouchEvent(event); +} + void Desktop::OnHostResized(const gfx::Size& size) { gfx::Rect bounds(0, 0, size.width(), size.height()); compositor_->WidgetSizeChanged(size); diff --git a/ui/aura/desktop.h b/ui/aura/desktop.h index d25923e..5b729b4 100644 --- a/ui/aura/desktop.h +++ b/ui/aura/desktop.h @@ -28,7 +28,9 @@ namespace aura { class DesktopDelegate; class DesktopHost; class DesktopObserver; +class KeyEvent; class MouseEvent; +class TouchEvent; // Desktop is responsible for hosting a set of windows. class AURA_EXPORT Desktop : public ui::CompositorDelegate { @@ -66,6 +68,9 @@ class AURA_EXPORT Desktop : public ui::CompositorDelegate { // Handles a key event. Returns true if handled. bool OnKeyEvent(const KeyEvent& event); + // Handles a touch event. Returns true if handled. + bool OnTouchEvent(const TouchEvent& event); + // Called when the host changes size. void OnHostResized(const gfx::Size& size); diff --git a/ui/aura/desktop_host_linux.cc b/ui/aura/desktop_host_linux.cc index 06030b7..c0fc3cc 100644 --- a/ui/aura/desktop_host_linux.cc +++ b/ui/aura/desktop_host_linux.cc @@ -8,6 +8,7 @@ #include "base/message_pump_x.h" #include "ui/aura/desktop.h" #include "ui/aura/event.h" +#include "ui/base/touch/touch_factory.h" #include <X11/Xlib.h> @@ -67,6 +68,9 @@ DesktopHostLinux::DesktopHostLinux(const gfx::Rect& bounds) PointerMotionMask; XSelectInput(xdisplay_, xwindow_, event_mask); XFlush(xdisplay_); + + if (base::MessagePumpForUI::HasXInput2()) + ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); } DesktopHostLinux::~DesktopHostLinux() { @@ -129,6 +133,37 @@ base::MessagePumpDispatcher::DispatchStatus DesktopHostLinux::Dispatch( handled = true; break; } + + case GenericEvent: { + ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); + if (!factory->ShouldProcessXI2Event(xev)) + break; + ui::EventType type = ui::EventTypeFromNative(xev); + switch (type) { + case ui::ET_TOUCH_PRESSED: + case ui::ET_TOUCH_RELEASED: + case ui::ET_TOUCH_MOVED: { + TouchEvent touchev(xev); + handled = desktop_->OnTouchEvent(touchev); + break; + } + case ui::ET_MOUSE_PRESSED: + case ui::ET_MOUSE_RELEASED: + case ui::ET_MOUSE_MOVED: + case ui::ET_MOUSE_DRAGGED: + case ui::ET_MOUSE_ENTERED: + case ui::ET_MOUSE_EXITED: { + MouseEvent mouseev(xev); + handled = desktop_->OnMouseEvent(mouseev); + break; + } + case ui::ET_UNKNOWN: + handled = false; + break; + default: + NOTREACHED(); + } + } } return handled ? EVENT_PROCESSED : EVENT_IGNORED; } diff --git a/ui/aura/event.cc b/ui/aura/event.cc index cabeae5..1ba9119 100644 --- a/ui/aura/event.cc +++ b/ui/aura/event.cc @@ -84,6 +84,37 @@ MouseEvent::MouseEvent(ui::EventType type, : LocatedEvent(type, location, flags) { } +TouchEvent::TouchEvent(const base::NativeEvent& native_event) + : LocatedEvent(native_event), + touch_id_(ui::GetTouchId(native_event)), + radius_x_(ui::GetTouchRadiusX(native_event)), + radius_y_(ui::GetTouchRadiusY(native_event)), + rotation_angle_(ui::GetTouchAngle(native_event)), + force_(ui::GetTouchForce(native_event)) { +} + +TouchEvent::TouchEvent(const TouchEvent& model, + Window* source, + Window* target) + : LocatedEvent(model, source, target), + touch_id_(model.touch_id_), + radius_x_(model.radius_x_), + radius_y_(model.radius_y_), + rotation_angle_(model.rotation_angle_), + force_(model.force_) { +} + +TouchEvent::TouchEvent(ui::EventType type, + const gfx::Point& location, + int touch_id) + : LocatedEvent(type, location, 0), + touch_id_(touch_id), + radius_x_(1.0f), + radius_y_(1.0f), + rotation_angle_(0.0f), + force_(0.0f) { +} + KeyEvent::KeyEvent(const base::NativeEvent& native_event) : Event(native_event, ui::EventTypeFromNative(native_event), diff --git a/ui/aura/event.h b/ui/aura/event.h index a084f87..481728d 100644 --- a/ui/aura/event.h +++ b/ui/aura/event.h @@ -87,6 +87,44 @@ class AURA_EXPORT MouseEvent : public LocatedEvent { DISALLOW_COPY_AND_ASSIGN(MouseEvent); }; +class AURA_EXPORT TouchEvent : public LocatedEvent { + public: + explicit TouchEvent(const base::NativeEvent& native_event); + + // Create a new TouchEvent which is identical to the provided model. + // If source / target windows are provided, the model location will be + // converted from |source| coordinate system to |target| coordinate system. + TouchEvent(const TouchEvent& model, Window* source, Window* target); + + // Used for synthetic events in testing. + TouchEvent(ui::EventType type, const gfx::Point& location, int touch_id); + + int touch_id() const { return touch_id_; } + float radius_x() const { return radius_x_; } + float radius_y() const { return radius_y_; } + float rotation_angle() const { return rotation_angle_; } + float force() const { return force_; } + + private: + // The identity (typically finger) of the touch starting at 0 and incrementing + // for each separable additional touch that the hardware can detect. + const int touch_id_; + + // Radius of the X (major) axis of the touch ellipse. 1.0 if unknown. + const float radius_x_; + + // Radius of the Y (minor) axis of the touch ellipse. 1.0 if unknown. + const float radius_y_; + + // Angle of the major axis away from the X axis. Default 0.0. + const float rotation_angle_; + + // Force (pressure) of the touch. Normalized to be [0, 1]. Default to be 0.0. + const float force_; + + DISALLOW_COPY_AND_ASSIGN(TouchEvent); +}; + class AURA_EXPORT KeyEvent : public Event { public: explicit KeyEvent(const base::NativeEvent& native_event); diff --git a/ui/aura/event_filter.cc b/ui/aura/event_filter.cc index b0d39a0..2f2f177 100644 --- a/ui/aura/event_filter.cc +++ b/ui/aura/event_filter.cc @@ -32,9 +32,15 @@ bool EventFilter::OnMouseEvent(Window* target, MouseEvent* event) { return false; } +ui::TouchStatus EventFilter::OnTouchEvent(Window* target, TouchEvent* event) { + if (event->type() == ui::ET_TOUCH_PRESSED) + ActivateIfNecessary(target, event); + return ui::TOUCH_STATUS_UNKNOWN; +} + void EventFilter::ActivateIfNecessary( Window* window, - MouseEvent* event) { + Event* event) { // TODO(beng): some windows (e.g. disabled ones, tooltips, etc) may not be // focusable. diff --git a/ui/aura/event_filter.h b/ui/aura/event_filter.h index 3772fd8..3a94104 100644 --- a/ui/aura/event_filter.h +++ b/ui/aura/event_filter.h @@ -7,11 +7,14 @@ #pragma once #include "base/basictypes.h" +#include "ui/base/events.h" namespace aura { -class Window; +class Event; class MouseEvent; +class TouchEvent; +class Window; // An object that filters events sent to an owner window, potentially performing // adjustments to the window's position, size and z-index. @@ -23,15 +26,17 @@ class EventFilter { // Try to handle |event| (before the owner's delegate gets a chance to). // Returns true if the event was handled by the WindowManager and should not // be forwarded to the owner's delegate. - // Default implementation for ET_MOUSE_PRESSED focuses the window. + // Default implementation for ET_MOUSE_PRESSED and ET_TOUCH_PRESSED focuses + // the window. virtual bool OnMouseEvent(Window* target, MouseEvent* event); + virtual ui::TouchStatus OnTouchEvent(Window* target, TouchEvent* event); protected: Window* owner() { return owner_; } private: // If necessary, activates |window| and changes focus. - void ActivateIfNecessary(Window* window, MouseEvent* event); + void ActivateIfNecessary(Window* window, Event* event); Window* owner_; diff --git a/ui/aura/root_window.cc b/ui/aura/root_window.cc index 40a763a..e6324b6 100644 --- a/ui/aura/root_window.cc +++ b/ui/aura/root_window.cc @@ -19,7 +19,8 @@ RootWindow::RootWindow() mouse_pressed_handler_(NULL), mouse_moved_handler_(NULL), focused_window_(NULL), - capture_window_(NULL) { + capture_window_(NULL), + touch_event_handler_(NULL) { set_name("RootWindow"); } @@ -60,6 +61,25 @@ bool RootWindow::HandleKeyEvent(const KeyEvent& event) { return false; } +bool RootWindow::HandleTouchEvent(const TouchEvent& event) { + bool handled = false; + Window* target = + touch_event_handler_ ? touch_event_handler_ : capture_window_; + if (!target) + target = GetEventHandlerForPoint(event.location()); + if (target) { + TouchEvent translated_event(event, this, target); + ui::TouchStatus status = target->OnTouchEvent(&translated_event); + if (status == ui::TOUCH_STATUS_START) + touch_event_handler_ = target; + else if (status == ui::TOUCH_STATUS_END || + status == ui::TOUCH_STATUS_CANCEL) + touch_event_handler_ = NULL; + handled = status != ui::TOUCH_STATUS_UNKNOWN; + } + return handled; +} + void RootWindow::SetCapture(Window* window) { if (capture_window_ == window) return; @@ -68,10 +88,14 @@ void RootWindow::SetCapture(Window* window) { capture_window_->delegate()->OnCaptureLost(); capture_window_ = window; - if (capture_window_ && mouse_pressed_handler_) { - // Make all subsequent mouse events go to the capture window. We shouldn't - // need to send an event here as OnCaptureLost should take care of that. - mouse_pressed_handler_ = capture_window_; + if (capture_window_) { + // Make all subsequent mouse events and touch go to the capture window. We + // shouldn't need to send an event here as OnCaptureLost should take care of + // that. + if (mouse_pressed_handler_) + mouse_pressed_handler_ = capture_window_; + if (touch_event_handler_) + touch_event_handler_ = capture_window_; } } @@ -100,6 +124,8 @@ void RootWindow::WindowDestroying(Window* window) { mouse_moved_handler_ = NULL; if (capture_window_ == window) capture_window_ = NULL; + if (touch_event_handler_ == window) + touch_event_handler_ = NULL; } void RootWindow::SetFocusedWindow(Window* focused_window) { diff --git a/ui/aura/root_window.h b/ui/aura/root_window.h index 1fea6f3..98cce7d 100644 --- a/ui/aura/root_window.h +++ b/ui/aura/root_window.h @@ -11,7 +11,9 @@ namespace aura { +class KeyEvent; class MouseEvent; +class TouchEvent; namespace internal { @@ -29,6 +31,9 @@ class RootWindow : public Window, // Handles a key event. Returns true if handled. bool HandleKeyEvent(const KeyEvent& event); + // Handles a touch event. Returns true if handled. + bool HandleTouchEvent(const TouchEvent& event); + // Sets capture to the specified window. void SetCapture(Window* window); @@ -67,6 +72,7 @@ class RootWindow : public Window, Window* mouse_moved_handler_; Window* focused_window_; Window* capture_window_; + Window* touch_event_handler_; DISALLOW_COPY_AND_ASSIGN(RootWindow); }; diff --git a/ui/aura/test/test_window_delegate.cc b/ui/aura/test/test_window_delegate.cc index 93e84fe..9986b78 100644 --- a/ui/aura/test/test_window_delegate.cc +++ b/ui/aura/test/test_window_delegate.cc @@ -41,7 +41,11 @@ bool TestWindowDelegate::OnMouseEvent(MouseEvent* event) { return false; } -bool TestWindowDelegate::ShouldActivate(MouseEvent* event) { +ui::TouchStatus TestWindowDelegate::OnTouchEvent(TouchEvent* event) { + return ui::TOUCH_STATUS_UNKNOWN; +} + +bool TestWindowDelegate::ShouldActivate(Event* event) { return true; } diff --git a/ui/aura/test/test_window_delegate.h b/ui/aura/test/test_window_delegate.h index e00b87b..4150f67 100644 --- a/ui/aura/test/test_window_delegate.h +++ b/ui/aura/test/test_window_delegate.h @@ -27,7 +27,8 @@ class TestWindowDelegate : public WindowDelegate { virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE; virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE; virtual bool OnMouseEvent(MouseEvent* event) OVERRIDE; - virtual bool ShouldActivate(MouseEvent* event) OVERRIDE; + virtual ui::TouchStatus OnTouchEvent(TouchEvent* event) OVERRIDE; + virtual bool ShouldActivate(Event* event) OVERRIDE; virtual void OnActivated() OVERRIDE; virtual void OnLostActive() OVERRIDE; virtual void OnCaptureLost() OVERRIDE; diff --git a/ui/aura/toplevel_window_event_filter.cc b/ui/aura/toplevel_window_event_filter.cc index 98d29d3..d57d072 100644 --- a/ui/aura/toplevel_window_event_filter.cc +++ b/ui/aura/toplevel_window_event_filter.cc @@ -158,6 +158,14 @@ bool ToplevelWindowEventFilter::OnMouseEvent(Window* target, return false; } +ui::TouchStatus ToplevelWindowEventFilter::OnTouchEvent(Window* target, + TouchEvent* event) { + // Process EventFilters implementation first so that it processes + // activation/focus first. + // TODO(sad): Allow moving/resizing/maximizing etc. from touch? + return EventFilter::OnTouchEvent(target, event); +} + void ToplevelWindowEventFilter::MoveWindowToFront(Window* target) { Window* parent = target->parent(); Window* child = target; diff --git a/ui/aura/toplevel_window_event_filter.h b/ui/aura/toplevel_window_event_filter.h index 7a03bf4..fe0c583 100644 --- a/ui/aura/toplevel_window_event_filter.h +++ b/ui/aura/toplevel_window_event_filter.h @@ -23,6 +23,8 @@ class ToplevelWindowEventFilter : public EventFilter { // Overridden from EventFilter: virtual bool OnMouseEvent(Window* target, MouseEvent* event) OVERRIDE; + virtual ui::TouchStatus OnTouchEvent(Window* target, + TouchEvent* event) OVERRIDE; private: // Moves the target window and all of its parents to the front of their diff --git a/ui/aura/window.cc b/ui/aura/window.cc index 9fa858e..74a7b43 100644 --- a/ui/aura/window.cc +++ b/ui/aura/window.cc @@ -262,6 +262,19 @@ bool Window::OnKeyEvent(KeyEvent* event) { return IsVisible() && delegate_->OnKeyEvent(event); } +ui::TouchStatus Window::OnTouchEvent(TouchEvent* event) { + if (!parent_ || !IsVisible()) + return ui::TOUCH_STATUS_UNKNOWN; + + if (!parent_->event_filter_.get()) + parent_->SetEventFilter(new EventFilter(parent_)); + + ui::TouchStatus status = parent_->event_filter_->OnTouchEvent(this, event); + if (status == ui::TOUCH_STATUS_UNKNOWN && delegate_) + status = delegate_->OnTouchEvent(event); + return status; +} + void Window::AddObserver(WindowObserver* observer) { observers_.AddObserver(observer); } diff --git a/ui/aura/window.h b/ui/aura/window.h index 4a71023..57c52be 100644 --- a/ui/aura/window.h +++ b/ui/aura/window.h @@ -12,6 +12,7 @@ #include "base/memory/scoped_ptr.h" #include "base/observer_list.h" #include "base/string16.h" +#include "ui/base/events.h" #include "ui/base/ui_base_types.h" #include "ui/aura/aura_export.h" #include "ui/gfx/compositor/layer_delegate.h" @@ -34,6 +35,7 @@ class KeyEvent; class LayoutManager; class MouseEvent; class ToplevelWindowContainer; +class TouchEvent; class WindowDelegate; class WindowObserver; @@ -167,6 +169,9 @@ class AURA_EXPORT Window : public ui::LayerDelegate { // Handles a key event. Returns true if handled. bool OnKeyEvent(KeyEvent* event); + // Handles a touch event. + ui::TouchStatus OnTouchEvent(TouchEvent* event); + // Add/remove observer. void AddObserver(WindowObserver* observer); void RemoveObserver(WindowObserver* observer); diff --git a/ui/aura/window_delegate.h b/ui/aura/window_delegate.h index 928f164..9a7253b 100644 --- a/ui/aura/window_delegate.h +++ b/ui/aura/window_delegate.h @@ -7,6 +7,7 @@ #pragma once #include "ui/aura/aura_export.h" +#include "ui/base/events.h" #include "ui/gfx/native_widget_types.h" namespace gfx { @@ -17,8 +18,10 @@ class Rect; namespace aura { +class Event; class KeyEvent; class MouseEvent; +class TouchEvent; // Delegate interface for aura::Window. class AURA_EXPORT WindowDelegate { @@ -43,10 +46,13 @@ class AURA_EXPORT WindowDelegate { virtual bool OnMouseEvent(MouseEvent* event) = 0; - // Returns true if the window should be activated |event| is either the mouse - // event supplied if the activation is the result of a mouse, or NULL if - // activation is attempted for another reason. - virtual bool ShouldActivate(MouseEvent* event) = 0; + virtual ui::TouchStatus OnTouchEvent(TouchEvent* event) = 0; + + // Returns true if the window should be activated. |event| is either the mouse + // event supplied if the activation is the result of a mouse, or the touch + // event if the activation is the result of a touch, or NULL if activation is + // attempted for another reason. + virtual bool ShouldActivate(Event* event) = 0; // Sent when the window is activated. virtual void OnActivated() = 0; diff --git a/ui/aura/window_unittest.cc b/ui/aura/window_unittest.cc index d332cb1..e1d8cb5 100644 --- a/ui/aura/window_unittest.cc +++ b/ui/aura/window_unittest.cc @@ -89,18 +89,25 @@ class CaptureWindowDelegateImpl : public TestWindowDelegate { public: explicit CaptureWindowDelegateImpl() : capture_lost_count_(0), - mouse_event_count_(0) { + mouse_event_count_(0), + touch_event_count_(0) { } int capture_lost_count() const { return capture_lost_count_; } void set_capture_lost_count(int value) { capture_lost_count_ = value; } int mouse_event_count() const { return mouse_event_count_; } void set_mouse_event_count(int value) { mouse_event_count_ = value; } + int touch_event_count() const { return touch_event_count_; } + void set_touch_event_count(int value) { touch_event_count_ = value; } virtual bool OnMouseEvent(MouseEvent* event) OVERRIDE { mouse_event_count_++; return false; } + virtual ui::TouchStatus OnTouchEvent(TouchEvent* event) OVERRIDE { + touch_event_count_++; + return ui::TOUCH_STATUS_UNKNOWN; + } virtual void OnCaptureLost() OVERRIDE { capture_lost_count_++; } @@ -108,6 +115,7 @@ class CaptureWindowDelegateImpl : public TestWindowDelegate { private: int capture_lost_count_; int mouse_event_count_; + int touch_event_count_; DISALLOW_COPY_AND_ASSIGN(CaptureWindowDelegateImpl); }; @@ -290,6 +298,11 @@ TEST_F(WindowTest, Focus) { scoped_ptr<Window> w121( CreateTestWindowWithDelegate(w121delegate, 121, gfx::Rect(5, 5, 5, 5), w12.get())); + ColorTestWindowDelegate* w122delegate = + new ColorTestWindowDelegate(SK_ColorRED); + scoped_ptr<Window> w122( + CreateTestWindowWithDelegate(w122delegate, 121, gfx::Rect(10, 5, 5, 5), + w12.get())); scoped_ptr<Window> w13( CreateTestWindow(SK_ColorGRAY, 13, gfx::Rect(5, 470, 50, 50), w1.get())); @@ -304,6 +317,17 @@ TEST_F(WindowTest, Focus) { // The key press should be sent to the focused sub-window. desktop->OnKeyEvent(KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_E, 0)); EXPECT_EQ(ui::VKEY_E, w121delegate->last_key_code()); + + // Touch on a sub-window (w122) to focus it. + click_point = w122->bounds().CenterPoint(); + Window::ConvertPointToWindow(w122->parent(), desktop->window(), &click_point); + desktop->OnTouchEvent(TouchEvent(ui::ET_TOUCH_PRESSED, click_point, 0)); + focus_manager = w122->GetFocusManager(); + EXPECT_EQ(w122.get(), focus_manager->GetFocusedWindow()); + + // The key press should be sent to the focused sub-window. + desktop->OnKeyEvent(KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_F, 0)); + EXPECT_EQ(ui::VKEY_F, w122delegate->last_key_code()); } // Various destruction assertions. @@ -370,6 +394,11 @@ TEST_F(WindowTest, CaptureTests) { EXPECT_EQ(2, delegate.mouse_event_count()); delegate.set_mouse_event_count(0); + desktop->OnTouchEvent(TouchEvent(ui::ET_TOUCH_PRESSED, gfx::Point(50, 50), + 0)); + EXPECT_EQ(1, delegate.touch_event_count()); + delegate.set_touch_event_count(0); + window->ReleaseCapture(); EXPECT_FALSE(window->HasCapture()); EXPECT_EQ(1, delegate.capture_lost_count()); @@ -377,6 +406,10 @@ TEST_F(WindowTest, CaptureTests) { desktop->OnMouseEvent(MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(50, 50), ui::EF_LEFT_BUTTON_DOWN)); EXPECT_EQ(0, delegate.mouse_event_count()); + + desktop->OnTouchEvent(TouchEvent(ui::ET_TOUCH_PRESSED, gfx::Point(50, 50), + 0)); + EXPECT_EQ(0, delegate.touch_event_count()); } // Verifies capture is reset when a window is destroyed. @@ -478,7 +511,7 @@ class ActivateWindowDelegate : public TestWindowDelegate { activated_count_ = lost_active_count_ = should_activate_count_ = 0; } - virtual bool ShouldActivate(MouseEvent* event) OVERRIDE { + virtual bool ShouldActivate(Event* event) OVERRIDE { should_activate_count_++; return activate_; } @@ -565,6 +598,71 @@ TEST_F(WindowTest, ActivateOnMouse) { EXPECT_EQ(0, d1.lost_active_count()); } +// Essentially the same as ActivateOnMouse, but for touch events. +TEST_F(WindowTest, ActivateOnTouch) { + Desktop* desktop = Desktop::GetInstance(); + + ActivateWindowDelegate d1; + scoped_ptr<Window> w1( + CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50), NULL)); + ActivateWindowDelegate d2; + scoped_ptr<Window> w2( + CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(70, 70, 50, 50), NULL)); + internal::FocusManager* focus_manager = w1->GetFocusManager(); + + d1.Clear(); + d2.Clear(); + + // Activate window1. + desktop->SetActiveWindow(w1.get(), NULL); + EXPECT_EQ(w1.get(), desktop->active_window()); + EXPECT_EQ(w1.get(), focus_manager->GetFocusedWindow()); + EXPECT_EQ(1, d1.activated_count()); + EXPECT_EQ(0, d1.lost_active_count()); + d1.Clear(); + + // Touch window2. + gfx::Point press_point = w2->bounds().CenterPoint(); + Window::ConvertPointToWindow(w2->parent(), desktop->window(), &press_point); + desktop->OnTouchEvent(TouchEvent(ui::ET_TOUCH_PRESSED, press_point, 0)); + + // Window2 should have become active. + EXPECT_EQ(w2.get(), desktop->active_window()); + EXPECT_EQ(w2.get(), focus_manager->GetFocusedWindow()); + EXPECT_EQ(0, d1.activated_count()); + EXPECT_EQ(1, d1.lost_active_count()); + EXPECT_EQ(1, d2.activated_count()); + EXPECT_EQ(0, d2.lost_active_count()); + d1.Clear(); + d2.Clear(); + + // Touch window1, but set it up so w1 doesn't activate on touch. + press_point = w1->bounds().CenterPoint(); + Window::ConvertPointToWindow(w1->parent(), desktop->window(), &press_point); + d1.set_activate(false); + desktop->OnTouchEvent(TouchEvent(ui::ET_TOUCH_PRESSED, press_point, 0)); + + // Window2 should still be active and focused. + EXPECT_EQ(w2.get(), desktop->active_window()); + EXPECT_EQ(w2.get(), focus_manager->GetFocusedWindow()); + EXPECT_EQ(0, d1.activated_count()); + EXPECT_EQ(0, d1.lost_active_count()); + EXPECT_EQ(0, d2.activated_count()); + EXPECT_EQ(0, d2.lost_active_count()); + d1.Clear(); + d2.Clear(); + + // Destroy window2, this should make window1 active. + d1.set_activate(true); + w2.reset(); + EXPECT_EQ(0, d2.activated_count()); + EXPECT_EQ(0, d2.lost_active_count()); + EXPECT_EQ(w1.get(), desktop->active_window()); + EXPECT_EQ(w1.get(), focus_manager->GetFocusedWindow()); + EXPECT_EQ(1, d1.activated_count()); + EXPECT_EQ(0, d1.lost_active_count()); +} + // Creates a window with a delegate (w111) that can handle events at a lower // z-index than a window without a delegate (w12). w12 is sized to fill the // entire bounds of the container. This test verifies that diff --git a/ui/base/events.h b/ui/base/events.h index 21b59db..1e83479 100644 --- a/ui/base/events.h +++ b/ui/base/events.h @@ -87,9 +87,22 @@ UI_EXPORT KeyboardCode KeyboardCodeFromNative( // Returns true if the message is a mouse event. UI_EXPORT bool IsMouseEvent(const base::NativeEvent& native_event); -// Get the mouse wheel offset from a native event. +// Gets the mouse wheel offset from a native event. UI_EXPORT int GetMouseWheelOffset(const base::NativeEvent& native_event); +// Gets the touch id from a native event. +UI_EXPORT int GetTouchId(const base::NativeEvent& native_event); + +// Gets the radius along the X/Y axis from a native event. Default is 1.0. +UI_EXPORT float GetTouchRadiusX(const base::NativeEvent& native_event); +UI_EXPORT float GetTouchRadiusY(const base::NativeEvent& native_event); + +// Gets the angle of the major axis away from the X axis. Default is 0.0. +UI_EXPORT float GetTouchAngle(const base::NativeEvent& native_event); + +// Gets the force from a native_event. Normalized to be [0, 1]. Default is 0.0. +UI_EXPORT float GetTouchForce(const base::NativeEvent& native_event); + } // namespace ui #endif // UI_BASE_EVENTS_H_ diff --git a/ui/base/win/events_win.cc b/ui/base/win/events_win.cc index 47edce7..320ef48 100644 --- a/ui/base/win/events_win.cc +++ b/ui/base/win/events_win.cc @@ -218,4 +218,29 @@ int GetMouseWheelOffset(const base::NativeEvent& native_event) { return GET_WHEEL_DELTA_WPARAM(native_event.wParam); } +int GetTouchId(const base::NativeEvent& xev) { + NOTIMPLEMENTED(); + return 0; +} + +float GetTouchRadiusX(const base::NativeEvent& native_event) { + NOTIMPLEMENTED(); + return 1.0; +} + +float GetTouchRadiusY(const base::NativeEvent& native_event) { + NOTIMPLEMENTED(); + return 1.0; +} + +float GetTouchAngle(const base::NativeEvent& native_event) { + NOTIMPLEMENTED(); + return 0.0; +} + +float GetTouchForce(const base::NativeEvent& native_event) { + NOTIMPLEMENTED(); + return 0.0; +} + } // namespace ui diff --git a/ui/base/x/events_x.cc b/ui/base/x/events_x.cc index 56fbed9..09e8f85 100644 --- a/ui/base/x/events_x.cc +++ b/ui/base/x/events_x.cc @@ -127,6 +127,13 @@ ui::EventType GetTouchEventType(const base::NativeEvent& native_event) { #endif // defined(USE_XI2_MT) } +float GetTouchParamFromXEvent(XEvent* xev, + ui::TouchFactory::TouchParam tp, + float default_value) { + ui::TouchFactory::GetInstance()->ExtractTouchParam(*xev, tp, &default_value); + return default_value; +} + } // namespace namespace ui { @@ -174,7 +181,6 @@ EventType EventTypeFromNative(const base::NativeEvent& native_event) { } } default: - NOTREACHED() << "Unknown Event Type:" << native_event->type; break; } return ET_UNKNOWN; @@ -257,4 +263,57 @@ int GetMouseWheelOffset(const base::NativeEvent& native_event) { kWheelScrollAmount : -kWheelScrollAmount; } +int GetTouchId(const base::NativeEvent& xev) { + float slot = 0; + ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); + XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); + if (!factory->IsRealTouchDevice(xievent->sourceid)) { + // TODO(sad): Come up with a way to generate touch-ids for multi-touch + // events when touch-events are generated from a mouse. + return slot; + } + +#if defined(USE_XI2_MT) + float tracking_id; + if (!factory->ExtractTouchParam( + *xev, ui::TouchFactory::TP_TRACKING_ID, &tracking_id)) + LOG(ERROR) << "Could not get the slot ID for the event. Using 0."; + else + slot = factory->GetSlotForTrackingID(tracking_id); +#else + if (!factory->ExtractTouchParam( + *xev, ui::TouchFactory::TP_SLOT_ID, &slot)) + LOG(ERROR) << "Could not get the slot ID for the event. Using 0."; +#endif + return slot; +} + +float GetTouchRadiusX(const base::NativeEvent& native_event) { + return GetTouchParamFromXEvent(native_event, + ui::TouchFactory::TP_TOUCH_MAJOR, 2.0) / 2.0; +} + +float GetTouchRadiusY(const base::NativeEvent& native_event) { + return GetTouchParamFromXEvent(native_event, + ui::TouchFactory::TP_TOUCH_MINOR, 2.0) / 2.0; +} + +float GetTouchAngle(const base::NativeEvent& native_event) { + return GetTouchParamFromXEvent(native_event, + ui::TouchFactory::TP_ORIENTATION, 0.0) / 2.0; +} + +float GetTouchForce(const base::NativeEvent& native_event) { + float force = 0.0; + force = GetTouchParamFromXEvent(native_event, ui::TouchFactory::TP_PRESSURE, + 0.0); + unsigned int deviceid = + static_cast<XIDeviceEvent*>(native_event->xcookie.data)->sourceid; + // Force is normalized to fall into [0, 1] + if (!ui::TouchFactory::GetInstance()->NormalizeTouchParam( + deviceid, ui::TouchFactory::TP_PRESSURE, &force)) + force = 0.0; + return force; +} + } // namespace ui diff --git a/views/aura_desktop/aura_desktop_main.cc b/views/aura_desktop/aura_desktop_main.cc index aca5b14..033c21a 100644 --- a/views/aura_desktop/aura_desktop_main.cc +++ b/views/aura_desktop/aura_desktop_main.cc @@ -49,7 +49,10 @@ class DemoWindowDelegate : public aura::WindowDelegate { virtual bool OnMouseEvent(aura::MouseEvent* event) OVERRIDE { return true; } - virtual bool ShouldActivate(aura::MouseEvent* event) OVERRIDE { + virtual ui::TouchStatus OnTouchEvent(aura::TouchEvent* event) OVERRIDE { + return ui::TOUCH_STATUS_END; + } + virtual bool ShouldActivate(aura::Event* event) OVERRIDE { return true; } virtual void OnActivated() OVERRIDE {} diff --git a/views/events/event.h b/views/events/event.h index 5312ecd..a7b3620 100644 --- a/views/events/event.h +++ b/views/events/event.h @@ -243,7 +243,7 @@ class VIEWS_EXPORT MouseEvent : public LocatedEvent { //////////////////////////////////////////////////////////////////////////////// class VIEWS_EXPORT TouchEvent : public LocatedEvent { public: - explicit TouchEvent(const base::NativeEvent& native_event); + explicit TouchEvent(const NativeEvent& native_event); // Create a new touch event. TouchEvent(ui::EventType type, diff --git a/views/events/event_aura.cc b/views/events/event_aura.cc index dca43fd..bf6a1c5 100644 --- a/views/events/event_aura.cc +++ b/views/events/event_aura.cc @@ -18,6 +18,18 @@ LocatedEvent::LocatedEvent(const NativeEvent& native_event) } //////////////////////////////////////////////////////////////////////////////// +// TouchEvent, public: + +TouchEvent::TouchEvent(const NativeEvent& event) + : LocatedEvent(event), + touch_id_(static_cast<aura::TouchEvent*>(event)->touch_id()), + radius_x_(static_cast<aura::TouchEvent*>(event)->radius_x()), + radius_y_(static_cast<aura::TouchEvent*>(event)->radius_y()), + rotation_angle_(static_cast<aura::TouchEvent*>(event)->rotation_angle()), + force_(static_cast<aura::TouchEvent*>(event)->force()) { +} + +//////////////////////////////////////////////////////////////////////////////// // KeyEvent, public: KeyEvent::KeyEvent(const NativeEvent& native_event) diff --git a/views/events/event_x.cc b/views/events/event_x.cc index 7dbaedb..1c1c51d 100644 --- a/views/events/event_x.cc +++ b/views/events/event_x.cc @@ -11,6 +11,7 @@ #include "base/logging.h" #include "base/utf_string_conversions.h" +#include "ui/base/events.h" #include "ui/base/keycodes/keyboard_code_conversion_x.h" #include "ui/base/touch/touch_factory.h" #include "views/widget/root_view.h" @@ -19,31 +20,6 @@ namespace views { namespace { -int GetTouchIDFromXEvent(XEvent* xev) { - float slot = 0; - ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); - XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); - if (!factory->IsRealTouchDevice(xievent->sourceid)) { - // TODO(sad): Come up with a way to generate touch-ids for multi-touch - // events when touch-events are generated from a mouse. - return slot; - } - -#if defined(USE_XI2_MT) - float tracking_id; - if (!factory->ExtractTouchParam( - *xev, ui::TouchFactory::TP_TRACKING_ID, &tracking_id)) - LOG(ERROR) << "Could not get the slot ID for the event. Using 0."; - else - slot = factory->GetSlotForTrackingID(tracking_id); -#else - if (!factory->ExtractTouchParam( - *xev, ui::TouchFactory::TP_SLOT_ID, &slot)) - LOG(ERROR) << "Could not get the slot ID for the event. Using 0."; -#endif - return slot; -} - uint16 GetCharacterFromXKeyEvent(XKeyEvent* key) { char buf[6]; int bytes_written = XLookupString(key, buf, 6, NULL, NULL); @@ -54,25 +30,6 @@ uint16 GetCharacterFromXKeyEvent(XKeyEvent* key) { result.length() == 1) ? result[0] : 0; } -float GetTouchParamFromXEvent(XEvent* xev, - ui::TouchFactory::TouchParam tp, - float default_value) { - ui::TouchFactory::GetInstance()->ExtractTouchParam(*xev, tp, &default_value); - return default_value; -} - -float GetTouchForceFromXEvent(XEvent* xev) { - float force = 0.0; - force = GetTouchParamFromXEvent(xev, ui::TouchFactory::TP_PRESSURE, 0.0); - unsigned int deviceid = - static_cast<XIDeviceEvent*>(xev->xcookie.data)->sourceid; - // Force is normalized to fall into [0, 1] - if (!ui::TouchFactory::GetInstance()->NormalizeTouchParam( - deviceid, ui::TouchFactory::TP_PRESSURE, &force)) - force = 0.0; - return force; -} - // The following two functions are copied from event_gtk.cc. These will be // removed when GTK dependency is removed. #if defined(TOOLKIT_USES_GTK) @@ -171,17 +128,11 @@ uint16 KeyEvent::GetUnmodifiedCharacter() const { TouchEvent::TouchEvent(const base::NativeEvent& native_event) : LocatedEvent(native_event), - touch_id_(GetTouchIDFromXEvent(native_event)), - radius_x_(GetTouchParamFromXEvent(native_event, - ui::TouchFactory::TP_TOUCH_MAJOR, - 2.0) / 2.0), - radius_y_(GetTouchParamFromXEvent(native_event, - ui::TouchFactory::TP_TOUCH_MINOR, - 2.0) / 2.0), - rotation_angle_(GetTouchParamFromXEvent(native_event, - ui::TouchFactory::TP_ORIENTATION, - 0.0)), - force_(GetTouchForceFromXEvent(native_event)) { + touch_id_(ui::GetTouchId(native_event)), + radius_x_(ui::GetTouchRadiusX(native_event)), + radius_y_(ui::GetTouchRadiusY(native_event)), + rotation_angle_(ui::GetTouchAngle(native_event)), + force_(ui::GetTouchForce(native_event)) { #if defined(USE_XI2_MT) if (type() == ui::ET_TOUCH_RELEASED) { // NOTE: The slot is allocated by TouchFactory for each XI_TouchBegin diff --git a/views/touchui/gesture_manager.cc b/views/touchui/gesture_manager.cc index 723db77..0ffc1e5 100644 --- a/views/touchui/gesture_manager.cc +++ b/views/touchui/gesture_manager.cc @@ -49,7 +49,7 @@ bool GestureManager::ProcessTouchEventForGesture(const TouchEvent& event, } else { Widget* source_widget = source->GetWidget(); Widget* top_widget = source_widget->GetTopLevelWidget(); - if (source_widget != top_widget) { + if (source_widget != top_widget && top_widget) { // This is necessary as TYPE_CHILD widget is still NativeWidgetGtk. // Fix this once TYPE_CHILD is switched to NativeWidgetViews. MouseEvent converted(mouseev, diff --git a/views/widget/native_widget_aura.cc b/views/widget/native_widget_aura.cc index 1158e7b..18c82cd 100644 --- a/views/widget/native_widget_aura.cc +++ b/views/widget/native_widget_aura.cc @@ -521,7 +521,13 @@ bool NativeWidgetAura::OnMouseEvent(aura::MouseEvent* event) { return delegate_->OnMouseEvent(mouse_event); } -bool NativeWidgetAura::ShouldActivate(aura::MouseEvent* event) { +ui::TouchStatus NativeWidgetAura::OnTouchEvent(aura::TouchEvent* event) { + DCHECK(window_->IsVisible()); + TouchEvent touch_event(event); + return delegate_->OnTouchEvent(touch_event); +} + +bool NativeWidgetAura::ShouldActivate(aura::Event* event) { return can_activate_; } diff --git a/views/widget/native_widget_aura.h b/views/widget/native_widget_aura.h index a21637b..9ba5f86 100644 --- a/views/widget/native_widget_aura.h +++ b/views/widget/native_widget_aura.h @@ -9,6 +9,7 @@ #include "base/memory/scoped_vector.h" #include "base/memory/weak_ptr.h" #include "ui/aura/window_delegate.h" +#include "ui/base/events.h" #include "views/views_export.h" #include "views/widget/native_widget_private.h" @@ -131,7 +132,8 @@ class VIEWS_EXPORT NativeWidgetAura : public internal::NativeWidgetPrivate, virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE; virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE; virtual bool OnMouseEvent(aura::MouseEvent* event) OVERRIDE; - virtual bool ShouldActivate(aura::MouseEvent* event) OVERRIDE; + virtual ui::TouchStatus OnTouchEvent(aura::TouchEvent* event) OVERRIDE; + virtual bool ShouldActivate(aura::Event* event) OVERRIDE; virtual void OnActivated() OVERRIDE; virtual void OnLostActive() OVERRIDE; virtual void OnCaptureLost() OVERRIDE; |