summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authordavemoore@chromium.org <davemoore@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-15 17:52:02 +0000
committerdavemoore@chromium.org <davemoore@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-15 17:52:02 +0000
commitaca200e532f35181e8ae0d66e7f27ca7c6966bd1 (patch)
tree299d4785d08390f53efb91ac31c1c6d80d6dc130 /ui
parent112f03ff93d980249601674796f12f5bab4ee839 (diff)
downloadchromium_src-aca200e532f35181e8ae0d66e7f27ca7c6966bd1.zip
chromium_src-aca200e532f35181e8ae0d66e7f27ca7c6966bd1.tar.gz
chromium_src-aca200e532f35181e8ae0d66e7f27ca7c6966bd1.tar.bz2
CMT can now generate motion events w/ valuators instead of a sequence of button events. This supports them
BUG=None TEST=None Review URL: http://codereview.chromium.org/8907005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@114660 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r--ui/aura/event.cc5
-rw-r--r--ui/aura/event.h23
-rw-r--r--ui/aura/root_window.cc22
-rw-r--r--ui/aura/root_window.h5
-rw-r--r--ui/aura/root_window_host_linux.cc28
-rw-r--r--ui/base/events.h10
-rw-r--r--ui/base/win/events_win.cc11
-rw-r--r--ui/base/x/events_x.cc160
-rw-r--r--ui/views/events/event.h13
-rw-r--r--ui/views/events/event_aura.cc6
-rw-r--r--ui/views/widget/native_widget_aura.cc4
11 files changed, 265 insertions, 22 deletions
diff --git a/ui/aura/event.cc b/ui/aura/event.cc
index 5cb2fd8..980b129 100644
--- a/ui/aura/event.cc
+++ b/ui/aura/event.cc
@@ -251,4 +251,9 @@ uint16 KeyEvent::GetUnmodifiedCharacter() const {
#endif
}
+ScrollEvent::ScrollEvent(const base::NativeEvent& native_event)
+ : MouseEvent(native_event) {
+ ui::GetScrollOffsets(native_event, &x_offset_, &y_offset_);
+}
+
} // namespace aura
diff --git a/ui/aura/event.h b/ui/aura/event.h
index 5dcb726..f4478f8 100644
--- a/ui/aura/event.h
+++ b/ui/aura/event.h
@@ -204,6 +204,29 @@ class AURA_EXPORT DropTargetEvent : public LocatedEvent {
DISALLOW_COPY_AND_ASSIGN(DropTargetEvent);
};
+class AURA_EXPORT ScrollEvent : public MouseEvent {
+ public:
+ ScrollEvent(const base::NativeEvent& native_event);
+ ScrollEvent(const ScrollEvent& model,
+ Window* source,
+ Window* target,
+ ui::EventType type,
+ int flags)
+ : MouseEvent(model, source, target, type, flags),
+ x_offset_(model.x_offset_),
+ y_offset_(model.y_offset_) {
+ }
+
+ float x_offset() const { return x_offset_; }
+ float y_offset() const { return y_offset_; }
+
+ private:
+ float x_offset_;
+ float y_offset_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScrollEvent);
+};
+
} // namespace aura
#endif // UI_AURA_EVENT_H_
diff --git a/ui/aura/root_window.cc b/ui/aura/root_window.cc
index 10535a7..ed230a5 100644
--- a/ui/aura/root_window.cc
+++ b/ui/aura/root_window.cc
@@ -170,6 +170,28 @@ bool RootWindow::DispatchKeyEvent(KeyEvent* event) {
return false;
}
+bool RootWindow::DispatchScrollEvent(ScrollEvent* event) {
+ event->UpdateForTransform(layer()->transform());
+
+ last_mouse_location_ = event->location();
+
+ Window* target =
+ mouse_pressed_handler_ ? mouse_pressed_handler_ : capture_window_;
+ if (!target)
+ target = GetEventHandlerForPoint(event->location());
+
+ if (target && target->delegate()) {
+ int flags = event->flags();
+ gfx::Point location_in_window = event->location();
+ Window::ConvertPointToWindow(this, target, &location_in_window);
+ if (IsNonClientLocation(target, location_in_window))
+ flags |= ui::EF_IS_NON_CLIENT;
+ ScrollEvent translated_event(*event, this, target, event->type(), flags);
+ return ProcessMouseEvent(target, &translated_event);
+ }
+ return false;
+}
+
bool RootWindow::DispatchTouchEvent(TouchEvent* event) {
event->UpdateForTransform(layer()->transform());
bool handled = false;
diff --git a/ui/aura/root_window.h b/ui/aura/root_window.h
index 76f70b5..f7b0862 100644
--- a/ui/aura/root_window.h
+++ b/ui/aura/root_window.h
@@ -37,6 +37,8 @@ class RootWindowObserver;
class KeyEvent;
class MouseEvent;
class ScreenAura;
+class StackingClient;
+class ScrollEvent;
class TouchEvent;
// RootWindow is responsible for hosting a set of windows.
@@ -81,6 +83,9 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate,
// Handles a key event. Returns true if handled.
bool DispatchKeyEvent(KeyEvent* event);
+ // Handles a scroll event. Returns true if handled.
+ bool DispatchScrollEvent(ScrollEvent* event);
+
// Handles a touch event. Returns true if handled.
bool DispatchTouchEvent(TouchEvent* event);
diff --git a/ui/aura/root_window_host_linux.cc b/ui/aura/root_window_host_linux.cc
index d577acd..6ed655b 100644
--- a/ui/aura/root_window_host_linux.cc
+++ b/ui/aura/root_window_host_linux.cc
@@ -197,7 +197,8 @@ int CoalescePendingXIMotionEvents(const XEvent* xev, XEvent* last_event) {
}
if (next_event.type == GenericEvent &&
- next_event.xgeneric.evtype == XI_Motion) {
+ next_event.xgeneric.evtype == XI_Motion &&
+ !ui::GetScrollOffsets(&next_event, NULL, NULL)) {
XIDeviceEvent* next_xievent =
static_cast<XIDeviceEvent*>(next_event.xcookie.data);
// Confirm that the motion event is targeted at the same window
@@ -343,7 +344,6 @@ RootWindowHostLinux::RootWindowHostLinux(const gfx::Rect& bounds)
XSelectInput(xdisplay_, x_root_window_, StructureNotifyMask);
XFlush(xdisplay_);
- // TODO(sad): Re-enable once crbug.com/106516 is fixed.
if (base::MessagePumpForUI::HasXInput2())
ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_);
@@ -422,22 +422,17 @@ base::MessagePumpDispatcher::DispatchStatus RootWindowHostLinux::Dispatch(
// Update the device list if necessary.
if (xev->xgeneric.evtype == XI_HierarchyChanged) {
- factory->UpdateDeviceList(xdisplay_);
+ ui::UpdateDeviceList();
handled = true;
break;
}
+ ui::EventType type = ui::EventTypeFromNative(xev);
// If this is a motion event we want to coalesce all pending motion
// events that are at the top of the queue.
XEvent last_event;
int num_coalesced = 0;
- if (xev->xgeneric.evtype == XI_Motion) {
- num_coalesced = CoalescePendingXIMotionEvents(xev, &last_event);
- if (num_coalesced > 0)
- xev = &last_event;
- }
- ui::EventType type = ui::EventTypeFromNative(xev);
switch (type) {
case ui::ET_TOUCH_PRESSED:
case ui::ET_TOUCH_RELEASED:
@@ -446,10 +441,16 @@ base::MessagePumpDispatcher::DispatchStatus RootWindowHostLinux::Dispatch(
handled = root_window_->DispatchTouchEvent(&touchev);
break;
}
+ case ui::ET_MOUSE_MOVED:
+ case ui::ET_MOUSE_DRAGGED: {
+ // If this is a motion event we want to coalesce all pending motion
+ // events that are at the top of the queue.
+ num_coalesced = CoalescePendingXIMotionEvents(xev, &last_event);
+ if (num_coalesced > 0)
+ xev = &last_event;
+ }
case ui::ET_MOUSE_PRESSED:
case ui::ET_MOUSE_RELEASED:
- case ui::ET_MOUSE_MOVED:
- case ui::ET_MOUSE_DRAGGED:
case ui::ET_MOUSEWHEEL:
case ui::ET_MOUSE_ENTERED:
case ui::ET_MOUSE_EXITED: {
@@ -457,6 +458,11 @@ base::MessagePumpDispatcher::DispatchStatus RootWindowHostLinux::Dispatch(
handled = root_window_->DispatchMouseEvent(&mouseev);
break;
}
+ case ui::ET_SCROLL: {
+ ScrollEvent scrollev(xev);
+ handled = root_window_->DispatchScrollEvent(&scrollev);
+ break;
+ }
case ui::ET_UNKNOWN:
handled = false;
break;
diff --git a/ui/base/events.h b/ui/base/events.h
index 69f83084..aab9366 100644
--- a/ui/base/events.h
+++ b/ui/base/events.h
@@ -35,6 +35,7 @@ enum EventType {
ET_TOUCH_CANCELLED,
ET_DROP_TARGET_EVENT,
ET_FOCUS_CHANGE,
+ ET_SCROLL,
};
// Event flags currently supported
@@ -70,6 +71,9 @@ enum TouchStatus {
// unused touch event was handled.
};
+// Updates the list of devices for cached properties.
+UI_EXPORT void UpdateDeviceList();
+
// Get the EventType from a native event.
UI_EXPORT EventType EventTypeFromNative(const base::NativeEvent& native_event);
@@ -111,6 +115,12 @@ 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);
+// Returns whether this is a scroll event and optionally gets the amount to be
+// scrolled. |x_offset| and |y_offset| can be NULL.
+UI_EXPORT bool GetScrollOffsets(const base::NativeEvent& native_event,
+ float* x_offset,
+ float* y_offset);
+
// Creates and returns no-op event.
UI_EXPORT base::NativeEvent CreateNoopEvent();
diff --git a/ui/base/win/events_win.cc b/ui/base/win/events_win.cc
index 418d6d0..c745526 100644
--- a/ui/base/win/events_win.cc
+++ b/ui/base/win/events_win.cc
@@ -253,6 +253,17 @@ float GetTouchForce(const base::NativeEvent& native_event) {
return 0.0;
}
+bool GetScrollOffsets(const base::NativeEvent& native_event,
+ float* x_offset,
+ float* y_offset) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+void UpdateDeviceList() {
+ NOTIMPLEMENTED();
+}
+
base::NativeEvent CreateNoopEvent() {
MSG event;
event.message = WM_USER;
diff --git a/ui/base/x/events_x.cc b/ui/base/x/events_x.cc
index 4f2db85..b5c8bed 100644
--- a/ui/base/x/events_x.cc
+++ b/ui/base/x/events_x.cc
@@ -5,6 +5,7 @@
#include "ui/base/events.h"
#include <X11/Xlib.h>
+#include <X11/extensions/XInput.h>
#include <X11/extensions/XInput2.h>
#include <string.h>
@@ -18,6 +19,10 @@
#include "base/message_pump_x.h"
#endif
+// Copied from xserver-properties.h
+#define AXIS_LABEL_PROP_REL_HWHEEL "Rel Horiz Wheel"
+#define AXIS_LABEL_PROP_REL_WHEEL "Rel Vert Wheel"
+
namespace {
// Scroll amount for each wheelscroll event. 53 is also the value used for GTK+.
@@ -35,6 +40,125 @@ static const int kMaxWheelButton = 9;
static const int kMaxWheelButton = 7;
#endif
+// A class to support the detection of scroll events, using X11 valuators.
+class UI_EXPORT ScrollEventData {
+ public:
+ // Returns the ScrollEventData singleton.
+ static ScrollEventData* GetInstance() {
+ return Singleton<ScrollEventData>::get();
+ }
+
+ // Updates the list of devices.
+ void UpdateDeviceList(Display* display) {
+ scroll_devices_.reset();
+ device_to_valuators_.clear();
+
+ int count = 0;
+ XDeviceInfo* dev_list = XListInputDevices(display, &count);
+ Atom xi_touchpad = XInternAtom(display, XI_TOUCHPAD, false);
+ for (int i = 0; i < count; ++i) {
+ XDeviceInfo* dev = dev_list + i;
+ if (dev->type == xi_touchpad)
+ scroll_devices_[dev_list[i].id] = true;
+ }
+ if (dev_list)
+ XFreeDeviceList(dev_list);
+
+ XIDeviceInfo* info_list = XIQueryDevice(display, XIAllDevices, &count);
+ Atom x_axis = XInternAtom(display, AXIS_LABEL_PROP_REL_HWHEEL, false);
+ Atom y_axis = XInternAtom(display, AXIS_LABEL_PROP_REL_WHEEL, false);
+ for (int i = 0; i < count; ++i) {
+ XIDeviceInfo* info = info_list + i;
+
+ if (!scroll_devices_[info->deviceid])
+ continue;
+
+ if (info->use != XISlavePointer && info->use != XIFloatingSlave) {
+ scroll_devices_[info->deviceid] = false;
+ continue;
+ }
+
+ Valuators valuators = {-1, -1};
+ for (int j = 0; j < info->num_classes; ++j) {
+ if (info->classes[j]->type != XIValuatorClass)
+ continue;
+
+ XIValuatorClassInfo* v =
+ reinterpret_cast<XIValuatorClassInfo*>(info->classes[j]);
+ if (v->label == x_axis)
+ valuators.x_scroll = v->number;
+ else if (v->label == y_axis)
+ valuators.y_scroll = v->number;
+ }
+ if (valuators.x_scroll >= 0 && valuators.y_scroll >= 0)
+ device_to_valuators_[info->deviceid] = valuators;
+ else
+ scroll_devices_[info->deviceid] = false;
+ }
+ }
+
+ // Returns true if this is a scroll event (a motion event with the necessary
+ // valuators. Also returns the offsets. |x_offset| and |y_offset| can be
+ // NULL.
+ bool GetScrollOffsets(const XEvent& xev, float* x_offset, float* y_offset) {
+ XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data);
+
+ if (x_offset)
+ *x_offset = 0;
+ if (y_offset)
+ *y_offset = 0;
+
+ if (!scroll_devices_[xiev->deviceid])
+ return false;
+
+ int x_scroll = device_to_valuators_[xiev->deviceid].x_scroll;
+ int y_scroll = device_to_valuators_[xiev->deviceid].y_scroll;
+
+ bool has_x_offset = XIMaskIsSet(xiev->valuators.mask, x_scroll);
+ bool has_y_offset = XIMaskIsSet(xiev->valuators.mask, y_scroll);
+ bool is_scroll = has_x_offset || has_y_offset;
+
+ if (!x_offset && !y_offset)
+ return is_scroll;
+
+ double* valuators = xiev->valuators.values;
+ for (int i = 0; i < xiev->valuators.mask_len * 8; ++i) {
+ if (XIMaskIsSet(xiev->valuators.mask, i)) {
+ if (x_offset && x_scroll == i)
+ *x_offset = -(*valuators);
+ else if (y_offset && y_scroll == i)
+ *y_offset = -(*valuators);
+ valuators++;
+ }
+ }
+
+ return is_scroll;
+ }
+
+ private:
+ // Requirement for Singleton
+ friend struct DefaultSingletonTraits<ScrollEventData>;
+
+ struct Valuators {
+ int x_scroll;
+ int y_scroll;
+ };
+
+ ScrollEventData() {
+ UpdateDeviceList(ui::GetXDisplay());
+ }
+
+ ~ScrollEventData() {}
+
+ // A quick lookup table for determining if events from the pointer device
+ // should be processed.
+ static const int kMaxDeviceNum = 128;
+ std::bitset<kMaxDeviceNum> scroll_devices_;
+ std::map<int, Valuators> device_to_valuators_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScrollEventData);
+};
+
int GetEventFlagsFromXState(unsigned int state) {
int flags = 0;
if (state & ControlMask)
@@ -192,21 +316,22 @@ EventType EventTypeFromNative(const base::NativeEvent& native_event) {
static_cast<XIDeviceEvent*>(native_event->xcookie.data);
if (TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid))
return GetTouchEventType(native_event);
- int button = EventButtonFromNative(native_event);
switch (xievent->evtype) {
case XI_ButtonPress:
- if (button >= kMinWheelButton &&
- button <= kMaxWheelButton)
- return ET_MOUSEWHEEL;
- return ET_MOUSE_PRESSED;
- case XI_ButtonRelease:
- if (button >= kMinWheelButton &&
- button <= kMaxWheelButton)
+ case XI_ButtonRelease: {
+ int button = EventButtonFromNative(native_event);
+ if (button >= kMinWheelButton && button <= kMaxWheelButton)
return ET_MOUSEWHEEL;
- return ET_MOUSE_RELEASED;
+ return xievent->evtype == XI_ButtonPress ?
+ ET_MOUSE_PRESSED : ET_MOUSE_RELEASED;
+ }
case XI_Motion:
- return GetButtonMaskForX2Event(xievent) ?
- ET_MOUSE_DRAGGED : ET_MOUSE_MOVED;
+ if (GetScrollOffsets(native_event, NULL, NULL))
+ return ET_SCROLL;
+ else if (GetButtonMaskForX2Event(xievent))
+ return ET_MOUSE_DRAGGED;
+ else
+ return ET_MOUSE_MOVED;
}
}
default:
@@ -405,6 +530,19 @@ float GetTouchForce(const base::NativeEvent& native_event) {
return force;
}
+bool GetScrollOffsets(const base::NativeEvent& native_event,
+ float* x_offset,
+ float* y_offset) {
+ return ScrollEventData::GetInstance()->GetScrollOffsets(
+ *native_event, x_offset, y_offset);
+}
+
+void UpdateDeviceList() {
+ Display* display = GetXDisplay();
+ ScrollEventData::GetInstance()->UpdateDeviceList(display);
+ TouchFactory::GetInstance()->UpdateDeviceList(display);
+}
+
base::NativeEvent CreateNoopEvent() {
static XEvent* noop = NULL;
if (!noop) {
diff --git a/ui/views/events/event.h b/ui/views/events/event.h
index c0cf2e0..4d0d2f1 100644
--- a/ui/views/events/event.h
+++ b/ui/views/events/event.h
@@ -410,6 +410,19 @@ class VIEWS_EXPORT DropTargetEvent : public LocatedEvent {
DISALLOW_COPY_AND_ASSIGN(DropTargetEvent);
};
+class VIEWS_EXPORT ScrollEvent : public MouseEvent {
+ public:
+ explicit ScrollEvent(const NativeEvent& native_event);
+ float x_offset() const { return x_offset_; }
+ float y_offset() const { return y_offset_; }
+
+ private:
+ float x_offset_;
+ float y_offset_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScrollEvent);
+};
+
} // namespace views
#endif // UI_VIEWS_EVENTS_EVENT_H_
diff --git a/ui/views/events/event_aura.cc b/ui/views/events/event_aura.cc
index 39ae3f7..9b3af83 100644
--- a/ui/views/events/event_aura.cc
+++ b/ui/views/events/event_aura.cc
@@ -59,4 +59,10 @@ MouseWheelEvent::MouseWheelEvent(const NativeEvent& native_event)
offset_(ui::GetMouseWheelOffset(native_event->native_event())) {
}
+ScrollEvent::ScrollEvent(const NativeEvent& native_event)
+ : MouseEvent(native_event) {
+ CHECK(ui::GetScrollOffsets(
+ native_event->native_event(), &x_offset_, &y_offset_));
+}
+
} // namespace views
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc
index 619018b..882a52e 100644
--- a/ui/views/widget/native_widget_aura.cc
+++ b/ui/views/widget/native_widget_aura.cc
@@ -651,6 +651,10 @@ bool NativeWidgetAura::OnMouseEvent(aura::MouseEvent* event) {
MouseWheelEvent wheel_event(event);
return delegate_->OnMouseEvent(wheel_event);
}
+ if (event->type() == ui::ET_SCROLL) {
+ ScrollEvent scroll_event(static_cast<aura::ScrollEvent*>(event));
+ return delegate_->OnMouseEvent(scroll_event);
+ }
MouseEvent mouse_event(event);
if (tooltip_manager_.get())
tooltip_manager_->UpdateTooltip();