Roll src/third_party/WebKit 06cb9e9:a978ee5 (svn 202558:202559)
[chromium-blink-merge.git] / ui / aura / window_tree_host_x11.cc
blob084296c34086b8ab8e2c9a20912036b04dedf0be
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
3 // found in the LICENSE file.
5 #include "ui/aura/window_tree_host_x11.h"
7 #include <strings.h>
8 #include <X11/cursorfont.h>
9 #include <X11/extensions/XInput2.h>
10 #include <X11/extensions/Xrandr.h>
11 #include <X11/Xatom.h>
12 #include <X11/Xcursor/Xcursor.h>
13 #include <X11/Xlib.h>
15 #include <algorithm>
16 #include <limits>
17 #include <string>
19 #include "base/basictypes.h"
20 #include "base/command_line.h"
21 #include "base/stl_util.h"
22 #include "base/strings/string_number_conversions.h"
23 #include "base/strings/string_split.h"
24 #include "base/strings/string_util.h"
25 #include "base/strings/stringprintf.h"
26 #include "base/sys_info.h"
27 #include "base/trace_event/trace_event.h"
28 #include "ui/aura/client/cursor_client.h"
29 #include "ui/aura/env.h"
30 #include "ui/aura/window.h"
31 #include "ui/aura/window_event_dispatcher.h"
32 #include "ui/base/cursor/cursor.h"
33 #include "ui/base/ui_base_switches.h"
34 #include "ui/base/view_prop.h"
35 #include "ui/base/x/x11_util.h"
36 #include "ui/compositor/compositor.h"
37 #include "ui/compositor/dip_util.h"
38 #include "ui/compositor/layer.h"
39 #include "ui/events/devices/x11/device_data_manager_x11.h"
40 #include "ui/events/devices/x11/device_list_cache_x11.h"
41 #include "ui/events/devices/x11/touch_factory_x11.h"
42 #include "ui/events/event.h"
43 #include "ui/events/event_switches.h"
44 #include "ui/events/event_utils.h"
45 #include "ui/events/keycodes/keyboard_codes.h"
46 #include "ui/events/platform/platform_event_observer.h"
47 #include "ui/events/platform/x11/x11_event_source.h"
48 #include "ui/gfx/screen.h"
50 using std::max;
51 using std::min;
53 namespace aura {
55 namespace {
57 const char* kAtomsToCache[] = {
58 "WM_DELETE_WINDOW",
59 "_NET_WM_PING",
60 "_NET_WM_PID",
61 NULL
64 ::Window FindEventTarget(const base::NativeEvent& xev) {
65 ::Window target = xev->xany.window;
66 if (xev->type == GenericEvent)
67 target = static_cast<XIDeviceEvent*>(xev->xcookie.data)->event;
68 return target;
71 void SelectXInput2EventsForRootWindow(XDisplay* display, ::Window root_window) {
72 CHECK(ui::IsXInput2Available());
73 unsigned char mask[XIMaskLen(XI_LASTEVENT)] = {};
74 memset(mask, 0, sizeof(mask));
76 XISetMask(mask, XI_HierarchyChanged);
78 XIEventMask evmask;
79 evmask.deviceid = XIAllDevices;
80 evmask.mask_len = sizeof(mask);
81 evmask.mask = mask;
82 XISelectEvents(display, root_window, &evmask, 1);
84 #if defined(OS_CHROMEOS)
85 if (base::SysInfo::IsRunningOnChromeOS()) {
86 // It is necessary to listen for touch events on the root window for proper
87 // touch event calibration on Chrome OS, but this is not currently necessary
88 // on the desktop. This seems to fail in some cases (e.g. when logging
89 // in incognito). So select for non-touch events first, and then select for
90 // touch-events (but keep the other events in the mask, i.e. do not memset
91 // |mask| back to 0).
92 // TODO(sad): Figure out why this happens. http://crbug.com/153976
93 XISetMask(mask, XI_TouchBegin);
94 XISetMask(mask, XI_TouchUpdate);
95 XISetMask(mask, XI_TouchEnd);
96 XISelectEvents(display, root_window, &evmask, 1);
98 #endif
101 bool default_override_redirect = false;
103 } // namespace
105 namespace internal {
107 // TODO(miletus) : Move this into DeviceDataManager.
108 // Accomplishes 2 tasks concerning touch event calibration:
109 // 1. Being a message-pump observer,
110 // routes all the touch events to the X root window,
111 // where they can be calibrated later.
112 // 2. Has the Calibrate method that does the actual bezel calibration,
113 // when invoked from X root window's event dispatcher.
114 class TouchEventCalibrate : public ui::PlatformEventObserver {
115 public:
116 TouchEventCalibrate() : left_(0), right_(0), top_(0), bottom_(0) {
117 if (ui::PlatformEventSource::GetInstance())
118 ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this);
119 std::vector<std::string> parts = base::SplitString(
120 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
121 switches::kTouchCalibration),
122 ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
123 if (parts.size() >= 4) {
124 if (!base::StringToInt(parts[0], &left_))
125 DLOG(ERROR) << "Incorrect left border calibration value passed.";
126 if (!base::StringToInt(parts[1], &right_))
127 DLOG(ERROR) << "Incorrect right border calibration value passed.";
128 if (!base::StringToInt(parts[2], &top_))
129 DLOG(ERROR) << "Incorrect top border calibration value passed.";
130 if (!base::StringToInt(parts[3], &bottom_))
131 DLOG(ERROR) << "Incorrect bottom border calibration value passed.";
135 ~TouchEventCalibrate() override {
136 if (ui::PlatformEventSource::GetInstance())
137 ui::PlatformEventSource::GetInstance()->RemovePlatformEventObserver(this);
140 // Modify the location of the |event|,
141 // expanding it from |bounds| to (|bounds| + bezels).
142 // Required when touchscreen is bigger than screen (i.e. has bezels),
143 // because we receive events in touchscreen coordinates,
144 // which need to be expanded when converting to screen coordinates,
145 // so that location on bezels will be outside of screen area.
146 void Calibrate(ui::TouchEvent* event, const gfx::Rect& bounds) {
147 int x = event->x();
148 int y = event->y();
150 if (!left_ && !right_ && !top_ && !bottom_)
151 return;
153 const int resolution_x = bounds.width();
154 const int resolution_y = bounds.height();
155 if (left_ || right_) {
156 // Offset the x position to the real
157 x -= left_;
158 // Scale the screen area back to the full resolution of the screen.
159 x = (x * resolution_x) / (resolution_x - (right_ + left_));
161 if (top_ || bottom_) {
162 // When there is a top bezel we add our border,
163 y -= top_;
164 // Scale the screen area back to the full resolution of the screen.
165 y = (y * resolution_y) / (resolution_y - (bottom_ + top_));
168 // Set the modified coordinate back to the event.
169 if (event->root_location() == event->location()) {
170 // Usually those will be equal,
171 // if not, I am not sure what the correct value should be.
172 event->set_root_location(gfx::Point(x, y));
174 event->set_location(gfx::Point(x, y));
177 private:
178 // ui::PlatformEventObserver:
179 void WillProcessEvent(const ui::PlatformEvent& event) override {
180 if (event->type == GenericEvent &&
181 (event->xgeneric.evtype == XI_TouchBegin ||
182 event->xgeneric.evtype == XI_TouchUpdate ||
183 event->xgeneric.evtype == XI_TouchEnd)) {
184 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(event->xcookie.data);
185 xievent->event = xievent->root;
186 xievent->event_x = xievent->root_x;
187 xievent->event_y = xievent->root_y;
191 void DidProcessEvent(const ui::PlatformEvent& event) override {}
193 // The difference in screen's native resolution pixels between
194 // the border of the touchscreen and the border of the screen,
195 // aka bezel sizes.
196 int left_;
197 int right_;
198 int top_;
199 int bottom_;
201 DISALLOW_COPY_AND_ASSIGN(TouchEventCalibrate);
204 } // namespace internal
206 ////////////////////////////////////////////////////////////////////////////////
207 // WindowTreeHostX11
209 WindowTreeHostX11::WindowTreeHostX11(const gfx::Rect& bounds)
210 : xdisplay_(gfx::GetXDisplay()),
211 xwindow_(0),
212 x_root_window_(DefaultRootWindow(xdisplay_)),
213 current_cursor_(ui::kCursorNull),
214 window_mapped_(false),
215 bounds_(bounds),
216 touch_calibrate_(new internal::TouchEventCalibrate),
217 atom_cache_(xdisplay_, kAtomsToCache) {
218 XSetWindowAttributes swa;
219 memset(&swa, 0, sizeof(swa));
220 swa.background_pixmap = None;
221 swa.override_redirect = default_override_redirect;
222 xwindow_ = XCreateWindow(
223 xdisplay_, x_root_window_,
224 bounds.x(), bounds.y(), bounds.width(), bounds.height(),
225 0, // border width
226 CopyFromParent, // depth
227 InputOutput,
228 CopyFromParent, // visual
229 CWBackPixmap | CWOverrideRedirect,
230 &swa);
231 if (ui::PlatformEventSource::GetInstance())
232 ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
234 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask |
235 KeyPressMask | KeyReleaseMask |
236 EnterWindowMask | LeaveWindowMask |
237 ExposureMask | VisibilityChangeMask |
238 StructureNotifyMask | PropertyChangeMask |
239 PointerMotionMask;
240 XSelectInput(xdisplay_, xwindow_, event_mask);
241 XFlush(xdisplay_);
243 if (ui::IsXInput2Available()) {
244 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_);
245 SelectXInput2EventsForRootWindow(xdisplay_, x_root_window_);
248 // TODO(erg): We currently only request window deletion events. We also
249 // should listen for activation events and anything else that GTK+ listens
250 // for, and do something useful.
251 ::Atom protocols[2];
252 protocols[0] = atom_cache_.GetAtom("WM_DELETE_WINDOW");
253 protocols[1] = atom_cache_.GetAtom("_NET_WM_PING");
254 XSetWMProtocols(xdisplay_, xwindow_, protocols, 2);
256 // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with
257 // the desktop environment.
258 XSetWMProperties(xdisplay_, xwindow_, NULL, NULL, NULL, 0, NULL, NULL, NULL);
260 // Likewise, the X server needs to know this window's pid so it knows which
261 // program to kill if the window hangs.
262 // XChangeProperty() expects "pid" to be long.
263 static_assert(sizeof(long) >= sizeof(pid_t),
264 "pid_t should not be larger than long");
265 long pid = getpid();
266 XChangeProperty(xdisplay_,
267 xwindow_,
268 atom_cache_.GetAtom("_NET_WM_PID"),
269 XA_CARDINAL,
271 PropModeReplace,
272 reinterpret_cast<unsigned char*>(&pid), 1);
274 // Allow subclasses to create and cache additional atoms.
275 atom_cache_.allow_uncached_atoms();
277 XRRSelectInput(xdisplay_, x_root_window_,
278 RRScreenChangeNotifyMask | RROutputChangeNotifyMask);
279 CreateCompositor();
280 OnAcceleratedWidgetAvailable();
283 WindowTreeHostX11::~WindowTreeHostX11() {
284 if (ui::PlatformEventSource::GetInstance())
285 ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
287 DestroyCompositor();
288 DestroyDispatcher();
289 XDestroyWindow(xdisplay_, xwindow_);
292 bool WindowTreeHostX11::CanDispatchEvent(const ui::PlatformEvent& event) {
293 ::Window target = FindEventTarget(event);
294 return target == xwindow_ || target == x_root_window_;
297 uint32_t WindowTreeHostX11::DispatchEvent(const ui::PlatformEvent& event) {
298 XEvent* xev = event;
299 if (FindEventTarget(xev) == x_root_window_) {
300 if (xev->type == GenericEvent)
301 DispatchXI2Event(xev);
302 return ui::POST_DISPATCH_NONE;
305 if (xev->type == MotionNotify) {
306 // Discard all but the most recent motion event that targets the same
307 // window with unchanged state.
308 XEvent last_event;
309 while (XPending(xev->xany.display)) {
310 XEvent next_event;
311 XPeekEvent(xev->xany.display, &next_event);
312 if (next_event.type == MotionNotify &&
313 next_event.xmotion.window == xev->xmotion.window &&
314 next_event.xmotion.subwindow == xev->xmotion.subwindow &&
315 next_event.xmotion.state == xev->xmotion.state) {
316 XNextEvent(xev->xany.display, &last_event);
317 xev = &last_event;
318 } else {
319 break;
324 if ((xev->type == EnterNotify || xev->type == LeaveNotify) &&
325 xev->xcrossing.detail == NotifyInferior) {
326 // Ignore EventNotify and LeaveNotify events from children of |xwindow_|.
327 // NativeViewGLSurfaceGLX adds a child to |xwindow_|.
328 // TODO(pkotwicz|tdanderson): Figure out whether the suppression is
329 // necessary. crbug.com/385716
330 return ui::POST_DISPATCH_STOP_PROPAGATION;
333 if (xev->type == EnterNotify ||
334 xev->type == LeaveNotify ||
335 xev->type == KeyPress ||
336 xev->type == KeyRelease ||
337 xev->type == ButtonPress ||
338 xev->type == ButtonRelease ||
339 xev->type == MotionNotify) {
340 switch (ui::EventTypeFromNative(xev)) {
341 case ui::ET_KEY_PRESSED:
342 case ui::ET_KEY_RELEASED: {
343 ui::KeyEvent keydown_event(xev);
344 SendEventToProcessor(&keydown_event);
345 break;
347 case ui::ET_MOUSE_MOVED:
348 case ui::ET_MOUSE_DRAGGED:
349 case ui::ET_MOUSE_ENTERED:
350 case ui::ET_MOUSE_EXITED:
351 case ui::ET_MOUSE_PRESSED:
352 case ui::ET_MOUSE_RELEASED: {
353 ui::MouseEvent mouse_event(xev);
354 if (xev->type == EnterNotify) {
355 aura::Window* root_window = window();
356 client::CursorClient* cursor_client =
357 client::GetCursorClient(root_window);
358 if (cursor_client) {
359 const gfx::Display display = gfx::Screen::GetScreenFor(
360 root_window)->GetDisplayNearestWindow(root_window);
361 cursor_client->SetDisplay(display);
363 // EnterNotify creates ET_MOUSE_MOVE. Mark as synthesized as this is
364 // not a real mouse move event.
365 mouse_event.set_flags(mouse_event.flags() | ui::EF_IS_SYNTHESIZED);
368 TranslateAndDispatchLocatedEvent(&mouse_event);
369 break;
371 case ui::ET_MOUSEWHEEL: {
372 ui::MouseWheelEvent mouseev(xev);
373 TranslateAndDispatchLocatedEvent(&mouseev);
374 break;
376 case ui::ET_UNKNOWN:
377 // No event is created for X11-release events for mouse-wheel buttons.
378 break;
379 default:
380 NOTREACHED();
382 return ui::POST_DISPATCH_STOP_PROPAGATION;
385 switch (xev->type) {
386 case Expose: {
387 gfx::Rect damage_rect(xev->xexpose.x, xev->xexpose.y,
388 xev->xexpose.width, xev->xexpose.height);
389 compositor()->ScheduleRedrawRect(damage_rect);
390 break;
392 case FocusOut:
393 if (xev->xfocus.mode != NotifyGrab)
394 OnHostLostWindowCapture();
395 break;
396 case ConfigureNotify: {
397 DCHECK_EQ(xwindow_, xev->xconfigure.event);
398 DCHECK_EQ(xwindow_, xev->xconfigure.window);
399 // It's possible that the X window may be resized by some other means
400 // than from within aura (e.g. the X window manager can change the
401 // size). Make sure the root window size is maintained properly.
402 gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y,
403 xev->xconfigure.width, xev->xconfigure.height);
404 bool size_changed = bounds_.size() != bounds.size();
405 bool origin_changed = bounds_.origin() != bounds.origin();
406 bounds_ = bounds;
407 OnConfigureNotify();
408 if (size_changed)
409 OnHostResized(bounds.size());
410 if (origin_changed)
411 OnHostMoved(bounds_.origin());
412 break;
414 case GenericEvent:
415 DispatchXI2Event(xev);
416 break;
417 case ClientMessage: {
418 Atom message_type = static_cast<Atom>(xev->xclient.data.l[0]);
419 if (message_type == atom_cache_.GetAtom("WM_DELETE_WINDOW")) {
420 // We have received a close message from the window manager.
421 OnHostCloseRequested();
422 } else if (message_type == atom_cache_.GetAtom("_NET_WM_PING")) {
423 XEvent reply_event = *xev;
424 reply_event.xclient.window = x_root_window_;
426 XSendEvent(xdisplay_,
427 reply_event.xclient.window,
428 False,
429 SubstructureRedirectMask | SubstructureNotifyMask,
430 &reply_event);
431 XFlush(xdisplay_);
433 break;
435 case MappingNotify: {
436 switch (xev->xmapping.request) {
437 case MappingModifier:
438 case MappingKeyboard:
439 XRefreshKeyboardMapping(&xev->xmapping);
440 break;
441 case MappingPointer:
442 ui::DeviceDataManagerX11::GetInstance()->UpdateButtonMap();
443 break;
444 default:
445 NOTIMPLEMENTED() << " Unknown request: " << xev->xmapping.request;
446 break;
448 break;
451 return ui::POST_DISPATCH_STOP_PROPAGATION;
454 ui::EventSource* WindowTreeHostX11::GetEventSource() {
455 return this;
458 gfx::AcceleratedWidget WindowTreeHostX11::GetAcceleratedWidget() {
459 return xwindow_;
462 void WindowTreeHostX11::ShowImpl() {
463 if (!window_mapped_) {
464 // Before we map the window, set size hints. Otherwise, some window managers
465 // will ignore toplevel XMoveWindow commands.
466 XSizeHints size_hints;
467 size_hints.flags = PPosition | PWinGravity;
468 size_hints.x = bounds_.x();
469 size_hints.y = bounds_.y();
470 // Set StaticGravity so that the window position is not affected by the
471 // frame width when running with window manager.
472 size_hints.win_gravity = StaticGravity;
473 XSetWMNormalHints(xdisplay_, xwindow_, &size_hints);
475 XMapWindow(xdisplay_, xwindow_);
477 // We now block until our window is mapped. Some X11 APIs will crash and
478 // burn if passed |xwindow_| before the window is mapped, and XMapWindow is
479 // asynchronous.
480 if (ui::X11EventSource::GetInstance())
481 ui::X11EventSource::GetInstance()->BlockUntilWindowMapped(xwindow_);
482 window_mapped_ = true;
486 void WindowTreeHostX11::HideImpl() {
487 if (window_mapped_) {
488 XWithdrawWindow(xdisplay_, xwindow_, 0);
489 window_mapped_ = false;
493 gfx::Rect WindowTreeHostX11::GetBounds() const {
494 return bounds_;
497 void WindowTreeHostX11::SetBounds(const gfx::Rect& bounds) {
498 // Even if the host window's size doesn't change, aura's root window
499 // size, which is in DIP, changes when the scale changes.
500 float current_scale = compositor()->device_scale_factor();
501 float new_scale = gfx::Screen::GetScreenFor(window())->
502 GetDisplayNearestWindow(window()).device_scale_factor();
503 bool origin_changed = bounds_.origin() != bounds.origin();
504 bool size_changed = bounds_.size() != bounds.size();
505 XWindowChanges changes = {0};
506 unsigned value_mask = 0;
508 if (size_changed) {
509 changes.width = bounds.width();
510 changes.height = bounds.height();
511 value_mask = CWHeight | CWWidth;
514 if (origin_changed) {
515 changes.x = bounds.x();
516 changes.y = bounds.y();
517 value_mask |= CWX | CWY;
519 if (value_mask)
520 XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes);
522 // Assume that the resize will go through as requested, which should be the
523 // case if we're running without a window manager. If there's a window
524 // manager, it can modify or ignore the request, but (per ICCCM) we'll get a
525 // (possibly synthetic) ConfigureNotify about the actual size and correct
526 // |bounds_| later.
527 bounds_ = bounds;
528 if (origin_changed)
529 OnHostMoved(bounds.origin());
530 if (size_changed || current_scale != new_scale) {
531 OnHostResized(bounds.size());
532 } else {
533 window()->SchedulePaintInRect(window()->bounds());
537 gfx::Point WindowTreeHostX11::GetLocationOnNativeScreen() const {
538 return bounds_.origin();
541 void WindowTreeHostX11::SetCapture() {
542 // Do not grab X11 input. Grabbing X11 input is asynchronous and this method
543 // is expected to be synchronous. Grabbing X11 input is unnecessary on
544 // ChromeOS because ChromeOS manages all of the X windows. When running
545 // ChromeOS on the desktop for the sake of debugging:
546 // - Implicit pointer grab as a result of pressing a mouse button
547 // - Releasing capture as a result of losing activation (FocusOut)
548 // is sufficient.
551 void WindowTreeHostX11::ReleaseCapture() {
554 void WindowTreeHostX11::SetCursorNative(gfx::NativeCursor cursor) {
555 if (cursor == current_cursor_)
556 return;
557 current_cursor_ = cursor;
558 SetCursorInternal(cursor);
561 void WindowTreeHostX11::MoveCursorToNative(const gfx::Point& location) {
562 XWarpPointer(xdisplay_, None, x_root_window_, 0, 0, 0, 0,
563 bounds_.x() + location.x(),
564 bounds_.y() + location.y());
567 void WindowTreeHostX11::OnCursorVisibilityChangedNative(bool show) {
570 void WindowTreeHostX11::DispatchXI2Event(const base::NativeEvent& event) {
571 ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
572 XEvent* xev = event;
573 XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev->xcookie.data);
574 if (!factory->ShouldProcessXI2Event(xev))
575 return;
577 TRACE_EVENT1("input", "WindowTreeHostX11::DispatchXI2Event",
578 "event_latency_us",
579 (ui::EventTimeForNow() - ui::EventTimeFromNative(event)).
580 InMicroseconds());
582 int num_coalesced = 0;
583 XEvent last_event;
584 if (xev->xgeneric.evtype == XI_Motion) {
585 // If this is a motion event, we want to coalesce all pending motion
586 // events that are at the top of the queue. Note, we don't coalesce
587 // touch update events here.
588 num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event);
589 if (num_coalesced > 0)
590 xev = &last_event;
592 ui::EventType type = ui::EventTypeFromNative(xev);
594 switch (type) {
595 case ui::ET_TOUCH_MOVED:
596 case ui::ET_TOUCH_PRESSED:
597 case ui::ET_TOUCH_CANCELLED:
598 case ui::ET_TOUCH_RELEASED: {
599 ui::TouchEvent touchev(xev);
600 if (ui::DeviceDataManagerX11::GetInstance()->TouchEventNeedsCalibrate(
601 xiev->deviceid)) {
602 touch_calibrate_->Calibrate(&touchev, bounds_);
604 TranslateAndDispatchLocatedEvent(&touchev);
605 break;
607 case ui::ET_MOUSE_MOVED:
608 case ui::ET_MOUSE_DRAGGED:
609 case ui::ET_MOUSE_PRESSED:
610 case ui::ET_MOUSE_RELEASED:
611 case ui::ET_MOUSE_ENTERED:
612 case ui::ET_MOUSE_EXITED: {
613 ui::MouseEvent mouseev(xev);
614 TranslateAndDispatchLocatedEvent(&mouseev);
615 break;
617 case ui::ET_MOUSEWHEEL: {
618 ui::MouseWheelEvent mouseev(xev);
619 TranslateAndDispatchLocatedEvent(&mouseev);
620 break;
622 case ui::ET_SCROLL_FLING_START:
623 case ui::ET_SCROLL_FLING_CANCEL:
624 case ui::ET_SCROLL: {
625 ui::ScrollEvent scrollev(xev);
626 SendEventToProcessor(&scrollev);
627 break;
629 case ui::ET_KEY_PRESSED:
630 case ui::ET_KEY_RELEASED: {
631 ui::KeyEvent key_event(xev);
632 SendEventToProcessor(&key_event);
633 break;
635 case ui::ET_UMA_DATA:
636 break;
637 case ui::ET_UNKNOWN:
638 break;
639 default:
640 NOTREACHED();
643 // If we coalesced an event we need to free its cookie.
644 if (num_coalesced > 0)
645 XFreeEventData(xev->xgeneric.display, &last_event.xcookie);
648 void WindowTreeHostX11::SetCursorInternal(gfx::NativeCursor cursor) {
649 XDefineCursor(xdisplay_, xwindow_, cursor.platform());
652 void WindowTreeHostX11::OnConfigureNotify() {}
654 void WindowTreeHostX11::TranslateAndDispatchLocatedEvent(
655 ui::LocatedEvent* event) {
656 SendEventToProcessor(event);
659 // static
660 WindowTreeHost* WindowTreeHost::Create(const gfx::Rect& bounds) {
661 return new WindowTreeHostX11(bounds);
664 // static
665 gfx::Size WindowTreeHost::GetNativeScreenSize() {
666 ::XDisplay* xdisplay = gfx::GetXDisplay();
667 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0));
670 namespace test {
672 void SetUseOverrideRedirectWindowByDefault(bool override_redirect) {
673 default_override_redirect = override_redirect;
676 } // namespace test
677 } // namespace aura