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

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: update window id 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 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 } 429 }
426 430
427 ui::MouseEvent mouseev(xev); 431 ui::MouseEvent mouseev(xev);
428 TranslateAndDispatchMouseEvent(&mouseev); 432 TranslateAndDispatchMouseEvent(&mouseev);
429 break; 433 break;
430 } 434 }
431 } 435 }
432 return true; 436 return true;
433 } 437 }
434 438
435 bool RootWindowHostLinux::DispatchEventForRootWindow(
436 const base::NativeEvent& event) {
437 switch (event->type) {
438 case ConfigureNotify:
439 DCHECK_EQ(x_root_window_, event->xconfigure.event);
440 x_root_bounds_.SetRect(event->xconfigure.x, event->xconfigure.y,
441 event->xconfigure.width, event->xconfigure.height);
442 break;
443
444 case GenericEvent:
445 DispatchXI2Event(event);
446 break;
447 }
448
449 return true;
450 }
451
452 void RootWindowHostLinux::DispatchXI2Event(const base::NativeEvent& event) {
453 ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
454 XEvent* xev = event;
455 if (!factory->ShouldProcessXI2Event(xev))
456 return;
457
458 ui::EventType type = ui::EventTypeFromNative(xev);
459 XEvent last_event;
460 int num_coalesced = 0;
461
462 switch (type) {
463 case ui::ET_TOUCH_MOVED:
464 num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event);
465 if (num_coalesced > 0)
466 xev = &last_event;
467 // fallthrough
468 case ui::ET_TOUCH_PRESSED:
469 case ui::ET_TOUCH_RELEASED: {
470 ui::TouchEvent touchev(xev);
471 #if defined(OS_CHROMEOS)
472 // X maps the touch-surface to the size of the X root-window. In
473 // multi-monitor setup, the X root-window size is a combination of
474 // both the monitor sizes. So it is necessary to remap the location of
475 // the event from the X root-window to the X host-window for the aura
476 // root-window.
477 if (base::chromeos::IsRunningOnChromeOS()) {
478 touchev.CalibrateLocation(x_root_bounds_.size(), bounds_.size());
479 if (!bounds_.Contains(touchev.location())) {
480 // This might still be in the bezel region.
481 gfx::Rect expanded(bounds_);
482 expanded.Inset(-kXRootWindowPaddingLeft,
483 -kXRootWindowPaddingTop,
484 -kXRootWindowPaddingRight,
485 -kXRootWindowPaddingBottom);
486 if (!expanded.Contains(touchev.location()))
487 break;
488 }
489 }
490 #endif // defined(OS_CHROMEOS)
491 delegate_->OnHostTouchEvent(&touchev);
492 break;
493 }
494 case ui::ET_MOUSE_MOVED:
495 case ui::ET_MOUSE_DRAGGED:
496 case ui::ET_MOUSE_PRESSED:
497 case ui::ET_MOUSE_RELEASED:
498 case ui::ET_MOUSE_ENTERED:
499 case ui::ET_MOUSE_EXITED: {
500 if (type == ui::ET_MOUSE_MOVED || type == ui::ET_MOUSE_DRAGGED) {
501 // If this is a motion event, we want to coalesce all pending motion
502 // events that are at the top of the queue.
503 num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event);
504 if (num_coalesced > 0)
505 xev = &last_event;
506 } else if (type == ui::ET_MOUSE_PRESSED) {
507 XIDeviceEvent* xievent =
508 static_cast<XIDeviceEvent*>(xev->xcookie.data);
509 int button = xievent->detail;
510 if (button == kBackMouseButton || button == kForwardMouseButton) {
511 client::UserActionClient* gesture_client =
512 client::GetUserActionClient(delegate_->AsRootWindow());
513 if (gesture_client) {
514 bool reverse_direction =
515 ui::IsTouchpadEvent(xev) && ui::IsNaturalScrollEnabled();
516 gesture_client->OnUserAction(
517 (button == kBackMouseButton && !reverse_direction) ||
518 (button == kForwardMouseButton && reverse_direction) ?
519 client::UserActionClient::BACK :
520 client::UserActionClient::FORWARD);
521 }
522 break;
523 }
524 }
525 ui::MouseEvent mouseev(xev);
526 TranslateAndDispatchMouseEvent(&mouseev);
527 break;
528 }
529 case ui::ET_MOUSEWHEEL: {
530 ui::MouseWheelEvent mouseev(xev);
531 TranslateAndDispatchMouseEvent(&mouseev);
532 break;
533 }
534 case ui::ET_SCROLL_FLING_START:
535 case ui::ET_SCROLL_FLING_CANCEL:
536 case ui::ET_SCROLL: {
537 ui::ScrollEvent scrollev(xev);
538 delegate_->OnHostScrollEvent(&scrollev);
539 break;
540 }
541 case ui::ET_UNKNOWN:
542 break;
543 default:
544 NOTREACHED();
545 }
546
547 // If we coalesced an event we need to free its cookie.
548 if (num_coalesced > 0)
549 XFreeEventData(xev->xgeneric.display, &last_event.xcookie);
550 }
551
552 void RootWindowHostLinux::SetDelegate(RootWindowHostDelegate* delegate) { 439 void RootWindowHostLinux::SetDelegate(RootWindowHostDelegate* delegate) {
553 delegate_ = delegate; 440 delegate_ = delegate;
554 } 441 }
555 442
556 RootWindow* RootWindowHostLinux::GetRootWindow() { 443 RootWindow* RootWindowHostLinux::GetRootWindow() {
557 return delegate_->AsRootWindow(); 444 return delegate_->AsRootWindow();
558 } 445 }
559 446
560 gfx::AcceleratedWidget RootWindowHostLinux::GetAcceleratedWidget() { 447 gfx::AcceleratedWidget RootWindowHostLinux::GetAcceleratedWidget() {
561 return xwindow_; 448 return xwindow_;
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
734 static const char* k_NET_WM_USER_TIME = "_NET_WM_USER_TIME"; 621 static const char* k_NET_WM_USER_TIME = "_NET_WM_USER_TIME";
735 focus_when_shown_ = focus_when_shown; 622 focus_when_shown_ = focus_when_shown;
736 if (IsWindowManagerPresent() && !focus_when_shown_) { 623 if (IsWindowManagerPresent() && !focus_when_shown_) {
737 ui::SetIntProperty(xwindow_, 624 ui::SetIntProperty(xwindow_,
738 k_NET_WM_USER_TIME, 625 k_NET_WM_USER_TIME,
739 k_NET_WM_USER_TIME, 626 k_NET_WM_USER_TIME,
740 0); 627 0);
741 } 628 }
742 } 629 }
743 630
631 bool RootWindowHostLinux::CopyAreaToSkCanvas(const gfx::Rect& source_bounds,
632 const gfx::Point& dest_offset,
633 SkCanvas* canvas) {
634 scoped_ptr<ui::XScopedImage> scoped_image(GetXImage(source_bounds));
635 if (!scoped_image.get())
636 return false;
637
638 XImage* image = scoped_image->get();
639 DCHECK(image);
640
641 if (image->bits_per_pixel == 32) {
642 // Set the alpha channel before copying to the canvas. Otherwise, areas of
643 // the framebuffer that were cleared by ply-image rather than being obscured
644 // by an image during boot may end up transparent.
645 // TODO(derat|marcheu): Remove this if/when ply-image has been updated to
646 // set the framebuffer's alpha channel regardless of whether the device
647 // claims to support alpha or not.
648 for (int i = 0; i < image->width * image->height * 4; i += 4)
649 image->data[i + 3] = 0xff;
650
651 SkBitmap bitmap;
652 bitmap.setConfig(SkBitmap::kARGB_8888_Config,
653 image->width, image->height,
654 image->bytes_per_line);
655 bitmap.setPixels(image->data);
656 SkCanvas::Config8888 config =
657 (image->byte_order == LSBFirst) ?
658 SkCanvas::kBGRA_Unpremul_Config8888 :
659 SkCanvas::kRGBA_Unpremul_Config8888;
660 canvas->writePixels(bitmap, dest_offset.x(), dest_offset.y(), config);
661 } else if (image->bits_per_pixel == 24) {
662 NOTIMPLEMENTED() << "Unsupported bits-per-pixel " << image->bits_per_pixel;
663 return false;
664 }
665
666 return true;
667 }
668
744 bool RootWindowHostLinux::GrabSnapshot( 669 bool RootWindowHostLinux::GrabSnapshot(
745 const gfx::Rect& snapshot_bounds, 670 const gfx::Rect& snapshot_bounds,
746 std::vector<unsigned char>* png_representation) { 671 std::vector<unsigned char>* png_representation) {
747 ui::XScopedImage image(XGetImage( 672 scoped_ptr<ui::XScopedImage> scoped_image(GetXImage(snapshot_bounds));
748 xdisplay_, xwindow_, 673 if (!scoped_image.get())
749 snapshot_bounds.x(), snapshot_bounds.y(), 674 return false;
750 snapshot_bounds.width(), snapshot_bounds.height(),
751 AllPlanes, ZPixmap));
752 675
753 if (!image.get()) { 676 XImage* image = scoped_image->get();
754 LOG(ERROR) << "XGetImage failed"; 677 DCHECK(image);
755 return false;
756 }
757 678
758 gfx::PNGCodec::ColorFormat color_format; 679 gfx::PNGCodec::ColorFormat color_format;
759 680
760 if (image->bits_per_pixel == 32) { 681 if (image->bits_per_pixel == 32) {
761 color_format = (image->byte_order == LSBFirst) ? 682 color_format = (image->byte_order == LSBFirst) ?
762 gfx::PNGCodec::FORMAT_BGRA : gfx::PNGCodec::FORMAT_RGBA; 683 gfx::PNGCodec::FORMAT_BGRA : gfx::PNGCodec::FORMAT_RGBA;
763 } else if (image->bits_per_pixel == 24) { 684 } else if (image->bits_per_pixel == 24) {
764 // PNGCodec accepts FORMAT_RGB for 3 bytes per pixel: 685 // PNGCodec accepts FORMAT_RGB for 3 bytes per pixel:
765 color_format = gfx::PNGCodec::FORMAT_RGB; 686 color_format = gfx::PNGCodec::FORMAT_RGB;
766 if (image->byte_order == LSBFirst) { 687 if (image->byte_order == LSBFirst) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
820 } 741 }
821 742
822 void RootWindowHostLinux::OnDeviceScaleFactorChanged( 743 void RootWindowHostLinux::OnDeviceScaleFactorChanged(
823 float device_scale_factor) { 744 float device_scale_factor) {
824 } 745 }
825 746
826 void RootWindowHostLinux::PrepareForShutdown() { 747 void RootWindowHostLinux::PrepareForShutdown() {
827 base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_); 748 base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_);
828 } 749 }
829 750
751 bool RootWindowHostLinux::DispatchEventForRootWindow(
Daniel Erat 2012/10/26 00:41:15 sorry, moved this code without any changes to it t
752 const base::NativeEvent& event) {
753 switch (event->type) {
754 case ConfigureNotify:
755 DCHECK_EQ(x_root_window_, event->xconfigure.event);
756 x_root_bounds_.SetRect(event->xconfigure.x, event->xconfigure.y,
757 event->xconfigure.width, event->xconfigure.height);
758 break;
759
760 case GenericEvent:
761 DispatchXI2Event(event);
762 break;
763 }
764
765 return true;
766 }
767
768 void RootWindowHostLinux::DispatchXI2Event(const base::NativeEvent& event) {
769 ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
770 XEvent* xev = event;
771 if (!factory->ShouldProcessXI2Event(xev))
772 return;
773
774 ui::EventType type = ui::EventTypeFromNative(xev);
775 XEvent last_event;
776 int num_coalesced = 0;
777
778 switch (type) {
779 case ui::ET_TOUCH_MOVED:
780 num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event);
781 if (num_coalesced > 0)
782 xev = &last_event;
783 // fallthrough
784 case ui::ET_TOUCH_PRESSED:
785 case ui::ET_TOUCH_RELEASED: {
786 ui::TouchEvent touchev(xev);
787 #if defined(OS_CHROMEOS)
788 // X maps the touch-surface to the size of the X root-window. In
789 // multi-monitor setup, the X root-window size is a combination of
790 // both the monitor sizes. So it is necessary to remap the location of
791 // the event from the X root-window to the X host-window for the aura
792 // root-window.
793 if (base::chromeos::IsRunningOnChromeOS()) {
794 touchev.CalibrateLocation(x_root_bounds_.size(), bounds_.size());
795 if (!bounds_.Contains(touchev.location())) {
796 // This might still be in the bezel region.
797 gfx::Rect expanded(bounds_);
798 expanded.Inset(-kXRootWindowPaddingLeft,
799 -kXRootWindowPaddingTop,
800 -kXRootWindowPaddingRight,
801 -kXRootWindowPaddingBottom);
802 if (!expanded.Contains(touchev.location()))
803 break;
804 }
805 }
806 #endif // defined(OS_CHROMEOS)
807 delegate_->OnHostTouchEvent(&touchev);
808 break;
809 }
810 case ui::ET_MOUSE_MOVED:
811 case ui::ET_MOUSE_DRAGGED:
812 case ui::ET_MOUSE_PRESSED:
813 case ui::ET_MOUSE_RELEASED:
814 case ui::ET_MOUSE_ENTERED:
815 case ui::ET_MOUSE_EXITED: {
816 if (type == ui::ET_MOUSE_MOVED || type == ui::ET_MOUSE_DRAGGED) {
817 // If this is a motion event, we want to coalesce all pending motion
818 // events that are at the top of the queue.
819 num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event);
820 if (num_coalesced > 0)
821 xev = &last_event;
822 } else if (type == ui::ET_MOUSE_PRESSED) {
823 XIDeviceEvent* xievent =
824 static_cast<XIDeviceEvent*>(xev->xcookie.data);
825 int button = xievent->detail;
826 if (button == kBackMouseButton || button == kForwardMouseButton) {
827 client::UserActionClient* gesture_client =
828 client::GetUserActionClient(delegate_->AsRootWindow());
829 if (gesture_client) {
830 bool reverse_direction =
831 ui::IsTouchpadEvent(xev) && ui::IsNaturalScrollEnabled();
832 gesture_client->OnUserAction(
833 (button == kBackMouseButton && !reverse_direction) ||
834 (button == kForwardMouseButton && reverse_direction) ?
835 client::UserActionClient::BACK :
836 client::UserActionClient::FORWARD);
837 }
838 break;
839 }
840 }
841 ui::MouseEvent mouseev(xev);
842 TranslateAndDispatchMouseEvent(&mouseev);
843 break;
844 }
845 case ui::ET_MOUSEWHEEL: {
846 ui::MouseWheelEvent mouseev(xev);
847 TranslateAndDispatchMouseEvent(&mouseev);
848 break;
849 }
850 case ui::ET_SCROLL_FLING_START:
851 case ui::ET_SCROLL_FLING_CANCEL:
852 case ui::ET_SCROLL: {
853 ui::ScrollEvent scrollev(xev);
854 delegate_->OnHostScrollEvent(&scrollev);
855 break;
856 }
857 case ui::ET_UNKNOWN:
858 break;
859 default:
860 NOTREACHED();
861 }
862
863 // If we coalesced an event we need to free its cookie.
864 if (num_coalesced > 0)
865 XFreeEventData(xev->xgeneric.display, &last_event.xcookie);
866 }
867
830 bool RootWindowHostLinux::IsWindowManagerPresent() { 868 bool RootWindowHostLinux::IsWindowManagerPresent() {
831 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership 869 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership
832 // of WM_Sn selections (where n is a screen number). 870 // of WM_Sn selections (where n is a screen number).
833 return XGetSelectionOwner( 871 return XGetSelectionOwner(
834 xdisplay_, atom_cache_.GetAtom("WM_S0")) != None; 872 xdisplay_, atom_cache_.GetAtom("WM_S0")) != None;
835 } 873 }
836 874
837 void RootWindowHostLinux::SetCursorInternal(gfx::NativeCursor cursor) { 875 void RootWindowHostLinux::SetCursorInternal(gfx::NativeCursor cursor) {
838 XDefineCursor(xdisplay_, xwindow_, cursor.platform()); 876 XDefineCursor(xdisplay_, xwindow_, cursor.platform());
839 } 877 }
840 878
841 void RootWindowHostLinux::TranslateAndDispatchMouseEvent( 879 void RootWindowHostLinux::TranslateAndDispatchMouseEvent(
842 ui::MouseEvent* event) { 880 ui::MouseEvent* event) {
843 RootWindow* root = GetRootWindow(); 881 RootWindow* root = GetRootWindow();
844 client::ScreenPositionClient* screen_position_client = 882 client::ScreenPositionClient* screen_position_client =
845 GetScreenPositionClient(root); 883 GetScreenPositionClient(root);
846 if (screen_position_client && !bounds_.Contains(event->location())) { 884 if (screen_position_client && !bounds_.Contains(event->location())) {
847 gfx::Point location(event->location()); 885 gfx::Point location(event->location());
848 screen_position_client->ConvertNativePointToScreen(root, &location); 886 screen_position_client->ConvertNativePointToScreen(root, &location);
849 screen_position_client->ConvertPointFromScreen(root, &location); 887 screen_position_client->ConvertPointFromScreen(root, &location);
850 // |delegate_|'s OnHoustMouseEvent expects native coordinates relative to 888 // |delegate_|'s OnHoustMouseEvent expects native coordinates relative to
851 // root. 889 // root.
852 location = ui::ConvertPointToPixel(root->layer(), location); 890 location = ui::ConvertPointToPixel(root->layer(), location);
853 event->set_location(location); 891 event->set_location(location);
854 event->set_root_location(location); 892 event->set_root_location(location);
855 } 893 }
856 delegate_->OnHostMouseEvent(event); 894 delegate_->OnHostMouseEvent(event);
857 } 895 }
858 896
897 scoped_ptr<ui::XScopedImage> RootWindowHostLinux::GetXImage(
898 const gfx::Rect& snapshot_bounds) {
899 scoped_ptr<ui::XScopedImage> image(new ui::XScopedImage(
900 XGetImage(xdisplay_, xwindow_,
901 snapshot_bounds.x(), snapshot_bounds.y(),
902 snapshot_bounds.width(), snapshot_bounds.height(),
903 AllPlanes, ZPixmap)));
904 if (!image->get()) {
905 LOG(ERROR) << "XGetImage failed";
906 image.reset();
907 }
908 return image.Pass();
909 }
910
859 // static 911 // static
860 RootWindowHost* RootWindowHost::Create(const gfx::Rect& bounds) { 912 RootWindowHost* RootWindowHost::Create(const gfx::Rect& bounds) {
861 return new RootWindowHostLinux(bounds); 913 return new RootWindowHostLinux(bounds);
862 } 914 }
863 915
864 // static 916 // static
865 gfx::Size RootWindowHost::GetNativeScreenSize() { 917 gfx::Size RootWindowHost::GetNativeScreenSize() {
866 ::Display* xdisplay = base::MessagePumpAuraX11::GetDefaultXDisplay(); 918 ::Display* xdisplay = base::MessagePumpAuraX11::GetDefaultXDisplay();
867 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); 919 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0));
868 } 920 }
869 921
870 } // namespace aura 922 } // 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