1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/display/screen_position_controller.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/shell.h"
#include "ash/wm/window_positioning_utils.h"
#include "ash/wm/window_properties.h"
#include "ash/wm/window_state.h"
#include "ui/aura/client/screen_position_client.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/wm/core/window_properties.h"
#include "ui/wm/core/window_util.h"
namespace ash {
// static
void ScreenPositionController::ConvertHostPointToRelativeToRootWindow(
aura::Window* root_window,
const aura::Window::Windows& root_windows,
gfx::Point* point,
aura::Window** target_root) {
DCHECK(!root_window->parent());
gfx::Point point_in_root(*point);
root_window->GetHost()->ConvertPixelsToDIP(&point_in_root);
gfx::Rect host_bounds(root_window->GetHost()->GetBoundsInPixels().size());
if (!host_bounds.Contains(*point)) {
// This conversion is necessary to deal with X's passive input
// grab while dragging window. For example, if we have two
// displays, say 1000x1000 (primary) and 500x500 (extended one
// on the right), and start dragging a window at (999, 123), and
// then move the pointer to the right, the pointer suddenly
// warps to the extended display. The destination is (0, 123) in
// the secondary root window's coordinates, or (1000, 123) in
// the screen coordinates. However, since the mouse is captured
// by X during drag, a weird LocatedEvent, something like (0, 1123)
// in the *primary* root window's coordinates, is sent to Chrome
// (Remember that in the native X11 world, the two root windows
// are always stacked vertically regardless of the display
// layout in Ash). We need to figure out that (0, 1123) in the
// primary root window's coordinates is actually (0, 123) in the
// extended root window's coordinates.
//
// For now Ozone works in a similar manner as X11. Transitioning from one
// display's coordinate system to anothers may cause events in the
// primary's coordinate system which fall in the extended display.
gfx::Point location_in_native(*point);
// |point| is in the native host window coordinate. Convert it to the native
// screen coordinate.
const gfx::Point host_origin =
root_window->GetHost()->GetBoundsInPixels().origin();
location_in_native.Offset(host_origin.x(), host_origin.y());
for (size_t i = 0; i < root_windows.size(); ++i) {
aura::WindowTreeHost* host = root_windows[i]->GetHost();
const gfx::Rect native_bounds = host->GetBoundsInPixels();
if (native_bounds.Contains(location_in_native)) {
*target_root = root_windows[i];
*point = location_in_native;
host->ConvertScreenInPixelsToDIP(point);
return;
}
}
}
*target_root = root_window;
*point = point_in_root;
}
void ScreenPositionController::ConvertPointToScreen(const aura::Window* window,
gfx::PointF* point) {
const aura::Window* root = window->GetRootWindow();
aura::Window::ConvertPointToTarget(window, root, point);
const gfx::Point display_origin =
display::Screen::GetScreen()
->GetDisplayNearestWindow(const_cast<aura::Window*>(root))
.bounds()
.origin();
point->Offset(display_origin.x(), display_origin.y());
}
void ScreenPositionController::ConvertPointFromScreen(
const aura::Window* window,
gfx::PointF* point) {
const aura::Window* root = window->GetRootWindow();
const gfx::Point display_origin =
display::Screen::GetScreen()
->GetDisplayNearestWindow(const_cast<aura::Window*>(root))
.bounds()
.origin();
point->Offset(-display_origin.x(), -display_origin.y());
aura::Window::ConvertPointToTarget(root, window, point);
}
void ScreenPositionController::ConvertHostPointToScreen(
aura::Window* root_window,
gfx::Point* point) {
aura::Window* root = root_window->GetRootWindow();
aura::Window* target_root = nullptr;
ConvertHostPointToRelativeToRootWindow(root, Shell::GetAllRootWindows(),
point, &target_root);
aura::client::ScreenPositionClient::ConvertPointToScreen(target_root, point);
}
void ScreenPositionController::SetBounds(aura::Window* window,
const gfx::Rect& bounds,
const display::Display& display) {
if (!window->parent()->GetProperty(::wm::kUsesScreenCoordinatesKey)) {
window->SetBounds(bounds);
return;
}
SetBoundsInScreen(window, bounds, display);
}
gfx::Point ScreenPositionController::GetRootWindowOriginInScreen(
const aura::Window* root_window) {
DCHECK(root_window->IsRootWindow());
const display::Display& display =
display::Screen::GetScreen()->GetDisplayNearestWindow(
const_cast<aura::Window*>(root_window));
return display.bounds().origin();
}
} // namespace ash
|