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