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

Side by Side Diff: ui/aura/root_window_host_linux.cc

Issue 11273059: ash: Clean up system background layer. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: apply review feedback Created 8 years, 1 month 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
« no previous file with comments | « ui/aura/root_window_host_linux.h ('k') | ui/aura/root_window_host_mac.mm » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "ui/aura/root_window_host_linux.h"
6 6
7 #include <strings.h>
7 #include <X11/cursorfont.h> 8 #include <X11/cursorfont.h>
8 #include <X11/extensions/Xfixes.h> 9 #include <X11/extensions/Xfixes.h>
9 #include <X11/extensions/XInput2.h> 10 #include <X11/extensions/XInput2.h>
10 #include <X11/extensions/Xrandr.h> 11 #include <X11/extensions/Xrandr.h>
11 #include <X11/Xatom.h> 12 #include <X11/Xatom.h>
12 #include <X11/Xcursor/Xcursor.h> 13 #include <X11/Xcursor/Xcursor.h>
13 #include <X11/Xlib.h> 14 #include <X11/Xlib.h>
15
14 #include <algorithm> 16 #include <algorithm>
15 17
16 #include "base/command_line.h" 18 #include "base/command_line.h"
17 #include "base/message_loop.h" 19 #include "base/message_loop.h"
18 #include "base/message_pump_aurax11.h" 20 #include "base/message_pump_aurax11.h"
19 #include "base/stl_util.h" 21 #include "base/stl_util.h"
20 #include "base/stringprintf.h" 22 #include "base/stringprintf.h"
23 #include "third_party/skia/include/core/SkBitmap.h"
24 #include "third_party/skia/include/core/SkCanvas.h"
21 #include "ui/aura/client/capture_client.h" 25 #include "ui/aura/client/capture_client.h"
22 #include "ui/aura/client/cursor_client.h" 26 #include "ui/aura/client/cursor_client.h"
23 #include "ui/aura/client/screen_position_client.h" 27 #include "ui/aura/client/screen_position_client.h"
24 #include "ui/aura/client/user_action_client.h" 28 #include "ui/aura/client/user_action_client.h"
25 #include "ui/aura/env.h" 29 #include "ui/aura/env.h"
26 #include "ui/aura/root_window.h" 30 #include "ui/aura/root_window.h"
27 #include "ui/base/cursor/cursor.h" 31 #include "ui/base/cursor/cursor.h"
28 #include "ui/base/events/event.h" 32 #include "ui/base/events/event.h"
29 #include "ui/base/keycodes/keyboard_codes.h" 33 #include "ui/base/keycodes/keyboard_codes.h"
30 #include "ui/base/touch/touch_factory.h" 34 #include "ui/base/touch/touch_factory.h"
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 } 416 }
413 417
414 ui::MouseEvent mouseev(xev); 418 ui::MouseEvent mouseev(xev);
415 TranslateAndDispatchMouseEvent(&mouseev); 419 TranslateAndDispatchMouseEvent(&mouseev);
416 break; 420 break;
417 } 421 }
418 } 422 }
419 return true; 423 return true;
420 } 424 }
421 425
422 bool RootWindowHostLinux::DispatchEventForRootWindow(
423 const base::NativeEvent& event) {
424 switch (event->type) {
425 case ConfigureNotify:
426 DCHECK_EQ(x_root_window_, event->xconfigure.event);
427 x_root_bounds_.SetRect(event->xconfigure.x, event->xconfigure.y,
428 event->xconfigure.width, event->xconfigure.height);
429 break;
430
431 case GenericEvent:
432 DispatchXI2Event(event);
433 break;
434 }
435
436 return true;
437 }
438
439 void RootWindowHostLinux::DispatchXI2Event(const base::NativeEvent& event) {
440 ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
441 XEvent* xev = event;
442 if (!factory->ShouldProcessXI2Event(xev))
443 return;
444
445 ui::EventType type = ui::EventTypeFromNative(xev);
446 XEvent last_event;
447 int num_coalesced = 0;
448
449 switch (type) {
450 case ui::ET_TOUCH_MOVED:
451 num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event);
452 if (num_coalesced > 0)
453 xev = &last_event;
454 // fallthrough
455 case ui::ET_TOUCH_PRESSED:
456 case ui::ET_TOUCH_RELEASED: {
457 ui::TouchEvent touchev(xev);
458 #if defined(OS_CHROMEOS)
459 // X maps the touch-surface to the size of the X root-window. In
460 // multi-monitor setup, the X root-window size is a combination of
461 // both the monitor sizes. So it is necessary to remap the location of
462 // the event from the X root-window to the X host-window for the aura
463 // root-window.
464 if (base::chromeos::IsRunningOnChromeOS()) {
465 touchev.CalibrateLocation(x_root_bounds_.size(), bounds_.size());
466 if (!bounds_.Contains(touchev.location())) {
467 // This might still be in the bezel region.
468 gfx::Rect expanded(bounds_);
469 expanded.Inset(-kXRootWindowPaddingLeft,
470 -kXRootWindowPaddingTop,
471 -kXRootWindowPaddingRight,
472 -kXRootWindowPaddingBottom);
473 if (!expanded.Contains(touchev.location()))
474 break;
475 }
476 }
477 #endif // defined(OS_CHROMEOS)
478 delegate_->OnHostTouchEvent(&touchev);
479 break;
480 }
481 case ui::ET_MOUSE_MOVED:
482 case ui::ET_MOUSE_DRAGGED:
483 case ui::ET_MOUSE_PRESSED:
484 case ui::ET_MOUSE_RELEASED:
485 case ui::ET_MOUSE_ENTERED:
486 case ui::ET_MOUSE_EXITED: {
487 if (type == ui::ET_MOUSE_MOVED || type == ui::ET_MOUSE_DRAGGED) {
488 // If this is a motion event, we want to coalesce all pending motion
489 // events that are at the top of the queue.
490 num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event);
491 if (num_coalesced > 0)
492 xev = &last_event;
493 } else if (type == ui::ET_MOUSE_PRESSED) {
494 XIDeviceEvent* xievent =
495 static_cast<XIDeviceEvent*>(xev->xcookie.data);
496 int button = xievent->detail;
497 if (button == kBackMouseButton || button == kForwardMouseButton) {
498 client::UserActionClient* gesture_client =
499 client::GetUserActionClient(delegate_->AsRootWindow());
500 if (gesture_client) {
501 bool reverse_direction =
502 ui::IsTouchpadEvent(xev) && ui::IsNaturalScrollEnabled();
503 gesture_client->OnUserAction(
504 (button == kBackMouseButton && !reverse_direction) ||
505 (button == kForwardMouseButton && reverse_direction) ?
506 client::UserActionClient::BACK :
507 client::UserActionClient::FORWARD);
508 }
509 break;
510 }
511 }
512 ui::MouseEvent mouseev(xev);
513 TranslateAndDispatchMouseEvent(&mouseev);
514 break;
515 }
516 case ui::ET_MOUSEWHEEL: {
517 ui::MouseWheelEvent mouseev(xev);
518 TranslateAndDispatchMouseEvent(&mouseev);
519 break;
520 }
521 case ui::ET_SCROLL_FLING_START:
522 case ui::ET_SCROLL_FLING_CANCEL:
523 case ui::ET_SCROLL: {
524 ui::ScrollEvent scrollev(xev);
525 delegate_->OnHostScrollEvent(&scrollev);
526 break;
527 }
528 case ui::ET_UNKNOWN:
529 break;
530 default:
531 NOTREACHED();
532 }
533
534 // If we coalesced an event we need to free its cookie.
535 if (num_coalesced > 0)
536 XFreeEventData(xev->xgeneric.display, &last_event.xcookie);
537 }
538
539 void RootWindowHostLinux::SetDelegate(RootWindowHostDelegate* delegate) { 426 void RootWindowHostLinux::SetDelegate(RootWindowHostDelegate* delegate) {
540 delegate_ = delegate; 427 delegate_ = delegate;
541 } 428 }
542 429
543 RootWindow* RootWindowHostLinux::GetRootWindow() { 430 RootWindow* RootWindowHostLinux::GetRootWindow() {
544 return delegate_->AsRootWindow(); 431 return delegate_->AsRootWindow();
545 } 432 }
546 433
547 gfx::AcceleratedWidget RootWindowHostLinux::GetAcceleratedWidget() { 434 gfx::AcceleratedWidget RootWindowHostLinux::GetAcceleratedWidget() {
548 return xwindow_; 435 return xwindow_;
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 static const char* k_NET_WM_USER_TIME = "_NET_WM_USER_TIME"; 608 static const char* k_NET_WM_USER_TIME = "_NET_WM_USER_TIME";
722 focus_when_shown_ = focus_when_shown; 609 focus_when_shown_ = focus_when_shown;
723 if (IsWindowManagerPresent() && !focus_when_shown_) { 610 if (IsWindowManagerPresent() && !focus_when_shown_) {
724 ui::SetIntProperty(xwindow_, 611 ui::SetIntProperty(xwindow_,
725 k_NET_WM_USER_TIME, 612 k_NET_WM_USER_TIME,
726 k_NET_WM_USER_TIME, 613 k_NET_WM_USER_TIME,
727 0); 614 0);
728 } 615 }
729 } 616 }
730 617
618 bool RootWindowHostLinux::CopyAreaToSkCanvas(const gfx::Rect& source_bounds,
619 const gfx::Point& dest_offset,
620 SkCanvas* canvas) {
621 scoped_ptr<ui::XScopedImage> scoped_image(GetXImage(source_bounds));
622 if (!scoped_image.get())
623 return false;
624
625 XImage* image = scoped_image->get();
626 DCHECK(image);
627
628 if (image->bits_per_pixel == 32) {
629 // Set the alpha channel before copying to the canvas. Otherwise, areas of
630 // the framebuffer that were cleared by ply-image rather than being obscured
631 // by an image during boot may end up transparent.
632 // TODO(derat|marcheu): Remove this if/when ply-image has been updated to
633 // set the framebuffer's alpha channel regardless of whether the device
634 // claims to support alpha or not.
635 for (int i = 0; i < image->width * image->height * 4; i += 4)
636 image->data[i + 3] = 0xff;
637
638 SkBitmap bitmap;
639 bitmap.setConfig(SkBitmap::kARGB_8888_Config,
640 image->width, image->height,
641 image->bytes_per_line);
642 bitmap.setPixels(image->data);
643 SkCanvas::Config8888 config =
644 (image->byte_order == LSBFirst) ?
645 SkCanvas::kBGRA_Unpremul_Config8888 :
646 SkCanvas::kRGBA_Unpremul_Config8888;
647 canvas->writePixels(bitmap, dest_offset.x(), dest_offset.y(), config);
648 } else if (image->bits_per_pixel == 24) {
649 NOTIMPLEMENTED() << "Unsupported bits-per-pixel " << image->bits_per_pixel;
650 return false;
651 }
652
653 return true;
654 }
655
731 bool RootWindowHostLinux::GrabSnapshot( 656 bool RootWindowHostLinux::GrabSnapshot(
732 const gfx::Rect& snapshot_bounds, 657 const gfx::Rect& snapshot_bounds,
733 std::vector<unsigned char>* png_representation) { 658 std::vector<unsigned char>* png_representation) {
734 ui::XScopedImage image(XGetImage( 659 scoped_ptr<ui::XScopedImage> scoped_image(GetXImage(snapshot_bounds));
735 xdisplay_, xwindow_, 660 if (!scoped_image.get())
736 snapshot_bounds.x(), snapshot_bounds.y(), 661 return false;
737 snapshot_bounds.width(), snapshot_bounds.height(),
738 AllPlanes, ZPixmap));
739 662
740 if (!image.get()) { 663 XImage* image = scoped_image->get();
741 LOG(ERROR) << "XGetImage failed"; 664 DCHECK(image);
742 return false;
743 }
744 665
745 gfx::PNGCodec::ColorFormat color_format; 666 gfx::PNGCodec::ColorFormat color_format;
746 667
747 if (image->bits_per_pixel == 32) { 668 if (image->bits_per_pixel == 32) {
748 color_format = (image->byte_order == LSBFirst) ? 669 color_format = (image->byte_order == LSBFirst) ?
749 gfx::PNGCodec::FORMAT_BGRA : gfx::PNGCodec::FORMAT_RGBA; 670 gfx::PNGCodec::FORMAT_BGRA : gfx::PNGCodec::FORMAT_RGBA;
750 } else if (image->bits_per_pixel == 24) { 671 } else if (image->bits_per_pixel == 24) {
751 // PNGCodec accepts FORMAT_RGB for 3 bytes per pixel: 672 // PNGCodec accepts FORMAT_RGB for 3 bytes per pixel:
752 color_format = gfx::PNGCodec::FORMAT_RGB; 673 color_format = gfx::PNGCodec::FORMAT_RGB;
753 if (image->byte_order == LSBFirst) { 674 if (image->byte_order == LSBFirst) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
807 } 728 }
808 729
809 void RootWindowHostLinux::OnDeviceScaleFactorChanged( 730 void RootWindowHostLinux::OnDeviceScaleFactorChanged(
810 float device_scale_factor) { 731 float device_scale_factor) {
811 } 732 }
812 733
813 void RootWindowHostLinux::PrepareForShutdown() { 734 void RootWindowHostLinux::PrepareForShutdown() {
814 base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_); 735 base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_);
815 } 736 }
816 737
738 bool RootWindowHostLinux::DispatchEventForRootWindow(
739 const base::NativeEvent& event) {
740 switch (event->type) {
741 case ConfigureNotify:
742 DCHECK_EQ(x_root_window_, event->xconfigure.event);
743 x_root_bounds_.SetRect(event->xconfigure.x, event->xconfigure.y,
744 event->xconfigure.width, event->xconfigure.height);
745 break;
746
747 case GenericEvent:
748 DispatchXI2Event(event);
749 break;
750 }
751
752 return true;
753 }
754
755 void RootWindowHostLinux::DispatchXI2Event(const base::NativeEvent& event) {
756 ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
757 XEvent* xev = event;
758 if (!factory->ShouldProcessXI2Event(xev))
759 return;
760
761 ui::EventType type = ui::EventTypeFromNative(xev);
762 XEvent last_event;
763 int num_coalesced = 0;
764
765 switch (type) {
766 case ui::ET_TOUCH_MOVED:
767 num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event);
768 if (num_coalesced > 0)
769 xev = &last_event;
770 // fallthrough
771 case ui::ET_TOUCH_PRESSED:
772 case ui::ET_TOUCH_RELEASED: {
773 ui::TouchEvent touchev(xev);
774 #if defined(OS_CHROMEOS)
775 // X maps the touch-surface to the size of the X root-window. In
776 // multi-monitor setup, the X root-window size is a combination of
777 // both the monitor sizes. So it is necessary to remap the location of
778 // the event from the X root-window to the X host-window for the aura
779 // root-window.
780 if (base::chromeos::IsRunningOnChromeOS()) {
781 touchev.CalibrateLocation(x_root_bounds_.size(), bounds_.size());
782 if (!bounds_.Contains(touchev.location())) {
783 // This might still be in the bezel region.
784 gfx::Rect expanded(bounds_);
785 expanded.Inset(-kXRootWindowPaddingLeft,
786 -kXRootWindowPaddingTop,
787 -kXRootWindowPaddingRight,
788 -kXRootWindowPaddingBottom);
789 if (!expanded.Contains(touchev.location()))
790 break;
791 }
792 }
793 #endif // defined(OS_CHROMEOS)
794 delegate_->OnHostTouchEvent(&touchev);
795 break;
796 }
797 case ui::ET_MOUSE_MOVED:
798 case ui::ET_MOUSE_DRAGGED:
799 case ui::ET_MOUSE_PRESSED:
800 case ui::ET_MOUSE_RELEASED:
801 case ui::ET_MOUSE_ENTERED:
802 case ui::ET_MOUSE_EXITED: {
803 if (type == ui::ET_MOUSE_MOVED || type == ui::ET_MOUSE_DRAGGED) {
804 // If this is a motion event, we want to coalesce all pending motion
805 // events that are at the top of the queue.
806 num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event);
807 if (num_coalesced > 0)
808 xev = &last_event;
809 } else if (type == ui::ET_MOUSE_PRESSED) {
810 XIDeviceEvent* xievent =
811 static_cast<XIDeviceEvent*>(xev->xcookie.data);
812 int button = xievent->detail;
813 if (button == kBackMouseButton || button == kForwardMouseButton) {
814 client::UserActionClient* gesture_client =
815 client::GetUserActionClient(delegate_->AsRootWindow());
816 if (gesture_client) {
817 bool reverse_direction =
818 ui::IsTouchpadEvent(xev) && ui::IsNaturalScrollEnabled();
819 gesture_client->OnUserAction(
820 (button == kBackMouseButton && !reverse_direction) ||
821 (button == kForwardMouseButton && reverse_direction) ?
822 client::UserActionClient::BACK :
823 client::UserActionClient::FORWARD);
824 }
825 break;
826 }
827 }
828 ui::MouseEvent mouseev(xev);
829 TranslateAndDispatchMouseEvent(&mouseev);
830 break;
831 }
832 case ui::ET_MOUSEWHEEL: {
833 ui::MouseWheelEvent mouseev(xev);
834 TranslateAndDispatchMouseEvent(&mouseev);
835 break;
836 }
837 case ui::ET_SCROLL_FLING_START:
838 case ui::ET_SCROLL_FLING_CANCEL:
839 case ui::ET_SCROLL: {
840 ui::ScrollEvent scrollev(xev);
841 delegate_->OnHostScrollEvent(&scrollev);
842 break;
843 }
844 case ui::ET_UNKNOWN:
845 break;
846 default:
847 NOTREACHED();
848 }
849
850 // If we coalesced an event we need to free its cookie.
851 if (num_coalesced > 0)
852 XFreeEventData(xev->xgeneric.display, &last_event.xcookie);
853 }
854
817 bool RootWindowHostLinux::IsWindowManagerPresent() { 855 bool RootWindowHostLinux::IsWindowManagerPresent() {
818 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership 856 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership
819 // of WM_Sn selections (where n is a screen number). 857 // of WM_Sn selections (where n is a screen number).
820 return XGetSelectionOwner( 858 return XGetSelectionOwner(
821 xdisplay_, atom_cache_.GetAtom("WM_S0")) != None; 859 xdisplay_, atom_cache_.GetAtom("WM_S0")) != None;
822 } 860 }
823 861
824 void RootWindowHostLinux::SetCursorInternal(gfx::NativeCursor cursor) { 862 void RootWindowHostLinux::SetCursorInternal(gfx::NativeCursor cursor) {
825 XDefineCursor(xdisplay_, xwindow_, cursor.platform()); 863 XDefineCursor(xdisplay_, xwindow_, cursor.platform());
826 } 864 }
827 865
828 void RootWindowHostLinux::TranslateAndDispatchMouseEvent( 866 void RootWindowHostLinux::TranslateAndDispatchMouseEvent(
829 ui::MouseEvent* event) { 867 ui::MouseEvent* event) {
830 RootWindow* root = GetRootWindow(); 868 RootWindow* root = GetRootWindow();
831 client::ScreenPositionClient* screen_position_client = 869 client::ScreenPositionClient* screen_position_client =
832 GetScreenPositionClient(root); 870 GetScreenPositionClient(root);
833 if (screen_position_client && !bounds_.Contains(event->location())) { 871 if (screen_position_client && !bounds_.Contains(event->location())) {
834 gfx::Point location(event->location()); 872 gfx::Point location(event->location());
835 screen_position_client->ConvertNativePointToScreen(root, &location); 873 screen_position_client->ConvertNativePointToScreen(root, &location);
836 screen_position_client->ConvertPointFromScreen(root, &location); 874 screen_position_client->ConvertPointFromScreen(root, &location);
837 // |delegate_|'s OnHoustMouseEvent expects native coordinates relative to 875 // |delegate_|'s OnHoustMouseEvent expects native coordinates relative to
838 // root. 876 // root.
839 location = ui::ConvertPointToPixel(root->layer(), location); 877 location = ui::ConvertPointToPixel(root->layer(), location);
840 event->set_location(location); 878 event->set_location(location);
841 event->set_root_location(location); 879 event->set_root_location(location);
842 } 880 }
843 delegate_->OnHostMouseEvent(event); 881 delegate_->OnHostMouseEvent(event);
844 } 882 }
845 883
884 scoped_ptr<ui::XScopedImage> RootWindowHostLinux::GetXImage(
885 const gfx::Rect& snapshot_bounds) {
886 scoped_ptr<ui::XScopedImage> image(new ui::XScopedImage(
887 XGetImage(xdisplay_, xwindow_,
888 snapshot_bounds.x(), snapshot_bounds.y(),
889 snapshot_bounds.width(), snapshot_bounds.height(),
890 AllPlanes, ZPixmap)));
891 if (!image->get()) {
892 LOG(ERROR) << "XGetImage failed";
893 image.reset();
894 }
895 return image.Pass();
896 }
897
846 // static 898 // static
847 RootWindowHost* RootWindowHost::Create(const gfx::Rect& bounds) { 899 RootWindowHost* RootWindowHost::Create(const gfx::Rect& bounds) {
848 return new RootWindowHostLinux(bounds); 900 return new RootWindowHostLinux(bounds);
849 } 901 }
850 902
851 // static 903 // static
852 gfx::Size RootWindowHost::GetNativeScreenSize() { 904 gfx::Size RootWindowHost::GetNativeScreenSize() {
853 ::Display* xdisplay = base::MessagePumpAuraX11::GetDefaultXDisplay(); 905 ::Display* xdisplay = base::MessagePumpAuraX11::GetDefaultXDisplay();
854 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); 906 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0));
855 } 907 }
856 908
857 } // namespace aura 909 } // namespace aura
OLDNEW
« no previous file with comments | « ui/aura/root_window_host_linux.h ('k') | ui/aura/root_window_host_mac.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698