ash: ozone: apply transformation to events outside the root window
[chromium-blink-merge.git] / ash / host / ash_window_tree_host_x11.cc
bloba76819593b642a7d181b4b4b8707d0c8d6aaeb6d
1 // Copyright 2014 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 "ash/host/ash_window_tree_host_x11.h"
7 #include <X11/extensions/Xfixes.h>
8 #include <X11/extensions/XInput2.h>
9 #include <X11/Xatom.h>
10 #include <X11/Xlib.h>
12 #include <string>
13 #include <vector>
15 #include "ash/host/ash_window_tree_host_init_params.h"
16 #include "ash/host/root_window_transformer.h"
17 #include "base/basictypes.h"
18 #include "base/sys_info.h"
19 #include "ui/aura/env.h"
20 #include "ui/aura/window.h"
21 #include "ui/aura/window_event_dispatcher.h"
22 #include "ui/base/x/x11_util.h"
23 #include "ui/events/devices/device_data_manager.h"
24 #include "ui/events/devices/x11/device_list_cache_x11.h"
25 #include "ui/events/devices/x11/touch_factory_x11.h"
26 #include "ui/events/event.h"
27 #include "ui/events/event_utils.h"
28 #include "ui/events/platform/platform_event_source.h"
29 #include "ui/gfx/rect.h"
30 #include "ui/gfx/screen.h"
32 namespace ash {
34 AshWindowTreeHostX11::AshWindowTreeHostX11(const gfx::Rect& initial_bounds)
35 : WindowTreeHostX11(initial_bounds),
36 transformer_helper_(this),
37 display_ids_(std::make_pair(gfx::Display::kInvalidDisplayID,
38 gfx::Display::kInvalidDisplayID)) {
39 aura::Env::GetInstance()->AddObserver(this);
42 AshWindowTreeHostX11::~AshWindowTreeHostX11() {
43 aura::Env::GetInstance()->RemoveObserver(this);
44 UnConfineCursor();
47 void AshWindowTreeHostX11::ToggleFullScreen() { NOTIMPLEMENTED(); }
49 bool AshWindowTreeHostX11::ConfineCursorToRootWindow() {
50 #if XFIXES_MAJOR >= 5
51 DCHECK(!pointer_barriers_.get());
52 if (pointer_barriers_)
53 return false;
54 pointer_barriers_.reset(new XID[4]);
55 gfx::Rect barrier(bounds());
56 barrier.Inset(transformer_helper_.GetHostInsets());
57 // Horizontal, top barriers.
58 pointer_barriers_[0] = XFixesCreatePointerBarrier(xdisplay(),
59 x_root_window(),
60 barrier.x(),
61 barrier.y(),
62 barrier.right(),
63 barrier.y(),
64 BarrierPositiveY,
66 XIAllDevices);
67 // Horizontal, bottom barriers.
68 pointer_barriers_[1] = XFixesCreatePointerBarrier(xdisplay(),
69 x_root_window(),
70 barrier.x(),
71 barrier.bottom(),
72 barrier.right(),
73 barrier.bottom(),
74 BarrierNegativeY,
76 XIAllDevices);
77 // Vertical, left barriers.
78 pointer_barriers_[2] = XFixesCreatePointerBarrier(xdisplay(),
79 x_root_window(),
80 barrier.x(),
81 barrier.y(),
82 barrier.x(),
83 barrier.bottom(),
84 BarrierPositiveX,
86 XIAllDevices);
87 // Vertical, right barriers.
88 pointer_barriers_[3] = XFixesCreatePointerBarrier(xdisplay(),
89 x_root_window(),
90 barrier.right(),
91 barrier.y(),
92 barrier.right(),
93 barrier.bottom(),
94 BarrierNegativeX,
96 XIAllDevices);
97 #endif
98 return true;
101 void AshWindowTreeHostX11::UnConfineCursor() {
102 #if XFIXES_MAJOR >= 5
103 if (pointer_barriers_) {
104 XFixesDestroyPointerBarrier(xdisplay(), pointer_barriers_[0]);
105 XFixesDestroyPointerBarrier(xdisplay(), pointer_barriers_[1]);
106 XFixesDestroyPointerBarrier(xdisplay(), pointer_barriers_[2]);
107 XFixesDestroyPointerBarrier(xdisplay(), pointer_barriers_[3]);
108 pointer_barriers_.reset();
110 #endif
113 void AshWindowTreeHostX11::SetRootWindowTransformer(
114 scoped_ptr<RootWindowTransformer> transformer) {
115 transformer_helper_.SetRootWindowTransformer(transformer.Pass());
116 if (pointer_barriers_) {
117 UnConfineCursor();
118 ConfineCursorToRootWindow();
122 gfx::Insets AshWindowTreeHostX11::GetHostInsets() const {
123 return transformer_helper_.GetHostInsets();
126 aura::WindowTreeHost* AshWindowTreeHostX11::AsWindowTreeHost() { return this; }
128 void AshWindowTreeHostX11::UpdateDisplayID(int64 id1, int64 id2) {
129 display_ids_.first = id1;
130 display_ids_.second = id2;
133 void AshWindowTreeHostX11::PrepareForShutdown() {
134 if (ui::PlatformEventSource::GetInstance())
135 ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
138 void AshWindowTreeHostX11::SetBounds(const gfx::Rect& bounds) {
139 WindowTreeHostX11::SetBounds(bounds);
140 if (pointer_barriers_) {
141 UnConfineCursor();
142 ConfineCursorToRootWindow();
146 gfx::Transform AshWindowTreeHostX11::GetRootTransform() const {
147 return transformer_helper_.GetTransform();
150 void AshWindowTreeHostX11::SetRootTransform(const gfx::Transform& transform) {
151 transformer_helper_.SetTransform(transform);
154 gfx::Transform AshWindowTreeHostX11::GetInverseRootTransform() const {
155 return transformer_helper_.GetInverseTransform();
158 void AshWindowTreeHostX11::UpdateRootWindowSize(const gfx::Size& host_size) {
159 transformer_helper_.UpdateWindowSize(host_size);
162 void AshWindowTreeHostX11::OnCursorVisibilityChangedNative(bool show) {
163 #if defined(OS_CHROMEOS)
164 SetCrOSTapPaused(!show);
165 #endif
168 void AshWindowTreeHostX11::OnWindowInitialized(aura::Window* window) {}
170 void AshWindowTreeHostX11::OnHostInitialized(aura::WindowTreeHost* host) {
171 if (host != AsWindowTreeHost())
172 return;
174 #if defined(OS_CHROMEOS)
175 // We have to enable Tap-to-click by default because the cursor is set to
176 // visible in Shell::InitRootWindowController.
177 SetCrOSTapPaused(false);
178 #endif
181 void AshWindowTreeHostX11::OnConfigureNotify() {
182 // Always update barrier and mouse location because |bounds_| might
183 // have already been updated in |SetBounds|.
184 if (pointer_barriers_) {
185 UnConfineCursor();
186 ConfineCursorToRootWindow();
190 bool AshWindowTreeHostX11::CanDispatchEvent(const ui::PlatformEvent& event) {
191 if(!WindowTreeHostX11::CanDispatchEvent(event))
192 return false;
193 XEvent* xev = event;
194 ui::EventType type = ui::EventTypeFromNative(xev);
195 // For touch event, check if the root window is residing on the according
196 // touch display.
197 switch (type) {
198 case ui::ET_TOUCH_MOVED:
199 case ui::ET_TOUCH_PRESSED:
200 case ui::ET_TOUCH_CANCELLED:
201 case ui::ET_TOUCH_RELEASED: {
202 #if defined(OS_CHROMEOS)
203 XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev->xcookie.data);
204 int64 touch_display_id =
205 ui::DeviceDataManager::GetInstance()->GetDisplayForTouchDevice(
206 xiev->deviceid);
207 // If we don't have record of display id for this touch device, check
208 // that if the event is within the bound of the root window. Note
209 // that in multi-monitor case, the event position is in framebuffer
210 // space so the bounds check will not work so well.
211 if (touch_display_id == gfx::Display::kInvalidDisplayID) {
212 if (base::SysInfo::IsRunningOnChromeOS() &&
213 !bounds().Contains(ui::EventLocationFromNative(xev)))
214 return false;
215 } else if (touch_display_id != display_ids_.first &&
216 touch_display_id != display_ids_.second) {
217 return false;
219 #endif // defined(OS_CHROMEOS)
220 return true;
222 default:
223 return true;
226 void AshWindowTreeHostX11::TranslateAndDispatchLocatedEvent(
227 ui::LocatedEvent* event) {
228 TranslateLocatedEvent(event);
229 SendEventToProcessor(event);
232 #if defined(OS_CHROMEOS)
233 void AshWindowTreeHostX11::SetCrOSTapPaused(bool state) {
234 if (!ui::IsXInput2Available())
235 return;
236 // Temporarily pause tap-to-click when the cursor is hidden.
237 Atom prop = atom_cache()->GetAtom("Tap Paused");
238 unsigned char value = state;
239 XIDeviceList dev_list =
240 ui::DeviceListCacheX11::GetInstance()->GetXI2DeviceList(xdisplay());
242 // Only slave pointer devices could possibly have tap-paused property.
243 for (int i = 0; i < dev_list.count; i++) {
244 if (dev_list[i].use == XISlavePointer) {
245 Atom old_type;
246 int old_format;
247 unsigned long old_nvalues, bytes;
248 unsigned char* data;
249 int result = XIGetProperty(xdisplay(),
250 dev_list[i].deviceid,
251 prop,
254 False,
255 AnyPropertyType,
256 &old_type,
257 &old_format,
258 &old_nvalues,
259 &bytes,
260 &data);
261 if (result != Success)
262 continue;
263 XFree(data);
264 XIChangeProperty(xdisplay(),
265 dev_list[i].deviceid,
266 prop,
267 XA_INTEGER,
269 PropModeReplace,
270 &value,
275 #endif
277 AshWindowTreeHost* AshWindowTreeHost::Create(
278 const AshWindowTreeHostInitParams& init_params) {
279 return new AshWindowTreeHostX11(init_params.initial_bounds);
282 } // namespace ash