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