| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/aura/window_tree_host_x11.h" | 5 #include "ui/aura/window_tree_host_x11.h" |
| 6 | 6 |
| 7 #include <strings.h> | 7 #include <strings.h> |
| 8 #include <X11/cursorfont.h> | 8 #include <X11/cursorfont.h> |
| 9 #include <X11/extensions/XInput2.h> | 9 #include <X11/extensions/XInput2.h> |
| 10 #include <X11/extensions/Xrandr.h> | 10 #include <X11/extensions/Xrandr.h> |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 XISetMask(mask, XI_TouchEnd); | 96 XISetMask(mask, XI_TouchEnd); |
| 97 XISelectEvents(display, root_window, &evmask, 1); | 97 XISelectEvents(display, root_window, &evmask, 1); |
| 98 } | 98 } |
| 99 #endif | 99 #endif |
| 100 } | 100 } |
| 101 | 101 |
| 102 bool default_override_redirect = false; | 102 bool default_override_redirect = false; |
| 103 | 103 |
| 104 } // namespace | 104 } // namespace |
| 105 | 105 |
| 106 namespace internal { | |
| 107 | |
| 108 // TODO(miletus) : Move this into DeviceDataManager. | |
| 109 // Accomplishes 2 tasks concerning touch event calibration: | |
| 110 // 1. Being a message-pump observer, | |
| 111 // routes all the touch events to the X root window, | |
| 112 // where they can be calibrated later. | |
| 113 // 2. Has the Calibrate method that does the actual bezel calibration, | |
| 114 // when invoked from X root window's event dispatcher. | |
| 115 class TouchEventCalibrate : public ui::PlatformEventObserver { | |
| 116 public: | |
| 117 TouchEventCalibrate() : left_(0), right_(0), top_(0), bottom_(0) { | |
| 118 if (ui::PlatformEventSource::GetInstance()) | |
| 119 ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this); | |
| 120 std::vector<std::string> parts = base::SplitString( | |
| 121 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | |
| 122 switches::kTouchCalibration), | |
| 123 ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); | |
| 124 if (parts.size() >= 4) { | |
| 125 if (!base::StringToInt(parts[0], &left_)) | |
| 126 DLOG(ERROR) << "Incorrect left border calibration value passed."; | |
| 127 if (!base::StringToInt(parts[1], &right_)) | |
| 128 DLOG(ERROR) << "Incorrect right border calibration value passed."; | |
| 129 if (!base::StringToInt(parts[2], &top_)) | |
| 130 DLOG(ERROR) << "Incorrect top border calibration value passed."; | |
| 131 if (!base::StringToInt(parts[3], &bottom_)) | |
| 132 DLOG(ERROR) << "Incorrect bottom border calibration value passed."; | |
| 133 } | |
| 134 } | |
| 135 | |
| 136 ~TouchEventCalibrate() override { | |
| 137 if (ui::PlatformEventSource::GetInstance()) | |
| 138 ui::PlatformEventSource::GetInstance()->RemovePlatformEventObserver(this); | |
| 139 } | |
| 140 | |
| 141 // Modify the location of the |event|, | |
| 142 // expanding it from |bounds| to (|bounds| + bezels). | |
| 143 // Required when touchscreen is bigger than screen (i.e. has bezels), | |
| 144 // because we receive events in touchscreen coordinates, | |
| 145 // which need to be expanded when converting to screen coordinates, | |
| 146 // so that location on bezels will be outside of screen area. | |
| 147 void Calibrate(ui::TouchEvent* event, const gfx::Rect& bounds) { | |
| 148 int x = event->x(); | |
| 149 int y = event->y(); | |
| 150 | |
| 151 if (!left_ && !right_ && !top_ && !bottom_) | |
| 152 return; | |
| 153 | |
| 154 const int resolution_x = bounds.width(); | |
| 155 const int resolution_y = bounds.height(); | |
| 156 if (left_ || right_) { | |
| 157 // Offset the x position to the real | |
| 158 x -= left_; | |
| 159 // Scale the screen area back to the full resolution of the screen. | |
| 160 x = (x * resolution_x) / (resolution_x - (right_ + left_)); | |
| 161 } | |
| 162 if (top_ || bottom_) { | |
| 163 // When there is a top bezel we add our border, | |
| 164 y -= top_; | |
| 165 // Scale the screen area back to the full resolution of the screen. | |
| 166 y = (y * resolution_y) / (resolution_y - (bottom_ + top_)); | |
| 167 } | |
| 168 | |
| 169 // Set the modified coordinate back to the event. | |
| 170 if (event->root_location() == event->location()) { | |
| 171 // Usually those will be equal, | |
| 172 // if not, I am not sure what the correct value should be. | |
| 173 event->set_root_location(gfx::Point(x, y)); | |
| 174 } | |
| 175 event->set_location(gfx::Point(x, y)); | |
| 176 } | |
| 177 | |
| 178 private: | |
| 179 // ui::PlatformEventObserver: | |
| 180 void WillProcessEvent(const ui::PlatformEvent& event) override { | |
| 181 if (event->type == GenericEvent && | |
| 182 (event->xgeneric.evtype == XI_TouchBegin || | |
| 183 event->xgeneric.evtype == XI_TouchUpdate || | |
| 184 event->xgeneric.evtype == XI_TouchEnd)) { | |
| 185 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(event->xcookie.data); | |
| 186 xievent->event = xievent->root; | |
| 187 xievent->event_x = xievent->root_x; | |
| 188 xievent->event_y = xievent->root_y; | |
| 189 } | |
| 190 } | |
| 191 | |
| 192 void DidProcessEvent(const ui::PlatformEvent& event) override {} | |
| 193 | |
| 194 // The difference in screen's native resolution pixels between | |
| 195 // the border of the touchscreen and the border of the screen, | |
| 196 // aka bezel sizes. | |
| 197 int left_; | |
| 198 int right_; | |
| 199 int top_; | |
| 200 int bottom_; | |
| 201 | |
| 202 DISALLOW_COPY_AND_ASSIGN(TouchEventCalibrate); | |
| 203 }; | |
| 204 | |
| 205 } // namespace internal | |
| 206 | |
| 207 //////////////////////////////////////////////////////////////////////////////// | 106 //////////////////////////////////////////////////////////////////////////////// |
| 208 // WindowTreeHostX11 | 107 // WindowTreeHostX11 |
| 209 | 108 |
| 210 WindowTreeHostX11::WindowTreeHostX11(const gfx::Rect& bounds) | 109 WindowTreeHostX11::WindowTreeHostX11(const gfx::Rect& bounds) |
| 211 : xdisplay_(gfx::GetXDisplay()), | 110 : xdisplay_(gfx::GetXDisplay()), |
| 212 xwindow_(0), | 111 xwindow_(0), |
| 213 x_root_window_(DefaultRootWindow(xdisplay_)), | 112 x_root_window_(DefaultRootWindow(xdisplay_)), |
| 214 current_cursor_(ui::kCursorNull), | 113 current_cursor_(ui::kCursorNull), |
| 215 window_mapped_(false), | 114 window_mapped_(false), |
| 216 bounds_(bounds), | 115 bounds_(bounds), |
| 217 touch_calibrate_(new internal::TouchEventCalibrate), | |
| 218 atom_cache_(xdisplay_, kAtomsToCache) { | 116 atom_cache_(xdisplay_, kAtomsToCache) { |
| 219 XSetWindowAttributes swa; | 117 XSetWindowAttributes swa; |
| 220 memset(&swa, 0, sizeof(swa)); | 118 memset(&swa, 0, sizeof(swa)); |
| 221 swa.background_pixmap = None; | 119 swa.background_pixmap = None; |
| 222 swa.bit_gravity = NorthWestGravity; | 120 swa.bit_gravity = NorthWestGravity; |
| 223 swa.override_redirect = default_override_redirect; | 121 swa.override_redirect = default_override_redirect; |
| 224 xwindow_ = XCreateWindow( | 122 xwindow_ = XCreateWindow( |
| 225 xdisplay_, x_root_window_, | 123 xdisplay_, x_root_window_, |
| 226 bounds.x(), bounds.y(), bounds.width(), bounds.height(), | 124 bounds.x(), bounds.y(), bounds.width(), bounds.height(), |
| 227 0, // border width | 125 0, // border width |
| (...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 bounds_.x() + location.x(), | 463 bounds_.x() + location.x(), |
| 566 bounds_.y() + location.y()); | 464 bounds_.y() + location.y()); |
| 567 } | 465 } |
| 568 | 466 |
| 569 void WindowTreeHostX11::OnCursorVisibilityChangedNative(bool show) { | 467 void WindowTreeHostX11::OnCursorVisibilityChangedNative(bool show) { |
| 570 } | 468 } |
| 571 | 469 |
| 572 void WindowTreeHostX11::DispatchXI2Event(const base::NativeEvent& event) { | 470 void WindowTreeHostX11::DispatchXI2Event(const base::NativeEvent& event) { |
| 573 ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); | 471 ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); |
| 574 XEvent* xev = event; | 472 XEvent* xev = event; |
| 575 XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev->xcookie.data); | |
| 576 if (!factory->ShouldProcessXI2Event(xev)) | 473 if (!factory->ShouldProcessXI2Event(xev)) |
| 577 return; | 474 return; |
| 578 | 475 |
| 579 TRACE_EVENT1("input", "WindowTreeHostX11::DispatchXI2Event", | 476 TRACE_EVENT1("input", "WindowTreeHostX11::DispatchXI2Event", |
| 580 "event_latency_us", | 477 "event_latency_us", |
| 581 (ui::EventTimeForNow() - ui::EventTimeFromNative(event)). | 478 (ui::EventTimeForNow() - ui::EventTimeFromNative(event)). |
| 582 InMicroseconds()); | 479 InMicroseconds()); |
| 583 | 480 |
| 584 int num_coalesced = 0; | 481 int num_coalesced = 0; |
| 585 XEvent last_event; | 482 XEvent last_event; |
| 586 if (xev->xgeneric.evtype == XI_Motion) { | 483 if (xev->xgeneric.evtype == XI_Motion) { |
| 587 // If this is a motion event, we want to coalesce all pending motion | 484 // If this is a motion event, we want to coalesce all pending motion |
| 588 // events that are at the top of the queue. Note, we don't coalesce | 485 // events that are at the top of the queue. Note, we don't coalesce |
| 589 // touch update events here. | 486 // touch update events here. |
| 590 num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event); | 487 num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event); |
| 591 if (num_coalesced > 0) | 488 if (num_coalesced > 0) |
| 592 xev = &last_event; | 489 xev = &last_event; |
| 593 } | 490 } |
| 594 ui::EventType type = ui::EventTypeFromNative(xev); | 491 ui::EventType type = ui::EventTypeFromNative(xev); |
| 595 | 492 |
| 596 switch (type) { | 493 switch (type) { |
| 597 case ui::ET_TOUCH_MOVED: | 494 case ui::ET_TOUCH_MOVED: |
| 598 case ui::ET_TOUCH_PRESSED: | 495 case ui::ET_TOUCH_PRESSED: |
| 599 case ui::ET_TOUCH_CANCELLED: | 496 case ui::ET_TOUCH_CANCELLED: |
| 600 case ui::ET_TOUCH_RELEASED: { | 497 case ui::ET_TOUCH_RELEASED: { |
| 601 ui::TouchEvent touchev(xev); | 498 ui::TouchEvent touchev(xev); |
| 602 if (ui::DeviceDataManagerX11::GetInstance()->TouchEventNeedsCalibrate( | |
| 603 xiev->deviceid)) { | |
| 604 touch_calibrate_->Calibrate(&touchev, bounds_); | |
| 605 } | |
| 606 TranslateAndDispatchLocatedEvent(&touchev); | 499 TranslateAndDispatchLocatedEvent(&touchev); |
| 607 break; | 500 break; |
| 608 } | 501 } |
| 609 case ui::ET_MOUSE_MOVED: | 502 case ui::ET_MOUSE_MOVED: |
| 610 case ui::ET_MOUSE_DRAGGED: | 503 case ui::ET_MOUSE_DRAGGED: |
| 611 case ui::ET_MOUSE_PRESSED: | 504 case ui::ET_MOUSE_PRESSED: |
| 612 case ui::ET_MOUSE_RELEASED: | 505 case ui::ET_MOUSE_RELEASED: |
| 613 case ui::ET_MOUSE_ENTERED: | 506 case ui::ET_MOUSE_ENTERED: |
| 614 case ui::ET_MOUSE_EXITED: { | 507 case ui::ET_MOUSE_EXITED: { |
| 615 ui::MouseEvent mouseev(xev); | 508 ui::MouseEvent mouseev(xev); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 664 } | 557 } |
| 665 | 558 |
| 666 namespace test { | 559 namespace test { |
| 667 | 560 |
| 668 void SetUseOverrideRedirectWindowByDefault(bool override_redirect) { | 561 void SetUseOverrideRedirectWindowByDefault(bool override_redirect) { |
| 669 default_override_redirect = override_redirect; | 562 default_override_redirect = override_redirect; |
| 670 } | 563 } |
| 671 | 564 |
| 672 } // namespace test | 565 } // namespace test |
| 673 } // namespace aura | 566 } // namespace aura |
| OLD | NEW |