Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: wm/host/root_window_host_linux.cc

Issue 11485006: Add window manager component. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase and add proper use_wm flag support Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/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"
25 #include "third_party/skia/include/core/SkBitmap.h" 27 #include "third_party/skia/include/core/SkBitmap.h"
26 #include "third_party/skia/include/core/SkCanvas.h" 28 #include "third_party/skia/include/core/SkCanvas.h"
27 #include "third_party/skia/include/core/SkPostConfig.h"
28 #include "ui/aura/client/capture_client.h" 29 #include "ui/aura/client/capture_client.h"
29 #include "ui/aura/client/cursor_client.h" 30 #include "ui/aura/client/cursor_client.h"
30 #include "ui/aura/client/screen_position_client.h" 31 #include "ui/aura/client/screen_position_client.h"
31 #include "ui/aura/client/user_action_client.h" 32 #include "ui/aura/client/user_action_client.h"
32 #include "ui/aura/env.h" 33 #include "ui/aura/env.h"
33 #include "ui/aura/root_window.h" 34 #include "ui/aura/root_window.h"
34 #include "ui/base/cursor/cursor.h" 35 #include "ui/base/cursor/cursor.h"
35 #include "ui/base/events/event.h" 36 #include "ui/base/events/event.h"
36 #include "ui/base/events/event_utils.h" 37 #include "ui/base/events/event_utils.h"
37 #include "ui/base/keycodes/keyboard_codes.h" 38 #include "ui/base/keycodes/keyboard_codes.h"
38 #include "ui/base/touch/touch_factory.h" 39 #include "ui/base/touch/touch_factory.h"
39 #include "ui/base/ui_base_switches.h" 40 #include "ui/base/ui_base_switches.h"
40 #include "ui/base/view_prop.h" 41 #include "ui/base/view_prop.h"
41 #include "ui/base/x/device_list_cache_x.h" 42 #include "ui/base/x/device_list_cache_x.h"
42 #include "ui/base/x/valuators.h" 43 #include "ui/base/x/valuators.h"
43 #include "ui/base/x/x11_util.h" 44 #include "ui/base/x/x11_util.h"
44 #include "ui/compositor/dip_util.h" 45 #include "ui/compositor/dip_util.h"
45 #include "ui/compositor/layer.h" 46 #include "ui/compositor/layer.h"
46 #include "ui/gfx/codec/png_codec.h" 47 #include "ui/gfx/codec/png_codec.h"
47 #include "ui/gfx/screen.h" 48 #include "ui/gfx/screen.h"
49 #include "wm/foreign_window.h"
50 #include "wm/foreign_window_widget.h"
48 51
49 #if defined(OS_CHROMEOS) 52 #if defined(OS_CHROMEOS)
50 #include "base/chromeos/chromeos_version.h" 53 #include "base/chromeos/chromeos_version.h"
51 #endif 54 #endif
52 55
53 using std::max; 56 using std::max;
54 using std::min; 57 using std::min;
55 58
56 namespace aura { 59 namespace wm {
57 60
58 namespace { 61 namespace {
59 62
60 // Standard Linux mouse buttons for going back and forward. 63 // Standard Linux mouse buttons for going back and forward.
61 const int kBackMouseButton = 8; 64 const int kBackMouseButton = 8;
62 const int kForwardMouseButton = 9; 65 const int kForwardMouseButton = 9;
63 66
64 // These are the same values that are used to calibrate touch events in 67 // These are the same values that are used to calibrate touch events in
65 // |CalibrateTouchCoordinates| (in ui/base/x/events_x.cc). 68 // |CalibrateTouchCoordinates| (in ui/base/x/events_x.cc).
66 // TODO(sad|skuhne): Remove the duplication of values (http://crbug.com/147605) 69 // TODO(sad|skuhne): Remove the duplication of values (http://crbug.com/147605)
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 case ui::VKEY_OEM_PLUS: 165 case ui::VKEY_OEM_PLUS:
163 case ui::VKEY_OEM_COMMA: 166 case ui::VKEY_OEM_COMMA:
164 case ui::VKEY_OEM_MINUS: 167 case ui::VKEY_OEM_MINUS:
165 case ui::VKEY_OEM_PERIOD: 168 case ui::VKEY_OEM_PERIOD:
166 return true; 169 return true;
167 default: 170 default:
168 return false; 171 return false;
169 } 172 }
170 } 173 }
171 174
175 unsigned InitWindowChanges(const gfx::Rect& bounds,
176 ::Window sibling_to_stack_above,
177 XWindowChanges& wc) {
178 wc.x = bounds.x();
179 wc.y = bounds.y();
180 wc.width = bounds.width();
181 wc.height = bounds.height();
182 if (!sibling_to_stack_above) {
183 wc.stack_mode = Below;
184 return CWX | CWY | CWWidth | CWHeight | CWStackMode;
185 }
186
187 wc.sibling = sibling_to_stack_above;
188 wc.stack_mode = Above;
189 return CWX | CWY | CWWidth | CWHeight | CWStackMode | CWSibling;
190 }
191
192 aura::Window* FindLowestCommonAncestor(
193 aura::Window* root, const aura::Window* p, const aura::Window* q) {
194 // Root is the LCA.
195 if (root == p || root == q)
196 return root;
197
198 aura::Window* prev = NULL;
199 const aura::Window::Windows& children = root->children();
200 for (size_t i = 0; i < children.size(); ++i) {
201 // Try to find LCA of p and q in subtree.
202 aura::Window* next = FindLowestCommonAncestor(children[i], p, q);
203 if (next) {
204 // If a LCA was previously found, p and q must be in different subtrees.
205 if (prev)
206 return root;
207
208 prev = next;
209 }
210 }
211
212 return prev;
213 }
214
215 gfx::Point GetTargetOriginInRootWindow(const aura::Window* window) {
danakj 2013/02/21 01:33:15 GetTargetOffset.. and return a Vector2d? Then GetT
reveman 2013/02/22 01:26:44 Sg, I'll get this fixed soon or maybe if it's not
danakj 2013/02/22 01:48:08 We can do it after, it should be easy to do either
reveman 2013/02/22 06:53:01 Got this done. Please verify that my changes to Re
216 gfx::Point origin;
217
218 const aura::Window* p = window;
219 for (; p != window->GetRootWindow(); p = p->parent())
220 origin += p->GetTargetBounds().OffsetFromOrigin();
221
222 return origin;
223 }
224
225 gfx::Rect GetTargetBoundsInRootWindow(const aura::Window* window) {
226 return gfx::Rect(
227 GetTargetOriginInRootWindow(window),
228 window->GetTargetBounds().size());
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 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 316
258 RootWindowHostLinux::RootWindowHostLinux(const gfx::Rect& bounds) 317 RootWindowHostLinux::RootWindowHostLinux(const gfx::Rect& bounds)
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),
326 pointer_barriers_(NULL),
267 touch_calibrate_(new internal::TouchEventCalibrate), 327 touch_calibrate_(new internal::TouchEventCalibrate),
268 mouse_move_filter_(new MouseMoveFilter), 328 mouse_move_filter_(new MouseMoveFilter),
269 atom_cache_(xdisplay_, kAtomsToCache) { 329 atom_cache_(xdisplay_, kAtomsToCache),
330 configure_window_(NULL),
331 x_input_window_(0),
332 need_to_set_default_cursor_(true) {
270 XSetWindowAttributes swa; 333 XSetWindowAttributes swa;
271 memset(&swa, 0, sizeof(swa)); 334 memset(&swa, 0, sizeof(swa));
272 swa.background_pixmap = None; 335 swa.background_pixmap = None;
273 xwindow_ = XCreateWindow( 336 xwindow_ = XCreateWindow(
274 xdisplay_, x_root_window_, 337 xdisplay_, x_root_window_,
275 bounds.x(), bounds.y(), bounds.width(), bounds.height(), 338 bounds.x(), bounds.y(), bounds.width(), bounds.height(),
276 0, // border width 339 0, // border width
277 CopyFromParent, // depth 340 CopyFromParent, // depth
278 InputOutput, 341 InputOutput,
279 CopyFromParent, // visual 342 CopyFromParent, // visual
280 CWBackPixmap, 343 CWBackPixmap,
281 &swa); 344 &swa);
345 x_input_window_ = XCreateWindow(
346 xdisplay_, xwindow_,
347 -100, -100, 1, 1,
348 0, // border width
349 CopyFromParent, // depth
350 InputOnly,
351 CopyFromParent, // visual
352 0,
353 NULL);
354 XMapWindow(xdisplay_, x_input_window_);
355 XCompositeRedirectSubwindows(xdisplay_, xwindow_, CompositeRedirectManual);
356
282 base::MessagePumpAuraX11::Current()->AddDispatcherForWindow(this, xwindow_); 357 base::MessagePumpAuraX11::Current()->AddDispatcherForWindow(this, xwindow_);
283 base::MessagePumpAuraX11::Current()->AddDispatcherForRootWindow(this); 358 base::MessagePumpAuraX11::Current()->AddDispatcherForRootWindow(this);
284 359
285 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | 360 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask |
286 KeyPressMask | KeyReleaseMask | 361 KeyPressMask | KeyReleaseMask |
287 EnterWindowMask | LeaveWindowMask | 362 EnterWindowMask | LeaveWindowMask |
288 ExposureMask | VisibilityChangeMask | 363 ExposureMask | VisibilityChangeMask |
289 StructureNotifyMask | PropertyChangeMask | 364 StructureNotifyMask | PropertyChangeMask |
290 PointerMotionMask; 365 PointerMotionMask |
366 SubstructureNotifyMask | SubstructureRedirectMask;
291 XSelectInput(xdisplay_, xwindow_, event_mask); 367 XSelectInput(xdisplay_, xwindow_, event_mask);
292 XFlush(xdisplay_); 368 XFlush(xdisplay_);
293 369
294 if (base::MessagePumpForUI::HasXInput2()) 370 if (base::MessagePumpForUI::HasXInput2())
295 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); 371 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_);
296 372
297 SelectEventsForRootWindow(); 373 SelectEventsForRootWindow();
298 374
299 // Get the initial size of the X root window. 375 // Get the initial size of the X root window.
300 XWindowAttributes attrs; 376 XWindowAttributes attrs;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 XRRSelectInput(xdisplay_, x_root_window_, 409 XRRSelectInput(xdisplay_, x_root_window_,
334 RRScreenChangeNotifyMask | RROutputChangeNotifyMask); 410 RRScreenChangeNotifyMask | RROutputChangeNotifyMask);
335 } 411 }
336 412
337 RootWindowHostLinux::~RootWindowHostLinux() { 413 RootWindowHostLinux::~RootWindowHostLinux() {
338 base::MessagePumpAuraX11::Current()->RemoveDispatcherForRootWindow(this); 414 base::MessagePumpAuraX11::Current()->RemoveDispatcherForRootWindow(this);
339 base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_); 415 base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_);
340 416
341 UnConfineCursor(); 417 UnConfineCursor();
342 418
419 GetRootWindow()->RemoveObserver(this);
420 XDestroyWindow(xdisplay_, x_input_window_);
343 XDestroyWindow(xdisplay_, xwindow_); 421 XDestroyWindow(xdisplay_, xwindow_);
344 } 422 }
345 423
346 bool RootWindowHostLinux::Dispatch(const base::NativeEvent& event) { 424 bool RootWindowHostLinux::Dispatch(const base::NativeEvent& event) {
347 XEvent* xev = event; 425 XEvent* xev = event;
348 426
349 if (FindEventTarget(event) == x_root_window_) 427 if (FindEventTarget(event) == x_root_window_)
350 return DispatchEventForRootWindow(event); 428 return DispatchEventForRootWindow(event);
351 429
352 switch (xev->type) { 430 switch (xev->type) {
431 case ConfigureNotify: {
432 if (event->xconfigure.window == x_input_window_)
433 return true;
434
435 ForeignWindowMap::iterator it = foreign_windows_.find(
436 event->xconfigure.window);
437 if (it != foreign_windows_.end()) {
438 ForeignWindow* window = it->second;
439
440 int border_size = event->xconfigure.border_width * 2;
441 gfx::Size size(event->xconfigure.width + border_size,
442 event->xconfigure.height + border_size);
443 window->SetWindowSize(size);
444 return true;
445 }
446 break;
447 }
448 case MapNotify: {
449 ForeignWindowMap::iterator it = foreign_windows_.find(
450 event->xmap.window);
451 if (it != foreign_windows_.end()) {
452 ForeignWindow* window = it->second;
453
454 window->SetWindowVisible(true);
455 return true;
456 }
457 break;
458 }
459 case UnmapNotify: {
460 ForeignWindowMap::iterator it = foreign_windows_.find(
461 event->xunmap.window);
462 if (it != foreign_windows_.end()) {
463 ForeignWindow* window = it->second;
464
465 // Hide top level widget.
466 views::Widget* widget = window->GetWidget();
467 widget->Hide();
468
469 window->SetWindowVisible(false);
470 return true;
471 }
472 break;
473 }
474 case CreateNotify: {
475 int border_size = event->xcreatewindow.border_width * 2;
476 gfx::Size size(event->xcreatewindow.width + border_size,
477 event->xcreatewindow.height + border_size);
478
479 // Create a foreign window for this X window.
480 ForeignWindow::CreateParams params(event->xcreatewindow.window, size);
481 scoped_refptr<ForeignWindow> window(new ForeignWindow(params));
482
483 // Create top level window widget.
484 ForeignWindowWidget::CreateWindow(window.get());
485
486 // Add foreign window to map.
487 foreign_windows_[event->xcreatewindow.window] = window.get();
488 return true;
489 }
490 case DestroyNotify: {
491 ForeignWindowMap::iterator it = foreign_windows_.find(
492 event->xdestroywindow.window);
493 if (it != foreign_windows_.end()) {
494 ForeignWindow* window = it->second;
495
496 // Tell foreign window that X window has been destroyed.
497 window->OnWindowDestroyed();
498
499 // Close top level widget.
500 views::Widget* widget = window->GetWidget();
501 widget->Close();
502
503 foreign_windows_.erase(it);
504 }
505 return true;
506 }
507 case MapRequest: {
508 ForeignWindowMap::iterator it = foreign_windows_.find(
509 event->xmaprequest.window);
510 if (it != foreign_windows_.end()) {
511 ForeignWindow* window = it->second;
512
513 // Show top level widget.
514 views::Widget* widget = window->GetWidget();
515 widget->Show();
516 }
517 return true;
518 }
519 case ConfigureRequest: {
520 // TODO(reveman): Respect ConfigureRequest events.
521 return true;
522 }
523 case CirculateRequest: {
524 // TODO(reveman): Respect CirculateRequest events.
525 return true;
526 }
527 }
528
529 switch (xev->type) {
353 case EnterNotify: { 530 case EnterNotify: {
354 ui::MouseEvent mouseenter_event(xev); 531 ui::MouseEvent mouseenter_event(xev);
355 TranslateAndDispatchMouseEvent(&mouseenter_event); 532 TranslateAndDispatchMouseEvent(&mouseenter_event);
356 break; 533 break;
357 } 534 }
358 case Expose: 535 case Expose:
359 delegate_->AsRootWindow()->ScheduleFullDraw(); 536 delegate_->AsRootWindow()->ScheduleFullDraw();
360 break; 537 break;
361 case KeyPress: { 538 case KeyPress: {
362 ui::KeyEvent keydown_event(xev, false); 539 ui::KeyEvent keydown_event(xev, false);
363 delegate_->OnHostKeyEvent(&keydown_event); 540 delegate_->OnHostKeyEvent(&keydown_event);
364 break; 541 break;
365 } 542 }
366 case KeyRelease: { 543 case KeyRelease: {
367 ui::KeyEvent keyup_event(xev, false); 544 ui::KeyEvent keyup_event(xev, false);
368 delegate_->OnHostKeyEvent(&keyup_event); 545 delegate_->OnHostKeyEvent(&keyup_event);
369 break; 546 break;
370 } 547 }
371 case ButtonPress: { 548 case ButtonPress: {
372 if (static_cast<int>(xev->xbutton.button) == kBackMouseButton || 549 if (static_cast<int>(xev->xbutton.button) == kBackMouseButton ||
373 static_cast<int>(xev->xbutton.button) == kForwardMouseButton) { 550 static_cast<int>(xev->xbutton.button) == kForwardMouseButton) {
374 client::UserActionClient* gesture_client = 551 aura::client::UserActionClient* gesture_client =
375 client::GetUserActionClient(delegate_->AsRootWindow()); 552 aura::client::GetUserActionClient(delegate_->AsRootWindow());
376 if (gesture_client) { 553 if (gesture_client) {
377 gesture_client->OnUserAction( 554 gesture_client->OnUserAction(
378 static_cast<int>(xev->xbutton.button) == kBackMouseButton ? 555 static_cast<int>(xev->xbutton.button) == kBackMouseButton ?
379 client::UserActionClient::BACK : 556 aura::client::UserActionClient::BACK :
380 client::UserActionClient::FORWARD); 557 aura::client::UserActionClient::FORWARD);
381 } 558 }
382 break; 559 break;
383 } 560 }
384 } // fallthrough 561 } // fallthrough
385 case ButtonRelease: { 562 case ButtonRelease: {
386 ui::MouseEvent mouseev(xev); 563 ui::MouseEvent mouseev(xev);
387 TranslateAndDispatchMouseEvent(&mouseev); 564 TranslateAndDispatchMouseEvent(&mouseev);
388 break; 565 break;
389 } 566 }
390 case FocusOut: 567 case FocusOut:
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 } 653 }
477 654
478 ui::MouseEvent mouseev(xev); 655 ui::MouseEvent mouseev(xev);
479 TranslateAndDispatchMouseEvent(&mouseev); 656 TranslateAndDispatchMouseEvent(&mouseev);
480 break; 657 break;
481 } 658 }
482 } 659 }
483 return true; 660 return true;
484 } 661 }
485 662
486 void RootWindowHostLinux::SetDelegate(RootWindowHostDelegate* delegate) { 663 void RootWindowHostLinux::OnWindowAdded(aura::Window* window) {
664 window->AddObserver(this);
665 }
666
667 void RootWindowHostLinux::OnWillRemoveWindow(aura::Window* window) {
668 if (configure_window_ == window)
669 configure_window_ = window->parent();
670
671 window->RemoveObserver(this);
672 }
673
674 void RootWindowHostLinux::OnWindowStackingChanged(aura::Window* window) {
675 ScheduleConfigure(GetRootWindow());
676 }
677
678 void RootWindowHostLinux::OnWindowVisibilityChanged(
679 aura::Window* window, bool visible) {
680 ScheduleConfigure(GetRootWindow());
681 }
682
683 void RootWindowHostLinux::OnWindowBoundsChanged(
684 aura::Window* window,
685 const gfx::Rect& old_bounds,
686 const gfx::Rect& new_bounds) {
687 ScheduleConfigure(GetRootWindow());
688 }
689
690 void RootWindowHostLinux::OnWindowDestroying(aura::Window* window) {
691 window->RemoveObserver(this);
692 }
693
694 ::Window RootWindowHostLinux::GetTopForeignWindow(const aura::Window* window) {
695 // children are ordered back to front, so walk through it in reverse.
696 const aura::Window::Windows& children = window->children();
697 for (size_t i = children.size(); i; --i) {
698 ::Window top = GetTopForeignWindow(children[i - 1]);
699 if (top)
700 return top;
701 }
702
703 ForeignWindow* foreign_window = ForeignWindow::GetForeignWindowForNativeView(
704 const_cast<gfx::NativeView>(window));
705 if (foreign_window) {
706 // Ignore windows that we're not allowed to configure.
707 if (foreign_window->IsManaged())
708 return foreign_window->GetWindowHandle();
709 }
710
711 return 0;
712 }
713
714 ::Window RootWindowHostLinux::FindForeignWindowToStackAbove(
715 const aura::Window* window) {
716 const aura::Window* parent = window->parent();
717 if (!parent)
718 return 0;
719
720 ::Window above = 0;
721
722 const aura::Window::Windows& children = parent->children();
723 for (size_t i = 0; i < children.size(); ++i) {
724 if (children[i] == window)
725 break;
726
727 ::Window top = GetTopForeignWindow(children[i]);
728 if (top)
729 above = top;
730 }
731
732 if (!above)
733 above = FindForeignWindowToStackAbove(parent);
734
735 return above;
736 }
737
738 void RootWindowHostLinux::MapWindowIfNeeded(ForeignWindow* window) {
739 ForeignWindow::DisplayState current_display_state =
740 window->GetDisplayState();
741
742 if (current_display_state != ForeignWindow::DISPLAY_NORMAL) {
743 // TODO(reveman): Ignore possible X error.
744 XMapWindow(xdisplay_, window->GetWindowHandle());
745
746 window->SetDisplayState(ForeignWindow::DISPLAY_NORMAL);
747 }
748 }
749
750 void RootWindowHostLinux::UnmapWindowIfNeeded(ForeignWindow* window) {
751 ForeignWindow::DisplayState current_display_state =
752 window->GetDisplayState();
753
754 if (current_display_state == ForeignWindow::DISPLAY_NORMAL) {
755 // TODO(reveman): Ignore possible X error.
756 XUnmapWindow(xdisplay_, window->GetWindowHandle());
757
758 window->SetDisplayState(ForeignWindow::DISPLAY_ICONIC);
759 }
760 }
761
762 void RootWindowHostLinux::RecursiveConfigure(
763 aura::Window* window,
764 const gfx::Point& origin,
765 ::Window* sibling_to_stack_above,
766 SkRegion* input_region) {
767 gfx::Rect bounds(origin, window->GetTargetBounds().size());
768 SkRegion::Op input_region_op;
769
770 ForeignWindow* foreign_window = ForeignWindow::GetForeignWindowForNativeView(
771 const_cast<gfx::NativeView>(window));
772 if (foreign_window) {
773 DCHECK(!bounds.IsEmpty());
774
775 // We should only be adjusting attributes of managed windows.
776 if (foreign_window->IsManaged()) {
777 if (!window->IsVisible())
778 UnmapWindowIfNeeded(foreign_window);
779
780 XWindowChanges wc;
781 unsigned mask = InitWindowChanges(bounds, *sibling_to_stack_above, wc);
782 // Get rid of any borders.
783 wc.border_width = 0;
784 mask |= CWBorderWidth;
785 // TODO(reveman): Ignore possible X error.
786 XConfigureWindow(xdisplay_,
787 foreign_window->GetWindowHandle(),
788 mask,
789 &wc);
790
791 *sibling_to_stack_above = foreign_window->GetWindowHandle();
792
793 if (window->IsVisible())
794 MapWindowIfNeeded(foreign_window);
795 }
796
797 // Remove foreign window bounds from input region.
798 bounds.Inset(window->hit_test_bounds_override_inner());
799 input_region_op = SkRegion::kDifference_Op;
800 } else {
801 // Add window bounds to output region.
802 bounds.Inset(window->hit_test_bounds_override_outer_mouse());
803 input_region_op = SkRegion::kUnion_Op;
804 }
805
806 if (window->delegate() && window->IsVisible()) {
807 input_region->op(bounds.x(),
808 bounds.y(),
809 bounds.right(),
810 bounds.bottom(),
811 input_region_op);
812 }
813
814 const aura::Window::Windows& children = window->children();
815 for (size_t i = 0; i < children.size(); ++i) {
816 RecursiveConfigure(
817 children[i],
818 origin + children[i]->GetTargetBounds().OffsetFromOrigin(),
819 sibling_to_stack_above,
820 input_region);
821 }
822 }
823
824 void RootWindowHostLinux::Configure() {
825 if (!configure_window_)
826 return;
827
828 SkRegion input_region;
829 ::Window sibling_to_stack_above =
830 FindForeignWindowToStackAbove(configure_window_);
831 RecursiveConfigure(configure_window_,
832 GetTargetOriginInRootWindow(configure_window_),
833 &sibling_to_stack_above,
834 &input_region);
835
836 // Update input window and set focus when we configure the root window.
837 if (configure_window_ == GetRootWindow()) {
838 // Configure input window above all other windows.
839 XWindowChanges wc;
840 gfx::Rect bounds(gfx::Point(0, 0), bounds_.size());
841 unsigned mask = InitWindowChanges(bounds, sibling_to_stack_above, wc);
842 XConfigureWindow(xdisplay_, x_input_window_, mask, &wc);
843
844 // Update input window shape.
845 std::vector<XRectangle> rectangles;
846 for (SkRegion::Iterator iter(input_region); !iter.done(); iter.next()) {
847 const SkIRect& sk_rect = iter.rect();
848 XRectangle x_rect;
849 x_rect.x = sk_rect.x();
850 x_rect.y = sk_rect.y();
851 x_rect.width = sk_rect.width();
852 x_rect.height = sk_rect.height();
853 rectangles.push_back(x_rect);
854 }
855
856 XShapeCombineRectangles(xdisplay_,
857 x_input_window_,
858 ShapeInput,
859 0,
860 0,
861 &rectangles.front(),
862 rectangles.size(),
863 ShapeSet,
864 Unsorted);
865 }
866
867 XFlush(xdisplay_);
868 configure_window_ = NULL;
869 }
870
871 void RootWindowHostLinux::ScheduleConfigure(aura::Window* window) {
872 if (!configure_window_) {
873 configure_window_ = window;
874 MessageLoop::current()->PostTask(
875 FROM_HERE,
876 base::Bind(&RootWindowHostLinux::Configure, AsWeakPtr()));
877 } else {
878 configure_window_ = FindLowestCommonAncestor(
879 GetRootWindow(), configure_window_, window);
880 }
881 }
882
883 void RootWindowHostLinux::SetDelegate(aura::RootWindowHostDelegate* delegate) {
884 DCHECK(!delegate_);
487 delegate_ = delegate; 885 delegate_ = delegate;
488 } 886 DCHECK(delegate_);
489 887 delegate_->AsRootWindow()->AddObserver(this);
490 RootWindow* RootWindowHostLinux::GetRootWindow() { 888 ScheduleConfigure(delegate_->AsRootWindow());
889 }
890
891 aura::RootWindow* RootWindowHostLinux::GetRootWindow() {
491 return delegate_->AsRootWindow(); 892 return delegate_->AsRootWindow();
492 } 893 }
493 894
494 gfx::AcceleratedWidget RootWindowHostLinux::GetAcceleratedWidget() { 895 gfx::AcceleratedWidget RootWindowHostLinux::GetAcceleratedWidget() {
495 return xwindow_; 896 return xwindow_;
496 } 897 }
497 898
498 void RootWindowHostLinux::Show() { 899 void RootWindowHostLinux::Show() {
499 if (!window_mapped_) { 900 if (!window_mapped_) {
500 // Before we map the window, set size hints. Otherwise, some window managers 901 // Before we map the window, set size hints. Otherwise, some window managers
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
587 } 988 }
588 989
589 void RootWindowHostLinux::SetCursor(gfx::NativeCursor cursor) { 990 void RootWindowHostLinux::SetCursor(gfx::NativeCursor cursor) {
590 if (cursor == current_cursor_) 991 if (cursor == current_cursor_)
591 return; 992 return;
592 current_cursor_ = cursor; 993 current_cursor_ = cursor;
593 SetCursorInternal(cursor); 994 SetCursorInternal(cursor);
594 } 995 }
595 996
596 bool RootWindowHostLinux::QueryMouseLocation(gfx::Point* location_return) { 997 bool RootWindowHostLinux::QueryMouseLocation(gfx::Point* location_return) {
597 client::CursorClient* cursor_client = 998 aura::client::CursorClient* cursor_client =
598 client::GetCursorClient(GetRootWindow()); 999 aura::client::GetCursorClient(GetRootWindow());
599 if (cursor_client && !cursor_client->IsMouseEventsEnabled()) { 1000 if (cursor_client && !cursor_client->IsMouseEventsEnabled()) {
600 *location_return = gfx::Point(0, 0); 1001 *location_return = gfx::Point(0, 0);
601 return false; 1002 return false;
602 } 1003 }
603 1004
604 ::Window root_return, child_return; 1005 ::Window root_return, child_return;
605 int root_x_return, root_y_return, win_x_return, win_y_return; 1006 int root_x_return, root_y_return, win_x_return, win_y_return;
606 unsigned int mask_return; 1007 unsigned int mask_return;
607 XQueryPointer(xdisplay_, 1008 XQueryPointer(xdisplay_,
608 xwindow_, 1009 xwindow_,
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
714 const gfx::Point& dest_offset, 1115 const gfx::Point& dest_offset,
715 SkCanvas* canvas) { 1116 SkCanvas* canvas) {
716 scoped_ptr<ui::XScopedImage> scoped_image(GetXImage(source_bounds)); 1117 scoped_ptr<ui::XScopedImage> scoped_image(GetXImage(source_bounds));
717 if (!scoped_image.get()) 1118 if (!scoped_image.get())
718 return false; 1119 return false;
719 1120
720 XImage* image = scoped_image->get(); 1121 XImage* image = scoped_image->get();
721 DCHECK(image); 1122 DCHECK(image);
722 1123
723 if (image->bits_per_pixel == 32) { 1124 if (image->bits_per_pixel == 32) {
724 if ((0xff << SK_R32_SHIFT) != image->red_mask ||
725 (0xff << SK_G32_SHIFT) != image->green_mask ||
726 (0xff << SK_B32_SHIFT) != image->blue_mask) {
727 LOG(WARNING) << "XImage and Skia byte orders differ";
728 return false;
729 }
730
731 // Set the alpha channel before copying to the canvas. Otherwise, areas of 1125 // Set the alpha channel before copying to the canvas. Otherwise, areas of
732 // the framebuffer that were cleared by ply-image rather than being obscured 1126 // the framebuffer that were cleared by ply-image rather than being obscured
733 // by an image during boot may end up transparent. 1127 // by an image during boot may end up transparent.
734 // TODO(derat|marcheu): Remove this if/when ply-image has been updated to 1128 // TODO(derat|marcheu): Remove this if/when ply-image has been updated to
735 // set the framebuffer's alpha channel regardless of whether the device 1129 // set the framebuffer's alpha channel regardless of whether the device
736 // claims to support alpha or not. 1130 // claims to support alpha or not.
737 for (int i = 0; i < image->width * image->height * 4; i += 4) 1131 for (int i = 0; i < image->width * image->height * 4; i += 4)
738 image->data[i + 3] = 0xff; 1132 image->data[i + 3] = 0xff;
739 1133
740 SkBitmap bitmap; 1134 SkBitmap bitmap;
741 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1135 bitmap.setConfig(SkBitmap::kARGB_8888_Config,
742 image->width, image->height, 1136 image->width, image->height,
743 image->bytes_per_line); 1137 image->bytes_per_line);
744 bitmap.setPixels(image->data); 1138 bitmap.setPixels(image->data);
745 canvas->drawBitmap(bitmap, SkIntToScalar(0), SkIntToScalar(0), NULL); 1139 SkCanvas::Config8888 config =
746 } else { 1140 (image->byte_order == LSBFirst) ?
1141 SkCanvas::kBGRA_Unpremul_Config8888 :
1142 SkCanvas::kRGBA_Unpremul_Config8888;
1143 canvas->writePixels(bitmap, dest_offset.x(), dest_offset.y(), config);
1144 } else if (image->bits_per_pixel == 24) {
747 NOTIMPLEMENTED() << "Unsupported bits-per-pixel " << image->bits_per_pixel; 1145 NOTIMPLEMENTED() << "Unsupported bits-per-pixel " << image->bits_per_pixel;
748 return false; 1146 return false;
749 } 1147 }
750 1148
751 return true; 1149 return true;
752 } 1150 }
753 1151
754 bool RootWindowHostLinux::GrabSnapshot( 1152 bool RootWindowHostLinux::GrabSnapshot(
755 const gfx::Rect& snapshot_bounds, 1153 const gfx::Rect& snapshot_bounds,
756 std::vector<unsigned char>* png_representation) { 1154 std::vector<unsigned char>* png_representation) {
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
860 XEvent last_event; 1258 XEvent last_event;
861 int num_coalesced = 0; 1259 int num_coalesced = 0;
862 1260
863 switch (type) { 1261 switch (type) {
864 case ui::ET_TOUCH_MOVED: 1262 case ui::ET_TOUCH_MOVED:
865 num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event); 1263 num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event);
866 if (num_coalesced > 0) 1264 if (num_coalesced > 0)
867 xev = &last_event; 1265 xev = &last_event;
868 // fallthrough 1266 // fallthrough
869 case ui::ET_TOUCH_PRESSED: 1267 case ui::ET_TOUCH_PRESSED:
870 case ui::ET_TOUCH_CANCELLED:
871 case ui::ET_TOUCH_RELEASED: { 1268 case ui::ET_TOUCH_RELEASED: {
872 ui::TouchEvent touchev(xev); 1269 ui::TouchEvent touchev(xev);
873 #if defined(OS_CHROMEOS) 1270 #if defined(OS_CHROMEOS)
874 if (base::chromeos::IsRunningOnChromeOS()) { 1271 if (base::chromeos::IsRunningOnChromeOS()) {
875 if (!bounds_.Contains(touchev.location())) { 1272 if (!bounds_.Contains(touchev.location())) {
876 // This might still be in the bezel region. 1273 // This might still be in the bezel region.
877 gfx::Rect expanded(bounds_); 1274 gfx::Rect expanded(bounds_);
878 expanded.Inset(-kXRootWindowPaddingLeft, 1275 expanded.Inset(-kXRootWindowPaddingLeft,
879 -kXRootWindowPaddingTop, 1276 -kXRootWindowPaddingTop,
880 -kXRootWindowPaddingRight, 1277 -kXRootWindowPaddingRight,
(...skipping 29 matching lines...) Expand all
910 if (mouse_move_filter_ && mouse_move_filter_->Filter(xev)) 1307 if (mouse_move_filter_ && mouse_move_filter_->Filter(xev))
911 break; 1308 break;
912 } else if (type == ui::ET_MOUSE_PRESSED || 1309 } else if (type == ui::ET_MOUSE_PRESSED ||
913 type == ui::ET_MOUSE_RELEASED) { 1310 type == ui::ET_MOUSE_RELEASED) {
914 XIDeviceEvent* xievent = 1311 XIDeviceEvent* xievent =
915 static_cast<XIDeviceEvent*>(xev->xcookie.data); 1312 static_cast<XIDeviceEvent*>(xev->xcookie.data);
916 int button = xievent->detail; 1313 int button = xievent->detail;
917 if (button == kBackMouseButton || button == kForwardMouseButton) { 1314 if (button == kBackMouseButton || button == kForwardMouseButton) {
918 if (type == ui::ET_MOUSE_RELEASED) 1315 if (type == ui::ET_MOUSE_RELEASED)
919 break; 1316 break;
920 client::UserActionClient* gesture_client = 1317 aura::client::UserActionClient* gesture_client =
921 client::GetUserActionClient(delegate_->AsRootWindow()); 1318 aura::client::GetUserActionClient(delegate_->AsRootWindow());
922 if (gesture_client) { 1319 if (gesture_client) {
923 bool reverse_direction = 1320 bool reverse_direction =
924 ui::IsTouchpadEvent(xev) && ui::IsNaturalScrollEnabled(); 1321 ui::IsTouchpadEvent(xev) && ui::IsNaturalScrollEnabled();
925 gesture_client->OnUserAction( 1322 gesture_client->OnUserAction(
926 (button == kBackMouseButton && !reverse_direction) || 1323 (button == kBackMouseButton && !reverse_direction) ||
927 (button == kForwardMouseButton && reverse_direction) ? 1324 (button == kForwardMouseButton && reverse_direction) ?
928 client::UserActionClient::BACK : 1325 aura::client::UserActionClient::BACK :
929 client::UserActionClient::FORWARD); 1326 aura::client::UserActionClient::FORWARD);
930 } 1327 }
931 break; 1328 break;
932 } 1329 }
933 } 1330 }
934 ui::MouseEvent mouseev(xev); 1331 ui::MouseEvent mouseev(xev);
935 TranslateAndDispatchMouseEvent(&mouseev); 1332 TranslateAndDispatchMouseEvent(&mouseev);
936 break; 1333 break;
937 } 1334 }
938 case ui::ET_MOUSEWHEEL: { 1335 case ui::ET_MOUSEWHEEL: {
939 ui::MouseWheelEvent mouseev(xev); 1336 ui::MouseWheelEvent mouseev(xev);
(...skipping 19 matching lines...) Expand all
959 } 1356 }
960 1357
961 bool RootWindowHostLinux::IsWindowManagerPresent() { 1358 bool RootWindowHostLinux::IsWindowManagerPresent() {
962 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership 1359 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership
963 // of WM_Sn selections (where n is a screen number). 1360 // of WM_Sn selections (where n is a screen number).
964 return XGetSelectionOwner( 1361 return XGetSelectionOwner(
965 xdisplay_, atom_cache_.GetAtom("WM_S0")) != None; 1362 xdisplay_, atom_cache_.GetAtom("WM_S0")) != None;
966 } 1363 }
967 1364
968 void RootWindowHostLinux::SetCursorInternal(gfx::NativeCursor cursor) { 1365 void RootWindowHostLinux::SetCursorInternal(gfx::NativeCursor cursor) {
969 XDefineCursor(xdisplay_, xwindow_, cursor.platform()); 1366 XDefineCursor(xdisplay_, x_input_window_, cursor.platform());
1367
1368 // Set default native window cursor.
1369 if (need_to_set_default_cursor_ && cursor.native_type() == ui::kCursorNull) {
1370 XDefineCursor(xdisplay_, xwindow_, cursor.platform());
1371 need_to_set_default_cursor_ = false;
1372 }
970 } 1373 }
971 1374
972 void RootWindowHostLinux::TranslateAndDispatchMouseEvent( 1375 void RootWindowHostLinux::TranslateAndDispatchMouseEvent(
973 ui::MouseEvent* event) { 1376 ui::MouseEvent* event) {
974 RootWindow* root = GetRootWindow(); 1377 aura::RootWindow* root = GetRootWindow();
975 client::ScreenPositionClient* screen_position_client = 1378 aura::client::ScreenPositionClient* screen_position_client =
976 GetScreenPositionClient(root); 1379 GetScreenPositionClient(root);
977 if (screen_position_client && !bounds_.Contains(event->location())) { 1380 if (screen_position_client && !bounds_.Contains(event->location())) {
978 gfx::Point location(event->location()); 1381 gfx::Point location(event->location());
979 screen_position_client->ConvertNativePointToScreen(root, &location); 1382 screen_position_client->ConvertNativePointToScreen(root, &location);
980 screen_position_client->ConvertPointFromScreen(root, &location); 1383 screen_position_client->ConvertPointFromScreen(root, &location);
981 // |delegate_|'s OnHoustMouseEvent expects native coordinates relative to 1384 // |delegate_|'s OnHoustMouseEvent expects native coordinates relative to
982 // root. 1385 // root.
983 location = ui::ConvertPointToPixel(root->layer(), location); 1386 location = ui::ConvertPointToPixel(root->layer(), location);
984 event->set_location(location); 1387 event->set_location(location);
985 event->set_root_location(location); 1388 event->set_root_location(location);
986 } 1389 }
987 delegate_->OnHostMouseEvent(event); 1390 delegate_->OnHostMouseEvent(event);
988 } 1391 }
989 1392
990 scoped_ptr<ui::XScopedImage> RootWindowHostLinux::GetXImage( 1393 scoped_ptr<ui::XScopedImage> RootWindowHostLinux::GetXImage(
991 const gfx::Rect& snapshot_bounds) { 1394 const gfx::Rect& snapshot_bounds) {
992 scoped_ptr<ui::XScopedImage> image(new ui::XScopedImage( 1395 scoped_ptr<ui::XScopedImage> image(new ui::XScopedImage(
993 XGetImage(xdisplay_, xwindow_, 1396 XGetImage(xdisplay_, xwindow_,
994 snapshot_bounds.x(), snapshot_bounds.y(), 1397 snapshot_bounds.x(), snapshot_bounds.y(),
995 snapshot_bounds.width(), snapshot_bounds.height(), 1398 snapshot_bounds.width(), snapshot_bounds.height(),
996 AllPlanes, ZPixmap))); 1399 AllPlanes, ZPixmap)));
997 if (!image->get()) { 1400 if (!image->get()) {
998 LOG(ERROR) << "XGetImage failed"; 1401 LOG(ERROR) << "XGetImage failed";
999 image.reset(); 1402 image.reset();
1000 } 1403 }
1001 return image.Pass(); 1404 return image.Pass();
1002 } 1405 }
1003 1406
1004 // static 1407 } // 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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698