Chromium Code Reviews| Index: ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc |
| diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc |
| index 3874e6705ac6083def2012a9dfbaa61fa28ffe65..4a2b0855580d986dd6772d611055455b0fad488d 100644 |
| --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc |
| +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc |
| @@ -32,6 +32,7 @@ |
| #include "ui/events/platform/x11/x11_event_source.h" |
| #include "ui/gfx/display.h" |
| #include "ui/gfx/geometry/insets.h" |
| +#include "ui/gfx/geometry/size_conversions.h" |
| #include "ui/gfx/image/image_skia.h" |
| #include "ui/gfx/image/image_skia_rep.h" |
| #include "ui/gfx/path.h" |
| @@ -190,11 +191,11 @@ std::vector<aura::Window*> DesktopWindowTreeHostX11::GetAllOpenWindows() { |
| } |
| gfx::Rect DesktopWindowTreeHostX11::GetX11RootWindowBounds() const { |
| - return bounds_; |
| + return bounds_in_pixels_; |
| } |
| gfx::Rect DesktopWindowTreeHostX11::GetX11RootWindowOuterBounds() const { |
| - gfx::Rect outer_bounds(bounds_); |
| + gfx::Rect outer_bounds(bounds_in_pixels_); |
| outer_bounds.Inset(-native_window_frame_borders_); |
| return outer_bounds; |
| } |
| @@ -382,7 +383,7 @@ void DesktopWindowTreeHostX11::ShowMaximizedWithBounds( |
| const gfx::Rect& restored_bounds) { |
| ShowWindowWithState(ui::SHOW_STATE_MAXIMIZED); |
| // Enforce |restored_bounds_| since calling Maximize() could have reset it. |
| - restored_bounds_ = restored_bounds; |
| + restored_bounds_ = ToPixelRect(restored_bounds); |
| } |
| bool DesktopWindowTreeHostX11::IsVisible() const { |
| @@ -390,12 +391,14 @@ bool DesktopWindowTreeHostX11::IsVisible() const { |
| } |
| void DesktopWindowTreeHostX11::SetSize(const gfx::Size& requested_size) { |
| - gfx::Size size = AdjustSize(requested_size); |
| - bool size_changed = bounds_.size() != size; |
| - XResizeWindow(xdisplay_, xwindow_, size.width(), size.height()); |
| - bounds_.set_size(size); |
| + gfx::Size size_in_pixels = ToPixelRect(gfx::Rect(requested_size)).size(); |
| + size_in_pixels = AdjustSize(size_in_pixels); |
| + bool size_changed = bounds_in_pixels_.size() != size_in_pixels; |
| + XResizeWindow(xdisplay_, xwindow_, size_in_pixels.width(), |
| + size_in_pixels.height()); |
| + bounds_in_pixels_.set_size(size_in_pixels); |
| if (size_changed) { |
| - OnHostResized(size); |
| + OnHostResized(size_in_pixels); |
| ResetWindowRegion(); |
| } |
| } |
| @@ -405,27 +408,29 @@ void DesktopWindowTreeHostX11::StackAtTop() { |
| } |
| void DesktopWindowTreeHostX11::CenterWindow(const gfx::Size& size) { |
| - gfx::Rect parent_bounds = GetWorkAreaBoundsInScreen(); |
| + gfx::Size size_in_pixels = ToPixelRect(gfx::Rect(size)).size(); |
| + gfx::Rect parent_bounds_in_pixels = GetWorkAreaBoundsInPixels(); |
| - // If |window_|'s transient parent bounds are big enough to contain |size|, |
| - // use them instead. |
| + // If |window_|'s transient parent bounds are big enough to contain |
| + // |size_in_pixels|, use them instead. |
| if (wm::GetTransientParent(content_window_)) { |
| gfx::Rect transient_parent_rect = |
| wm::GetTransientParent(content_window_)->GetBoundsInScreen(); |
| - if (transient_parent_rect.height() >= size.height() && |
| - transient_parent_rect.width() >= size.width()) { |
| - parent_bounds = transient_parent_rect; |
| + if (transient_parent_rect.height() >= size_in_pixels.height() && |
| + transient_parent_rect.width() >= size_in_pixels.width()) { |
| + parent_bounds_in_pixels = ToPixelRect(transient_parent_rect); |
| } |
| } |
| gfx::Rect window_bounds( |
| - parent_bounds.x() + (parent_bounds.width() - size.width()) / 2, |
| - parent_bounds.y() + (parent_bounds.height() - size.height()) / 2, |
| - size.width(), |
| - size.height()); |
| + parent_bounds_in_pixels.x() + |
| + (parent_bounds_in_pixels.width() - size_in_pixels.width()) / 2, |
| + parent_bounds_in_pixels.y() + |
| + (parent_bounds_in_pixels.height() - size_in_pixels.height()) / 2, |
| + size_in_pixels.width(), size_in_pixels.height()); |
| // Don't size the window bigger than the parent, otherwise the user may not be |
| // able to close or move it. |
| - window_bounds.AdjustToFit(parent_bounds); |
| + window_bounds.AdjustToFit(parent_bounds_in_pixels); |
| SetBounds(window_bounds); |
| } |
| @@ -449,19 +454,19 @@ void DesktopWindowTreeHostX11::GetWindowPlacement( |
| } |
| gfx::Rect DesktopWindowTreeHostX11::GetWindowBoundsInScreen() const { |
| - return bounds_; |
| + return ToDIPRect(bounds_in_pixels_); |
| } |
| gfx::Rect DesktopWindowTreeHostX11::GetClientAreaBoundsInScreen() const { |
| - // TODO(erg): The NativeWidgetAura version returns |bounds_|, claiming its |
| - // needed for View::ConvertPointToScreen() to work |
| - // correctly. DesktopWindowTreeHostWin::GetClientAreaBoundsInScreen() just |
| - // asks windows what it thinks the client rect is. |
| + // TODO(erg): The NativeWidgetAura version returns |bounds_in_pixels_|, |
| + // claiming it's needed for View::ConvertPointToScreen() to work correctly. |
| + // DesktopWindowTreeHostWin::GetClientAreaBoundsInScreen() just asks windows |
| + // what it thinks the client rect is. |
| // |
| // Attempts to calculate the rect by asking the NonClientFrameView what it |
| // thought its GetBoundsForClientView() were broke combobox drop down |
| // placement. |
| - return bounds_; |
| + return GetWindowBoundsInScreen(); |
| } |
| gfx::Rect DesktopWindowTreeHostX11::GetRestoredBounds() const { |
| @@ -470,30 +475,13 @@ gfx::Rect DesktopWindowTreeHostX11::GetRestoredBounds() const { |
| // or restoring bounds, we can record the current bounds before we request |
| // maximization, and clear it when we detect a state change. |
| if (!restored_bounds_.IsEmpty()) |
| - return restored_bounds_; |
| + return ToDIPRect(restored_bounds_); |
| return GetWindowBoundsInScreen(); |
| } |
| gfx::Rect DesktopWindowTreeHostX11::GetWorkAreaBoundsInScreen() const { |
| - std::vector<int> value; |
| - if (ui::GetIntArrayProperty(x_root_window_, "_NET_WORKAREA", &value) && |
| - value.size() >= 4) { |
| - return gfx::Rect(value[0], value[1], value[2], value[3]); |
| - } |
| - |
| - // Fetch the geometry of the root window. |
| - Window root; |
| - int x, y; |
| - unsigned int width, height; |
| - unsigned int border_width, depth; |
| - if (!XGetGeometry(xdisplay_, x_root_window_, &root, &x, &y, |
| - &width, &height, &border_width, &depth)) { |
| - NOTIMPLEMENTED(); |
| - return gfx::Rect(0, 0, 10, 10); |
| - } |
| - |
| - return gfx::Rect(x, y, width, height); |
| + return ToDIPRect(GetWorkAreaBoundsInPixels()); |
| } |
| void DesktopWindowTreeHostX11::SetShape(gfx::NativeRegion native_region) { |
| @@ -539,8 +527,9 @@ void DesktopWindowTreeHostX11::Maximize() { |
| // Resize the window so that it does not have the same size as a monitor. |
| // (Otherwise, some window managers immediately put the window back in |
| // fullscreen mode). |
| - gfx::Rect adjusted_bounds(bounds_.origin(), AdjustSize(bounds_.size())); |
| - if (adjusted_bounds != bounds_) |
| + gfx::Rect adjusted_bounds(bounds_in_pixels_.origin(), |
| + AdjustSize(bounds_in_pixels_.size())); |
| + if (adjusted_bounds != bounds_in_pixels_) |
| SetBounds(adjusted_bounds); |
| } |
| @@ -551,7 +540,7 @@ void DesktopWindowTreeHostX11::Maximize() { |
| // When we are in the process of requesting to maximize a window, we can |
| // accurately keep track of our restored bounds instead of relying on the |
| // heuristics that are in the PropertyNotify and ConfigureNotify handlers. |
| - restored_bounds_ = bounds_; |
| + restored_bounds_ = bounds_in_pixels_; |
| SetWMSpecState(true, |
| atom_cache_.GetAtom("_NET_WM_STATE_MAXIMIZED_VERT"), |
| @@ -737,15 +726,15 @@ void DesktopWindowTreeHostX11::SetFullscreen(bool fullscreen) { |
| // synchronously. |
| // See https://crbug.com/361408 |
| if (fullscreen) { |
| - restored_bounds_ = bounds_; |
| + restored_bounds_ = bounds_in_pixels_; |
| const gfx::Display display = |
| gfx::Screen::GetScreenFor(NULL)->GetDisplayNearestWindow(window()); |
| - bounds_ = display.bounds(); |
| + bounds_in_pixels_ = ToPixelRect(display.bounds()); |
| } else { |
| - bounds_ = restored_bounds_; |
| + bounds_in_pixels_ = restored_bounds_; |
| } |
| - OnHostMoved(bounds_.origin()); |
| - OnHostResized(bounds_.size()); |
| + OnHostMoved(bounds_in_pixels_.origin()); |
| + OnHostResized(bounds_in_pixels_.size()); |
| if (HasWMSpecProperty("_NET_WM_STATE_FULLSCREEN") == fullscreen) { |
| Relayout(); |
| @@ -862,6 +851,20 @@ void DesktopWindowTreeHostX11::SizeConstraintsChanged() { |
| //////////////////////////////////////////////////////////////////////////////// |
| // DesktopWindowTreeHostX11, aura::WindowTreeHost implementation: |
| +gfx::Transform DesktopWindowTreeHostX11::GetRootTransform() const { |
|
pkotwicz
2015/02/18 22:58:50
Nit: I would be tempted to query the device scale
sadrul
2015/02/18 23:33:58
Done.
|
| + float scale = gfx::Display::GetForcedDeviceScaleFactor(); |
| + if (window_mapped_) { |
| + const gfx::Display display = |
| + gfx::Screen::GetNativeScreen()->GetDisplayNearestPoint( |
| + bounds_in_pixels_.origin()); |
|
pkotwicz
2015/02/18 22:58:50
tldr: If you plan on making ToPixelRect() / ToDIPR
sadrul
2015/02/18 23:33:58
Changed to use DisplayNearestWindow() instead.
|
| + scale = display.device_scale_factor(); |
| + } |
| + |
| + gfx::Transform transform; |
| + transform.Scale(scale, scale); |
| + return transform; |
| +} |
| + |
| ui::EventSource* DesktopWindowTreeHostX11::GetEventSource() { |
| return this; |
| } |
| @@ -884,14 +887,15 @@ void DesktopWindowTreeHostX11::Hide() { |
| } |
| gfx::Rect DesktopWindowTreeHostX11::GetBounds() const { |
| - return bounds_; |
| + return bounds_in_pixels_; |
| } |
| -void DesktopWindowTreeHostX11::SetBounds(const gfx::Rect& requested_bounds) { |
| - gfx::Rect bounds(requested_bounds.origin(), |
| - AdjustSize(requested_bounds.size())); |
| - bool origin_changed = bounds_.origin() != bounds.origin(); |
| - bool size_changed = bounds_.size() != bounds.size(); |
| +void DesktopWindowTreeHostX11::SetBounds( |
| + const gfx::Rect& requested_bounds_in_pixel) { |
| + gfx::Rect bounds(requested_bounds_in_pixel.origin(), |
| + AdjustSize(requested_bounds_in_pixel.size())); |
| + bool origin_changed = bounds_in_pixels_.origin() != bounds.origin(); |
| + bool size_changed = bounds_in_pixels_.size() != bounds.size(); |
| XWindowChanges changes = {0}; |
| unsigned value_mask = 0; |
| @@ -927,8 +931,8 @@ void DesktopWindowTreeHostX11::SetBounds(const gfx::Rect& requested_bounds) { |
| // case if we're running without a window manager. If there's a window |
| // manager, it can modify or ignore the request, but (per ICCCM) we'll get a |
| // (possibly synthetic) ConfigureNotify about the actual size and correct |
| - // |bounds_| later. |
| - bounds_ = bounds; |
| + // |bounds_in_pixels_| later. |
| + bounds_in_pixels_ = bounds; |
| if (origin_changed) |
| native_widget_delegate_->AsWidget()->OnNativeWidgetMove(); |
| @@ -939,7 +943,7 @@ void DesktopWindowTreeHostX11::SetBounds(const gfx::Rect& requested_bounds) { |
| } |
| gfx::Point DesktopWindowTreeHostX11::GetLocationOnNativeScreen() const { |
| - return bounds_.origin(); |
| + return bounds_in_pixels_.origin(); |
| } |
| void DesktopWindowTreeHostX11::SetCapture() { |
| @@ -982,7 +986,8 @@ void DesktopWindowTreeHostX11::SetCursorNative(gfx::NativeCursor cursor) { |
| void DesktopWindowTreeHostX11::MoveCursorToNative(const gfx::Point& location) { |
| XWarpPointer(xdisplay_, None, x_root_window_, 0, 0, 0, 0, |
| - bounds_.x() + location.x(), bounds_.y() + location.y()); |
| + bounds_in_pixels_.x() + location.x(), |
| + bounds_in_pixels_.y() + location.y()); |
| } |
| void DesktopWindowTreeHostX11::OnCursorVisibilityChangedNative(bool show) { |
| @@ -1058,18 +1063,14 @@ void DesktopWindowTreeHostX11::InitX11Window( |
| } |
| } |
| - bounds_ = gfx::Rect(params.bounds.origin(), |
| - AdjustSize(params.bounds.size())); |
| - xwindow_ = XCreateWindow( |
| - xdisplay_, x_root_window_, |
| - bounds_.x(), bounds_.y(), |
| - bounds_.width(), bounds_.height(), |
| - 0, // border width |
| - depth, |
| - InputOutput, |
| - visual, |
| - attribute_mask, |
| - &swa); |
| + bounds_in_pixels_ = ToPixelRect(params.bounds); |
| + bounds_in_pixels_ = gfx::Rect(bounds_in_pixels_.origin(), |
| + AdjustSize(bounds_in_pixels_.size())); |
| + xwindow_ = XCreateWindow(xdisplay_, x_root_window_, bounds_in_pixels_.x(), |
| + bounds_in_pixels_.y(), bounds_in_pixels_.width(), |
| + bounds_in_pixels_.height(), |
| + 0, // border width |
| + depth, InputOutput, visual, attribute_mask, &swa); |
| if (ui::PlatformEventSource::GetInstance()) |
| ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this); |
| open_windows().push_back(xwindow_); |
| @@ -1208,20 +1209,20 @@ void DesktopWindowTreeHostX11::InitX11Window( |
| } |
| gfx::Size DesktopWindowTreeHostX11::AdjustSize( |
| - const gfx::Size& requested_size) { |
| + const gfx::Size& requested_size_in_pixels) { |
| std::vector<gfx::Display> displays = |
| gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_NATIVE)->GetAllDisplays(); |
| // Compare against all monitor sizes. The window manager can move the window |
| // to whichever monitor it wants. |
| for (size_t i = 0; i < displays.size(); ++i) { |
| - if (requested_size == displays[i].size()) { |
| - return gfx::Size(requested_size.width() - 1, |
| - requested_size.height() - 1); |
| + if (requested_size_in_pixels == displays[i].GetSizeInPixel()) { |
| + return gfx::Size(requested_size_in_pixels.width() - 1, |
| + requested_size_in_pixels.height() - 1); |
| } |
| } |
| // Do not request a 0x0 window size. It causes an XError. |
| - gfx::Size size = requested_size; |
| + gfx::Size size = requested_size_in_pixels; |
| size.SetToMax(gfx::Size(1,1)); |
| return size; |
| } |
| @@ -1265,10 +1266,10 @@ void DesktopWindowTreeHostX11::OnWMStateUpdated() { |
| DCHECK(!IsFullscreen()); |
| if (IsMaximized()) { |
| // The request that we become maximized originated from a different |
| - // process. |bounds_| already contains our maximized bounds. Do a best |
| - // effort attempt to get restored bounds by setting it to our previously |
| - // set bounds (and if we get this wrong, we aren't any worse off since |
| - // we'd otherwise be returning our maximized bounds). |
| + // process. |bounds_in_pixels_| already contains our maximized bounds. Do |
| + // a best effort attempt to get restored bounds by setting it to our |
| + // previously set bounds (and if we get this wrong, we aren't any worse |
| + // off since we'd otherwise be returning our maximized bounds). |
| restored_bounds_ = previous_bounds_; |
| } |
| } else if (!IsMaximized() && !IsFullscreen()) { |
| @@ -1481,7 +1482,8 @@ void DesktopWindowTreeHostX11::ResetWindowRegion() { |
| if (widget->non_client_view()) { |
| // Some frame views define a custom (non-rectangular) window mask. If |
| // so, use it to define the window shape. If not, fall through. |
| - widget->non_client_view()->GetWindowMask(bounds_.size(), &window_mask); |
| + widget->non_client_view()->GetWindowMask(bounds_in_pixels_.size(), |
| + &window_mask); |
| if (window_mask.countPoints() > 0) { |
| window_shape_ = gfx::CreateRegionFromSkPath(window_mask); |
| XShapeCombineRegion(xdisplay_, xwindow_, ShapeBounding, |
| @@ -1505,8 +1507,10 @@ void DesktopWindowTreeHostX11::ResetWindowRegion() { |
| // is due to a bug in KWin <= 4.11.5 (KDE bug #330573) where setting a null |
| // shape causes the hint to disable system borders to be ignored (resulting |
| // in a double border). |
| - XRectangle r = {0, 0, static_cast<unsigned short>(bounds_.width()), |
| - static_cast<unsigned short>(bounds_.height())}; |
| + XRectangle r = {0, |
| + 0, |
| + static_cast<unsigned short>(bounds_in_pixels_.width()), |
| + static_cast<unsigned short>(bounds_in_pixels_.height())}; |
| XShapeCombineRectangles( |
| xdisplay_, xwindow_, ShapeBounding, 0, 0, &r, 1, ShapeSet, YXBanded); |
| } |
| @@ -1581,8 +1585,8 @@ void DesktopWindowTreeHostX11::MapWindow(ui::WindowShowState show_state) { |
| // will ignore toplevel XMoveWindow commands. |
| XSizeHints size_hints; |
| size_hints.flags = PPosition; |
| - size_hints.x = bounds_.x(); |
| - size_hints.y = bounds_.y(); |
| + size_hints.x = bounds_in_pixels_.x(); |
| + size_hints.y = bounds_in_pixels_.y(); |
| XSetWMNormalHints(xdisplay_, xwindow_, &size_hints); |
| // If SHOW_STATE_INACTIVE, tell the window manager not to focus the window |
| @@ -1742,13 +1746,13 @@ uint32_t DesktopWindowTreeHostX11::DispatchEvent( |
| } |
| gfx::Rect bounds(translated_x, translated_y, |
| xev->xconfigure.width, xev->xconfigure.height); |
| - bool size_changed = bounds_.size() != bounds.size(); |
| - bool origin_changed = bounds_.origin() != bounds.origin(); |
| - previous_bounds_ = bounds_; |
| - bounds_ = bounds; |
| + bool size_changed = bounds_in_pixels_.size() != bounds.size(); |
| + bool origin_changed = bounds_in_pixels_.origin() != bounds.origin(); |
| + previous_bounds_ = bounds_in_pixels_; |
| + bounds_in_pixels_ = bounds; |
| if (origin_changed) |
| - OnHostMoved(bounds_.origin()); |
| + OnHostMoved(bounds_in_pixels_.origin()); |
| if (size_changed) { |
| delayed_resize_task_.Reset(base::Bind( |
| @@ -1930,6 +1934,41 @@ void DesktopWindowTreeHostX11::DelayedResize(const gfx::Size& size) { |
| delayed_resize_task_.Cancel(); |
| } |
| +gfx::Rect DesktopWindowTreeHostX11::GetWorkAreaBoundsInPixels() const { |
| + std::vector<int> value; |
| + if (ui::GetIntArrayProperty(x_root_window_, "_NET_WORKAREA", &value) && |
| + value.size() >= 4) { |
| + return gfx::Rect(value[0], value[1], value[2], value[3]); |
| + } |
| + |
| + // Fetch the geometry of the root window. |
| + Window root; |
| + int x, y; |
| + unsigned int width, height; |
| + unsigned int border_width, depth; |
| + if (!XGetGeometry(xdisplay_, x_root_window_, &root, &x, &y, &width, &height, |
| + &border_width, &depth)) { |
| + NOTIMPLEMENTED(); |
| + return gfx::Rect(0, 0, 10, 10); |
| + } |
| + |
| + return gfx::Rect(x, y, width, height); |
| +} |
| + |
| +gfx::Rect DesktopWindowTreeHostX11::ToDIPRect( |
| + const gfx::Rect& rect_in_pixels) const { |
| + gfx::RectF rect_in_dip = rect_in_pixels; |
| + GetRootTransform().TransformRectReverse(&rect_in_dip); |
| + return gfx::ToEnclosingRect(rect_in_dip); |
| +} |
| + |
| +gfx::Rect DesktopWindowTreeHostX11::ToPixelRect( |
| + const gfx::Rect& rect_in_dip) const { |
| + gfx::RectF rect_in_pixels = rect_in_dip; |
| + GetRootTransform().TransformRect(&rect_in_pixels); |
| + return gfx::ToEnclosingRect(rect_in_pixels); |
| +} |
| + |
| //////////////////////////////////////////////////////////////////////////////// |
| // DesktopWindowTreeHost, public: |