OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/aura/window_tree_host_x11.h" | 5 #include "ui/aura/window_tree_host_x11.h" |
6 | 6 |
7 #include <strings.h> | 7 #include <strings.h> |
8 #include <X11/cursorfont.h> | 8 #include <X11/cursorfont.h> |
9 #include <X11/extensions/Xfixes.h> | |
10 #include <X11/extensions/XInput2.h> | 9 #include <X11/extensions/XInput2.h> |
11 #include <X11/extensions/Xrandr.h> | 10 #include <X11/extensions/Xrandr.h> |
12 #include <X11/Xatom.h> | 11 #include <X11/Xatom.h> |
13 #include <X11/Xcursor/Xcursor.h> | 12 #include <X11/Xcursor/Xcursor.h> |
14 #include <X11/Xlib.h> | 13 #include <X11/Xlib.h> |
15 | 14 |
16 #include <algorithm> | 15 #include <algorithm> |
17 #include <limits> | 16 #include <limits> |
18 #include <string> | 17 #include <string> |
19 | 18 |
20 #include "base/basictypes.h" | 19 #include "base/basictypes.h" |
21 #include "base/command_line.h" | 20 #include "base/command_line.h" |
22 #include "base/debug/trace_event.h" | 21 #include "base/debug/trace_event.h" |
23 #include "base/stl_util.h" | 22 #include "base/stl_util.h" |
24 #include "base/strings/string_number_conversions.h" | 23 #include "base/strings/string_number_conversions.h" |
25 #include "base/strings/string_util.h" | 24 #include "base/strings/string_util.h" |
26 #include "base/strings/stringprintf.h" | 25 #include "base/strings/stringprintf.h" |
27 #include "base/sys_info.h" | 26 #include "base/sys_info.h" |
28 #include "ui/aura/client/cursor_client.h" | 27 #include "ui/aura/client/cursor_client.h" |
29 #include "ui/aura/client/screen_position_client.h" | |
30 #include "ui/aura/env.h" | 28 #include "ui/aura/env.h" |
| 29 #include "ui/aura/window.h" |
31 #include "ui/aura/window_event_dispatcher.h" | 30 #include "ui/aura/window_event_dispatcher.h" |
32 #include "ui/base/cursor/cursor.h" | 31 #include "ui/base/cursor/cursor.h" |
33 #include "ui/base/ui_base_switches.h" | 32 #include "ui/base/ui_base_switches.h" |
34 #include "ui/base/view_prop.h" | 33 #include "ui/base/view_prop.h" |
35 #include "ui/base/x/x11_util.h" | 34 #include "ui/base/x/x11_util.h" |
36 #include "ui/compositor/compositor.h" | 35 #include "ui/compositor/compositor.h" |
37 #include "ui/compositor/dip_util.h" | 36 #include "ui/compositor/dip_util.h" |
38 #include "ui/compositor/layer.h" | 37 #include "ui/compositor/layer.h" |
39 #include "ui/events/event.h" | 38 #include "ui/events/event.h" |
40 #include "ui/events/event_switches.h" | 39 #include "ui/events/event_switches.h" |
41 #include "ui/events/event_utils.h" | 40 #include "ui/events/event_utils.h" |
42 #include "ui/events/keycodes/keyboard_codes.h" | 41 #include "ui/events/keycodes/keyboard_codes.h" |
43 #include "ui/events/platform/platform_event_observer.h" | |
44 #include "ui/events/platform/x11/x11_event_source.h" | 42 #include "ui/events/platform/x11/x11_event_source.h" |
45 #include "ui/events/x/device_data_manager.h" | 43 #include "ui/events/x/device_data_manager.h" |
46 #include "ui/events/x/device_list_cache_x.h" | 44 #include "ui/events/x/device_list_cache_x.h" |
47 #include "ui/events/x/touch_factory_x11.h" | 45 #include "ui/events/x/touch_factory_x11.h" |
48 #include "ui/gfx/screen.h" | 46 #include "ui/gfx/screen.h" |
49 | 47 |
50 using std::max; | 48 using std::max; |
51 using std::min; | 49 using std::min; |
52 | 50 |
53 namespace aura { | 51 namespace aura { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 XISetMask(mask, XI_TouchEnd); | 99 XISetMask(mask, XI_TouchEnd); |
102 XISelectEvents(display, root_window, &evmask, 1); | 100 XISelectEvents(display, root_window, &evmask, 1); |
103 } | 101 } |
104 #endif | 102 #endif |
105 } | 103 } |
106 | 104 |
107 bool default_override_redirect = false; | 105 bool default_override_redirect = false; |
108 | 106 |
109 } // namespace | 107 } // namespace |
110 | 108 |
111 namespace internal { | |
112 | |
113 // Accomplishes 2 tasks concerning touch event calibration: | |
114 // 1. Being a message-pump observer, | |
115 // routes all the touch events to the X root window, | |
116 // where they can be calibrated later. | |
117 // 2. Has the Calibrate method that does the actual bezel calibration, | |
118 // when invoked from X root window's event dispatcher. | |
119 class TouchEventCalibrate : public ui::PlatformEventObserver { | |
120 public: | |
121 TouchEventCalibrate() | |
122 : left_(0), | |
123 right_(0), | |
124 top_(0), | |
125 bottom_(0) { | |
126 if (ui::PlatformEventSource::GetInstance()) | |
127 ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this); | |
128 #if defined(USE_XI2_MT) | |
129 std::vector<std::string> parts; | |
130 if (Tokenize(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | |
131 switches::kTouchCalibration), ",", &parts) >= 4) { | |
132 if (!base::StringToInt(parts[0], &left_)) | |
133 DLOG(ERROR) << "Incorrect left border calibration value passed."; | |
134 if (!base::StringToInt(parts[1], &right_)) | |
135 DLOG(ERROR) << "Incorrect right border calibration value passed."; | |
136 if (!base::StringToInt(parts[2], &top_)) | |
137 DLOG(ERROR) << "Incorrect top border calibration value passed."; | |
138 if (!base::StringToInt(parts[3], &bottom_)) | |
139 DLOG(ERROR) << "Incorrect bottom border calibration value passed."; | |
140 } | |
141 #endif // defined(USE_XI2_MT) | |
142 } | |
143 | |
144 virtual ~TouchEventCalibrate() { | |
145 if (ui::PlatformEventSource::GetInstance()) | |
146 ui::PlatformEventSource::GetInstance()->RemovePlatformEventObserver(this); | |
147 } | |
148 | |
149 // Modify the location of the |event|, | |
150 // expanding it from |bounds| to (|bounds| + bezels). | |
151 // Required when touchscreen is bigger than screen (i.e. has bezels), | |
152 // because we receive events in touchscreen coordinates, | |
153 // which need to be expanded when converting to screen coordinates, | |
154 // so that location on bezels will be outside of screen area. | |
155 void Calibrate(ui::TouchEvent* event, const gfx::Rect& bounds) { | |
156 #if defined(USE_XI2_MT) | |
157 int x = event->x(); | |
158 int y = event->y(); | |
159 | |
160 if (!left_ && !right_ && !top_ && !bottom_) | |
161 return; | |
162 | |
163 const int resolution_x = bounds.width(); | |
164 const int resolution_y = bounds.height(); | |
165 // The "grace area" (10% in this case) is to make it easier for the user to | |
166 // navigate to the corner. | |
167 const double kGraceAreaFraction = 0.1; | |
168 if (left_ || right_) { | |
169 // Offset the x position to the real | |
170 x -= left_; | |
171 // Check if we are in the grace area of the left side. | |
172 // Note: We might not want to do this when the gesture is locked? | |
173 if (x < 0 && x > -left_ * kGraceAreaFraction) | |
174 x = 0; | |
175 // Check if we are in the grace area of the right side. | |
176 // Note: We might not want to do this when the gesture is locked? | |
177 if (x > resolution_x - left_ && | |
178 x < resolution_x - left_ + right_ * kGraceAreaFraction) | |
179 x = resolution_x - left_; | |
180 // Scale the screen area back to the full resolution of the screen. | |
181 x = (x * resolution_x) / (resolution_x - (right_ + left_)); | |
182 } | |
183 if (top_ || bottom_) { | |
184 // When there is a top bezel we add our border, | |
185 y -= top_; | |
186 | |
187 // Check if we are in the grace area of the top side. | |
188 // Note: We might not want to do this when the gesture is locked? | |
189 if (y < 0 && y > -top_ * kGraceAreaFraction) | |
190 y = 0; | |
191 | |
192 // Check if we are in the grace area of the bottom side. | |
193 // Note: We might not want to do this when the gesture is locked? | |
194 if (y > resolution_y - top_ && | |
195 y < resolution_y - top_ + bottom_ * kGraceAreaFraction) | |
196 y = resolution_y - top_; | |
197 // Scale the screen area back to the full resolution of the screen. | |
198 y = (y * resolution_y) / (resolution_y - (bottom_ + top_)); | |
199 } | |
200 | |
201 // Set the modified coordinate back to the event. | |
202 if (event->root_location() == event->location()) { | |
203 // Usually those will be equal, | |
204 // if not, I am not sure what the correct value should be. | |
205 event->set_root_location(gfx::Point(x, y)); | |
206 } | |
207 event->set_location(gfx::Point(x, y)); | |
208 #endif // defined(USE_XI2_MT) | |
209 } | |
210 | |
211 private: | |
212 // ui::PlatformEventObserver: | |
213 virtual void WillProcessEvent(const ui::PlatformEvent& event) OVERRIDE { | |
214 #if defined(USE_XI2_MT) | |
215 if (event->type == GenericEvent && | |
216 (event->xgeneric.evtype == XI_TouchBegin || | |
217 event->xgeneric.evtype == XI_TouchUpdate || | |
218 event->xgeneric.evtype == XI_TouchEnd)) { | |
219 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(event->xcookie.data); | |
220 xievent->event = xievent->root; | |
221 xievent->event_x = xievent->root_x; | |
222 xievent->event_y = xievent->root_y; | |
223 } | |
224 #endif // defined(USE_XI2_MT) | |
225 } | |
226 | |
227 virtual void DidProcessEvent(const ui::PlatformEvent& event) OVERRIDE {} | |
228 | |
229 // The difference in screen's native resolution pixels between | |
230 // the border of the touchscreen and the border of the screen, | |
231 // aka bezel sizes. | |
232 int left_; | |
233 int right_; | |
234 int top_; | |
235 int bottom_; | |
236 | |
237 DISALLOW_COPY_AND_ASSIGN(TouchEventCalibrate); | |
238 }; | |
239 | |
240 } // namespace internal | |
241 | |
242 //////////////////////////////////////////////////////////////////////////////// | 109 //////////////////////////////////////////////////////////////////////////////// |
243 // WindowTreeHostX11 | 110 // WindowTreeHostX11 |
244 | 111 |
245 WindowTreeHostX11::WindowTreeHostX11(const gfx::Rect& bounds) | 112 WindowTreeHostX11::WindowTreeHostX11(const gfx::Rect& bounds) |
246 : xdisplay_(gfx::GetXDisplay()), | 113 : xdisplay_(gfx::GetXDisplay()), |
247 xwindow_(0), | 114 xwindow_(0), |
248 x_root_window_(DefaultRootWindow(xdisplay_)), | 115 x_root_window_(DefaultRootWindow(xdisplay_)), |
249 current_cursor_(ui::kCursorNull), | 116 current_cursor_(ui::kCursorNull), |
250 window_mapped_(false), | 117 window_mapped_(false), |
251 bounds_(bounds), | 118 bounds_(bounds), |
252 is_internal_display_(false), | |
253 touch_calibrate_(new internal::TouchEventCalibrate), | |
254 atom_cache_(xdisplay_, kAtomsToCache) { | 119 atom_cache_(xdisplay_, kAtomsToCache) { |
255 XSetWindowAttributes swa; | 120 XSetWindowAttributes swa; |
256 memset(&swa, 0, sizeof(swa)); | 121 memset(&swa, 0, sizeof(swa)); |
257 swa.background_pixmap = None; | 122 swa.background_pixmap = None; |
258 swa.override_redirect = default_override_redirect; | 123 swa.override_redirect = default_override_redirect; |
259 xwindow_ = XCreateWindow( | 124 xwindow_ = XCreateWindow( |
260 xdisplay_, x_root_window_, | 125 xdisplay_, x_root_window_, |
261 bounds.x(), bounds.y(), bounds.width(), bounds.height(), | 126 bounds.x(), bounds.y(), bounds.width(), bounds.height(), |
262 0, // border width | 127 0, // border width |
263 CopyFromParent, // depth | 128 CopyFromParent, // depth |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 XChangeProperty(xdisplay_, | 167 XChangeProperty(xdisplay_, |
303 xwindow_, | 168 xwindow_, |
304 atom_cache_.GetAtom("_NET_WM_PID"), | 169 atom_cache_.GetAtom("_NET_WM_PID"), |
305 XA_CARDINAL, | 170 XA_CARDINAL, |
306 32, | 171 32, |
307 PropModeReplace, | 172 PropModeReplace, |
308 reinterpret_cast<unsigned char*>(&pid), 1); | 173 reinterpret_cast<unsigned char*>(&pid), 1); |
309 | 174 |
310 XRRSelectInput(xdisplay_, x_root_window_, | 175 XRRSelectInput(xdisplay_, x_root_window_, |
311 RRScreenChangeNotifyMask | RROutputChangeNotifyMask); | 176 RRScreenChangeNotifyMask | RROutputChangeNotifyMask); |
312 Env::GetInstance()->AddObserver(this); | |
313 CreateCompositor(GetAcceleratedWidget()); | 177 CreateCompositor(GetAcceleratedWidget()); |
314 } | 178 } |
315 | 179 |
316 WindowTreeHostX11::~WindowTreeHostX11() { | 180 WindowTreeHostX11::~WindowTreeHostX11() { |
317 Env::GetInstance()->RemoveObserver(this); | |
318 if (ui::PlatformEventSource::GetInstance()) | 181 if (ui::PlatformEventSource::GetInstance()) |
319 ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this); | 182 ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this); |
320 | 183 |
321 UnConfineCursor(); | |
322 | |
323 DestroyCompositor(); | 184 DestroyCompositor(); |
324 DestroyDispatcher(); | 185 DestroyDispatcher(); |
325 XDestroyWindow(xdisplay_, xwindow_); | 186 XDestroyWindow(xdisplay_, xwindow_); |
326 } | 187 } |
327 | 188 |
328 bool WindowTreeHostX11::CanDispatchEvent(const ui::PlatformEvent& event) { | 189 bool WindowTreeHostX11::CanDispatchEvent(const ui::PlatformEvent& event) { |
329 ::Window target = FindEventTarget(event); | 190 ::Window target = FindEventTarget(event); |
330 return target == xwindow_ || target == x_root_window_; | 191 return target == xwindow_ || target == x_root_window_; |
331 } | 192 } |
332 | 193 |
(...skipping 12 matching lines...) Expand all Loading... |
345 client::GetCursorClient(root_window); | 206 client::GetCursorClient(root_window); |
346 if (cursor_client) { | 207 if (cursor_client) { |
347 const gfx::Display display = gfx::Screen::GetScreenFor(root_window)-> | 208 const gfx::Display display = gfx::Screen::GetScreenFor(root_window)-> |
348 GetDisplayNearestWindow(root_window); | 209 GetDisplayNearestWindow(root_window); |
349 cursor_client->SetDisplay(display); | 210 cursor_client->SetDisplay(display); |
350 } | 211 } |
351 ui::MouseEvent mouse_event(xev); | 212 ui::MouseEvent mouse_event(xev); |
352 // EnterNotify creates ET_MOUSE_MOVE. Mark as synthesized as this is not | 213 // EnterNotify creates ET_MOUSE_MOVE. Mark as synthesized as this is not |
353 // real mouse move event. | 214 // real mouse move event. |
354 mouse_event.set_flags(mouse_event.flags() | ui::EF_IS_SYNTHESIZED); | 215 mouse_event.set_flags(mouse_event.flags() | ui::EF_IS_SYNTHESIZED); |
355 TranslateAndDispatchMouseEvent(&mouse_event); | 216 TranslateAndDispatchLocatedEvent(&mouse_event); |
356 break; | 217 break; |
357 } | 218 } |
358 case LeaveNotify: { | 219 case LeaveNotify: { |
359 ui::MouseEvent mouse_event(xev); | 220 ui::MouseEvent mouse_event(xev); |
360 TranslateAndDispatchMouseEvent(&mouse_event); | 221 TranslateAndDispatchLocatedEvent(&mouse_event); |
361 break; | 222 break; |
362 } | 223 } |
363 case Expose: { | 224 case Expose: { |
364 gfx::Rect damage_rect(xev->xexpose.x, xev->xexpose.y, | 225 gfx::Rect damage_rect(xev->xexpose.x, xev->xexpose.y, |
365 xev->xexpose.width, xev->xexpose.height); | 226 xev->xexpose.width, xev->xexpose.height); |
366 compositor()->ScheduleRedrawRect(damage_rect); | 227 compositor()->ScheduleRedrawRect(damage_rect); |
367 break; | 228 break; |
368 } | 229 } |
369 case KeyPress: { | 230 case KeyPress: { |
370 ui::KeyEvent keydown_event(xev, false); | 231 ui::KeyEvent keydown_event(xev, false); |
371 SendEventToProcessor(&keydown_event); | 232 SendEventToProcessor(&keydown_event); |
372 break; | 233 break; |
373 } | 234 } |
374 case KeyRelease: { | 235 case KeyRelease: { |
375 ui::KeyEvent keyup_event(xev, false); | 236 ui::KeyEvent keyup_event(xev, false); |
376 SendEventToProcessor(&keyup_event); | 237 SendEventToProcessor(&keyup_event); |
377 break; | 238 break; |
378 } | 239 } |
379 case ButtonPress: | 240 case ButtonPress: |
380 case ButtonRelease: { | 241 case ButtonRelease: { |
381 switch (ui::EventTypeFromNative(xev)) { | 242 switch (ui::EventTypeFromNative(xev)) { |
382 case ui::ET_MOUSEWHEEL: { | 243 case ui::ET_MOUSEWHEEL: { |
383 ui::MouseWheelEvent mouseev(xev); | 244 ui::MouseWheelEvent mouseev(xev); |
384 TranslateAndDispatchMouseEvent(&mouseev); | 245 TranslateAndDispatchLocatedEvent(&mouseev); |
385 break; | 246 break; |
386 } | 247 } |
387 case ui::ET_MOUSE_PRESSED: | 248 case ui::ET_MOUSE_PRESSED: |
388 case ui::ET_MOUSE_RELEASED: { | 249 case ui::ET_MOUSE_RELEASED: { |
389 ui::MouseEvent mouseev(xev); | 250 ui::MouseEvent mouseev(xev); |
390 TranslateAndDispatchMouseEvent(&mouseev); | 251 TranslateAndDispatchLocatedEvent(&mouseev); |
391 break; | 252 break; |
392 } | 253 } |
393 case ui::ET_UNKNOWN: | 254 case ui::ET_UNKNOWN: |
394 // No event is created for X11-release events for mouse-wheel buttons. | 255 // No event is created for X11-release events for mouse-wheel buttons. |
395 break; | 256 break; |
396 default: | 257 default: |
397 NOTREACHED(); | 258 NOTREACHED(); |
398 } | 259 } |
399 break; | 260 break; |
400 } | 261 } |
401 case FocusOut: | 262 case FocusOut: |
402 if (xev->xfocus.mode != NotifyGrab) | 263 if (xev->xfocus.mode != NotifyGrab) |
403 OnHostLostWindowCapture(); | 264 OnHostLostWindowCapture(); |
404 break; | 265 break; |
405 case ConfigureNotify: { | 266 case ConfigureNotify: { |
406 DCHECK_EQ(xwindow_, xev->xconfigure.event); | 267 DCHECK_EQ(xwindow_, xev->xconfigure.event); |
407 DCHECK_EQ(xwindow_, xev->xconfigure.window); | 268 DCHECK_EQ(xwindow_, xev->xconfigure.window); |
408 // It's possible that the X window may be resized by some other means | 269 // It's possible that the X window may be resized by some other means |
409 // than from within aura (e.g. the X window manager can change the | 270 // than from within aura (e.g. the X window manager can change the |
410 // size). Make sure the root window size is maintained properly. | 271 // size). Make sure the root window size is maintained properly. |
411 gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y, | 272 gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y, |
412 xev->xconfigure.width, xev->xconfigure.height); | 273 xev->xconfigure.width, xev->xconfigure.height); |
413 bool size_changed = bounds_.size() != bounds.size(); | 274 bool size_changed = bounds_.size() != bounds.size(); |
414 bool origin_changed = bounds_.origin() != bounds.origin(); | 275 bool origin_changed = bounds_.origin() != bounds.origin(); |
415 bounds_ = bounds; | 276 bounds_ = bounds; |
416 UpdateIsInternalDisplay(); | 277 OnConfigureNotify(); |
417 // Always update barrier and mouse location because |bounds_| might | |
418 // have already been updated in |SetBounds|. | |
419 if (pointer_barriers_) { | |
420 UnConfineCursor(); | |
421 ConfineCursorToRootWindow(); | |
422 } | |
423 if (size_changed) | 278 if (size_changed) |
424 OnHostResized(bounds.size()); | 279 OnHostResized(bounds.size()); |
425 if (origin_changed) | 280 if (origin_changed) |
426 OnHostMoved(bounds_.origin()); | 281 OnHostMoved(bounds_.origin()); |
427 break; | 282 break; |
428 } | 283 } |
429 case GenericEvent: | 284 case GenericEvent: |
430 DispatchXI2Event(xev); | 285 DispatchXI2Event(xev); |
431 break; | 286 break; |
432 case ClientMessage: { | 287 case ClientMessage: { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
473 next_event.xmotion.subwindow == xev->xmotion.subwindow && | 328 next_event.xmotion.subwindow == xev->xmotion.subwindow && |
474 next_event.xmotion.state == xev->xmotion.state) { | 329 next_event.xmotion.state == xev->xmotion.state) { |
475 XNextEvent(xev->xany.display, &last_event); | 330 XNextEvent(xev->xany.display, &last_event); |
476 xev = &last_event; | 331 xev = &last_event; |
477 } else { | 332 } else { |
478 break; | 333 break; |
479 } | 334 } |
480 } | 335 } |
481 | 336 |
482 ui::MouseEvent mouseev(xev); | 337 ui::MouseEvent mouseev(xev); |
483 TranslateAndDispatchMouseEvent(&mouseev); | 338 TranslateAndDispatchLocatedEvent(&mouseev); |
484 break; | 339 break; |
485 } | 340 } |
486 } | 341 } |
487 return ui::POST_DISPATCH_STOP_PROPAGATION; | 342 return ui::POST_DISPATCH_STOP_PROPAGATION; |
488 } | 343 } |
489 | 344 |
490 gfx::AcceleratedWidget WindowTreeHostX11::GetAcceleratedWidget() { | 345 gfx::AcceleratedWidget WindowTreeHostX11::GetAcceleratedWidget() { |
491 return xwindow_; | 346 return xwindow_; |
492 } | 347 } |
493 | 348 |
(...skipping 21 matching lines...) Expand all Loading... |
515 } | 370 } |
516 } | 371 } |
517 | 372 |
518 void WindowTreeHostX11::Hide() { | 373 void WindowTreeHostX11::Hide() { |
519 if (window_mapped_) { | 374 if (window_mapped_) { |
520 XWithdrawWindow(xdisplay_, xwindow_, 0); | 375 XWithdrawWindow(xdisplay_, xwindow_, 0); |
521 window_mapped_ = false; | 376 window_mapped_ = false; |
522 } | 377 } |
523 } | 378 } |
524 | 379 |
525 void WindowTreeHostX11::ToggleFullScreen() { | |
526 NOTIMPLEMENTED(); | |
527 } | |
528 | |
529 gfx::Rect WindowTreeHostX11::GetBounds() const { | 380 gfx::Rect WindowTreeHostX11::GetBounds() const { |
530 return bounds_; | 381 return bounds_; |
531 } | 382 } |
532 | 383 |
533 void WindowTreeHostX11::SetBounds(const gfx::Rect& bounds) { | 384 void WindowTreeHostX11::SetBounds(const gfx::Rect& bounds) { |
534 // Even if the host window's size doesn't change, aura's root window | 385 // Even if the host window's size doesn't change, aura's root window |
535 // size, which is in DIP, changes when the scale changes. | 386 // size, which is in DIP, changes when the scale changes. |
536 float current_scale = compositor()->device_scale_factor(); | 387 float current_scale = compositor()->device_scale_factor(); |
537 float new_scale = gfx::Screen::GetScreenFor(window())-> | 388 float new_scale = gfx::Screen::GetScreenFor(window())-> |
538 GetDisplayNearestWindow(window()).device_scale_factor(); | 389 GetDisplayNearestWindow(window()).device_scale_factor(); |
(...skipping 15 matching lines...) Expand all Loading... |
554 } | 405 } |
555 if (value_mask) | 406 if (value_mask) |
556 XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes); | 407 XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes); |
557 | 408 |
558 // Assume that the resize will go through as requested, which should be the | 409 // Assume that the resize will go through as requested, which should be the |
559 // case if we're running without a window manager. If there's a window | 410 // case if we're running without a window manager. If there's a window |
560 // manager, it can modify or ignore the request, but (per ICCCM) we'll get a | 411 // manager, it can modify or ignore the request, but (per ICCCM) we'll get a |
561 // (possibly synthetic) ConfigureNotify about the actual size and correct | 412 // (possibly synthetic) ConfigureNotify about the actual size and correct |
562 // |bounds_| later. | 413 // |bounds_| later. |
563 bounds_ = bounds; | 414 bounds_ = bounds; |
564 UpdateIsInternalDisplay(); | |
565 if (origin_changed) | 415 if (origin_changed) |
566 OnHostMoved(bounds.origin()); | 416 OnHostMoved(bounds.origin()); |
567 if (size_changed || current_scale != new_scale) { | 417 if (size_changed || current_scale != new_scale) { |
568 OnHostResized(bounds.size()); | 418 OnHostResized(bounds.size()); |
569 } else { | 419 } else { |
570 window()->SchedulePaintInRect(window()->bounds()); | 420 window()->SchedulePaintInRect(window()->bounds()); |
571 } | 421 } |
572 } | 422 } |
573 | 423 |
574 gfx::Insets WindowTreeHostX11::GetInsets() const { | |
575 return insets_; | |
576 } | |
577 | |
578 void WindowTreeHostX11::SetInsets(const gfx::Insets& insets) { | |
579 insets_ = insets; | |
580 if (pointer_barriers_) { | |
581 UnConfineCursor(); | |
582 ConfineCursorToRootWindow(); | |
583 } | |
584 } | |
585 | |
586 gfx::Point WindowTreeHostX11::GetLocationOnNativeScreen() const { | 424 gfx::Point WindowTreeHostX11::GetLocationOnNativeScreen() const { |
587 return bounds_.origin(); | 425 return bounds_.origin(); |
588 } | 426 } |
589 | 427 |
590 void WindowTreeHostX11::SetCapture() { | 428 void WindowTreeHostX11::SetCapture() { |
591 // TODO(oshima): Grab x input. | 429 // TODO(oshima): Grab x input. |
592 } | 430 } |
593 | 431 |
594 void WindowTreeHostX11::ReleaseCapture() { | 432 void WindowTreeHostX11::ReleaseCapture() { |
595 // TODO(oshima): Release x input. | 433 // TODO(oshima): Release x input. |
(...skipping 16 matching lines...) Expand all Loading... |
612 &child_return, | 450 &child_return, |
613 &root_x_return, &root_y_return, | 451 &root_x_return, &root_y_return, |
614 &win_x_return, &win_y_return, | 452 &win_x_return, &win_y_return, |
615 &mask_return); | 453 &mask_return); |
616 *location_return = gfx::Point(max(0, min(bounds_.width(), win_x_return)), | 454 *location_return = gfx::Point(max(0, min(bounds_.width(), win_x_return)), |
617 max(0, min(bounds_.height(), win_y_return))); | 455 max(0, min(bounds_.height(), win_y_return))); |
618 return (win_x_return >= 0 && win_x_return < bounds_.width() && | 456 return (win_x_return >= 0 && win_x_return < bounds_.width() && |
619 win_y_return >= 0 && win_y_return < bounds_.height()); | 457 win_y_return >= 0 && win_y_return < bounds_.height()); |
620 } | 458 } |
621 | 459 |
622 bool WindowTreeHostX11::ConfineCursorToRootWindow() { | |
623 #if XFIXES_MAJOR >= 5 | |
624 DCHECK(!pointer_barriers_.get()); | |
625 if (pointer_barriers_) | |
626 return false; | |
627 pointer_barriers_.reset(new XID[4]); | |
628 gfx::Rect bounds(bounds_); | |
629 bounds.Inset(insets_); | |
630 // Horizontal, top barriers. | |
631 pointer_barriers_[0] = XFixesCreatePointerBarrier( | |
632 xdisplay_, x_root_window_, | |
633 bounds.x(), bounds.y(), bounds.right(), bounds.y(), | |
634 BarrierPositiveY, | |
635 0, XIAllDevices); | |
636 // Horizontal, bottom barriers. | |
637 pointer_barriers_[1] = XFixesCreatePointerBarrier( | |
638 xdisplay_, x_root_window_, | |
639 bounds.x(), bounds.bottom(), bounds.right(), bounds.bottom(), | |
640 BarrierNegativeY, | |
641 0, XIAllDevices); | |
642 // Vertical, left barriers. | |
643 pointer_barriers_[2] = XFixesCreatePointerBarrier( | |
644 xdisplay_, x_root_window_, | |
645 bounds.x(), bounds.y(), bounds.x(), bounds.bottom(), | |
646 BarrierPositiveX, | |
647 0, XIAllDevices); | |
648 // Vertical, right barriers. | |
649 pointer_barriers_[3] = XFixesCreatePointerBarrier( | |
650 xdisplay_, x_root_window_, | |
651 bounds.right(), bounds.y(), bounds.right(), bounds.bottom(), | |
652 BarrierNegativeX, | |
653 0, XIAllDevices); | |
654 #endif | |
655 return true; | |
656 } | |
657 | |
658 void WindowTreeHostX11::UnConfineCursor() { | |
659 #if XFIXES_MAJOR >= 5 | |
660 if (pointer_barriers_) { | |
661 XFixesDestroyPointerBarrier(xdisplay_, pointer_barriers_[0]); | |
662 XFixesDestroyPointerBarrier(xdisplay_, pointer_barriers_[1]); | |
663 XFixesDestroyPointerBarrier(xdisplay_, pointer_barriers_[2]); | |
664 XFixesDestroyPointerBarrier(xdisplay_, pointer_barriers_[3]); | |
665 pointer_barriers_.reset(); | |
666 } | |
667 #endif | |
668 } | |
669 | |
670 void WindowTreeHostX11::PostNativeEvent( | 460 void WindowTreeHostX11::PostNativeEvent( |
671 const base::NativeEvent& native_event) { | 461 const base::NativeEvent& native_event) { |
672 DCHECK(xwindow_); | 462 DCHECK(xwindow_); |
673 DCHECK(xdisplay_); | 463 DCHECK(xdisplay_); |
674 XEvent xevent = *native_event; | 464 XEvent xevent = *native_event; |
675 xevent.xany.display = xdisplay_; | 465 xevent.xany.display = xdisplay_; |
676 xevent.xany.window = xwindow_; | 466 xevent.xany.window = xwindow_; |
677 | 467 |
678 switch (xevent.type) { | 468 switch (xevent.type) { |
679 case EnterNotify: | 469 case EnterNotify: |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
711 SetCursorInternal(cursor); | 501 SetCursorInternal(cursor); |
712 } | 502 } |
713 | 503 |
714 void WindowTreeHostX11::MoveCursorToNative(const gfx::Point& location) { | 504 void WindowTreeHostX11::MoveCursorToNative(const gfx::Point& location) { |
715 XWarpPointer(xdisplay_, None, x_root_window_, 0, 0, 0, 0, | 505 XWarpPointer(xdisplay_, None, x_root_window_, 0, 0, 0, 0, |
716 bounds_.x() + location.x(), | 506 bounds_.x() + location.x(), |
717 bounds_.y() + location.y()); | 507 bounds_.y() + location.y()); |
718 } | 508 } |
719 | 509 |
720 void WindowTreeHostX11::OnCursorVisibilityChangedNative(bool show) { | 510 void WindowTreeHostX11::OnCursorVisibilityChangedNative(bool show) { |
721 SetCrOSTapPaused(!show); | |
722 } | |
723 | |
724 void WindowTreeHostX11::OnWindowInitialized(Window* window) { | |
725 } | |
726 | |
727 void WindowTreeHostX11::OnHostInitialized(WindowTreeHost* host) { | |
728 // TODO(beng): I'm not sure that this comment makes much sense anymore?? | |
729 // UpdateIsInternalDisplay relies on WED's kDisplayIdKey property being set | |
730 // available by the time WED::Init is called. (set in | |
731 // DisplayManager::CreateRootWindowForDisplay) | |
732 // Ready when NotifyHostInitialized is called from WED::Init. | |
733 if (host != this) | |
734 return; | |
735 UpdateIsInternalDisplay(); | |
736 | |
737 // We have to enable Tap-to-click by default because the cursor is set to | |
738 // visible in Shell::InitRootWindowController. | |
739 SetCrOSTapPaused(false); | |
740 } | 511 } |
741 | 512 |
742 ui::EventProcessor* WindowTreeHostX11::GetEventProcessor() { | 513 ui::EventProcessor* WindowTreeHostX11::GetEventProcessor() { |
743 return dispatcher(); | 514 return dispatcher(); |
744 } | 515 } |
745 | 516 |
746 void WindowTreeHostX11::DispatchXI2Event(const base::NativeEvent& event) { | 517 void WindowTreeHostX11::DispatchXI2Event(const base::NativeEvent& event) { |
747 ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); | 518 ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); |
748 XEvent* xev = event; | 519 XEvent* xev = event; |
749 if (!factory->ShouldProcessXI2Event(xev)) | 520 if (!factory->ShouldProcessXI2Event(xev)) |
(...skipping 15 matching lines...) Expand all Loading... |
765 case ui::ET_TOUCH_RELEASED: { | 536 case ui::ET_TOUCH_RELEASED: { |
766 #if defined(OS_CHROMEOS) | 537 #if defined(OS_CHROMEOS) |
767 // Bail out early before generating a ui::TouchEvent if this event | 538 // Bail out early before generating a ui::TouchEvent if this event |
768 // is not within the range of this RootWindow. Converting an xevent | 539 // is not within the range of this RootWindow. Converting an xevent |
769 // to ui::TouchEvent might change the state of the global touch tracking | 540 // to ui::TouchEvent might change the state of the global touch tracking |
770 // state, e.g. touch release event can remove the touch id from the | 541 // state, e.g. touch release event can remove the touch id from the |
771 // record, and doing this multiple time when there are multiple | 542 // record, and doing this multiple time when there are multiple |
772 // RootWindow will cause problem. So only generate the ui::TouchEvent | 543 // RootWindow will cause problem. So only generate the ui::TouchEvent |
773 // when we are sure it belongs to this RootWindow. | 544 // when we are sure it belongs to this RootWindow. |
774 if (base::SysInfo::IsRunningOnChromeOS() && | 545 if (base::SysInfo::IsRunningOnChromeOS() && |
775 !bounds_.Contains(ui::EventLocationFromNative(xev))) | 546 !bounds().Contains(ui::EventLocationFromNative(xev))) |
776 break; | 547 return; |
777 #endif // defined(OS_CHROMEOS) | 548 #endif |
778 ui::TouchEvent touchev(xev); | 549 ui::TouchEvent touchev(xev); |
779 #if defined(OS_CHROMEOS) | 550 TranslateAndDispatchLocatedEvent(&touchev); |
780 if (base::SysInfo::IsRunningOnChromeOS()) { | |
781 // X maps the touch-surface to the size of the X root-window. | |
782 // In multi-monitor setup, Coordinate Transformation Matrix | |
783 // repositions the touch-surface onto part of X root-window | |
784 // containing aura root-window corresponding to the touchscreen. | |
785 // However, if aura root-window has non-zero origin, | |
786 // we need to relocate the event into aura root-window coordinates. | |
787 touchev.Relocate(bounds_.origin()); | |
788 #if defined(USE_XI2_MT) | |
789 if (is_internal_display_) | |
790 touch_calibrate_->Calibrate(&touchev, bounds_); | |
791 #endif // defined(USE_XI2_MT) | |
792 } | |
793 #endif // defined(OS_CHROMEOS) | |
794 SendEventToProcessor(&touchev); | |
795 break; | 551 break; |
796 } | 552 } |
797 case ui::ET_MOUSE_MOVED: | 553 case ui::ET_MOUSE_MOVED: |
798 case ui::ET_MOUSE_DRAGGED: | 554 case ui::ET_MOUSE_DRAGGED: |
799 case ui::ET_MOUSE_PRESSED: | 555 case ui::ET_MOUSE_PRESSED: |
800 case ui::ET_MOUSE_RELEASED: | 556 case ui::ET_MOUSE_RELEASED: |
801 case ui::ET_MOUSE_ENTERED: | 557 case ui::ET_MOUSE_ENTERED: |
802 case ui::ET_MOUSE_EXITED: { | 558 case ui::ET_MOUSE_EXITED: { |
803 if (type == ui::ET_MOUSE_MOVED || type == ui::ET_MOUSE_DRAGGED) { | 559 if (type == ui::ET_MOUSE_MOVED || type == ui::ET_MOUSE_DRAGGED) { |
804 // If this is a motion event, we want to coalesce all pending motion | 560 // If this is a motion event, we want to coalesce all pending motion |
805 // events that are at the top of the queue. | 561 // events that are at the top of the queue. |
806 num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event); | 562 num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event); |
807 if (num_coalesced > 0) | 563 if (num_coalesced > 0) |
808 xev = &last_event; | 564 xev = &last_event; |
809 } | 565 } |
810 ui::MouseEvent mouseev(xev); | 566 ui::MouseEvent mouseev(xev); |
811 TranslateAndDispatchMouseEvent(&mouseev); | 567 TranslateAndDispatchLocatedEvent(&mouseev); |
812 break; | 568 break; |
813 } | 569 } |
814 case ui::ET_MOUSEWHEEL: { | 570 case ui::ET_MOUSEWHEEL: { |
815 ui::MouseWheelEvent mouseev(xev); | 571 ui::MouseWheelEvent mouseev(xev); |
816 TranslateAndDispatchMouseEvent(&mouseev); | 572 TranslateAndDispatchLocatedEvent(&mouseev); |
817 break; | 573 break; |
818 } | 574 } |
819 case ui::ET_SCROLL_FLING_START: | 575 case ui::ET_SCROLL_FLING_START: |
820 case ui::ET_SCROLL_FLING_CANCEL: | 576 case ui::ET_SCROLL_FLING_CANCEL: |
821 case ui::ET_SCROLL: { | 577 case ui::ET_SCROLL: { |
822 ui::ScrollEvent scrollev(xev); | 578 ui::ScrollEvent scrollev(xev); |
823 SendEventToProcessor(&scrollev); | 579 SendEventToProcessor(&scrollev); |
824 break; | 580 break; |
825 } | 581 } |
826 case ui::ET_UMA_DATA: | 582 case ui::ET_UMA_DATA: |
(...skipping 13 matching lines...) Expand all Loading... |
840 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership | 596 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership |
841 // of WM_Sn selections (where n is a screen number). | 597 // of WM_Sn selections (where n is a screen number). |
842 return XGetSelectionOwner( | 598 return XGetSelectionOwner( |
843 xdisplay_, atom_cache_.GetAtom("WM_S0")) != None; | 599 xdisplay_, atom_cache_.GetAtom("WM_S0")) != None; |
844 } | 600 } |
845 | 601 |
846 void WindowTreeHostX11::SetCursorInternal(gfx::NativeCursor cursor) { | 602 void WindowTreeHostX11::SetCursorInternal(gfx::NativeCursor cursor) { |
847 XDefineCursor(xdisplay_, xwindow_, cursor.platform()); | 603 XDefineCursor(xdisplay_, xwindow_, cursor.platform()); |
848 } | 604 } |
849 | 605 |
850 void WindowTreeHostX11::TranslateAndDispatchMouseEvent( | 606 void WindowTreeHostX11::OnConfigureNotify() {} |
851 ui::MouseEvent* event) { | |
852 Window* root_window = window(); | |
853 client::ScreenPositionClient* screen_position_client = | |
854 client::GetScreenPositionClient(root_window); | |
855 gfx::Rect local(bounds_.size()); | |
856 | 607 |
857 if (screen_position_client && !local.Contains(event->location())) { | 608 void WindowTreeHostX11::TranslateAndDispatchLocatedEvent( |
858 gfx::Point location(event->location()); | 609 ui::LocatedEvent* event) { |
859 // In order to get the correct point in screen coordinates | |
860 // during passive grab, we first need to find on which host window | |
861 // the mouse is on, and find out the screen coordinates on that | |
862 // host window, then convert it back to this host window's coordinate. | |
863 screen_position_client->ConvertHostPointToScreen(root_window, &location); | |
864 screen_position_client->ConvertPointFromScreen(root_window, &location); | |
865 ConvertPointToHost(&location); | |
866 event->set_location(location); | |
867 event->set_root_location(location); | |
868 } | |
869 SendEventToProcessor(event); | 610 SendEventToProcessor(event); |
870 } | 611 } |
871 | 612 |
872 void WindowTreeHostX11::UpdateIsInternalDisplay() { | |
873 Window* root_window = window(); | |
874 gfx::Screen* screen = gfx::Screen::GetScreenFor(root_window); | |
875 gfx::Display display = screen->GetDisplayNearestWindow(root_window); | |
876 is_internal_display_ = display.IsInternal(); | |
877 } | |
878 | |
879 void WindowTreeHostX11::SetCrOSTapPaused(bool state) { | |
880 #if defined(OS_CHROMEOS) | |
881 if (!ui::IsXInput2Available()) | |
882 return; | |
883 // Temporarily pause tap-to-click when the cursor is hidden. | |
884 Atom prop = atom_cache_.GetAtom("Tap Paused"); | |
885 unsigned char value = state; | |
886 XIDeviceList dev_list = | |
887 ui::DeviceListCacheX::GetInstance()->GetXI2DeviceList(xdisplay_); | |
888 | |
889 // Only slave pointer devices could possibly have tap-paused property. | |
890 for (int i = 0; i < dev_list.count; i++) { | |
891 if (dev_list[i].use == XISlavePointer) { | |
892 Atom old_type; | |
893 int old_format; | |
894 unsigned long old_nvalues, bytes; | |
895 unsigned char* data; | |
896 int result = XIGetProperty(xdisplay_, dev_list[i].deviceid, prop, 0, 0, | |
897 False, AnyPropertyType, &old_type, &old_format, | |
898 &old_nvalues, &bytes, &data); | |
899 if (result != Success) | |
900 continue; | |
901 XFree(data); | |
902 XIChangeProperty(xdisplay_, dev_list[i].deviceid, prop, XA_INTEGER, 8, | |
903 PropModeReplace, &value, 1); | |
904 } | |
905 } | |
906 #endif | |
907 } | |
908 | |
909 // static | 613 // static |
910 WindowTreeHost* WindowTreeHost::Create(const gfx::Rect& bounds) { | 614 WindowTreeHost* WindowTreeHost::Create(const gfx::Rect& bounds) { |
911 return new WindowTreeHostX11(bounds); | 615 return new WindowTreeHostX11(bounds); |
912 } | 616 } |
913 | 617 |
914 // static | 618 // static |
915 gfx::Size WindowTreeHost::GetNativeScreenSize() { | 619 gfx::Size WindowTreeHost::GetNativeScreenSize() { |
916 ::XDisplay* xdisplay = gfx::GetXDisplay(); | 620 ::XDisplay* xdisplay = gfx::GetXDisplay(); |
917 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); | 621 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); |
918 } | 622 } |
919 | 623 |
920 namespace test { | 624 namespace test { |
921 | 625 |
922 void SetUseOverrideRedirectWindowByDefault(bool override_redirect) { | 626 void SetUseOverrideRedirectWindowByDefault(bool override_redirect) { |
923 default_override_redirect = override_redirect; | 627 default_override_redirect = override_redirect; |
924 } | 628 } |
925 | 629 |
926 } // namespace test | 630 } // namespace test |
927 } // namespace aura | 631 } // namespace aura |
OLD | NEW |