OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/desktop_host.h" | 5 #include "ui/aura/desktop_host.h" |
6 | 6 |
7 #include <X11/cursorfont.h> | 7 #include <X11/cursorfont.h> |
8 #include <X11/Xlib.h> | 8 #include <X11/Xlib.h> |
9 | 9 |
10 // Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class. | 10 // Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class. |
(...skipping 15 matching lines...) Expand all Loading... |
26 #include <X11/extensions/XInput2.h> | 26 #include <X11/extensions/XInput2.h> |
27 #include <X11/Xlib.h> | 27 #include <X11/Xlib.h> |
28 | 28 |
29 using std::max; | 29 using std::max; |
30 using std::min; | 30 using std::min; |
31 | 31 |
32 namespace aura { | 32 namespace aura { |
33 | 33 |
34 namespace { | 34 namespace { |
35 | 35 |
| 36 // The events reported for slave devices can have incorrect information for some |
| 37 // fields. This utility function is used to check for such inconsistencies. |
| 38 void CheckXEventForConsistency(XEvent* xevent) { |
| 39 static bool expect_master_event = false; |
| 40 static XIDeviceEvent slave_event; |
| 41 static gfx::Point slave_location; |
| 42 |
| 43 // Note: If an event comes from a slave pointer device, then it will be |
| 44 // followed by the same event, but reported from its master pointer device. |
| 45 // However, if the event comes from a floating slave device (e.g. a |
| 46 // touchscreen), then it will not be followed by a duplicate event, since the |
| 47 // floating slave isn't attached to a master. |
| 48 |
| 49 bool was_expecting_master_event = expect_master_event; |
| 50 expect_master_event = false; |
| 51 |
| 52 if (!xevent || xevent->type != GenericEvent) |
| 53 return; |
| 54 |
| 55 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xevent->xcookie.data); |
| 56 if (xievent->evtype != XI_Motion && |
| 57 xievent->evtype != XI_ButtonPress && |
| 58 xievent->evtype != XI_ButtonRelease) { |
| 59 return; |
| 60 } |
| 61 |
| 62 if (xievent->sourceid == xievent->deviceid) { |
| 63 slave_event = *xievent; |
| 64 slave_location = ui::EventLocationFromNative(xevent); |
| 65 expect_master_event = true; |
| 66 } else if (was_expecting_master_event) { |
| 67 CHECK_EQ(slave_location.x(), ui::EventLocationFromNative(xevent).x()); |
| 68 CHECK_EQ(slave_location.y(), ui::EventLocationFromNative(xevent).y()); |
| 69 |
| 70 CHECK_EQ(slave_event.type, xievent->type); |
| 71 CHECK_EQ(slave_event.evtype, xievent->evtype); |
| 72 CHECK_EQ(slave_event.detail, xievent->detail); |
| 73 CHECK_EQ(slave_event.flags, xievent->flags); |
| 74 CHECK_EQ(slave_event.buttons.mask_len, xievent->buttons.mask_len); |
| 75 CHECK_EQ(slave_event.valuators.mask_len, xievent->valuators.mask_len); |
| 76 CHECK_EQ(slave_event.mods.base, xievent->mods.base); |
| 77 CHECK_EQ(slave_event.mods.latched, xievent->mods.latched); |
| 78 CHECK_EQ(slave_event.mods.locked, xievent->mods.locked); |
| 79 CHECK_EQ(slave_event.mods.effective, xievent->mods.effective); |
| 80 } |
| 81 } |
| 82 |
36 // Returns X font cursor shape from an Aura cursor. | 83 // Returns X font cursor shape from an Aura cursor. |
37 int CursorShapeFromNative(gfx::NativeCursor native_cursor) { | 84 int CursorShapeFromNative(gfx::NativeCursor native_cursor) { |
38 switch (native_cursor) { | 85 switch (native_cursor) { |
39 case aura::kCursorNull: | 86 case aura::kCursorNull: |
40 return XC_left_ptr; | 87 return XC_left_ptr; |
41 case aura::kCursorPointer: | 88 case aura::kCursorPointer: |
42 return XC_left_ptr; | 89 return XC_left_ptr; |
43 case aura::kCursorCross: | 90 case aura::kCursorCross: |
44 return XC_crosshair; | 91 return XC_crosshair; |
45 case aura::kCursorHand: | 92 case aura::kCursorHand: |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 | 181 |
135 // If we can't get the cookie, abort the check. | 182 // If we can't get the cookie, abort the check. |
136 if (!XGetEventData(next_event.xgeneric.display, &next_event.xcookie)) | 183 if (!XGetEventData(next_event.xgeneric.display, &next_event.xcookie)) |
137 return num_coalesed; | 184 return num_coalesed; |
138 | 185 |
139 // If this isn't from a valid device, throw the event away, as | 186 // If this isn't from a valid device, throw the event away, as |
140 // that's what the message pump would do. Device events come in pairs | 187 // that's what the message pump would do. Device events come in pairs |
141 // with one from the master and one from the slave so there will | 188 // with one from the master and one from the slave so there will |
142 // always be at least one pending. | 189 // always be at least one pending. |
143 if (!ui::TouchFactory::GetInstance()->ShouldProcessXI2Event(&next_event)) { | 190 if (!ui::TouchFactory::GetInstance()->ShouldProcessXI2Event(&next_event)) { |
| 191 CheckXEventForConsistency(&next_event); |
144 XFreeEventData(display, &next_event.xcookie); | 192 XFreeEventData(display, &next_event.xcookie); |
145 XNextEvent(display, &next_event); | 193 XNextEvent(display, &next_event); |
146 continue; | 194 continue; |
147 } | 195 } |
148 | 196 |
149 if (next_event.type == GenericEvent && | 197 if (next_event.type == GenericEvent && |
150 next_event.xgeneric.evtype == XI_Motion) { | 198 next_event.xgeneric.evtype == XI_Motion) { |
151 XIDeviceEvent* next_xievent = | 199 XIDeviceEvent* next_xievent = |
152 static_cast<XIDeviceEvent*>(next_event.xcookie.data); | 200 static_cast<XIDeviceEvent*>(next_event.xcookie.data); |
153 // Confirm that the motion event is targeted at the same window | 201 // Confirm that the motion event is targeted at the same window |
154 // and that no buttons or modifiers have changed. | 202 // and that no buttons or modifiers have changed. |
155 if (xievent->event == next_xievent->event && | 203 if (xievent->event == next_xievent->event && |
156 xievent->child == next_xievent->child && | 204 xievent->child == next_xievent->child && |
157 xievent->buttons.mask_len == next_xievent->buttons.mask_len && | 205 xievent->buttons.mask_len == next_xievent->buttons.mask_len && |
158 (memcmp(xievent->buttons.mask, | 206 (memcmp(xievent->buttons.mask, |
159 next_xievent->buttons.mask, | 207 next_xievent->buttons.mask, |
160 xievent->buttons.mask_len) == 0) && | 208 xievent->buttons.mask_len) == 0) && |
161 xievent->mods.base == next_xievent->mods.base && | 209 xievent->mods.base == next_xievent->mods.base && |
162 xievent->mods.latched == next_xievent->mods.latched && | 210 xievent->mods.latched == next_xievent->mods.latched && |
163 xievent->mods.locked == next_xievent->mods.locked && | 211 xievent->mods.locked == next_xievent->mods.locked && |
164 xievent->mods.effective == next_xievent->mods.effective) { | 212 xievent->mods.effective == next_xievent->mods.effective) { |
165 XFreeEventData(display, &next_event.xcookie); | 213 XFreeEventData(display, &next_event.xcookie); |
166 // Free the previous cookie. | 214 // Free the previous cookie. |
167 if (num_coalesed > 0) | 215 if (num_coalesed > 0) |
168 XFreeEventData(display, &last_event->xcookie); | 216 XFreeEventData(display, &last_event->xcookie); |
169 // Get the event and its cookie data. | 217 // Get the event and its cookie data. |
170 XNextEvent(display, last_event); | 218 XNextEvent(display, last_event); |
171 XGetEventData(display, &last_event->xcookie); | 219 XGetEventData(display, &last_event->xcookie); |
| 220 CheckXEventForConsistency(last_event); |
172 ++num_coalesed; | 221 ++num_coalesed; |
173 continue; | 222 continue; |
174 } else { | 223 } else { |
175 // This isn't an event we want so free its cookie data. | 224 // This isn't an event we want so free its cookie data. |
176 XFreeEventData(display, &next_event.xcookie); | 225 XFreeEventData(display, &next_event.xcookie); |
177 } | 226 } |
178 } | 227 } |
179 break; | 228 break; |
180 } | 229 } |
181 return num_coalesed; | 230 return num_coalesed; |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 root_window_(DefaultRootWindow(xdisplay_)), | 322 root_window_(DefaultRootWindow(xdisplay_)), |
274 current_cursor_(aura::kCursorNull), | 323 current_cursor_(aura::kCursorNull), |
275 bounds_(bounds) { | 324 bounds_(bounds) { |
276 xwindow_ = XCreateSimpleWindow(xdisplay_, root_window_, | 325 xwindow_ = XCreateSimpleWindow(xdisplay_, root_window_, |
277 bounds.x(), bounds.y(), | 326 bounds.x(), bounds.y(), |
278 bounds.width(), bounds.height(), | 327 bounds.width(), bounds.height(), |
279 0, 0, 0); | 328 0, 0, 0); |
280 | 329 |
281 long event_mask = ButtonPressMask | ButtonReleaseMask | | 330 long event_mask = ButtonPressMask | ButtonReleaseMask | |
282 KeyPressMask | KeyReleaseMask | | 331 KeyPressMask | KeyReleaseMask | |
| 332 EnterWindowMask | LeaveWindowMask | |
283 ExposureMask | VisibilityChangeMask | | 333 ExposureMask | VisibilityChangeMask | |
284 StructureNotifyMask | PropertyChangeMask | | 334 StructureNotifyMask | PropertyChangeMask | |
285 PointerMotionMask; | 335 PointerMotionMask; |
286 XSelectInput(xdisplay_, xwindow_, event_mask); | 336 XSelectInput(xdisplay_, xwindow_, event_mask); |
287 XSelectInput(xdisplay_, root_window_, StructureNotifyMask); | 337 XSelectInput(xdisplay_, root_window_, StructureNotifyMask); |
288 XFlush(xdisplay_); | 338 XFlush(xdisplay_); |
289 | 339 |
290 // TODO(sadrul): reenable once 103981 is fixed. | |
291 #if defined(TOUCH_UI) | |
292 if (base::MessagePumpForUI::HasXInput2()) | 340 if (base::MessagePumpForUI::HasXInput2()) |
293 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); | 341 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); |
294 #endif | |
295 } | 342 } |
296 | 343 |
297 DesktopHostLinux::~DesktopHostLinux() { | 344 DesktopHostLinux::~DesktopHostLinux() { |
298 XDestroyWindow(xdisplay_, xwindow_); | 345 XDestroyWindow(xdisplay_, xwindow_); |
299 | 346 |
300 // Clears XCursorCache. | 347 // Clears XCursorCache. |
301 ui::GetXCursor(ui::kCursorClearXCursorCache); | 348 ui::GetXCursor(ui::kCursorClearXCursorCache); |
302 } | 349 } |
303 | 350 |
304 base::MessagePumpDispatcher::DispatchStatus DesktopHostLinux::Dispatch( | 351 base::MessagePumpDispatcher::DispatchStatus DesktopHostLinux::Dispatch( |
305 XEvent* xev) { | 352 XEvent* xev) { |
306 DLOG(WARNING) << "DispatchEvent:" << xev->type; | 353 DLOG(WARNING) << "DispatchEvent:" << xev->type; |
307 | 354 |
308 bool handled = false; | 355 bool handled = false; |
| 356 |
| 357 CheckXEventForConsistency(xev); |
| 358 |
309 switch (xev->type) { | 359 switch (xev->type) { |
310 case Expose: | 360 case Expose: |
311 desktop_->Draw(); | 361 desktop_->Draw(); |
312 handled = true; | 362 handled = true; |
313 break; | 363 break; |
314 case KeyPress: { | 364 case KeyPress: { |
315 KeyEvent keydown_event(xev, false); | 365 KeyEvent keydown_event(xev, false); |
316 handled = desktop_->DispatchKeyEvent(&keydown_event); | 366 handled = desktop_->DispatchKeyEvent(&keydown_event); |
317 if (ShouldSendCharEventForKeyboardCode(keydown_event.key_code())) { | 367 if (ShouldSendCharEventForKeyboardCode(keydown_event.key_code())) { |
318 KeyEvent char_event(xev, true); | 368 KeyEvent char_event(xev, true); |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
548 return new DesktopHostLinux(bounds); | 598 return new DesktopHostLinux(bounds); |
549 } | 599 } |
550 | 600 |
551 // static | 601 // static |
552 gfx::Size DesktopHost::GetNativeScreenSize() { | 602 gfx::Size DesktopHost::GetNativeScreenSize() { |
553 ::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay(); | 603 ::Display* xdisplay = base::MessagePumpX::GetDefaultXDisplay(); |
554 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); | 604 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); |
555 } | 605 } |
556 | 606 |
557 } // namespace aura | 607 } // namespace aura |
OLD | NEW |