diff options
author | ynovikov@chromium.org <ynovikov@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-20 02:12:45 +0000 |
---|---|---|
committer | ynovikov@chromium.org <ynovikov@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-20 02:12:45 +0000 |
commit | 2fef677f1d969249243685cf12b885395eac407f (patch) | |
tree | b1454d68bdab6ecce56c11254c0ea3a86b1e57eb /ui | |
parent | 077768766015caee7144ace4277232fe87007422 (diff) | |
download | chromium_src-2fef677f1d969249243685cf12b885395eac407f.zip chromium_src-2fef677f1d969249243685cf12b885395eac407f.tar.gz chromium_src-2fef677f1d969249243685cf12b885395eac407f.tar.bz2 |
Disable touch calibration on external touchscreen.
Move CalibrateTouchCoordinates() code from events_x.cc into
TouchEventCalibrate::Calibrate() and call it from
RootWindowHostLinux::DispatchXI2Event() only on internal display.
This changes the order in handling of a touch event.
Used to be: 1. Calibrate, 2. Find matching window, 3. Relocate to window origin
Now: 1. Find matching window, 2. Relocate, 3. Calibrate with matching window
This change in order:
a) Makes finding matching window simpler and faster.
b) Makes calibration more correct, since matching window bounds are used.
To make the calibration even more correct,
calibration parameters have to be adjusted for non-native resolutions.
BUG=171310,147605
TEST=Make sure touches are positioned correctly on internal and external
displays in single, extended desktop and mirror modes,
and when switching primary display.
Review URL: https://chromiumcodereview.appspot.com/12087124
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@189200 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r-- | ui/aura/root_window_host_linux.cc | 140 | ||||
-rw-r--r-- | ui/base/x/events_x.cc | 98 |
2 files changed, 113 insertions, 125 deletions
diff --git a/ui/aura/root_window_host_linux.cc b/ui/aura/root_window_host_linux.cc index a32b25c..edb27ec 100644 --- a/ui/aura/root_window_host_linux.cc +++ b/ui/aura/root_window_host_linux.cc @@ -21,6 +21,8 @@ #include "base/message_loop.h" #include "base/message_pump_aurax11.h" #include "base/stl_util.h" +#include "base/string_number_conversions.h" +#include "base/string_util.h" #include "base/stringprintf.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkCanvas.h" @@ -61,14 +63,6 @@ namespace { const int kBackMouseButton = 8; const int kForwardMouseButton = 9; -// These are the same values that are used to calibrate touch events in -// |CalibrateTouchCoordinates| (in ui/base/x/events_x.cc). -// TODO(sad|skuhne): Remove the duplication of values (http://crbug.com/147605) -const int kXRootWindowPaddingLeft = 40; -const int kXRootWindowPaddingRight = 40; -const int kXRootWindowPaddingBottom = 30; -const int kXRootWindowPaddingTop = 0; - const char* kAtomsToCache[] = { "WM_DELETE_WINDOW", "_NET_WM_PING", @@ -173,18 +167,102 @@ bool ShouldSendCharEventForKeyboardCode(ui::KeyboardCode keycode) { namespace internal { -// A very lightweight message-pump observer that routes all the touch events to -// the X root window so that they can be calibrated properly. +// Accomplishes 2 tasks concerning touch event calibration: +// 1. Being a message-pump observer, +// routes all the touch events to the X root window, +// where they can be calibrated later. +// 2. Has the Calibrate method that does the actual bezel calibration, +// when invoked from X root window's event dispatcher. class TouchEventCalibrate : public base::MessagePumpObserver { public: - TouchEventCalibrate() { + TouchEventCalibrate() + : left_(0), + right_(0), + top_(0), + bottom_(0) { MessageLoopForUI::current()->AddObserver(this); +#if defined(USE_XI2_MT) + std::vector<std::string> parts; + if (Tokenize(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + switches::kTouchCalibration), ",", &parts) >= 4) { + if (!base::StringToInt(parts[0], &left_)) + DLOG(ERROR) << "Incorrect left border calibration value passed."; + if (!base::StringToInt(parts[1], &right_)) + DLOG(ERROR) << "Incorrect right border calibration value passed."; + if (!base::StringToInt(parts[2], &top_)) + DLOG(ERROR) << "Incorrect top border calibration value passed."; + if (!base::StringToInt(parts[3], &bottom_)) + DLOG(ERROR) << "Incorrect bottom border calibration value passed."; + } +#endif // defined(USE_XI2_MT) } virtual ~TouchEventCalibrate() { MessageLoopForUI::current()->RemoveObserver(this); } + // Modify the location of the |event|, + // expanding it from |bounds| to (|bounds| + bezels). + // Required when touchscreen is bigger than screen (i.e. has bezels), + // because we receive events in touchscreen coordinates, + // which need to be expanded when converting to screen coordinates, + // so that location on bezels will be outside of screen area. + void Calibrate(ui::TouchEvent* event, const gfx::Rect& bounds) { +#if defined(USE_XI2_MT) + int x = event->x(); + int y = event->y(); + + if (!left_ && !right_ && !top_ && !bottom_) + return; + + const int resolution_x = bounds.width(); + const int resolution_y = bounds.height(); + // The "grace area" (10% in this case) is to make it easier for the user to + // navigate to the corner. + const double kGraceAreaFraction = 0.1; + if (left_ || right_) { + // Offset the x position to the real + x -= left_; + // Check if we are in the grace area of the left side. + // Note: We might not want to do this when the gesture is locked? + if (x < 0 && x > -left_ * kGraceAreaFraction) + x = 0; + // Check if we are in the grace area of the right side. + // Note: We might not want to do this when the gesture is locked? + if (x > resolution_x - left_ && + x < resolution_x - left_ + right_ * kGraceAreaFraction) + x = resolution_x - left_; + // Scale the screen area back to the full resolution of the screen. + x = (x * resolution_x) / (resolution_x - (right_ + left_)); + } + if (top_ || bottom_) { + // When there is a top bezel we add our border, + y -= top_; + + // Check if we are in the grace area of the top side. + // Note: We might not want to do this when the gesture is locked? + if (y < 0 && y > -top_ * kGraceAreaFraction) + y = 0; + + // Check if we are in the grace area of the bottom side. + // Note: We might not want to do this when the gesture is locked? + if (y > resolution_y - top_ && + y < resolution_y - top_ + bottom_ * kGraceAreaFraction) + y = resolution_y - top_; + // Scale the screen area back to the full resolution of the screen. + y = (y * resolution_y) / (resolution_y - (bottom_ + top_)); + } + + // Set the modified coordinate back to the event. + if (event->root_location() == event->location()) { + // Usually those will be equal, + // if not, I am not sure what the correct value should be. + event->set_root_location(gfx::Point(x, y)); + } + event->set_location(gfx::Point(x, y)); +#endif // defined(USE_XI2_MT) + } + private: // Overridden from base::MessagePumpObserver: virtual base::EventStatus WillProcessEvent( @@ -199,13 +277,21 @@ class TouchEventCalibrate : public base::MessagePumpObserver { xievent->event_x = xievent->root_x; xievent->event_y = xievent->root_y; } -#endif +#endif // defined(USE_XI2_MT) return base::EVENT_CONTINUE; } virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE { } + // The difference in screen's native resolution pixels between + // the border of the touchscreen and the border of the screen, + // aka bezel sizes. + int left_; + int right_; + int top_; + int bottom_; + DISALLOW_COPY_AND_ASSIGN(TouchEventCalibrate); }; @@ -904,24 +990,20 @@ void RootWindowHostLinux::DispatchXI2Event(const base::NativeEvent& event) { ui::TouchEvent touchev(xev); #if defined(OS_CHROMEOS) if (base::chromeos::IsRunningOnChromeOS()) { - if (!bounds_.Contains(touchev.location())) { - // This might still be in the bezel region. - gfx::Rect expanded(bounds_); - expanded.Inset(-kXRootWindowPaddingLeft, - -kXRootWindowPaddingTop, - -kXRootWindowPaddingRight, - -kXRootWindowPaddingBottom); - if (!expanded.Contains(touchev.location())) - break; - } + if (!bounds_.Contains(touchev.location())) + break; + // X maps the touch-surface to the size of the X root-window. + // In multi-monitor setup, Coordinate Transformation Matrix + // repositions the touch-surface onto part of X root-window + // containing aura root-window corresponding to the touchscreen. + // However, if aura root-window has non-zero origin, + // we need to relocate the event into aura root-window coordinates. + touchev.Relocate(bounds_.origin()); +#if defined(USE_XI2_MT) + if (is_internal_display_) + touch_calibrate_->Calibrate(&touchev, bounds_); +#endif // defined(USE_XI2_MT) } - // X maps the touch-surface to the size of the X root-window. - // In multi-monitor setup, Coordinate Transformation Matrix - // repositions the touch-surface onto part of X root-window - // containing aura root-window corresponding to the touchscreen. - // However, if aura root-window has non-zero origin, - // we need to relocate the event into aura root-window coordinates. - touchev.Relocate(bounds_.origin()); #endif // defined(OS_CHROMEOS) delegate_->OnHostTouchEvent(&touchev); break; diff --git a/ui/base/x/events_x.cc b/ui/base/x/events_x.cc index 7124c1a..f951a556 100644 --- a/ui/base/x/events_x.cc +++ b/ui/base/x/events_x.cc @@ -9,16 +9,12 @@ #include <X11/extensions/XInput2.h> #include <X11/Xlib.h> -#include "base/command_line.h" #include "base/logging.h" #include "base/memory/singleton.h" #include "base/message_pump_aurax11.h" -#include "base/string_number_conversions.h" -#include "base/strings/string_split.h" #include "ui/base/events/event_utils.h" #include "ui/base/keycodes/keyboard_code_conversion_x.h" #include "ui/base/touch/touch_factory.h" -#include "ui/base/ui_base_switches.h" #include "ui/base/x/device_list_cache_x.h" #include "ui/base/x/valuators.h" #include "ui/base/x/x11_atom_cache.h" @@ -79,17 +75,6 @@ const char* kCMTCachedAtoms[] = { NULL }; -#if defined(USE_XI2_MT) -// If the calibration values were read, if this is true. -bool calibration_values_read = false; - -// The (positive) calibration values for the four border sides. -int left_border_touch_calibration = 0; -int top_border_touch_calibration = 0; -int right_border_touch_calibration = 0; -int bottom_border_touch_calibration = 0; -#endif - // A class to support the detection of scroll events, using X11 valuators. class CMTEventData { public: @@ -686,86 +671,6 @@ Atom GetNoopEventAtom() { "noop", False); } -#if defined(USE_XI2_MT) - -void ReadTouchCalibrationValues() { - calibration_values_read = true; - - std::vector<std::string> parts; - base::SplitString(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - switches::kTouchCalibration), ',', &parts); - if (parts.size() >= 4) { - if (!base::StringToInt(parts[0], &left_border_touch_calibration)) - DLOG(ERROR) << "Incorrect left border calibration value passed."; - if (!base::StringToInt(parts[1], &right_border_touch_calibration)) - DLOG(ERROR) << "Incorrect right border calibration value passed."; - if (!base::StringToInt(parts[2], &top_border_touch_calibration)) - DLOG(ERROR) << "Incorrect top border calibration value passed."; - if (!base::StringToInt(parts[3], &bottom_border_touch_calibration)) - DLOG(ERROR) << "Incorrect bottom border calibration value passed."; - } -} - -gfx::Point CalibrateTouchCoordinates( - const XIDeviceEvent* xievent) { - int x = static_cast<int>(xievent->event_x); - int y = static_cast<int>(xievent->event_y); - - if (!calibration_values_read) - ReadTouchCalibrationValues(); - - if (!left_border_touch_calibration && !right_border_touch_calibration && - !top_border_touch_calibration && !bottom_border_touch_calibration) - return gfx::Point(x, y); - - gfx::Display display = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay(); - gfx::Rect bounds = display.bounds(); - const int resolution_x = bounds.width() * display.device_scale_factor(); - const int resolution_y = bounds.height() * display.device_scale_factor(); - // The "grace area" (10% in this case) is to make it easier for the user to - // navigate to the corner. - const double kGraceAreaFraction = 0.1; - if (left_border_touch_calibration || right_border_touch_calibration) { - // Offset the x position to the real - x -= left_border_touch_calibration; - // Check if we are in the grace area of the left side. - // Note: We might not want to do this when the gesture is locked? - if (x < 0 && x > -left_border_touch_calibration * kGraceAreaFraction) - x = 0; - // Check if we are in the grace area of the right side. - // Note: We might not want to do this when the gesture is locked? - if (x > resolution_x - left_border_touch_calibration && - x < resolution_x - left_border_touch_calibration + - right_border_touch_calibration * kGraceAreaFraction) - x = resolution_x - left_border_touch_calibration; - // Scale the screen area back to the full resolution of the screen. - x = (x * resolution_x) / (resolution_x - (right_border_touch_calibration + - left_border_touch_calibration)); - } - if (top_border_touch_calibration || bottom_border_touch_calibration) { - // When there is a top bezel we add our border, - y -= top_border_touch_calibration; - - // Check if we are in the grace area of the top side. - // Note: We might not want to do this when the gesture is locked? - if (y < 0 && y > -top_border_touch_calibration * kGraceAreaFraction) - y = 0; - - // Check if we are in the grace area of the bottom side. - // Note: We might not want to do this when the gesture is locked? - if (y > resolution_y - top_border_touch_calibration && - y < resolution_y - top_border_touch_calibration + - bottom_border_touch_calibration * kGraceAreaFraction) - y = resolution_y - top_border_touch_calibration; - // Scale the screen area back to the full resolution of the screen. - y = (y * resolution_y) / (resolution_y - (bottom_border_touch_calibration + - top_border_touch_calibration)); - } - // Set the modified coordinate back to the event. - return gfx::Point(x, y); -} -#endif // defined(USE_XI2_MT) - } // namespace namespace ui { @@ -966,7 +871,8 @@ gfx::Point EventLocationFromNative(const base::NativeEvent& native_event) { xievent->evtype == XI_TouchUpdate || xievent->evtype == XI_TouchEnd) // Note: Touch events are always touch screen events. - return CalibrateTouchCoordinates(xievent); + return gfx::Point(static_cast<int>(xievent->event_x), + static_cast<int>(xievent->event_y)); #endif // Read the position from the valuators, because the location reported in // event_x/event_y seems to be different (and doesn't match for events |