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); | |
danakj
2013/02/22 21:42:59
Yep looks good!
| |
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 |