Make common depend on app_mode_app_support.
[chromium-blink-merge.git] / ash / host / ash_window_tree_host_x11.cc
blob882ef13409b01a0ddfaca88b6412efdec2f3bc5e
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/null_event_targeter.h"
29 #include "ui/events/platform/platform_event_source.h"
30 #include "ui/gfx/geometry/rect.h"
31 #include "ui/gfx/screen.h"
33 namespace ash {
35 AshWindowTreeHostX11::AshWindowTreeHostX11(const gfx::Rect& initial_bounds)
36 : WindowTreeHostX11(initial_bounds), transformer_helper_(this) {
37 aura::Env::GetInstance()->AddObserver(this);
40 AshWindowTreeHostX11::~AshWindowTreeHostX11() {
41 aura::Env::GetInstance()->RemoveObserver(this);
42 UnConfineCursor();
45 void AshWindowTreeHostX11::ToggleFullScreen() { NOTIMPLEMENTED(); }
47 bool AshWindowTreeHostX11::ConfineCursorToRootWindow() {
48 #if XFIXES_MAJOR >= 5
49 DCHECK(!pointer_barriers_.get());
50 if (pointer_barriers_)
51 return false;
52 pointer_barriers_.reset(new XID[4]);
53 gfx::Rect barrier(bounds());
54 barrier.Inset(transformer_helper_.GetHostInsets());
55 // Horizontal, top barriers.
56 pointer_barriers_[0] = XFixesCreatePointerBarrier(xdisplay(),
57 x_root_window(),
58 barrier.x(),
59 barrier.y(),
60 barrier.right(),
61 barrier.y(),
62 BarrierPositiveY,
64 XIAllDevices);
65 // Horizontal, bottom barriers.
66 pointer_barriers_[1] = XFixesCreatePointerBarrier(xdisplay(),
67 x_root_window(),
68 barrier.x(),
69 barrier.bottom(),
70 barrier.right(),
71 barrier.bottom(),
72 BarrierNegativeY,
74 XIAllDevices);
75 // Vertical, left barriers.
76 pointer_barriers_[2] = XFixesCreatePointerBarrier(xdisplay(),
77 x_root_window(),
78 barrier.x(),
79 barrier.y(),
80 barrier.x(),
81 barrier.bottom(),
82 BarrierPositiveX,
84 XIAllDevices);
85 // Vertical, right barriers.
86 pointer_barriers_[3] = XFixesCreatePointerBarrier(xdisplay(),
87 x_root_window(),
88 barrier.right(),
89 barrier.y(),
90 barrier.right(),
91 barrier.bottom(),
92 BarrierNegativeX,
94 XIAllDevices);
95 #endif
96 return true;
99 void AshWindowTreeHostX11::UnConfineCursor() {
100 #if XFIXES_MAJOR >= 5
101 if (pointer_barriers_) {
102 XFixesDestroyPointerBarrier(xdisplay(), pointer_barriers_[0]);
103 XFixesDestroyPointerBarrier(xdisplay(), pointer_barriers_[1]);
104 XFixesDestroyPointerBarrier(xdisplay(), pointer_barriers_[2]);
105 XFixesDestroyPointerBarrier(xdisplay(), pointer_barriers_[3]);
106 pointer_barriers_.reset();
108 #endif
111 void AshWindowTreeHostX11::SetRootWindowTransformer(
112 scoped_ptr<RootWindowTransformer> transformer) {
113 transformer_helper_.SetRootWindowTransformer(transformer.Pass());
114 if (pointer_barriers_) {
115 UnConfineCursor();
116 ConfineCursorToRootWindow();
120 gfx::Insets AshWindowTreeHostX11::GetHostInsets() const {
121 return transformer_helper_.GetHostInsets();
124 aura::WindowTreeHost* AshWindowTreeHostX11::AsWindowTreeHost() { return this; }
126 void AshWindowTreeHostX11::PrepareForShutdown() {
127 // Block the root window from dispatching events because it is weird for a
128 // ScreenPositionClient not to be attached to the root window and for
129 // ui::EventHandlers to be unable to convert the event's location to screen
130 // coordinates.
131 window()->SetEventTargeter(
132 scoped_ptr<ui::EventTargeter>(new ui::NullEventTargeter));
134 if (ui::PlatformEventSource::GetInstance()) {
135 // Block X events which are not turned into ui::Events from getting
136 // processed. (e.g. ConfigureNotify)
137 ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
141 void AshWindowTreeHostX11::SetBounds(const gfx::Rect& bounds) {
142 WindowTreeHostX11::SetBounds(bounds);
143 if (pointer_barriers_) {
144 UnConfineCursor();
145 ConfineCursorToRootWindow();
149 gfx::Transform AshWindowTreeHostX11::GetRootTransform() const {
150 return transformer_helper_.GetTransform();
153 void AshWindowTreeHostX11::SetRootTransform(const gfx::Transform& transform) {
154 transformer_helper_.SetTransform(transform);
157 gfx::Transform AshWindowTreeHostX11::GetInverseRootTransform() const {
158 return transformer_helper_.GetInverseTransform();
161 void AshWindowTreeHostX11::UpdateRootWindowSize(const gfx::Size& host_size) {
162 transformer_helper_.UpdateWindowSize(host_size);
165 void AshWindowTreeHostX11::OnCursorVisibilityChangedNative(bool show) {
166 #if defined(OS_CHROMEOS)
167 SetCrOSTapPaused(!show);
168 #endif
171 void AshWindowTreeHostX11::OnWindowInitialized(aura::Window* window) {}
173 void AshWindowTreeHostX11::OnHostInitialized(aura::WindowTreeHost* host) {
174 if (host != AsWindowTreeHost())
175 return;
177 #if defined(OS_CHROMEOS)
178 // We have to enable Tap-to-click by default because the cursor is set to
179 // visible in Shell::InitRootWindowController.
180 SetCrOSTapPaused(false);
181 #endif
184 void AshWindowTreeHostX11::OnConfigureNotify() {
185 // Always update barrier and mouse location because |bounds_| might
186 // have already been updated in |SetBounds|.
187 if (pointer_barriers_) {
188 UnConfineCursor();
189 ConfineCursorToRootWindow();
193 bool AshWindowTreeHostX11::CanDispatchEvent(const ui::PlatformEvent& event) {
194 if(!WindowTreeHostX11::CanDispatchEvent(event))
195 return false;
196 XEvent* xev = event;
197 ui::EventType type = ui::EventTypeFromNative(xev);
198 // For touch event, check if the root window is residing on the according
199 // touch display.
200 switch (type) {
201 case ui::ET_TOUCH_MOVED:
202 case ui::ET_TOUCH_PRESSED:
203 case ui::ET_TOUCH_CANCELLED:
204 case ui::ET_TOUCH_RELEASED: {
205 #if defined(OS_CHROMEOS)
206 XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev->xcookie.data);
207 int64 touch_display_id =
208 ui::DeviceDataManager::GetInstance()->GetTargetDisplayForTouchDevice(
209 xiev->deviceid);
210 // If we don't have record of display id for this touch device, check
211 // that if the event is within the bound of the root window. Note
212 // that in multi-monitor case, the event position is in framebuffer
213 // space so the bounds check will not work so well.
214 if (touch_display_id == gfx::Display::kInvalidDisplayID) {
215 if (base::SysInfo::IsRunningOnChromeOS() &&
216 !bounds().Contains(ui::EventLocationFromNative(xev)))
217 return false;
218 } else {
219 gfx::Screen* screen = gfx::Screen::GetScreenFor(window());
220 gfx::Display display = screen->GetDisplayNearestWindow(window());
221 return touch_display_id == display.id();
223 #endif // defined(OS_CHROMEOS)
224 return true;
226 default:
227 return true;
230 void AshWindowTreeHostX11::TranslateAndDispatchLocatedEvent(
231 ui::LocatedEvent* event) {
232 TranslateLocatedEvent(event);
233 SendEventToProcessor(event);
236 #if defined(OS_CHROMEOS)
237 void AshWindowTreeHostX11::SetCrOSTapPaused(bool state) {
238 if (!ui::IsXInput2Available())
239 return;
240 // Temporarily pause tap-to-click when the cursor is hidden.
241 Atom prop = atom_cache()->GetAtom("Tap Paused");
242 unsigned char value = state;
243 const XIDeviceList& dev_list =
244 ui::DeviceListCacheX11::GetInstance()->GetXI2DeviceList(xdisplay());
246 // Only slave pointer devices could possibly have tap-paused property.
247 for (int i = 0; i < dev_list.count; i++) {
248 if (dev_list[i].use == XISlavePointer) {
249 Atom old_type;
250 int old_format;
251 unsigned long old_nvalues, bytes;
252 unsigned char* data;
253 int result = XIGetProperty(xdisplay(),
254 dev_list[i].deviceid,
255 prop,
258 False,
259 AnyPropertyType,
260 &old_type,
261 &old_format,
262 &old_nvalues,
263 &bytes,
264 &data);
265 if (result != Success)
266 continue;
267 XFree(data);
268 XIChangeProperty(xdisplay(),
269 dev_list[i].deviceid,
270 prop,
271 XA_INTEGER,
273 PropModeReplace,
274 &value,
279 #endif
281 AshWindowTreeHost* AshWindowTreeHost::Create(
282 const AshWindowTreeHostInitParams& init_params) {
283 return new AshWindowTreeHostX11(init_params.initial_bounds);
286 } // namespace ash