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"
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>
19 #include "base/basictypes.h"
20 #include "base/command_line.h"
21 #include "base/debug/trace_event.h"
22 #include "base/stl_util.h"
23 #include "base/strings/string_number_conversions.h"
24 #include "base/strings/string_util.h"
25 #include "base/strings/stringprintf.h"
26 #include "base/sys_info.h"
27 #include "ui/aura/client/cursor_client.h"
28 #include "ui/aura/env.h"
29 #include "ui/aura/window.h"
30 #include "ui/aura/window_event_dispatcher.h"
31 #include "ui/base/cursor/cursor.h"
32 #include "ui/base/ui_base_switches.h"
33 #include "ui/base/view_prop.h"
34 #include "ui/base/x/x11_util.h"
35 #include "ui/compositor/compositor.h"
36 #include "ui/compositor/dip_util.h"
37 #include "ui/compositor/layer.h"
38 #include "ui/events/devices/x11/device_data_manager_x11.h"
39 #include "ui/events/devices/x11/device_list_cache_x11.h"
40 #include "ui/events/devices/x11/touch_factory_x11.h"
41 #include "ui/events/event.h"
42 #include "ui/events/event_switches.h"
43 #include "ui/events/event_utils.h"
44 #include "ui/events/keycodes/keyboard_codes.h"
45 #include "ui/events/platform/platform_event_observer.h"
46 #include "ui/events/platform/x11/x11_event_source.h"
47 #include "ui/gfx/screen.h"
56 const char* kAtomsToCache
[] = {
63 ::Window
FindEventTarget(const base::NativeEvent
& xev
) {
64 ::Window target
= xev
->xany
.window
;
65 if (xev
->type
== GenericEvent
)
66 target
= static_cast<XIDeviceEvent
*>(xev
->xcookie
.data
)->event
;
70 void SelectXInput2EventsForRootWindow(XDisplay
* display
, ::Window root_window
) {
71 CHECK(ui::IsXInput2Available());
72 unsigned char mask
[XIMaskLen(XI_LASTEVENT
)] = {};
73 memset(mask
, 0, sizeof(mask
));
75 XISetMask(mask
, XI_HierarchyChanged
);
78 evmask
.deviceid
= XIAllDevices
;
79 evmask
.mask_len
= sizeof(mask
);
81 XISelectEvents(display
, root_window
, &evmask
, 1);
83 #if defined(OS_CHROMEOS)
84 if (base::SysInfo::IsRunningOnChromeOS()) {
85 // It is necessary to listen for touch events on the root window for proper
86 // touch event calibration on Chrome OS, but this is not currently necessary
87 // on the desktop. This seems to fail in some cases (e.g. when logging
88 // in incognito). So select for non-touch events first, and then select for
89 // touch-events (but keep the other events in the mask, i.e. do not memset
91 // TODO(sad): Figure out why this happens. http://crbug.com/153976
92 XISetMask(mask
, XI_TouchBegin
);
93 XISetMask(mask
, XI_TouchUpdate
);
94 XISetMask(mask
, XI_TouchEnd
);
95 XISelectEvents(display
, root_window
, &evmask
, 1);
100 bool default_override_redirect
= false;
106 // TODO(miletus) : Move this into DeviceDataManager.
107 // Accomplishes 2 tasks concerning touch event calibration:
108 // 1. Being a message-pump observer,
109 // routes all the touch events to the X root window,
110 // where they can be calibrated later.
111 // 2. Has the Calibrate method that does the actual bezel calibration,
112 // when invoked from X root window's event dispatcher.
113 class TouchEventCalibrate
: public ui::PlatformEventObserver
{
115 TouchEventCalibrate() : left_(0), right_(0), top_(0), bottom_(0) {
116 if (ui::PlatformEventSource::GetInstance())
117 ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this);
118 #if defined(USE_XI2_MT)
119 std::vector
<std::string
> parts
;
120 if (Tokenize(CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
121 switches::kTouchCalibration
),
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.";
133 #endif // defined(USE_XI2_MT)
136 ~TouchEventCalibrate() override
{
137 if (ui::PlatformEventSource::GetInstance())
138 ui::PlatformEventSource::GetInstance()->RemovePlatformEventObserver(this);
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 #if defined(USE_XI2_MT)
152 if (!left_
&& !right_
&& !top_
&& !bottom_
)
155 const int resolution_x
= bounds
.width();
156 const int resolution_y
= bounds
.height();
157 // The "grace area" (10% in this case) is to make it easier for the user to
158 // navigate to the corner.
159 const double kGraceAreaFraction
= 0.1;
160 if (left_
|| right_
) {
161 // Offset the x position to the real
163 // Check if we are in the grace area of the left side.
164 // Note: We might not want to do this when the gesture is locked?
165 if (x
< 0 && x
> -left_
* kGraceAreaFraction
)
167 // Check if we are in the grace area of the right side.
168 // Note: We might not want to do this when the gesture is locked?
169 if (x
> resolution_x
- left_
&&
170 x
< resolution_x
- left_
+ right_
* kGraceAreaFraction
)
171 x
= resolution_x
- left_
;
172 // Scale the screen area back to the full resolution of the screen.
173 x
= (x
* resolution_x
) / (resolution_x
- (right_
+ left_
));
175 if (top_
|| bottom_
) {
176 // When there is a top bezel we add our border,
179 // Check if we are in the grace area of the top side.
180 // Note: We might not want to do this when the gesture is locked?
181 if (y
< 0 && y
> -top_
* kGraceAreaFraction
)
184 // Check if we are in the grace area of the bottom side.
185 // Note: We might not want to do this when the gesture is locked?
186 if (y
> resolution_y
- top_
&&
187 y
< resolution_y
- top_
+ bottom_
* kGraceAreaFraction
)
188 y
= resolution_y
- top_
;
189 // Scale the screen area back to the full resolution of the screen.
190 y
= (y
* resolution_y
) / (resolution_y
- (bottom_
+ top_
));
193 // Set the modified coordinate back to the event.
194 if (event
->root_location() == event
->location()) {
195 // Usually those will be equal,
196 // if not, I am not sure what the correct value should be.
197 event
->set_root_location(gfx::Point(x
, y
));
199 event
->set_location(gfx::Point(x
, y
));
200 #endif // defined(USE_XI2_MT)
204 // ui::PlatformEventObserver:
205 void WillProcessEvent(const ui::PlatformEvent
& event
) override
{
206 #if defined(USE_XI2_MT)
207 if (event
->type
== GenericEvent
&&
208 (event
->xgeneric
.evtype
== XI_TouchBegin
||
209 event
->xgeneric
.evtype
== XI_TouchUpdate
||
210 event
->xgeneric
.evtype
== XI_TouchEnd
)) {
211 XIDeviceEvent
* xievent
= static_cast<XIDeviceEvent
*>(event
->xcookie
.data
);
212 xievent
->event
= xievent
->root
;
213 xievent
->event_x
= xievent
->root_x
;
214 xievent
->event_y
= xievent
->root_y
;
216 #endif // defined(USE_XI2_MT)
219 void DidProcessEvent(const ui::PlatformEvent
& event
) override
{}
221 // The difference in screen's native resolution pixels between
222 // the border of the touchscreen and the border of the screen,
229 DISALLOW_COPY_AND_ASSIGN(TouchEventCalibrate
);
232 } // namespace internal
234 ////////////////////////////////////////////////////////////////////////////////
237 WindowTreeHostX11::WindowTreeHostX11(const gfx::Rect
& bounds
)
238 : xdisplay_(gfx::GetXDisplay()),
240 x_root_window_(DefaultRootWindow(xdisplay_
)),
241 current_cursor_(ui::kCursorNull
),
242 window_mapped_(false),
244 touch_calibrate_(new internal::TouchEventCalibrate
),
245 atom_cache_(xdisplay_
, kAtomsToCache
) {
246 XSetWindowAttributes swa
;
247 memset(&swa
, 0, sizeof(swa
));
248 swa
.background_pixmap
= None
;
249 swa
.override_redirect
= default_override_redirect
;
250 xwindow_
= XCreateWindow(
251 xdisplay_
, x_root_window_
,
252 bounds
.x(), bounds
.y(), bounds
.width(), bounds
.height(),
254 CopyFromParent
, // depth
256 CopyFromParent
, // visual
257 CWBackPixmap
| CWOverrideRedirect
,
259 if (ui::PlatformEventSource::GetInstance())
260 ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
262 long event_mask
= ButtonPressMask
| ButtonReleaseMask
| FocusChangeMask
|
263 KeyPressMask
| KeyReleaseMask
|
264 EnterWindowMask
| LeaveWindowMask
|
265 ExposureMask
| VisibilityChangeMask
|
266 StructureNotifyMask
| PropertyChangeMask
|
268 XSelectInput(xdisplay_
, xwindow_
, event_mask
);
271 if (ui::IsXInput2Available()) {
272 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_
);
273 SelectXInput2EventsForRootWindow(xdisplay_
, x_root_window_
);
276 // TODO(erg): We currently only request window deletion events. We also
277 // should listen for activation events and anything else that GTK+ listens
278 // for, and do something useful.
280 protocols
[0] = atom_cache_
.GetAtom("WM_DELETE_WINDOW");
281 protocols
[1] = atom_cache_
.GetAtom("_NET_WM_PING");
282 XSetWMProtocols(xdisplay_
, xwindow_
, protocols
, 2);
284 // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with
285 // the desktop environment.
286 XSetWMProperties(xdisplay_
, xwindow_
, NULL
, NULL
, NULL
, 0, NULL
, NULL
, NULL
);
288 // Likewise, the X server needs to know this window's pid so it knows which
289 // program to kill if the window hangs.
290 // XChangeProperty() expects "pid" to be long.
291 COMPILE_ASSERT(sizeof(long) >= sizeof(pid_t
), pid_t_bigger_than_long
);
293 XChangeProperty(xdisplay_
,
295 atom_cache_
.GetAtom("_NET_WM_PID"),
299 reinterpret_cast<unsigned char*>(&pid
), 1);
301 // Allow subclasses to create and cache additional atoms.
302 atom_cache_
.allow_uncached_atoms();
304 XRRSelectInput(xdisplay_
, x_root_window_
,
305 RRScreenChangeNotifyMask
| RROutputChangeNotifyMask
);
306 CreateCompositor(GetAcceleratedWidget());
309 WindowTreeHostX11::~WindowTreeHostX11() {
310 if (ui::PlatformEventSource::GetInstance())
311 ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
315 XDestroyWindow(xdisplay_
, xwindow_
);
318 bool WindowTreeHostX11::CanDispatchEvent(const ui::PlatformEvent
& event
) {
319 ::Window target
= FindEventTarget(event
);
320 return target
== xwindow_
|| target
== x_root_window_
;
323 uint32_t WindowTreeHostX11::DispatchEvent(const ui::PlatformEvent
& event
) {
325 if (FindEventTarget(xev
) == x_root_window_
) {
326 if (xev
->type
== GenericEvent
)
327 DispatchXI2Event(xev
);
328 return ui::POST_DISPATCH_NONE
;
331 if (xev
->type
== MotionNotify
) {
332 // Discard all but the most recent motion event that targets the same
333 // window with unchanged state.
335 while (XPending(xev
->xany
.display
)) {
337 XPeekEvent(xev
->xany
.display
, &next_event
);
338 if (next_event
.type
== MotionNotify
&&
339 next_event
.xmotion
.window
== xev
->xmotion
.window
&&
340 next_event
.xmotion
.subwindow
== xev
->xmotion
.subwindow
&&
341 next_event
.xmotion
.state
== xev
->xmotion
.state
) {
342 XNextEvent(xev
->xany
.display
, &last_event
);
350 if ((xev
->type
== EnterNotify
|| xev
->type
== LeaveNotify
) &&
351 xev
->xcrossing
.detail
== NotifyInferior
) {
352 // Ignore EventNotify and LeaveNotify events from children of |xwindow_|.
353 // NativeViewGLSurfaceGLX adds a child to |xwindow_|.
354 // TODO(pkotwicz|tdanderson): Figure out whether the suppression is
355 // necessary. crbug.com/385716
356 return ui::POST_DISPATCH_STOP_PROPAGATION
;
359 if (xev
->type
== EnterNotify
||
360 xev
->type
== LeaveNotify
||
361 xev
->type
== KeyPress
||
362 xev
->type
== KeyRelease
||
363 xev
->type
== ButtonPress
||
364 xev
->type
== ButtonRelease
||
365 xev
->type
== MotionNotify
) {
366 switch (ui::EventTypeFromNative(xev
)) {
367 case ui::ET_KEY_PRESSED
:
368 case ui::ET_KEY_RELEASED
: {
369 ui::KeyEvent
keydown_event(xev
);
370 SendEventToProcessor(&keydown_event
);
373 case ui::ET_MOUSE_MOVED
:
374 case ui::ET_MOUSE_DRAGGED
:
375 case ui::ET_MOUSE_ENTERED
:
376 case ui::ET_MOUSE_EXITED
:
377 case ui::ET_MOUSE_PRESSED
:
378 case ui::ET_MOUSE_RELEASED
: {
379 ui::MouseEvent
mouse_event(xev
);
380 if (xev
->type
== EnterNotify
) {
381 aura::Window
* root_window
= window();
382 client::CursorClient
* cursor_client
=
383 client::GetCursorClient(root_window
);
385 const gfx::Display display
= gfx::Screen::GetScreenFor(
386 root_window
)->GetDisplayNearestWindow(root_window
);
387 cursor_client
->SetDisplay(display
);
389 // EnterNotify creates ET_MOUSE_MOVE. Mark as synthesized as this is
390 // not a real mouse move event.
391 mouse_event
.set_flags(mouse_event
.flags() | ui::EF_IS_SYNTHESIZED
);
394 TranslateAndDispatchLocatedEvent(&mouse_event
);
397 case ui::ET_MOUSEWHEEL
: {
398 ui::MouseWheelEvent
mouseev(xev
);
399 TranslateAndDispatchLocatedEvent(&mouseev
);
403 // No event is created for X11-release events for mouse-wheel buttons.
408 return ui::POST_DISPATCH_STOP_PROPAGATION
;
413 gfx::Rect
damage_rect(xev
->xexpose
.x
, xev
->xexpose
.y
,
414 xev
->xexpose
.width
, xev
->xexpose
.height
);
415 compositor()->ScheduleRedrawRect(damage_rect
);
419 if (xev
->xfocus
.mode
!= NotifyGrab
)
420 OnHostLostWindowCapture();
422 case ConfigureNotify
: {
423 DCHECK_EQ(xwindow_
, xev
->xconfigure
.event
);
424 DCHECK_EQ(xwindow_
, xev
->xconfigure
.window
);
425 // It's possible that the X window may be resized by some other means
426 // than from within aura (e.g. the X window manager can change the
427 // size). Make sure the root window size is maintained properly.
428 gfx::Rect
bounds(xev
->xconfigure
.x
, xev
->xconfigure
.y
,
429 xev
->xconfigure
.width
, xev
->xconfigure
.height
);
430 bool size_changed
= bounds_
.size() != bounds
.size();
431 bool origin_changed
= bounds_
.origin() != bounds
.origin();
435 OnHostResized(bounds
.size());
437 OnHostMoved(bounds_
.origin());
441 DispatchXI2Event(xev
);
443 case ClientMessage
: {
444 Atom message_type
= static_cast<Atom
>(xev
->xclient
.data
.l
[0]);
445 if (message_type
== atom_cache_
.GetAtom("WM_DELETE_WINDOW")) {
446 // We have received a close message from the window manager.
447 OnHostCloseRequested();
448 } else if (message_type
== atom_cache_
.GetAtom("_NET_WM_PING")) {
449 XEvent reply_event
= *xev
;
450 reply_event
.xclient
.window
= x_root_window_
;
452 XSendEvent(xdisplay_
,
453 reply_event
.xclient
.window
,
455 SubstructureRedirectMask
| SubstructureNotifyMask
,
461 case MappingNotify
: {
462 switch (xev
->xmapping
.request
) {
463 case MappingModifier
:
464 case MappingKeyboard
:
465 XRefreshKeyboardMapping(&xev
->xmapping
);
468 ui::DeviceDataManagerX11::GetInstance()->UpdateButtonMap();
471 NOTIMPLEMENTED() << " Unknown request: " << xev
->xmapping
.request
;
477 return ui::POST_DISPATCH_STOP_PROPAGATION
;
480 ui::EventSource
* WindowTreeHostX11::GetEventSource() {
484 gfx::AcceleratedWidget
WindowTreeHostX11::GetAcceleratedWidget() {
488 void WindowTreeHostX11::Show() {
489 if (!window_mapped_
) {
490 // Before we map the window, set size hints. Otherwise, some window managers
491 // will ignore toplevel XMoveWindow commands.
492 XSizeHints size_hints
;
493 size_hints
.flags
= PPosition
| PWinGravity
;
494 size_hints
.x
= bounds_
.x();
495 size_hints
.y
= bounds_
.y();
496 // Set StaticGravity so that the window position is not affected by the
497 // frame width when running with window manager.
498 size_hints
.win_gravity
= StaticGravity
;
499 XSetWMNormalHints(xdisplay_
, xwindow_
, &size_hints
);
501 XMapWindow(xdisplay_
, xwindow_
);
503 // We now block until our window is mapped. Some X11 APIs will crash and
504 // burn if passed |xwindow_| before the window is mapped, and XMapWindow is
506 if (ui::X11EventSource::GetInstance())
507 ui::X11EventSource::GetInstance()->BlockUntilWindowMapped(xwindow_
);
508 window_mapped_
= true;
512 void WindowTreeHostX11::Hide() {
513 if (window_mapped_
) {
514 XWithdrawWindow(xdisplay_
, xwindow_
, 0);
515 window_mapped_
= false;
519 gfx::Rect
WindowTreeHostX11::GetBounds() const {
523 void WindowTreeHostX11::SetBounds(const gfx::Rect
& bounds
) {
524 // Even if the host window's size doesn't change, aura's root window
525 // size, which is in DIP, changes when the scale changes.
526 float current_scale
= compositor()->device_scale_factor();
527 float new_scale
= gfx::Screen::GetScreenFor(window())->
528 GetDisplayNearestWindow(window()).device_scale_factor();
529 bool origin_changed
= bounds_
.origin() != bounds
.origin();
530 bool size_changed
= bounds_
.size() != bounds
.size();
531 XWindowChanges changes
= {0};
532 unsigned value_mask
= 0;
535 changes
.width
= bounds
.width();
536 changes
.height
= bounds
.height();
537 value_mask
= CWHeight
| CWWidth
;
540 if (origin_changed
) {
541 changes
.x
= bounds
.x();
542 changes
.y
= bounds
.y();
543 value_mask
|= CWX
| CWY
;
546 XConfigureWindow(xdisplay_
, xwindow_
, value_mask
, &changes
);
548 // Assume that the resize will go through as requested, which should be the
549 // case if we're running without a window manager. If there's a window
550 // manager, it can modify or ignore the request, but (per ICCCM) we'll get a
551 // (possibly synthetic) ConfigureNotify about the actual size and correct
555 OnHostMoved(bounds
.origin());
556 if (size_changed
|| current_scale
!= new_scale
) {
557 OnHostResized(bounds
.size());
559 window()->SchedulePaintInRect(window()->bounds());
563 gfx::Point
WindowTreeHostX11::GetLocationOnNativeScreen() const {
564 return bounds_
.origin();
567 void WindowTreeHostX11::SetCapture() {
568 // TODO(oshima): Grab x input.
571 void WindowTreeHostX11::ReleaseCapture() {
572 // TODO(oshima): Release x input.
575 void WindowTreeHostX11::PostNativeEvent(
576 const base::NativeEvent
& native_event
) {
579 XEvent xevent
= *native_event
;
580 xevent
.xany
.display
= xdisplay_
;
581 xevent
.xany
.window
= xwindow_
;
583 switch (xevent
.type
) {
590 case ButtonRelease
: {
591 // The fields used below are in the same place for all of events
592 // above. Using xmotion from XEvent's unions to avoid repeating
594 xevent
.xmotion
.root
= x_root_window_
;
595 xevent
.xmotion
.time
= CurrentTime
;
597 gfx::Point
point(xevent
.xmotion
.x
, xevent
.xmotion
.y
);
598 ConvertPointToNativeScreen(&point
);
599 xevent
.xmotion
.x_root
= point
.x();
600 xevent
.xmotion
.y_root
= point
.y();
605 XSendEvent(xdisplay_
, xwindow_
, False
, 0, &xevent
);
609 void WindowTreeHostX11::SetCursorNative(gfx::NativeCursor cursor
) {
610 if (cursor
== current_cursor_
)
612 current_cursor_
= cursor
;
613 SetCursorInternal(cursor
);
616 void WindowTreeHostX11::MoveCursorToNative(const gfx::Point
& location
) {
617 XWarpPointer(xdisplay_
, None
, x_root_window_
, 0, 0, 0, 0,
618 bounds_
.x() + location
.x(),
619 bounds_
.y() + location
.y());
622 void WindowTreeHostX11::OnCursorVisibilityChangedNative(bool show
) {
625 ui::EventProcessor
* WindowTreeHostX11::GetEventProcessor() {
629 void WindowTreeHostX11::DispatchXI2Event(const base::NativeEvent
& event
) {
630 ui::TouchFactory
* factory
= ui::TouchFactory::GetInstance();
632 XIDeviceEvent
* xiev
= static_cast<XIDeviceEvent
*>(xev
->xcookie
.data
);
633 if (!factory
->ShouldProcessXI2Event(xev
))
636 TRACE_EVENT1("input", "WindowTreeHostX11::DispatchXI2Event",
638 (ui::EventTimeForNow() - ui::EventTimeFromNative(event
)).
641 int num_coalesced
= 0;
643 if (xev
->xgeneric
.evtype
== XI_Motion
) {
644 // If this is a motion event, we want to coalesce all pending motion
645 // events that are at the top of the queue. Note, we don't coalesce
646 // touch update events here.
647 num_coalesced
= ui::CoalescePendingMotionEvents(xev
, &last_event
);
648 if (num_coalesced
> 0)
651 ui::EventType type
= ui::EventTypeFromNative(xev
);
654 case ui::ET_TOUCH_MOVED
:
655 case ui::ET_TOUCH_PRESSED
:
656 case ui::ET_TOUCH_CANCELLED
:
657 case ui::ET_TOUCH_RELEASED
: {
658 ui::TouchEvent
touchev(xev
);
659 if (ui::DeviceDataManagerX11::GetInstance()->TouchEventNeedsCalibrate(
661 touch_calibrate_
->Calibrate(&touchev
, bounds_
);
663 TranslateAndDispatchLocatedEvent(&touchev
);
666 case ui::ET_MOUSE_MOVED
:
667 case ui::ET_MOUSE_DRAGGED
:
668 case ui::ET_MOUSE_PRESSED
:
669 case ui::ET_MOUSE_RELEASED
:
670 case ui::ET_MOUSE_ENTERED
:
671 case ui::ET_MOUSE_EXITED
: {
672 ui::MouseEvent
mouseev(xev
);
673 TranslateAndDispatchLocatedEvent(&mouseev
);
676 case ui::ET_MOUSEWHEEL
: {
677 ui::MouseWheelEvent
mouseev(xev
);
678 TranslateAndDispatchLocatedEvent(&mouseev
);
681 case ui::ET_SCROLL_FLING_START
:
682 case ui::ET_SCROLL_FLING_CANCEL
:
683 case ui::ET_SCROLL
: {
684 ui::ScrollEvent
scrollev(xev
);
685 SendEventToProcessor(&scrollev
);
688 case ui::ET_KEY_PRESSED
:
689 case ui::ET_KEY_RELEASED
: {
690 ui::KeyEvent
key_event(xev
);
691 SendEventToProcessor(&key_event
);
694 case ui::ET_UMA_DATA
:
702 // If we coalesced an event we need to free its cookie.
703 if (num_coalesced
> 0)
704 XFreeEventData(xev
->xgeneric
.display
, &last_event
.xcookie
);
707 void WindowTreeHostX11::SetCursorInternal(gfx::NativeCursor cursor
) {
708 XDefineCursor(xdisplay_
, xwindow_
, cursor
.platform());
711 void WindowTreeHostX11::OnConfigureNotify() {}
713 void WindowTreeHostX11::TranslateAndDispatchLocatedEvent(
714 ui::LocatedEvent
* event
) {
715 SendEventToProcessor(event
);
719 WindowTreeHost
* WindowTreeHost::Create(const gfx::Rect
& bounds
) {
720 return new WindowTreeHostX11(bounds
);
724 gfx::Size
WindowTreeHost::GetNativeScreenSize() {
725 ::XDisplay
* xdisplay
= gfx::GetXDisplay();
726 return gfx::Size(DisplayWidth(xdisplay
, 0), DisplayHeight(xdisplay
, 0));
731 void SetUseOverrideRedirectWindowByDefault(bool override_redirect
) {
732 default_override_redirect
= override_redirect
;