| 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 |