Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / ash / host / ash_window_tree_host_x11.cc
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.
4
5 #include "ash/host/ash_window_tree_host_x11.h"
6
7 #include <X11/extensions/Xfixes.h>
8 #include <X11/extensions/XInput2.h>
9 #include <X11/Xatom.h>
10 #include <X11/Xlib.h>
11
12 #include <string>
13 #include <vector>
14
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/client/screen_position_client.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/platform/platform_event_source.h"
30 #include "ui/gfx/rect.h"
31 #include "ui/gfx/screen.h"
32
33 namespace ash {
34
35 AshWindowTreeHostX11::AshWindowTreeHostX11(const gfx::Rect& initial_bounds)
36     : WindowTreeHostX11(initial_bounds),
37       transformer_helper_(this),
38       display_ids_(std::make_pair(gfx::Display::kInvalidDisplayID,
39                                   gfx::Display::kInvalidDisplayID)) {
40   aura::Env::GetInstance()->AddObserver(this);
41 }
42
43 AshWindowTreeHostX11::~AshWindowTreeHostX11() {
44   aura::Env::GetInstance()->RemoveObserver(this);
45   UnConfineCursor();
46 }
47
48 void AshWindowTreeHostX11::ToggleFullScreen() { NOTIMPLEMENTED(); }
49
50 bool AshWindowTreeHostX11::ConfineCursorToRootWindow() {
51 #if XFIXES_MAJOR >= 5
52   DCHECK(!pointer_barriers_.get());
53   if (pointer_barriers_)
54     return false;
55   pointer_barriers_.reset(new XID[4]);
56   gfx::Rect barrier(bounds());
57   barrier.Inset(transformer_helper_.GetHostInsets());
58   // Horizontal, top barriers.
59   pointer_barriers_[0] = XFixesCreatePointerBarrier(xdisplay(),
60                                                     x_root_window(),
61                                                     barrier.x(),
62                                                     barrier.y(),
63                                                     barrier.right(),
64                                                     barrier.y(),
65                                                     BarrierPositiveY,
66                                                     0,
67                                                     XIAllDevices);
68   // Horizontal, bottom barriers.
69   pointer_barriers_[1] = XFixesCreatePointerBarrier(xdisplay(),
70                                                     x_root_window(),
71                                                     barrier.x(),
72                                                     barrier.bottom(),
73                                                     barrier.right(),
74                                                     barrier.bottom(),
75                                                     BarrierNegativeY,
76                                                     0,
77                                                     XIAllDevices);
78   // Vertical, left  barriers.
79   pointer_barriers_[2] = XFixesCreatePointerBarrier(xdisplay(),
80                                                     x_root_window(),
81                                                     barrier.x(),
82                                                     barrier.y(),
83                                                     barrier.x(),
84                                                     barrier.bottom(),
85                                                     BarrierPositiveX,
86                                                     0,
87                                                     XIAllDevices);
88   // Vertical, right barriers.
89   pointer_barriers_[3] = XFixesCreatePointerBarrier(xdisplay(),
90                                                     x_root_window(),
91                                                     barrier.right(),
92                                                     barrier.y(),
93                                                     barrier.right(),
94                                                     barrier.bottom(),
95                                                     BarrierNegativeX,
96                                                     0,
97                                                     XIAllDevices);
98 #endif
99   return true;
100 }
101
102 void AshWindowTreeHostX11::UnConfineCursor() {
103 #if XFIXES_MAJOR >= 5
104   if (pointer_barriers_) {
105     XFixesDestroyPointerBarrier(xdisplay(), pointer_barriers_[0]);
106     XFixesDestroyPointerBarrier(xdisplay(), pointer_barriers_[1]);
107     XFixesDestroyPointerBarrier(xdisplay(), pointer_barriers_[2]);
108     XFixesDestroyPointerBarrier(xdisplay(), pointer_barriers_[3]);
109     pointer_barriers_.reset();
110   }
111 #endif
112 }
113
114 void AshWindowTreeHostX11::SetRootWindowTransformer(
115     scoped_ptr<RootWindowTransformer> transformer) {
116   transformer_helper_.SetRootWindowTransformer(transformer.Pass());
117   if (pointer_barriers_) {
118     UnConfineCursor();
119     ConfineCursorToRootWindow();
120   }
121 }
122
123 gfx::Insets AshWindowTreeHostX11::GetHostInsets() const {
124   return transformer_helper_.GetHostInsets();
125 }
126
127 aura::WindowTreeHost* AshWindowTreeHostX11::AsWindowTreeHost() { return this; }
128
129 void AshWindowTreeHostX11::UpdateDisplayID(int64 id1, int64 id2) {
130   display_ids_.first = id1;
131   display_ids_.second = id2;
132 }
133
134 void AshWindowTreeHostX11::PrepareForShutdown() {
135   if (ui::PlatformEventSource::GetInstance())
136     ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
137 }
138
139 void AshWindowTreeHostX11::SetBounds(const gfx::Rect& bounds) {
140   WindowTreeHostX11::SetBounds(bounds);
141   if (pointer_barriers_) {
142     UnConfineCursor();
143     ConfineCursorToRootWindow();
144   }
145 }
146
147 gfx::Transform AshWindowTreeHostX11::GetRootTransform() const {
148   return transformer_helper_.GetTransform();
149 }
150
151 void AshWindowTreeHostX11::SetRootTransform(const gfx::Transform& transform) {
152   transformer_helper_.SetTransform(transform);
153 }
154
155 gfx::Transform AshWindowTreeHostX11::GetInverseRootTransform() const {
156   return transformer_helper_.GetInverseTransform();
157 }
158
159 void AshWindowTreeHostX11::UpdateRootWindowSize(const gfx::Size& host_size) {
160   transformer_helper_.UpdateWindowSize(host_size);
161 }
162
163 void AshWindowTreeHostX11::OnCursorVisibilityChangedNative(bool show) {
164 #if defined(OS_CHROMEOS)
165   SetCrOSTapPaused(!show);
166 #endif
167 }
168
169 void AshWindowTreeHostX11::OnWindowInitialized(aura::Window* window) {}
170
171 void AshWindowTreeHostX11::OnHostInitialized(aura::WindowTreeHost* host) {
172   if (host != AsWindowTreeHost())
173     return;
174
175 #if defined(OS_CHROMEOS)
176   // We have to enable Tap-to-click by default because the cursor is set to
177   // visible in Shell::InitRootWindowController.
178   SetCrOSTapPaused(false);
179 #endif
180 }
181
182 void AshWindowTreeHostX11::OnConfigureNotify() {
183   // Always update barrier and mouse location because |bounds_| might
184   // have already been updated in |SetBounds|.
185   if (pointer_barriers_) {
186     UnConfineCursor();
187     ConfineCursorToRootWindow();
188   }
189 }
190
191 bool AshWindowTreeHostX11::CanDispatchEvent(const ui::PlatformEvent& event) {
192   if(!WindowTreeHostX11::CanDispatchEvent(event))
193     return false;
194   XEvent* xev = event;
195   ui::EventType type = ui::EventTypeFromNative(xev);
196   // For touch event, check if the root window is residing on the according
197   // touch display.
198   switch (type) {
199     case ui::ET_TOUCH_MOVED:
200     case ui::ET_TOUCH_PRESSED:
201     case ui::ET_TOUCH_CANCELLED:
202     case ui::ET_TOUCH_RELEASED: {
203 #if defined(OS_CHROMEOS)
204       XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev->xcookie.data);
205       int64 touch_display_id =
206           ui::DeviceDataManager::GetInstance()->GetDisplayForTouchDevice(
207               xiev->deviceid);
208       // If we don't have record of display id for this touch device, check
209       // that if the event is within the bound of the root window. Note
210       // that in multi-monitor case, the event position is in framebuffer
211       // space so the bounds check will not work so well.
212       if (touch_display_id == gfx::Display::kInvalidDisplayID) {
213         if (base::SysInfo::IsRunningOnChromeOS() &&
214             !bounds().Contains(ui::EventLocationFromNative(xev)))
215           return false;
216       } else if (touch_display_id != display_ids_.first &&
217                  touch_display_id != display_ids_.second) {
218         return false;
219       }
220 #endif  // defined(OS_CHROMEOS)
221       return true;
222     }
223     default:
224       return true;
225   }
226 }
227 void AshWindowTreeHostX11::TranslateAndDispatchLocatedEvent(
228     ui::LocatedEvent* event) {
229   if (!event->IsTouchEvent()) {
230     aura::Window* root_window = window();
231     aura::client::ScreenPositionClient* screen_position_client =
232         aura::client::GetScreenPositionClient(root_window);
233     gfx::Rect local(bounds().size());
234     local.Inset(transformer_helper_.GetHostInsets());
235
236     if (screen_position_client && !local.Contains(event->location())) {
237       gfx::Point location(event->location());
238       // In order to get the correct point in screen coordinates
239       // during passive grab, we first need to find on which host window
240       // the mouse is on, and find out the screen coordinates on that
241       // host window, then convert it back to this host window's coordinate.
242       screen_position_client->ConvertHostPointToScreen(root_window,
243                                                        &location);
244       screen_position_client->ConvertPointFromScreen(root_window, &location);
245       ConvertPointToHost(&location);
246       event->set_location(location);
247       event->set_root_location(location);
248     }
249   }
250   SendEventToProcessor(event);
251 }
252
253 #if defined(OS_CHROMEOS)
254 void AshWindowTreeHostX11::SetCrOSTapPaused(bool state) {
255   if (!ui::IsXInput2Available())
256     return;
257   // Temporarily pause tap-to-click when the cursor is hidden.
258   Atom prop = atom_cache()->GetAtom("Tap Paused");
259   unsigned char value = state;
260   XIDeviceList dev_list =
261       ui::DeviceListCacheX11::GetInstance()->GetXI2DeviceList(xdisplay());
262
263   // Only slave pointer devices could possibly have tap-paused property.
264   for (int i = 0; i < dev_list.count; i++) {
265     if (dev_list[i].use == XISlavePointer) {
266       Atom old_type;
267       int old_format;
268       unsigned long old_nvalues, bytes;
269       unsigned char* data;
270       int result = XIGetProperty(xdisplay(),
271                                  dev_list[i].deviceid,
272                                  prop,
273                                  0,
274                                  0,
275                                  False,
276                                  AnyPropertyType,
277                                  &old_type,
278                                  &old_format,
279                                  &old_nvalues,
280                                  &bytes,
281                                  &data);
282       if (result != Success)
283         continue;
284       XFree(data);
285       XIChangeProperty(xdisplay(),
286                        dev_list[i].deviceid,
287                        prop,
288                        XA_INTEGER,
289                        8,
290                        PropModeReplace,
291                        &value,
292                        1);
293     }
294   }
295 }
296 #endif
297
298 AshWindowTreeHost* AshWindowTreeHost::Create(
299     const AshWindowTreeHostInitParams& init_params) {
300   return new AshWindowTreeHostX11(init_params.initial_bounds);
301 }
302
303 }  // namespace ash