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 |