mirror_window_controller.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "ash/display/mirror_window_controller.h" 6 7#if defined(USE_X11) 8#include <X11/Xlib.h> 9 10// Xlib.h defines RootWindow. 11#undef RootWindow 12#endif 13 14#include "ash/display/cursor_window_controller.h" 15#include "ash/display/display_controller.h" 16#include "ash/display/display_info.h" 17#include "ash/display/display_manager.h" 18#include "ash/display/root_window_transformers.h" 19#include "ash/host/window_tree_host_factory.h" 20#include "ash/root_window_settings.h" 21#include "ash/shell.h" 22#include "base/strings/stringprintf.h" 23#include "ui/aura/client/capture_client.h" 24#include "ui/aura/root_window.h" 25#include "ui/aura/root_window_transformer.h" 26#include "ui/aura/window_delegate.h" 27#include "ui/base/layout.h" 28#include "ui/compositor/reflector.h" 29#include "ui/gfx/canvas.h" 30#include "ui/gfx/native_widget_types.h" 31 32#if defined(USE_X11) 33#include "ui/gfx/x/x11_types.h" 34#endif 35 36namespace ash { 37namespace internal { 38namespace { 39 40#if defined(USE_X11) 41// Mirror window shouldn't handle input events. 42void DisableInput(XID window) { 43 long event_mask = ExposureMask | VisibilityChangeMask | 44 StructureNotifyMask | PropertyChangeMask; 45 XSelectInput(gfx::GetXDisplay(), window, event_mask); 46} 47#endif 48 49class NoneCaptureClient : public aura::client::CaptureClient { 50 public: 51 NoneCaptureClient() {} 52 virtual ~NoneCaptureClient() {} 53 54 private: 55 // Does a capture on the |window|. 56 virtual void SetCapture(aura::Window* window) OVERRIDE {} 57 58 // Releases a capture from the |window|. 59 virtual void ReleaseCapture(aura::Window* window) OVERRIDE {} 60 61 // Returns the current capture window. 62 virtual aura::Window* GetCaptureWindow() OVERRIDE { 63 return NULL; 64 } 65 virtual aura::Window* GetGlobalCaptureWindow() OVERRIDE { 66 return NULL; 67 } 68 69 DISALLOW_COPY_AND_ASSIGN(NoneCaptureClient); 70}; 71 72} // namespace 73 74MirrorWindowController::MirrorWindowController() {} 75 76MirrorWindowController::~MirrorWindowController() { 77 // Make sure the root window gets deleted before cursor_window_delegate. 78 Close(); 79} 80 81void MirrorWindowController::UpdateWindow(const DisplayInfo& display_info) { 82 static int mirror_root_window_count = 0; 83 84 if (!root_window_.get()) { 85 const gfx::Rect& bounds_in_native = display_info.bounds_in_native(); 86 aura::RootWindow::CreateParams params(bounds_in_native); 87 params.host = Shell::GetInstance()->window_tree_host_factory()-> 88 CreateWindowTreeHost(bounds_in_native); 89 root_window_.reset(new aura::RootWindow(params)); 90 root_window_->window()->SetName( 91 base::StringPrintf("MirrorRootWindow-%d", mirror_root_window_count++)); 92 root_window_->host()->compositor()->SetBackgroundColor(SK_ColorBLACK); 93 // No need to remove RootWindowObserver because 94 // the DisplayController object outlives RootWindow objects. 95 root_window_->AddRootWindowObserver( 96 Shell::GetInstance()->display_controller()); 97 root_window_->AddRootWindowObserver(this); 98 // TODO(oshima): TouchHUD is using idkey. 99 InitRootWindowSettings(root_window_->window())->display_id = 100 display_info.id(); 101 root_window_->host()->InitHost(); 102#if defined(USE_X11) 103 DisableInput(root_window_->host()->GetAcceleratedWidget()); 104#endif 105 106 aura::client::SetCaptureClient(root_window_->window(), 107 new NoneCaptureClient()); 108 root_window_->host()->Show(); 109 110 // TODO(oshima): Start mirroring. 111 aura::Window* mirror_window = new aura::Window(NULL); 112 mirror_window->Init(aura::WINDOW_LAYER_TEXTURED); 113 root_window_->window()->AddChild(mirror_window); 114 mirror_window->SetBounds(root_window_->window()->bounds()); 115 mirror_window->Show(); 116 reflector_ = ui::ContextFactory::GetInstance()->CreateReflector( 117 Shell::GetPrimaryRootWindow()->GetDispatcher()->host()->compositor(), 118 mirror_window->layer()); 119 } else { 120 GetRootWindowSettings(root_window_->window())->display_id = 121 display_info.id(); 122 root_window_->host()->SetBounds(display_info.bounds_in_native()); 123 } 124 125 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 126 const DisplayInfo& source_display_info = display_manager->GetDisplayInfo( 127 Shell::GetScreen()->GetPrimaryDisplay().id()); 128 DCHECK(display_manager->IsMirrored()); 129 scoped_ptr<aura::RootWindowTransformer> transformer( 130 internal::CreateRootWindowTransformerForMirroredDisplay( 131 source_display_info, 132 display_info)); 133 root_window_->host()->SetRootWindowTransformer(transformer.Pass()); 134} 135 136void MirrorWindowController::UpdateWindow() { 137 if (root_window_.get()) { 138 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 139 const DisplayInfo& mirror_display_info = display_manager->GetDisplayInfo( 140 display_manager->mirrored_display_id()); 141 UpdateWindow(mirror_display_info); 142 } 143} 144 145void MirrorWindowController::Close() { 146 if (root_window_.get()) { 147 ui::ContextFactory::GetInstance()->RemoveReflector(reflector_); 148 reflector_ = NULL; 149 NoneCaptureClient* capture_client = static_cast<NoneCaptureClient*>( 150 aura::client::GetCaptureClient(root_window_->window())); 151 aura::client::SetCaptureClient(root_window_->window(), NULL); 152 delete capture_client; 153 154 root_window_->RemoveRootWindowObserver( 155 Shell::GetInstance()->display_controller()); 156 root_window_->RemoveRootWindowObserver(this); 157 root_window_.reset(); 158 } 159} 160 161void MirrorWindowController::OnWindowTreeHostResized( 162 const aura::RootWindow* root) { 163 // Do not use |old_size| as it contains RootWindow's (but not host's) size, 164 // and this parameter wil be removed soon. 165 if (mirror_window_host_size_ == root->host()->GetBounds().size()) 166 return; 167 mirror_window_host_size_ = root->host()->GetBounds().size(); 168 reflector_->OnMirroringCompositorResized(); 169 root_window_->host()->SetRootWindowTransformer( 170 CreateRootWindowTransformer().Pass()); 171 Shell::GetInstance()->display_controller()->cursor_window_controller()-> 172 UpdateLocation(); 173} 174 175 176scoped_ptr<aura::RootWindowTransformer> 177MirrorWindowController::CreateRootWindowTransformer() const { 178 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 179 const DisplayInfo& mirror_display_info = display_manager->GetDisplayInfo( 180 display_manager->mirrored_display_id()); 181 const DisplayInfo& source_display_info = display_manager->GetDisplayInfo( 182 Shell::GetScreen()->GetPrimaryDisplay().id()); 183 DCHECK(display_manager->IsMirrored()); 184 return scoped_ptr<aura::RootWindowTransformer>( 185 internal::CreateRootWindowTransformerForMirroredDisplay( 186 source_display_info, 187 mirror_display_info)); 188} 189 190} // namespace internal 191} // namespace ash 192