OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/root_window_host_linux.h" | 5 #include "wm/host/root_window_host_linux.h" |
6 | 6 |
7 #include <strings.h> | |
8 #include <X11/cursorfont.h> | |
9 #include <X11/extensions/Xfixes.h> | |
10 #include <X11/extensions/XInput2.h> | |
11 #include <X11/extensions/Xrandr.h> | |
12 #include <X11/Xatom.h> | 7 #include <X11/Xatom.h> |
13 #include <X11/Xcursor/Xcursor.h> | 8 #include <X11/Xcursor/Xcursor.h> |
14 #include <X11/Xlib.h> | 9 #include <X11/Xlib.h> |
| 10 #include <X11/cursorfont.h> |
| 11 #include <X11/extensions/XInput2.h> |
| 12 #include <X11/extensions/Xcomposite.h> |
| 13 #include <X11/extensions/Xfixes.h> |
| 14 #include <X11/extensions/Xrandr.h> |
| 15 #include <X11/extensions/shape.h> |
| 16 #include <strings.h> |
15 | 17 |
16 #include <algorithm> | 18 #include <algorithm> |
17 #include <limits> | 19 #include <limits> |
18 #include <string> | 20 #include <string> |
19 | 21 |
20 #include "base/command_line.h" | 22 #include "base/command_line.h" |
21 #include "base/message_loop.h" | 23 #include "base/message_loop.h" |
22 #include "base/message_pump_aurax11.h" | 24 #include "base/message_pump_aurax11.h" |
23 #include "base/stl_util.h" | 25 #include "base/stl_util.h" |
24 #include "base/stringprintf.h" | 26 #include "base/stringprintf.h" |
(...skipping 13 matching lines...) Expand all Loading... |
38 #include "ui/base/touch/touch_factory.h" | 40 #include "ui/base/touch/touch_factory.h" |
39 #include "ui/base/ui_base_switches.h" | 41 #include "ui/base/ui_base_switches.h" |
40 #include "ui/base/view_prop.h" | 42 #include "ui/base/view_prop.h" |
41 #include "ui/base/x/device_list_cache_x.h" | 43 #include "ui/base/x/device_list_cache_x.h" |
42 #include "ui/base/x/valuators.h" | 44 #include "ui/base/x/valuators.h" |
43 #include "ui/base/x/x11_util.h" | 45 #include "ui/base/x/x11_util.h" |
44 #include "ui/compositor/dip_util.h" | 46 #include "ui/compositor/dip_util.h" |
45 #include "ui/compositor/layer.h" | 47 #include "ui/compositor/layer.h" |
46 #include "ui/gfx/codec/png_codec.h" | 48 #include "ui/gfx/codec/png_codec.h" |
47 #include "ui/gfx/screen.h" | 49 #include "ui/gfx/screen.h" |
| 50 #include "wm/foreign_window.h" |
| 51 #include "wm/foreign_window_widget.h" |
48 | 52 |
49 #if defined(OS_CHROMEOS) | 53 #if defined(OS_CHROMEOS) |
50 #include "base/chromeos/chromeos_version.h" | 54 #include "base/chromeos/chromeos_version.h" |
51 #endif | 55 #endif |
52 | 56 |
53 using std::max; | 57 using std::max; |
54 using std::min; | 58 using std::min; |
55 | 59 |
56 namespace aura { | 60 namespace wm { |
57 | 61 |
58 namespace { | 62 namespace { |
59 | 63 |
60 // Standard Linux mouse buttons for going back and forward. | 64 // Standard Linux mouse buttons for going back and forward. |
61 const int kBackMouseButton = 8; | 65 const int kBackMouseButton = 8; |
62 const int kForwardMouseButton = 9; | 66 const int kForwardMouseButton = 9; |
63 | 67 |
64 // These are the same values that are used to calibrate touch events in | 68 // These are the same values that are used to calibrate touch events in |
65 // |CalibrateTouchCoordinates| (in ui/base/x/events_x.cc). | 69 // |CalibrateTouchCoordinates| (in ui/base/x/events_x.cc). |
66 // TODO(sad|skuhne): Remove the duplication of values (http://crbug.com/147605) | 70 // TODO(sad|skuhne): Remove the duplication of values (http://crbug.com/147605) |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 case ui::VKEY_OEM_PLUS: | 166 case ui::VKEY_OEM_PLUS: |
163 case ui::VKEY_OEM_COMMA: | 167 case ui::VKEY_OEM_COMMA: |
164 case ui::VKEY_OEM_MINUS: | 168 case ui::VKEY_OEM_MINUS: |
165 case ui::VKEY_OEM_PERIOD: | 169 case ui::VKEY_OEM_PERIOD: |
166 return true; | 170 return true; |
167 default: | 171 default: |
168 return false; | 172 return false; |
169 } | 173 } |
170 } | 174 } |
171 | 175 |
| 176 unsigned InitWindowChanges(const gfx::Rect& bounds, |
| 177 ::Window sibling_to_stack_above, |
| 178 XWindowChanges& wc) { |
| 179 wc.x = bounds.x(); |
| 180 wc.y = bounds.y(); |
| 181 wc.width = bounds.width(); |
| 182 wc.height = bounds.height(); |
| 183 if (!sibling_to_stack_above) { |
| 184 wc.stack_mode = Below; |
| 185 return CWX | CWY | CWWidth | CWHeight | CWStackMode; |
| 186 } |
| 187 |
| 188 wc.sibling = sibling_to_stack_above; |
| 189 wc.stack_mode = Above; |
| 190 return CWX | CWY | CWWidth | CWHeight | CWStackMode | CWSibling; |
| 191 } |
| 192 |
| 193 aura::Window* FindLowestCommonAncestor( |
| 194 aura::Window* root, const aura::Window* p, const aura::Window* q) { |
| 195 // Root is the LCA. |
| 196 if (root == p || root == q) |
| 197 return root; |
| 198 |
| 199 aura::Window* prev = NULL; |
| 200 const aura::Window::Windows& children = root->children(); |
| 201 for (size_t i = 0; i < children.size(); ++i) { |
| 202 // Try to find LCA of p and q in subtree. |
| 203 aura::Window* next = FindLowestCommonAncestor(children[i], p, q); |
| 204 if (next) { |
| 205 // If a LCA was previously found, p and q must be in different subtrees. |
| 206 if (prev) |
| 207 return root; |
| 208 |
| 209 prev = next; |
| 210 } |
| 211 } |
| 212 |
| 213 return prev; |
| 214 } |
| 215 |
| 216 gfx::Vector2d GetTargetOffsetInRootWindow(const aura::Window* window) { |
| 217 gfx::Vector2d offset; |
| 218 |
| 219 const aura::Window* p = window; |
| 220 for (; p != window->GetRootWindow(); p = p->parent()) |
| 221 offset += p->GetTargetBounds().OffsetFromOrigin(); |
| 222 |
| 223 return offset; |
| 224 } |
| 225 |
| 226 gfx::Rect GetTargetBoundsInRootWindow(const aura::Window* window) { |
| 227 return gfx::Rect(window->GetTargetBounds().size()) + |
| 228 GetTargetOffsetInRootWindow(window); |
| 229 } |
| 230 |
172 } // namespace | 231 } // namespace |
173 | 232 |
174 namespace internal { | 233 namespace internal { |
175 | 234 |
176 // A very lightweight message-pump observer that routes all the touch events to | 235 // A very lightweight message-pump observer that routes all the touch events to |
177 // the X root window so that they can be calibrated properly. | 236 // the X root window so that they can be calibrated properly. |
178 class TouchEventCalibrate : public base::MessagePumpObserver { | 237 class TouchEventCalibrate : public base::MessagePumpObserver { |
179 public: | 238 public: |
180 TouchEventCalibrate() { | 239 TouchEventCalibrate() { |
181 MessageLoopForUI::current()->AddObserver(this); | 240 MessageLoopForUI::current()->AddObserver(this); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 : delegate_(NULL), | 318 : delegate_(NULL), |
260 xdisplay_(base::MessagePumpAuraX11::GetDefaultXDisplay()), | 319 xdisplay_(base::MessagePumpAuraX11::GetDefaultXDisplay()), |
261 xwindow_(0), | 320 xwindow_(0), |
262 x_root_window_(DefaultRootWindow(xdisplay_)), | 321 x_root_window_(DefaultRootWindow(xdisplay_)), |
263 current_cursor_(ui::kCursorNull), | 322 current_cursor_(ui::kCursorNull), |
264 window_mapped_(false), | 323 window_mapped_(false), |
265 bounds_(bounds), | 324 bounds_(bounds), |
266 focus_when_shown_(false), | 325 focus_when_shown_(false), |
267 touch_calibrate_(new internal::TouchEventCalibrate), | 326 touch_calibrate_(new internal::TouchEventCalibrate), |
268 mouse_move_filter_(new MouseMoveFilter), | 327 mouse_move_filter_(new MouseMoveFilter), |
269 atom_cache_(xdisplay_, kAtomsToCache) { | 328 atom_cache_(xdisplay_, kAtomsToCache), |
| 329 configure_window_(NULL), |
| 330 x_input_window_(0), |
| 331 need_to_set_default_cursor_(true) { |
270 XSetWindowAttributes swa; | 332 XSetWindowAttributes swa; |
271 memset(&swa, 0, sizeof(swa)); | 333 memset(&swa, 0, sizeof(swa)); |
272 swa.background_pixmap = None; | 334 swa.background_pixmap = None; |
273 xwindow_ = XCreateWindow( | 335 xwindow_ = XCreateWindow( |
274 xdisplay_, x_root_window_, | 336 xdisplay_, x_root_window_, |
275 bounds.x(), bounds.y(), bounds.width(), bounds.height(), | 337 bounds.x(), bounds.y(), bounds.width(), bounds.height(), |
276 0, // border width | 338 0, // border width |
277 CopyFromParent, // depth | 339 CopyFromParent, // depth |
278 InputOutput, | 340 InputOutput, |
279 CopyFromParent, // visual | 341 CopyFromParent, // visual |
280 CWBackPixmap, | 342 CWBackPixmap, |
281 &swa); | 343 &swa); |
| 344 x_input_window_ = XCreateWindow( |
| 345 xdisplay_, xwindow_, |
| 346 -100, -100, 1, 1, |
| 347 0, // border width |
| 348 CopyFromParent, // depth |
| 349 InputOnly, |
| 350 CopyFromParent, // visual |
| 351 0, |
| 352 NULL); |
| 353 XMapWindow(xdisplay_, x_input_window_); |
| 354 XCompositeRedirectSubwindows(xdisplay_, xwindow_, CompositeRedirectManual); |
| 355 |
282 base::MessagePumpAuraX11::Current()->AddDispatcherForWindow(this, xwindow_); | 356 base::MessagePumpAuraX11::Current()->AddDispatcherForWindow(this, xwindow_); |
283 base::MessagePumpAuraX11::Current()->AddDispatcherForRootWindow(this); | 357 base::MessagePumpAuraX11::Current()->AddDispatcherForRootWindow(this); |
284 | 358 |
285 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | | 359 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | |
286 KeyPressMask | KeyReleaseMask | | 360 KeyPressMask | KeyReleaseMask | |
287 EnterWindowMask | LeaveWindowMask | | 361 EnterWindowMask | LeaveWindowMask | |
288 ExposureMask | VisibilityChangeMask | | 362 ExposureMask | VisibilityChangeMask | |
289 StructureNotifyMask | PropertyChangeMask | | 363 StructureNotifyMask | PropertyChangeMask | |
290 PointerMotionMask; | 364 PointerMotionMask | |
| 365 SubstructureNotifyMask | SubstructureRedirectMask; |
291 XSelectInput(xdisplay_, xwindow_, event_mask); | 366 XSelectInput(xdisplay_, xwindow_, event_mask); |
292 XFlush(xdisplay_); | 367 XFlush(xdisplay_); |
293 | 368 |
294 if (base::MessagePumpForUI::HasXInput2()) | 369 if (base::MessagePumpForUI::HasXInput2()) |
295 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); | 370 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); |
296 | 371 |
297 SelectEventsForRootWindow(); | 372 SelectEventsForRootWindow(); |
298 | 373 |
299 // Get the initial size of the X root window. | 374 // Get the initial size of the X root window. |
300 XWindowAttributes attrs; | 375 XWindowAttributes attrs; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 XRRSelectInput(xdisplay_, x_root_window_, | 408 XRRSelectInput(xdisplay_, x_root_window_, |
334 RRScreenChangeNotifyMask | RROutputChangeNotifyMask); | 409 RRScreenChangeNotifyMask | RROutputChangeNotifyMask); |
335 } | 410 } |
336 | 411 |
337 RootWindowHostLinux::~RootWindowHostLinux() { | 412 RootWindowHostLinux::~RootWindowHostLinux() { |
338 base::MessagePumpAuraX11::Current()->RemoveDispatcherForRootWindow(this); | 413 base::MessagePumpAuraX11::Current()->RemoveDispatcherForRootWindow(this); |
339 base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_); | 414 base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_); |
340 | 415 |
341 UnConfineCursor(); | 416 UnConfineCursor(); |
342 | 417 |
| 418 GetRootWindow()->RemoveObserver(this); |
| 419 XDestroyWindow(xdisplay_, x_input_window_); |
343 XDestroyWindow(xdisplay_, xwindow_); | 420 XDestroyWindow(xdisplay_, xwindow_); |
344 } | 421 } |
345 | 422 |
346 bool RootWindowHostLinux::Dispatch(const base::NativeEvent& event) { | 423 bool RootWindowHostLinux::Dispatch(const base::NativeEvent& event) { |
347 XEvent* xev = event; | 424 XEvent* xev = event; |
348 | 425 |
349 if (FindEventTarget(event) == x_root_window_) | 426 if (FindEventTarget(event) == x_root_window_) |
350 return DispatchEventForRootWindow(event); | 427 return DispatchEventForRootWindow(event); |
351 | 428 |
352 switch (xev->type) { | 429 switch (xev->type) { |
| 430 case ConfigureNotify: { |
| 431 if (event->xconfigure.window == x_input_window_) |
| 432 return true; |
| 433 |
| 434 ForeignWindowMap::iterator it = foreign_windows_.find( |
| 435 event->xconfigure.window); |
| 436 if (it != foreign_windows_.end()) { |
| 437 ForeignWindow* window = it->second; |
| 438 |
| 439 int border_size = event->xconfigure.border_width * 2; |
| 440 gfx::Size size(event->xconfigure.width + border_size, |
| 441 event->xconfigure.height + border_size); |
| 442 window->OnWindowSizeChanged(size); |
| 443 return true; |
| 444 } |
| 445 break; |
| 446 } |
| 447 case MapNotify: { |
| 448 ForeignWindowMap::iterator it = foreign_windows_.find( |
| 449 event->xmap.window); |
| 450 if (it != foreign_windows_.end()) { |
| 451 ForeignWindow* window = it->second; |
| 452 |
| 453 window->OnWindowVisibilityChanged(true); |
| 454 return true; |
| 455 } |
| 456 break; |
| 457 } |
| 458 case UnmapNotify: { |
| 459 ForeignWindowMap::iterator it = foreign_windows_.find( |
| 460 event->xunmap.window); |
| 461 if (it != foreign_windows_.end()) { |
| 462 ForeignWindow* window = it->second; |
| 463 |
| 464 // Hide top level widget. |
| 465 views::Widget* widget = window->GetWidget(); |
| 466 widget->Hide(); |
| 467 |
| 468 window->OnWindowVisibilityChanged(false); |
| 469 return true; |
| 470 } |
| 471 break; |
| 472 } |
| 473 case CreateNotify: { |
| 474 int border_size = event->xcreatewindow.border_width * 2; |
| 475 gfx::Size size(event->xcreatewindow.width + border_size, |
| 476 event->xcreatewindow.height + border_size); |
| 477 |
| 478 // Create a foreign window for this X window. |
| 479 ForeignWindow::CreateParams params(event->xcreatewindow.window, size); |
| 480 scoped_refptr<ForeignWindow> window(new ForeignWindow(params)); |
| 481 |
| 482 // Create top level window widget. |
| 483 ForeignWindowWidget::CreateWindow(window.get()); |
| 484 |
| 485 // Add foreign window to map. |
| 486 foreign_windows_[event->xcreatewindow.window] = window.get(); |
| 487 return true; |
| 488 } |
| 489 case DestroyNotify: { |
| 490 ForeignWindowMap::iterator it = foreign_windows_.find( |
| 491 event->xdestroywindow.window); |
| 492 if (it != foreign_windows_.end()) { |
| 493 ForeignWindow* window = it->second; |
| 494 |
| 495 // Tell foreign window that X window has been destroyed. |
| 496 window->OnWindowDestroyed(); |
| 497 |
| 498 // Close top level widget. |
| 499 views::Widget* widget = window->GetWidget(); |
| 500 widget->Close(); |
| 501 |
| 502 foreign_windows_.erase(it); |
| 503 } |
| 504 return true; |
| 505 } |
| 506 case MapRequest: { |
| 507 ForeignWindowMap::iterator it = foreign_windows_.find( |
| 508 event->xmaprequest.window); |
| 509 if (it != foreign_windows_.end()) { |
| 510 ForeignWindow* window = it->second; |
| 511 |
| 512 // Show top level widget. |
| 513 views::Widget* widget = window->GetWidget(); |
| 514 widget->Show(); |
| 515 } |
| 516 return true; |
| 517 } |
| 518 case ConfigureRequest: { |
| 519 // TODO(reveman): Respect ConfigureRequest events. |
| 520 return true; |
| 521 } |
| 522 case CirculateRequest: { |
| 523 // TODO(reveman): Respect CirculateRequest events. |
| 524 return true; |
| 525 } |
| 526 } |
| 527 |
| 528 switch (xev->type) { |
353 case EnterNotify: { | 529 case EnterNotify: { |
354 ui::MouseEvent mouseenter_event(xev); | 530 ui::MouseEvent mouseenter_event(xev); |
355 TranslateAndDispatchMouseEvent(&mouseenter_event); | 531 TranslateAndDispatchMouseEvent(&mouseenter_event); |
356 break; | 532 break; |
357 } | 533 } |
358 case Expose: | 534 case Expose: |
359 delegate_->AsRootWindow()->ScheduleFullDraw(); | 535 delegate_->AsRootWindow()->ScheduleFullDraw(); |
360 break; | 536 break; |
361 case KeyPress: { | 537 case KeyPress: { |
362 ui::KeyEvent keydown_event(xev, false); | 538 ui::KeyEvent keydown_event(xev, false); |
363 delegate_->OnHostKeyEvent(&keydown_event); | 539 delegate_->OnHostKeyEvent(&keydown_event); |
364 break; | 540 break; |
365 } | 541 } |
366 case KeyRelease: { | 542 case KeyRelease: { |
367 ui::KeyEvent keyup_event(xev, false); | 543 ui::KeyEvent keyup_event(xev, false); |
368 delegate_->OnHostKeyEvent(&keyup_event); | 544 delegate_->OnHostKeyEvent(&keyup_event); |
369 break; | 545 break; |
370 } | 546 } |
371 case ButtonPress: { | 547 case ButtonPress: { |
372 if (static_cast<int>(xev->xbutton.button) == kBackMouseButton || | 548 if (static_cast<int>(xev->xbutton.button) == kBackMouseButton || |
373 static_cast<int>(xev->xbutton.button) == kForwardMouseButton) { | 549 static_cast<int>(xev->xbutton.button) == kForwardMouseButton) { |
374 client::UserActionClient* gesture_client = | 550 aura::client::UserActionClient* gesture_client = |
375 client::GetUserActionClient(delegate_->AsRootWindow()); | 551 aura::client::GetUserActionClient(delegate_->AsRootWindow()); |
376 if (gesture_client) { | 552 if (gesture_client) { |
377 gesture_client->OnUserAction( | 553 gesture_client->OnUserAction( |
378 static_cast<int>(xev->xbutton.button) == kBackMouseButton ? | 554 static_cast<int>(xev->xbutton.button) == kBackMouseButton ? |
379 client::UserActionClient::BACK : | 555 aura::client::UserActionClient::BACK : |
380 client::UserActionClient::FORWARD); | 556 aura::client::UserActionClient::FORWARD); |
381 } | 557 } |
382 break; | 558 break; |
383 } | 559 } |
384 } // fallthrough | 560 } // fallthrough |
385 case ButtonRelease: { | 561 case ButtonRelease: { |
386 ui::MouseEvent mouseev(xev); | 562 ui::MouseEvent mouseev(xev); |
387 TranslateAndDispatchMouseEvent(&mouseev); | 563 TranslateAndDispatchMouseEvent(&mouseev); |
388 break; | 564 break; |
389 } | 565 } |
390 case FocusOut: | 566 case FocusOut: |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
476 } | 652 } |
477 | 653 |
478 ui::MouseEvent mouseev(xev); | 654 ui::MouseEvent mouseev(xev); |
479 TranslateAndDispatchMouseEvent(&mouseev); | 655 TranslateAndDispatchMouseEvent(&mouseev); |
480 break; | 656 break; |
481 } | 657 } |
482 } | 658 } |
483 return true; | 659 return true; |
484 } | 660 } |
485 | 661 |
486 void RootWindowHostLinux::SetDelegate(RootWindowHostDelegate* delegate) { | 662 void RootWindowHostLinux::OnWindowAdded(aura::Window* window) { |
| 663 window->AddObserver(this); |
| 664 } |
| 665 |
| 666 void RootWindowHostLinux::OnWillRemoveWindow(aura::Window* window) { |
| 667 if (configure_window_ == window) |
| 668 configure_window_ = window->parent(); |
| 669 |
| 670 window->RemoveObserver(this); |
| 671 } |
| 672 |
| 673 void RootWindowHostLinux::OnWindowStackingChanged(aura::Window* window) { |
| 674 ScheduleConfigure(GetRootWindow()); |
| 675 } |
| 676 |
| 677 void RootWindowHostLinux::OnWindowVisibilityChanged( |
| 678 aura::Window* window, bool visible) { |
| 679 ScheduleConfigure(GetRootWindow()); |
| 680 } |
| 681 |
| 682 void RootWindowHostLinux::OnWindowBoundsChanged( |
| 683 aura::Window* window, |
| 684 const gfx::Rect& old_bounds, |
| 685 const gfx::Rect& new_bounds) { |
| 686 ScheduleConfigure(GetRootWindow()); |
| 687 } |
| 688 |
| 689 void RootWindowHostLinux::OnWindowDestroying(aura::Window* window) { |
| 690 window->RemoveObserver(this); |
| 691 } |
| 692 |
| 693 ::Window RootWindowHostLinux::GetTopForeignWindow(const aura::Window* window) { |
| 694 // children are ordered back to front, so walk through it in reverse. |
| 695 const aura::Window::Windows& children = window->children(); |
| 696 for (size_t i = children.size(); i; --i) { |
| 697 ::Window top = GetTopForeignWindow(children[i - 1]); |
| 698 if (top) |
| 699 return top; |
| 700 } |
| 701 |
| 702 ForeignWindow* foreign_window = ForeignWindow::GetForeignWindowForNativeView( |
| 703 const_cast<gfx::NativeView>(window)); |
| 704 if (foreign_window) { |
| 705 // Ignore windows that we're not allowed to configure. |
| 706 if (foreign_window->IsManaged()) |
| 707 return foreign_window->GetWindowHandle(); |
| 708 } |
| 709 |
| 710 return 0; |
| 711 } |
| 712 |
| 713 ::Window RootWindowHostLinux::FindForeignWindowToStackAbove( |
| 714 const aura::Window* window) { |
| 715 const aura::Window* parent = window->parent(); |
| 716 if (!parent) |
| 717 return 0; |
| 718 |
| 719 ::Window above = 0; |
| 720 |
| 721 const aura::Window::Windows& children = parent->children(); |
| 722 for (size_t i = 0; i < children.size(); ++i) { |
| 723 if (children[i] == window) |
| 724 break; |
| 725 |
| 726 ::Window top = GetTopForeignWindow(children[i]); |
| 727 if (top) |
| 728 above = top; |
| 729 } |
| 730 |
| 731 if (!above) |
| 732 above = FindForeignWindowToStackAbove(parent); |
| 733 |
| 734 return above; |
| 735 } |
| 736 |
| 737 void RootWindowHostLinux::MapWindowIfNeeded(ForeignWindow* window) { |
| 738 ForeignWindow::DisplayState current_display_state = |
| 739 window->GetDisplayState(); |
| 740 |
| 741 if (current_display_state != ForeignWindow::DISPLAY_NORMAL) { |
| 742 // TODO(reveman): Ignore possible X error. |
| 743 XMapWindow(xdisplay_, window->GetWindowHandle()); |
| 744 |
| 745 window->SetDisplayState(ForeignWindow::DISPLAY_NORMAL); |
| 746 } |
| 747 } |
| 748 |
| 749 void RootWindowHostLinux::UnmapWindowIfNeeded(ForeignWindow* window) { |
| 750 ForeignWindow::DisplayState current_display_state = |
| 751 window->GetDisplayState(); |
| 752 |
| 753 if (current_display_state == ForeignWindow::DISPLAY_NORMAL) { |
| 754 // TODO(reveman): Ignore possible X error. |
| 755 XUnmapWindow(xdisplay_, window->GetWindowHandle()); |
| 756 |
| 757 window->SetDisplayState(ForeignWindow::DISPLAY_ICONIC); |
| 758 } |
| 759 } |
| 760 |
| 761 void RootWindowHostLinux::RecursiveConfigure( |
| 762 aura::Window* window, |
| 763 gfx::Vector2d offset, |
| 764 ::Window* sibling_to_stack_above, |
| 765 SkRegion* input_region) { |
| 766 gfx::Rect bounds(gfx::Rect(window->GetTargetBounds().size()) + offset); |
| 767 SkRegion::Op input_region_op; |
| 768 |
| 769 ForeignWindow* foreign_window = ForeignWindow::GetForeignWindowForNativeView( |
| 770 const_cast<gfx::NativeView>(window)); |
| 771 if (foreign_window) { |
| 772 DCHECK(!bounds.IsEmpty()); |
| 773 |
| 774 // We should only be adjusting attributes of managed windows. |
| 775 if (foreign_window->IsManaged()) { |
| 776 if (!window->IsVisible()) |
| 777 UnmapWindowIfNeeded(foreign_window); |
| 778 |
| 779 XWindowChanges wc; |
| 780 unsigned mask = InitWindowChanges(bounds, *sibling_to_stack_above, wc); |
| 781 // Get rid of any borders. |
| 782 wc.border_width = 0; |
| 783 mask |= CWBorderWidth; |
| 784 // TODO(reveman): Ignore possible X error. |
| 785 XConfigureWindow(xdisplay_, |
| 786 foreign_window->GetWindowHandle(), |
| 787 mask, |
| 788 &wc); |
| 789 |
| 790 *sibling_to_stack_above = foreign_window->GetWindowHandle(); |
| 791 |
| 792 if (window->IsVisible()) |
| 793 MapWindowIfNeeded(foreign_window); |
| 794 } |
| 795 |
| 796 // Remove foreign window bounds from input region. |
| 797 bounds.Inset(window->hit_test_bounds_override_inner()); |
| 798 input_region_op = SkRegion::kDifference_Op; |
| 799 } else { |
| 800 // Add window bounds to output region. |
| 801 bounds.Inset(window->hit_test_bounds_override_outer_mouse()); |
| 802 input_region_op = SkRegion::kUnion_Op; |
| 803 } |
| 804 |
| 805 if (window->delegate() && window->IsVisible()) { |
| 806 input_region->op(bounds.x(), |
| 807 bounds.y(), |
| 808 bounds.right(), |
| 809 bounds.bottom(), |
| 810 input_region_op); |
| 811 } |
| 812 |
| 813 const aura::Window::Windows& children = window->children(); |
| 814 for (size_t i = 0; i < children.size(); ++i) { |
| 815 RecursiveConfigure( |
| 816 children[i], |
| 817 offset + children[i]->GetTargetBounds().OffsetFromOrigin(), |
| 818 sibling_to_stack_above, |
| 819 input_region); |
| 820 } |
| 821 } |
| 822 |
| 823 void RootWindowHostLinux::Configure() { |
| 824 if (!configure_window_) |
| 825 return; |
| 826 |
| 827 SkRegion input_region; |
| 828 ::Window sibling_to_stack_above = |
| 829 FindForeignWindowToStackAbove(configure_window_); |
| 830 RecursiveConfigure(configure_window_, |
| 831 GetTargetOffsetInRootWindow(configure_window_), |
| 832 &sibling_to_stack_above, |
| 833 &input_region); |
| 834 |
| 835 // Update input window and set focus when we configure the root window. |
| 836 if (configure_window_ == GetRootWindow()) { |
| 837 // Configure input window above all other windows. |
| 838 XWindowChanges wc; |
| 839 gfx::Rect bounds(gfx::Point(0, 0), bounds_.size()); |
| 840 unsigned mask = InitWindowChanges(bounds, sibling_to_stack_above, wc); |
| 841 XConfigureWindow(xdisplay_, x_input_window_, mask, &wc); |
| 842 |
| 843 // Update input window shape. |
| 844 std::vector<XRectangle> rectangles; |
| 845 for (SkRegion::Iterator iter(input_region); !iter.done(); iter.next()) { |
| 846 const SkIRect& sk_rect = iter.rect(); |
| 847 XRectangle x_rect; |
| 848 x_rect.x = sk_rect.x(); |
| 849 x_rect.y = sk_rect.y(); |
| 850 x_rect.width = sk_rect.width(); |
| 851 x_rect.height = sk_rect.height(); |
| 852 rectangles.push_back(x_rect); |
| 853 } |
| 854 |
| 855 XShapeCombineRectangles(xdisplay_, |
| 856 x_input_window_, |
| 857 ShapeInput, |
| 858 0, |
| 859 0, |
| 860 &rectangles.front(), |
| 861 rectangles.size(), |
| 862 ShapeSet, |
| 863 Unsorted); |
| 864 } |
| 865 |
| 866 XFlush(xdisplay_); |
| 867 configure_window_ = NULL; |
| 868 } |
| 869 |
| 870 void RootWindowHostLinux::ScheduleConfigure(aura::Window* window) { |
| 871 if (!configure_window_) { |
| 872 configure_window_ = window; |
| 873 MessageLoop::current()->PostTask( |
| 874 FROM_HERE, |
| 875 base::Bind(&RootWindowHostLinux::Configure, AsWeakPtr())); |
| 876 } else { |
| 877 configure_window_ = FindLowestCommonAncestor( |
| 878 GetRootWindow(), configure_window_, window); |
| 879 } |
| 880 } |
| 881 |
| 882 void RootWindowHostLinux::SetDelegate(aura::RootWindowHostDelegate* delegate) { |
| 883 DCHECK(!delegate_); |
487 delegate_ = delegate; | 884 delegate_ = delegate; |
488 } | 885 DCHECK(delegate_); |
489 | 886 delegate_->AsRootWindow()->AddObserver(this); |
490 RootWindow* RootWindowHostLinux::GetRootWindow() { | 887 ScheduleConfigure(delegate_->AsRootWindow()); |
| 888 } |
| 889 |
| 890 aura::RootWindow* RootWindowHostLinux::GetRootWindow() { |
491 return delegate_->AsRootWindow(); | 891 return delegate_->AsRootWindow(); |
492 } | 892 } |
493 | 893 |
494 gfx::AcceleratedWidget RootWindowHostLinux::GetAcceleratedWidget() { | 894 gfx::AcceleratedWidget RootWindowHostLinux::GetAcceleratedWidget() { |
495 return xwindow_; | 895 return xwindow_; |
496 } | 896 } |
497 | 897 |
498 void RootWindowHostLinux::Show() { | 898 void RootWindowHostLinux::Show() { |
499 if (!window_mapped_) { | 899 if (!window_mapped_) { |
500 // Before we map the window, set size hints. Otherwise, some window managers | 900 // Before we map the window, set size hints. Otherwise, some window managers |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
587 } | 987 } |
588 | 988 |
589 void RootWindowHostLinux::SetCursor(gfx::NativeCursor cursor) { | 989 void RootWindowHostLinux::SetCursor(gfx::NativeCursor cursor) { |
590 if (cursor == current_cursor_) | 990 if (cursor == current_cursor_) |
591 return; | 991 return; |
592 current_cursor_ = cursor; | 992 current_cursor_ = cursor; |
593 SetCursorInternal(cursor); | 993 SetCursorInternal(cursor); |
594 } | 994 } |
595 | 995 |
596 bool RootWindowHostLinux::QueryMouseLocation(gfx::Point* location_return) { | 996 bool RootWindowHostLinux::QueryMouseLocation(gfx::Point* location_return) { |
597 client::CursorClient* cursor_client = | 997 aura::client::CursorClient* cursor_client = |
598 client::GetCursorClient(GetRootWindow()); | 998 aura::client::GetCursorClient(GetRootWindow()); |
599 if (cursor_client && !cursor_client->IsMouseEventsEnabled()) { | 999 if (cursor_client && !cursor_client->IsMouseEventsEnabled()) { |
600 *location_return = gfx::Point(0, 0); | 1000 *location_return = gfx::Point(0, 0); |
601 return false; | 1001 return false; |
602 } | 1002 } |
603 | 1003 |
604 ::Window root_return, child_return; | 1004 ::Window root_return, child_return; |
605 int root_x_return, root_y_return, win_x_return, win_y_return; | 1005 int root_x_return, root_y_return, win_x_return, win_y_return; |
606 unsigned int mask_return; | 1006 unsigned int mask_return; |
607 XQueryPointer(xdisplay_, | 1007 XQueryPointer(xdisplay_, |
608 xwindow_, | 1008 xwindow_, |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
910 if (mouse_move_filter_ && mouse_move_filter_->Filter(xev)) | 1310 if (mouse_move_filter_ && mouse_move_filter_->Filter(xev)) |
911 break; | 1311 break; |
912 } else if (type == ui::ET_MOUSE_PRESSED || | 1312 } else if (type == ui::ET_MOUSE_PRESSED || |
913 type == ui::ET_MOUSE_RELEASED) { | 1313 type == ui::ET_MOUSE_RELEASED) { |
914 XIDeviceEvent* xievent = | 1314 XIDeviceEvent* xievent = |
915 static_cast<XIDeviceEvent*>(xev->xcookie.data); | 1315 static_cast<XIDeviceEvent*>(xev->xcookie.data); |
916 int button = xievent->detail; | 1316 int button = xievent->detail; |
917 if (button == kBackMouseButton || button == kForwardMouseButton) { | 1317 if (button == kBackMouseButton || button == kForwardMouseButton) { |
918 if (type == ui::ET_MOUSE_RELEASED) | 1318 if (type == ui::ET_MOUSE_RELEASED) |
919 break; | 1319 break; |
920 client::UserActionClient* gesture_client = | 1320 aura::client::UserActionClient* gesture_client = |
921 client::GetUserActionClient(delegate_->AsRootWindow()); | 1321 aura::client::GetUserActionClient(delegate_->AsRootWindow()); |
922 if (gesture_client) { | 1322 if (gesture_client) { |
923 bool reverse_direction = | 1323 bool reverse_direction = |
924 ui::IsTouchpadEvent(xev) && ui::IsNaturalScrollEnabled(); | 1324 ui::IsTouchpadEvent(xev) && ui::IsNaturalScrollEnabled(); |
925 gesture_client->OnUserAction( | 1325 gesture_client->OnUserAction( |
926 (button == kBackMouseButton && !reverse_direction) || | 1326 (button == kBackMouseButton && !reverse_direction) || |
927 (button == kForwardMouseButton && reverse_direction) ? | 1327 (button == kForwardMouseButton && reverse_direction) ? |
928 client::UserActionClient::BACK : | 1328 aura::client::UserActionClient::BACK : |
929 client::UserActionClient::FORWARD); | 1329 aura::client::UserActionClient::FORWARD); |
930 } | 1330 } |
931 break; | 1331 break; |
932 } | 1332 } |
933 } | 1333 } |
934 ui::MouseEvent mouseev(xev); | 1334 ui::MouseEvent mouseev(xev); |
935 TranslateAndDispatchMouseEvent(&mouseev); | 1335 TranslateAndDispatchMouseEvent(&mouseev); |
936 break; | 1336 break; |
937 } | 1337 } |
938 case ui::ET_MOUSEWHEEL: { | 1338 case ui::ET_MOUSEWHEEL: { |
939 ui::MouseWheelEvent mouseev(xev); | 1339 ui::MouseWheelEvent mouseev(xev); |
(...skipping 19 matching lines...) Expand all Loading... |
959 } | 1359 } |
960 | 1360 |
961 bool RootWindowHostLinux::IsWindowManagerPresent() { | 1361 bool RootWindowHostLinux::IsWindowManagerPresent() { |
962 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership | 1362 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership |
963 // of WM_Sn selections (where n is a screen number). | 1363 // of WM_Sn selections (where n is a screen number). |
964 return XGetSelectionOwner( | 1364 return XGetSelectionOwner( |
965 xdisplay_, atom_cache_.GetAtom("WM_S0")) != None; | 1365 xdisplay_, atom_cache_.GetAtom("WM_S0")) != None; |
966 } | 1366 } |
967 | 1367 |
968 void RootWindowHostLinux::SetCursorInternal(gfx::NativeCursor cursor) { | 1368 void RootWindowHostLinux::SetCursorInternal(gfx::NativeCursor cursor) { |
969 XDefineCursor(xdisplay_, xwindow_, cursor.platform()); | 1369 XDefineCursor(xdisplay_, x_input_window_, cursor.platform()); |
| 1370 |
| 1371 // Set default native window cursor. |
| 1372 if (need_to_set_default_cursor_ && cursor.native_type() == ui::kCursorNull) { |
| 1373 XDefineCursor(xdisplay_, xwindow_, cursor.platform()); |
| 1374 need_to_set_default_cursor_ = false; |
| 1375 } |
970 } | 1376 } |
971 | 1377 |
972 void RootWindowHostLinux::TranslateAndDispatchMouseEvent( | 1378 void RootWindowHostLinux::TranslateAndDispatchMouseEvent( |
973 ui::MouseEvent* event) { | 1379 ui::MouseEvent* event) { |
974 RootWindow* root = GetRootWindow(); | 1380 aura::RootWindow* root = GetRootWindow(); |
975 client::ScreenPositionClient* screen_position_client = | 1381 aura::client::ScreenPositionClient* screen_position_client = |
976 GetScreenPositionClient(root); | 1382 GetScreenPositionClient(root); |
977 if (screen_position_client && !bounds_.Contains(event->location())) { | 1383 if (screen_position_client && !bounds_.Contains(event->location())) { |
978 gfx::Point location(event->location()); | 1384 gfx::Point location(event->location()); |
979 screen_position_client->ConvertNativePointToScreen(root, &location); | 1385 screen_position_client->ConvertNativePointToScreen(root, &location); |
980 screen_position_client->ConvertPointFromScreen(root, &location); | 1386 screen_position_client->ConvertPointFromScreen(root, &location); |
981 // |delegate_|'s OnHoustMouseEvent expects native coordinates relative to | 1387 // |delegate_|'s OnHoustMouseEvent expects native coordinates relative to |
982 // root. | 1388 // root. |
983 location = ui::ConvertPointToPixel(root->layer(), location); | 1389 location = ui::ConvertPointToPixel(root->layer(), location); |
984 event->set_location(location); | 1390 event->set_location(location); |
985 event->set_root_location(location); | 1391 event->set_root_location(location); |
986 } | 1392 } |
987 delegate_->OnHostMouseEvent(event); | 1393 delegate_->OnHostMouseEvent(event); |
988 } | 1394 } |
989 | 1395 |
990 scoped_ptr<ui::XScopedImage> RootWindowHostLinux::GetXImage( | 1396 scoped_ptr<ui::XScopedImage> RootWindowHostLinux::GetXImage( |
991 const gfx::Rect& snapshot_bounds) { | 1397 const gfx::Rect& snapshot_bounds) { |
992 scoped_ptr<ui::XScopedImage> image(new ui::XScopedImage( | 1398 scoped_ptr<ui::XScopedImage> image(new ui::XScopedImage( |
993 XGetImage(xdisplay_, xwindow_, | 1399 XGetImage(xdisplay_, xwindow_, |
994 snapshot_bounds.x(), snapshot_bounds.y(), | 1400 snapshot_bounds.x(), snapshot_bounds.y(), |
995 snapshot_bounds.width(), snapshot_bounds.height(), | 1401 snapshot_bounds.width(), snapshot_bounds.height(), |
996 AllPlanes, ZPixmap))); | 1402 AllPlanes, ZPixmap))); |
997 if (!image->get()) { | 1403 if (!image->get()) { |
998 LOG(ERROR) << "XGetImage failed"; | 1404 LOG(ERROR) << "XGetImage failed"; |
999 image.reset(); | 1405 image.reset(); |
1000 } | 1406 } |
1001 return image.Pass(); | 1407 return image.Pass(); |
1002 } | 1408 } |
1003 | 1409 |
1004 // static | 1410 } // namespace wm |
1005 RootWindowHost* RootWindowHost::Create(const gfx::Rect& bounds) { | |
1006 return new RootWindowHostLinux(bounds); | |
1007 } | |
1008 | |
1009 // static | |
1010 gfx::Size RootWindowHost::GetNativeScreenSize() { | |
1011 ::Display* xdisplay = base::MessagePumpAuraX11::GetDefaultXDisplay(); | |
1012 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); | |
1013 } | |
1014 | |
1015 } // namespace aura | |
OLD | NEW |