| 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 |