Chromium Code Reviews| 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 |