1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file. 4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ash/display/root_window_transformers.h" 6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <cmath> 8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ash/display/display_info.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ash/display/display_manager.h" 11a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ash/host/root_window_transformer.h" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ash/magnifier/magnification_controller.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ash/shell.h" 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/basictypes.h" 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/skia/include/utils/SkMatrix44.h" 17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h" 18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/aura/window_property.h" 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/compositor/dip_util.h" 20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/gfx/display.h" 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/gfx/insets.h" 22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/gfx/size_conversions.h" 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/gfx/transform.h" 24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/gfx/transform.h" 25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)DECLARE_WINDOW_PROPERTY_TYPE(gfx::Display::Rotation); 27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace ash { 29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace { 30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#if defined(OS_WIN) 32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)DEFINE_WINDOW_PROPERTY_KEY(gfx::Display::Rotation, kRotationPropertyKey, 33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Display::ROTATE_0); 348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#endif 35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Round near zero value to zero. 37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void RoundNearZero(gfx::Transform* transform) { 38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const float kEpsilon = 0.001f; 39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SkMatrix44& matrix = transform->matrix(); 40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (int x = 0; x < 4; ++x) { 41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (int y = 0; y < 4; ++y) { 42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (std::abs(SkMScalarToFloat(matrix.get(x, y))) < kEpsilon) 43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) matrix.set(x, y, SkFloatToMScalar(0.0f)); 44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// TODO(oshima): Transformers should be able to adjust itself 49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// when the device scale factor is changed, instead of 50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// precalculating the transform using fixed value. 51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)gfx::Transform CreateRotationTransform(aura::Window* root_window, 53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const gfx::Display& display) { 54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DisplayInfo info = 55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Shell::GetInstance()->display_manager()->GetDisplayInfo(display.id()); 56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // TODO(oshima): Add animation. (crossfade+rotation, or just cross-fade) 58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#if defined(OS_WIN) 59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Windows 8 bots refused to resize the host window, and 60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // updating the transform results in incorrectly resizing 61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // the root window. Don't apply the transform unless 62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // necessary so that unit tests pass on win8 bots. 63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (info.rotation() == root_window->GetProperty(kRotationPropertyKey)) 64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return gfx::Transform(); 65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) root_window->SetProperty(kRotationPropertyKey, info.rotation()); 66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif 67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Transform rotate; 69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // The origin is (0, 0), so the translate width/height must be reduced by 70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // 1 pixel. 71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) float one_pixel = 1.0f / display.device_scale_factor(); 72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) switch (info.rotation()) { 73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case gfx::Display::ROTATE_0: 74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case gfx::Display::ROTATE_90: 76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) rotate.Translate(display.bounds().height() - one_pixel, 0); 77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) rotate.Rotate(90); 78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case gfx::Display::ROTATE_270: 80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) rotate.Translate(0, display.bounds().width() - one_pixel); 81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) rotate.Rotate(270); 82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case gfx::Display::ROTATE_180: 84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) rotate.Translate(display.bounds().width() - one_pixel, 85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) display.bounds().height() - one_pixel); 86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) rotate.Rotate(180); 87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RoundNearZero(&rotate); 91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return rotate; 92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)gfx::Transform CreateMagnifierTransform(aura::Window* root_window) { 95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) MagnificationController* magnifier = 96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Shell::GetInstance()->magnification_controller(); 97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) float magnifier_scale = 1.f; 98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Point magnifier_offset; 99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (magnifier && magnifier->IsEnabled()) { 100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) magnifier_scale = magnifier->GetScale(); 101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) magnifier_offset = magnifier->GetWindowPosition(); 102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Transform transform; 104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (magnifier_scale != 1.f) { 105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) transform.Scale(magnifier_scale, magnifier_scale); 106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) transform.Translate(-magnifier_offset.x(), -magnifier_offset.y()); 107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return transform; 109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)gfx::Transform CreateInsetsAndScaleTransform(const gfx::Insets& insets, 112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) float device_scale_factor, 113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) float ui_scale) { 114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Transform transform; 115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (insets.top() != 0 || insets.left() != 0) { 116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) float x_offset = insets.left() / device_scale_factor; 117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) float y_offset = insets.top() / device_scale_factor; 118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) transform.Translate(x_offset, y_offset); 119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) float inverted_scale = 1.0f / ui_scale; 121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) transform.Scale(inverted_scale, inverted_scale); 122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return transform; 123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// RootWindowTransformer for ash environment. 126a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochclass AshRootWindowTransformer : public RootWindowTransformer { 127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public: 1281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) AshRootWindowTransformer(aura::Window* root, 129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const gfx::Display& display) 130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) : root_window_(root) { 131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DisplayInfo info = Shell::GetInstance()->display_manager()-> 132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) GetDisplayInfo(display.id()); 133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) host_insets_ = info.GetOverscanInsetsInPixel(); 134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) root_window_ui_scale_ = info.GetEffectiveUIScale(); 135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) root_window_bounds_transform_ = 136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CreateInsetsAndScaleTransform(host_insets_, 137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) display.device_scale_factor(), 138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) root_window_ui_scale_) * 139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CreateRotationTransform(root, display); 140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) transform_ = root_window_bounds_transform_ * CreateMagnifierTransform(root); 141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CHECK(transform_.GetInverse(&invert_transform_)); 142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // aura::RootWindowTransformer overrides: 145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual gfx::Transform GetTransform() const OVERRIDE { 146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return transform_; 147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual gfx::Transform GetInverseTransform() const OVERRIDE { 149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return invert_transform_; 150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual gfx::Rect GetRootWindowBounds( 152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const gfx::Size& host_size) const OVERRIDE { 153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Rect bounds(host_size); 154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bounds.Inset(host_insets_); 155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bounds = ui::ConvertRectToDIP(root_window_->layer(), bounds); 156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::RectF new_bounds(bounds); 157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) root_window_bounds_transform_.TransformRect(&new_bounds); 158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Apply |root_window_scale_| twice as the downscaling 159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // is already applied once in |SetTransformInternal()|. 160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // TODO(oshima): This is a bit ugly. Consider specifying 161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // the pseudo host resolution instead. 162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) new_bounds.Scale(root_window_ui_scale_ * root_window_ui_scale_); 163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Ignore the origin because RootWindow's insets are handled by 164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // the transform. 165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Floor the size because the bounds is no longer aligned to 166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // backing pixel when |root_window_scale_| is specified 167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // (850 height at 1.25 scale becomes 1062.5 for example.) 168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return gfx::Rect(gfx::ToFlooredSize(new_bounds.size())); 169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual gfx::Insets GetHostInsets() const OVERRIDE { 172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return host_insets_; 173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private: 176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual ~AshRootWindowTransformer() {} 177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) aura::Window* root_window_; 179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Transform transform_; 180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // The accurate representation of the inverse of the |transform_|. 182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // This is used to avoid computation error caused by 183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // |gfx::Transform::GetInverse|. 184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Transform invert_transform_; 185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // The transform of the root window bounds. This is used to calculate 187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // the size of root window. 188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Transform root_window_bounds_transform_; 189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 19068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // The scale of the root window. See |display_info::ui_scale_| 19168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // for more info. 192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) float root_window_ui_scale_; 193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Insets host_insets_; 195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(AshRootWindowTransformer); 197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}; 198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// RootWindowTransformer for mirror root window. We simply copy the 200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// texture (bitmap) of the source display into the mirror window, so 201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// the root window bounds is the same as the source display's 202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// pixel size (excluding overscan insets). 203a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochclass MirrorRootWindowTransformer : public RootWindowTransformer { 204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public: 205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) MirrorRootWindowTransformer(const DisplayInfo& source_display_info, 206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const DisplayInfo& mirror_display_info) { 20768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) root_bounds_ = gfx::Rect(source_display_info.bounds_in_native().size()); 208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Rect mirror_display_rect = 20968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) gfx::Rect(mirror_display_info.bounds_in_native().size()); 210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 2117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) bool letterbox = root_bounds_.width() * mirror_display_rect.height() > 2127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) root_bounds_.height() * mirror_display_rect.width(); 2137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (letterbox) { 2147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) float mirror_scale_ratio = 2157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) (static_cast<float>(root_bounds_.width()) / 2167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) static_cast<float>(mirror_display_rect.width())); 2177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) float inverted_scale = 1.0f / mirror_scale_ratio; 2187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) int margin = static_cast<int>( 2197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) (mirror_display_rect.height() - 2207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) root_bounds_.height() * inverted_scale) / 2); 2217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) insets_.Set(0, margin, 0, margin); 2227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) transform_.Translate(0, margin); 2247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) transform_.Scale(inverted_scale, inverted_scale); 2257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } else { 2267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) float mirror_scale_ratio = 2277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) (static_cast<float>(root_bounds_.height()) / 2287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) static_cast<float>(mirror_display_rect.height())); 2297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) float inverted_scale = 1.0f / mirror_scale_ratio; 2307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) int margin = static_cast<int>( 2317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) (mirror_display_rect.width() - 2327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) root_bounds_.width() * inverted_scale) / 2); 2337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) insets_.Set(margin, 0, margin, 0); 2347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) transform_.Translate(margin, 0); 2367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) transform_.Scale(inverted_scale, inverted_scale); 2377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // aura::RootWindowTransformer overrides: 241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual gfx::Transform GetTransform() const OVERRIDE { 242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return transform_; 243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual gfx::Transform GetInverseTransform() const OVERRIDE { 245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Transform invert; 246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CHECK(transform_.GetInverse(&invert)); 247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return invert; 248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual gfx::Rect GetRootWindowBounds( 250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const gfx::Size& host_size) const OVERRIDE { 251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return root_bounds_; 252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual gfx::Insets GetHostInsets() const OVERRIDE { 2547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return insets_; 255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private: 258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual ~MirrorRootWindowTransformer() {} 259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Transform transform_; 261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Rect root_bounds_; 2627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) gfx::Insets insets_; 263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MirrorRootWindowTransformer); 265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}; 266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} // namespace 268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 269a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochRootWindowTransformer* CreateRootWindowTransformerForDisplay( 2701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) aura::Window* root, 271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const gfx::Display& display) { 272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return new AshRootWindowTransformer(root, display); 273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 275a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochRootWindowTransformer* CreateRootWindowTransformerForMirroredDisplay( 276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const DisplayInfo& source_display_info, 277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const DisplayInfo& mirror_display_info) { 278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return new MirrorRootWindowTransformer(source_display_info, 279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) mirror_display_info); 280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} // namespace ash 283