OLD | NEW |
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 <X11/Xatom.h> | 7 #include <X11/Xatom.h> |
8 #include <X11/Xcursor/Xcursor.h> | 8 #include <X11/Xcursor/Xcursor.h> |
9 #include <X11/Xlib.h> | 9 #include <X11/Xlib.h> |
10 #include <X11/cursorfont.h> | 10 #include <X11/cursorfont.h> |
11 #include <X11/extensions/XInput2.h> | 11 #include <X11/extensions/XInput2.h> |
| 12 #include <X11/extensions/Xcomposite.h> |
12 #include <X11/extensions/Xfixes.h> | 13 #include <X11/extensions/Xfixes.h> |
13 #include <X11/extensions/Xrandr.h> | 14 #include <X11/extensions/Xrandr.h> |
| 15 #include <X11/extensions/shape.h> |
14 #include <algorithm> | 16 #include <algorithm> |
15 | 17 |
16 #include "base/command_line.h" | 18 #include "base/command_line.h" |
17 #include "base/message_pump_aurax11.h" | 19 #include "base/message_pump_aurax11.h" |
18 #include "base/stl_util.h" | 20 #include "base/stl_util.h" |
19 #include "base/stringprintf.h" | 21 #include "base/stringprintf.h" |
20 #include "grit/ui_resources.h" | 22 #include "grit/ui_resources.h" |
| 23 #include "ui/aura/aura_switches.h" |
21 #include "ui/aura/client/capture_client.h" | 24 #include "ui/aura/client/capture_client.h" |
22 #include "ui/aura/client/user_action_client.h" | 25 #include "ui/aura/client/user_action_client.h" |
23 #include "ui/aura/dispatcher_linux.h" | 26 #include "ui/aura/dispatcher_linux.h" |
24 #include "ui/aura/env.h" | 27 #include "ui/aura/env.h" |
25 #include "ui/aura/event.h" | 28 #include "ui/aura/event.h" |
26 #include "ui/aura/root_window.h" | 29 #include "ui/aura/root_window.h" |
27 #include "ui/base/cursor/cursor.h" | 30 #include "ui/base/cursor/cursor.h" |
28 #include "ui/base/keycodes/keyboard_codes.h" | 31 #include "ui/base/keycodes/keyboard_codes.h" |
29 #include "ui/base/resource/resource_bundle.h" | 32 #include "ui/base/resource/resource_bundle.h" |
30 #include "ui/base/touch/touch_factory.h" | 33 #include "ui/base/touch/touch_factory.h" |
(...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 | 472 |
470 float scale_factor_; | 473 float scale_factor_; |
471 | 474 |
472 DISALLOW_COPY_AND_ASSIGN(ImageCursors); | 475 DISALLOW_COPY_AND_ASSIGN(ImageCursors); |
473 }; | 476 }; |
474 | 477 |
475 RootWindowHostLinux::RootWindowHostLinux(const gfx::Rect& bounds) | 478 RootWindowHostLinux::RootWindowHostLinux(const gfx::Rect& bounds) |
476 : root_window_(NULL), | 479 : root_window_(NULL), |
477 xdisplay_(base::MessagePumpAuraX11::GetDefaultXDisplay()), | 480 xdisplay_(base::MessagePumpAuraX11::GetDefaultXDisplay()), |
478 xwindow_(0), | 481 xwindow_(0), |
| 482 x_output_window_(0), |
479 x_root_window_(DefaultRootWindow(xdisplay_)), | 483 x_root_window_(DefaultRootWindow(xdisplay_)), |
480 current_cursor_(ui::kCursorNull), | 484 current_cursor_(ui::kCursorNull), |
481 cursor_shown_(true), | 485 cursor_shown_(true), |
482 bounds_(bounds), | 486 bounds_(bounds), |
483 focus_when_shown_(false), | 487 focus_when_shown_(true), |
484 pointer_barriers_(NULL), | 488 pointer_barriers_(NULL), |
485 image_cursors_(new ImageCursors), | 489 image_cursors_(new ImageCursors), |
486 atom_cache_(xdisplay_, kAtomsToCache) { | 490 atom_cache_(xdisplay_, kAtomsToCache) { |
487 XSetWindowAttributes swa; | 491 XSetWindowAttributes swa; |
488 memset(&swa, 0, sizeof(swa)); | 492 memset(&swa, 0, sizeof(swa)); |
489 swa.background_pixmap = None; | 493 swa.background_pixmap = None; |
490 xwindow_ = XCreateWindow( | 494 long output_event_mask = ExposureMask | VisibilityChangeMask; |
491 xdisplay_, x_root_window_, | 495 long input_event_mask = ButtonPressMask | ButtonReleaseMask | |
492 bounds.x(), bounds.y(), bounds.width(), bounds.height(), | 496 FocusChangeMask | KeyPressMask | KeyReleaseMask | |
493 0, // border width | 497 EnterWindowMask | LeaveWindowMask | |
494 CopyFromParent, // depth | 498 StructureNotifyMask | PropertyChangeMask | |
495 InputOutput, | 499 PointerMotionMask; |
496 CopyFromParent, // visual | 500 if (CommandLine::ForCurrentProcess()->HasSwitch( |
497 CWBackPixmap, | 501 switches::kAuraHostWindowUseFullscreen)) { |
498 &swa); | 502 x_output_window_ = XCompositeGetOverlayWindow(xdisplay_, x_root_window_); |
| 503 XserverRegion region = XFixesCreateRegion(xdisplay_, NULL, 0); |
| 504 XFixesSetWindowShapeRegion( |
| 505 xdisplay_, x_output_window_, ShapeInput, 0, 0, region); |
| 506 XFixesDestroyRegion(xdisplay_, region); |
| 507 XSelectInput(xdisplay_, x_output_window_, output_event_mask); |
| 508 static_cast<DispatcherLinux*>(Env::GetInstance()->GetDispatcher())-> |
| 509 AddDispatcherForWindow(this, x_output_window_); |
| 510 xwindow_ = XCreateWindow( |
| 511 xdisplay_, x_root_window_, |
| 512 bounds.x(), bounds.y(), bounds.width(), bounds.height(), |
| 513 0, // border width |
| 514 CopyFromParent, // depth |
| 515 InputOnly, |
| 516 CopyFromParent, // visual |
| 517 0, |
| 518 0); |
| 519 XSelectInput(xdisplay_, xwindow_, input_event_mask); |
| 520 } else { |
| 521 x_output_window_ = xwindow_ = XCreateWindow( |
| 522 xdisplay_, x_root_window_, |
| 523 bounds.x(), bounds.y(), bounds.width(), bounds.height(), |
| 524 0, // border width |
| 525 CopyFromParent, // depth |
| 526 InputOutput, |
| 527 CopyFromParent, // visual |
| 528 CWBackPixmap, |
| 529 &swa); |
| 530 XSelectInput(xdisplay_, xwindow_, input_event_mask | output_event_mask); |
| 531 } |
499 static_cast<DispatcherLinux*>(Env::GetInstance()->GetDispatcher())-> | 532 static_cast<DispatcherLinux*>(Env::GetInstance()->GetDispatcher())-> |
500 AddDispatcherForWindow(this, xwindow_); | 533 AddDispatcherForWindow(this, xwindow_); |
501 | 534 |
502 prop_.reset(new ui::ViewProp(xwindow_, kRootWindowHostLinuxKey, this)); | 535 prop_.reset(new ui::ViewProp(xwindow_, kRootWindowHostLinuxKey, this)); |
503 | 536 |
504 long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | | |
505 KeyPressMask | KeyReleaseMask | | |
506 EnterWindowMask | LeaveWindowMask | | |
507 ExposureMask | VisibilityChangeMask | | |
508 StructureNotifyMask | PropertyChangeMask | | |
509 PointerMotionMask; | |
510 XSelectInput(xdisplay_, xwindow_, event_mask); | |
511 XFlush(xdisplay_); | 537 XFlush(xdisplay_); |
512 | 538 |
513 if (base::MessagePumpForUI::HasXInput2()) | 539 if (base::MessagePumpForUI::HasXInput2()) |
514 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); | 540 ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); |
515 | 541 |
516 // Initialize invisible cursor. | 542 // Initialize invisible cursor. |
517 char nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | 543 char nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; |
518 XColor black; | 544 XColor black; |
519 black.red = black.green = black.blue = 0; | 545 black.red = black.green = black.blue = 0; |
520 Pixmap blank = XCreateBitmapFromData(xdisplay_, xwindow_, | 546 Pixmap blank = XCreateBitmapFromData(xdisplay_, x_output_window_, |
521 nodata, 8, 8); | 547 nodata, 8, 8); |
522 invisible_cursor_ = XCreatePixmapCursor(xdisplay_, blank, blank, | 548 invisible_cursor_ = XCreatePixmapCursor(xdisplay_, blank, blank, |
523 &black, &black, 0, 0); | 549 &black, &black, 0, 0); |
524 XFreePixmap(xdisplay_, blank); | 550 XFreePixmap(xdisplay_, blank); |
525 | 551 |
526 if (RootWindow::hide_host_cursor()) | 552 if (RootWindow::hide_host_cursor()) |
527 XDefineCursor(xdisplay_, x_root_window_, invisible_cursor_); | 553 XDefineCursor(xdisplay_, x_root_window_, invisible_cursor_); |
528 | 554 |
529 // TODO(erg): We currently only request window deletion events. We also | 555 // TODO(erg): We currently only request window deletion events. We also |
530 // should listen for activation events and anything else that GTK+ listens | 556 // should listen for activation events and anything else that GTK+ listens |
(...skipping 29 matching lines...) Expand all Loading... |
560 } | 586 } |
561 | 587 |
562 RootWindowHostLinux::~RootWindowHostLinux() { | 588 RootWindowHostLinux::~RootWindowHostLinux() { |
563 static_cast<DispatcherLinux*>(Env::GetInstance()->GetDispatcher())-> | 589 static_cast<DispatcherLinux*>(Env::GetInstance()->GetDispatcher())-> |
564 RemoveDispatcherForWindow(xwindow_); | 590 RemoveDispatcherForWindow(xwindow_); |
565 | 591 |
566 UnConfineCursor(); | 592 UnConfineCursor(); |
567 | 593 |
568 XDestroyWindow(xdisplay_, xwindow_); | 594 XDestroyWindow(xdisplay_, xwindow_); |
569 | 595 |
| 596 if (CommandLine::ForCurrentProcess()->HasSwitch( |
| 597 switches::kAuraHostWindowUseFullscreen)) |
| 598 XCompositeReleaseOverlayWindow(xdisplay_, x_root_window_); |
| 599 |
570 // Clears XCursorCache. | 600 // Clears XCursorCache. |
571 ui::GetXCursor(ui::kCursorClearXCursorCache); | 601 ui::GetXCursor(ui::kCursorClearXCursorCache); |
572 | 602 |
573 XFreeCursor(xdisplay_, invisible_cursor_); | 603 XFreeCursor(xdisplay_, invisible_cursor_); |
574 } | 604 } |
575 | 605 |
576 bool RootWindowHostLinux::Dispatch(const base::NativeEvent& event) { | 606 bool RootWindowHostLinux::Dispatch(const base::NativeEvent& event) { |
577 XEvent* xev = event; | 607 XEvent* xev = event; |
578 | 608 |
579 CheckXEventForConsistency(xev); | 609 CheckXEventForConsistency(xev); |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
781 root_window_ = root_window; | 811 root_window_ = root_window; |
782 // The device scale factor is now accessible, so load cursors now. | 812 // The device scale factor is now accessible, so load cursors now. |
783 image_cursors_->Reload(root_window_->layer()->device_scale_factor()); | 813 image_cursors_->Reload(root_window_->layer()->device_scale_factor()); |
784 } | 814 } |
785 | 815 |
786 RootWindow* RootWindowHostLinux::GetRootWindow() { | 816 RootWindow* RootWindowHostLinux::GetRootWindow() { |
787 return root_window_; | 817 return root_window_; |
788 } | 818 } |
789 | 819 |
790 gfx::AcceleratedWidget RootWindowHostLinux::GetAcceleratedWidget() { | 820 gfx::AcceleratedWidget RootWindowHostLinux::GetAcceleratedWidget() { |
| 821 return x_output_window_; |
| 822 } |
| 823 |
| 824 gfx::AcceleratedWidget RootWindowHostLinux:: |
| 825 GetAcceleratedWidgetUsedForEvents() { |
791 return xwindow_; | 826 return xwindow_; |
792 } | 827 } |
793 | 828 |
794 void RootWindowHostLinux::Show() { | 829 void RootWindowHostLinux::Show() { |
795 // Before we map the window, set size hints. Otherwise, some window managers | 830 // Before we map the window, set size hints. Otherwise, some window managers |
796 // will ignore toplevel XMoveWindow commands. | 831 // will ignore toplevel XMoveWindow commands. |
797 XSizeHints size_hints; | 832 XSizeHints size_hints; |
798 size_hints.flags = PPosition; | 833 size_hints.flags = PPosition; |
799 size_hints.x = bounds_.x(); | 834 size_hints.x = bounds_.x(); |
800 size_hints.y = bounds_.y(); | 835 size_hints.y = bounds_.y(); |
(...skipping 17 matching lines...) Expand all Loading... |
818 float new_scale = | 853 float new_scale = |
819 gfx::Screen::GetDisplayNearestWindow(root_window_).device_scale_factor(); | 854 gfx::Screen::GetDisplayNearestWindow(root_window_).device_scale_factor(); |
820 bool size_changed = bounds_.size() != bounds.size() || | 855 bool size_changed = bounds_.size() != bounds.size() || |
821 current_scale != new_scale; | 856 current_scale != new_scale; |
822 | 857 |
823 if (!size_changed) { | 858 if (!size_changed) { |
824 root_window_->SchedulePaintInRect(root_window_->bounds()); | 859 root_window_->SchedulePaintInRect(root_window_->bounds()); |
825 return; | 860 return; |
826 } | 861 } |
827 | 862 |
828 if (bounds.size() != bounds_.size()) | 863 if (bounds.size() != bounds_.size()) { |
829 XResizeWindow(xdisplay_, xwindow_, bounds.width(), bounds.height()); | 864 XResizeWindow(xdisplay_, xwindow_, bounds.width(), bounds.height()); |
| 865 if (x_output_window_ != xwindow_) |
| 866 XResizeWindow( |
| 867 xdisplay_, x_output_window_, bounds.width(), bounds.height()); |
| 868 } |
830 | 869 |
831 if (bounds.origin() != bounds_.origin()) | 870 if (bounds.origin() != bounds_.origin()) { |
832 XMoveWindow(xdisplay_, xwindow_, bounds.x(), bounds.y()); | 871 XMoveWindow(xdisplay_, xwindow_, bounds.x(), bounds.y()); |
| 872 if (x_output_window_ != xwindow_) |
| 873 XMoveWindow(xdisplay_, x_output_window_, bounds.x(), bounds.y()); |
| 874 } |
833 | 875 |
834 // Assume that the resize will go through as requested, which should be the | 876 // Assume that the resize will go through as requested, which should be the |
835 // case if we're running without a window manager. If there's a window | 877 // case if we're running without a window manager. If there's a window |
836 // manager, it can modify or ignore the request, but (per ICCCM) we'll get a | 878 // manager, it can modify or ignore the request, but (per ICCCM) we'll get a |
837 // (possibly synthetic) ConfigureNotify about the actual size and correct | 879 // (possibly synthetic) ConfigureNotify about the actual size and correct |
838 // |bounds_| later. | 880 // |bounds_| later. |
839 bounds_ = bounds; | 881 bounds_ = bounds; |
840 if (size_changed) | 882 if (size_changed) |
841 root_window_->OnHostResized(bounds.size()); | 883 root_window_->OnHostResized(bounds.size()); |
842 } | 884 } |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
946 k_NET_WM_USER_TIME, | 988 k_NET_WM_USER_TIME, |
947 k_NET_WM_USER_TIME, | 989 k_NET_WM_USER_TIME, |
948 0); | 990 0); |
949 } | 991 } |
950 } | 992 } |
951 | 993 |
952 bool RootWindowHostLinux::GrabSnapshot( | 994 bool RootWindowHostLinux::GrabSnapshot( |
953 const gfx::Rect& snapshot_bounds, | 995 const gfx::Rect& snapshot_bounds, |
954 std::vector<unsigned char>* png_representation) { | 996 std::vector<unsigned char>* png_representation) { |
955 XImage* image = XGetImage( | 997 XImage* image = XGetImage( |
956 xdisplay_, xwindow_, | 998 xdisplay_, x_output_window_, |
957 snapshot_bounds.x(), snapshot_bounds.y(), | 999 snapshot_bounds.x(), snapshot_bounds.y(), |
958 snapshot_bounds.width(), snapshot_bounds.height(), | 1000 snapshot_bounds.width(), snapshot_bounds.height(), |
959 AllPlanes, ZPixmap); | 1001 AllPlanes, ZPixmap); |
960 | 1002 |
961 if (!image) { | 1003 if (!image) { |
962 LOG(ERROR) << "XGetImage failed"; | 1004 LOG(ERROR) << "XGetImage failed"; |
963 return false; | 1005 return false; |
964 } | 1006 } |
965 | 1007 |
966 gfx::PNGCodec::ColorFormat color_format; | 1008 gfx::PNGCodec::ColorFormat color_format; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1027 break; | 1069 break; |
1028 } | 1070 } |
1029 XSendEvent(xdisplay_, xwindow_, False, 0, &xevent); | 1071 XSendEvent(xdisplay_, xwindow_, False, 0, &xevent); |
1030 } | 1072 } |
1031 | 1073 |
1032 void RootWindowHostLinux::OnDeviceScaleFactorChanged( | 1074 void RootWindowHostLinux::OnDeviceScaleFactorChanged( |
1033 float device_scale_factor) { | 1075 float device_scale_factor) { |
1034 image_cursors_->Reload(device_scale_factor); | 1076 image_cursors_->Reload(device_scale_factor); |
1035 } | 1077 } |
1036 | 1078 |
| 1079 bool RootWindowHostLinux::DispatchNativeEvent( |
| 1080 const base::NativeEvent& native_event) { |
| 1081 return Dispatch(native_event); |
| 1082 } |
| 1083 |
1037 bool RootWindowHostLinux::IsWindowManagerPresent() { | 1084 bool RootWindowHostLinux::IsWindowManagerPresent() { |
1038 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership | 1085 // Per ICCCM 2.8, "Manager Selections", window managers should take ownership |
1039 // of WM_Sn selections (where n is a screen number). | 1086 // of WM_Sn selections (where n is a screen number). |
1040 return XGetSelectionOwner( | 1087 return XGetSelectionOwner( |
1041 xdisplay_, atom_cache_.GetAtom("WM_S0")) != None; | 1088 xdisplay_, atom_cache_.GetAtom("WM_S0")) != None; |
1042 } | 1089 } |
1043 | 1090 |
1044 void RootWindowHostLinux::SetCursorInternal(gfx::NativeCursor cursor) { | 1091 void RootWindowHostLinux::SetCursorInternal(gfx::NativeCursor cursor) { |
1045 ::Cursor xcursor = | 1092 ::Cursor xcursor = |
1046 image_cursors_->IsImageCursor(cursor) ? | 1093 image_cursors_->IsImageCursor(cursor) ? |
1047 image_cursors_->ImageCursorFromNative(cursor) : | 1094 image_cursors_->ImageCursorFromNative(cursor) : |
1048 (cursor == ui::kCursorNone ? invisible_cursor_ : | 1095 (cursor == ui::kCursorNone ? invisible_cursor_ : |
1049 (cursor == ui::kCursorCustom ? cursor.platform() : | 1096 (cursor == ui::kCursorCustom ? cursor.platform() : |
1050 ui::GetXCursor(CursorShapeFromNative(cursor)))); | 1097 ui::GetXCursor(CursorShapeFromNative(cursor)))); |
1051 XDefineCursor(xdisplay_, xwindow_, xcursor); | 1098 if (x_output_window_ != xwindow_) |
| 1099 XDefineCursor(xdisplay_, x_root_window_, xcursor); |
| 1100 else |
| 1101 XDefineCursor(xdisplay_, xwindow_, xcursor); |
| 1102 GetRootWindow()->OnCursorChanged(xcursor); |
1052 } | 1103 } |
1053 | 1104 |
1054 // static | 1105 // static |
1055 RootWindowHost* RootWindowHost::Create(const gfx::Rect& bounds) { | 1106 RootWindowHost* RootWindowHost::Create(const gfx::Rect& bounds) { |
1056 return new RootWindowHostLinux(bounds); | 1107 return new RootWindowHostLinux(bounds); |
1057 } | 1108 } |
1058 | 1109 |
1059 // static | 1110 // static |
1060 RootWindowHost* RootWindowHost::GetForAcceleratedWidget( | 1111 RootWindowHost* RootWindowHost::GetForAcceleratedWidget( |
1061 gfx::AcceleratedWidget accelerated_widget) { | 1112 gfx::AcceleratedWidget accelerated_widget) { |
1062 return reinterpret_cast<RootWindowHost*>( | 1113 return reinterpret_cast<RootWindowHost*>( |
1063 ui::ViewProp::GetValue(accelerated_widget, kRootWindowHostLinuxKey)); | 1114 ui::ViewProp::GetValue(accelerated_widget, kRootWindowHostLinuxKey)); |
1064 } | 1115 } |
1065 | 1116 |
1066 // static | 1117 // static |
1067 gfx::Size RootWindowHost::GetNativeScreenSize() { | 1118 gfx::Size RootWindowHost::GetNativeScreenSize() { |
1068 ::Display* xdisplay = base::MessagePumpAuraX11::GetDefaultXDisplay(); | 1119 ::Display* xdisplay = base::MessagePumpAuraX11::GetDefaultXDisplay(); |
1069 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); | 1120 return gfx::Size(DisplayWidth(xdisplay, 0), DisplayHeight(xdisplay, 0)); |
1070 } | 1121 } |
1071 | 1122 |
1072 } // namespace aura | 1123 } // namespace aura |
OLD | NEW |