mirror_window_controller.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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/ash_window_tree_host.h" 20#include "ash/host/ash_window_tree_host_init_params.h" 21#include "ash/host/root_window_transformer.h" 22#include "ash/root_window_settings.h" 23#include "ash/shell.h" 24#include "base/strings/stringprintf.h" 25#include "ui/aura/client/capture_client.h" 26#include "ui/aura/window_delegate.h" 27#include "ui/aura/window_event_dispatcher.h" 28#include "ui/aura/window_tree_host.h" 29#include "ui/base/layout.h" 30#include "ui/compositor/reflector.h" 31#include "ui/gfx/canvas.h" 32#include "ui/gfx/native_widget_types.h" 33 34#if defined(USE_X11) 35#include "ui/gfx/x/x11_types.h" 36#endif 37 38namespace ash { 39namespace { 40 41#if defined(USE_X11) 42// Mirror window shouldn't handle input events. 43void DisableInput(XID window) { 44 long event_mask = ExposureMask | VisibilityChangeMask | 45 StructureNotifyMask | PropertyChangeMask; 46 XSelectInput(gfx::GetXDisplay(), window, event_mask); 47} 48#endif 49 50class NoneCaptureClient : public aura::client::CaptureClient { 51 public: 52 NoneCaptureClient() {} 53 virtual ~NoneCaptureClient() {} 54 55 private: 56 // Does a capture on the |window|. 57 virtual void SetCapture(aura::Window* window) OVERRIDE {} 58 59 // Releases a capture from the |window|. 60 virtual void ReleaseCapture(aura::Window* window) OVERRIDE {} 61 62 // Returns the current capture window. 63 virtual aura::Window* GetCaptureWindow() OVERRIDE { 64 return NULL; 65 } 66 virtual aura::Window* GetGlobalCaptureWindow() OVERRIDE { 67 return NULL; 68 } 69 70 DISALLOW_COPY_AND_ASSIGN(NoneCaptureClient); 71}; 72 73} // namespace 74 75MirrorWindowController::MirrorWindowController() {} 76 77MirrorWindowController::~MirrorWindowController() { 78 // Make sure the root window gets deleted before cursor_window_delegate. 79 Close(); 80} 81 82void MirrorWindowController::UpdateWindow(const DisplayInfo& display_info) { 83 static int mirror_host_count = 0; 84 if (!ash_host_.get()) { 85 AshWindowTreeHostInitParams init_params; 86 init_params.initial_bounds = display_info.bounds_in_native(); 87 ash_host_.reset(AshWindowTreeHost::Create(init_params)); 88 aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost(); 89 host->window()->SetName( 90 base::StringPrintf("MirrorRootWindow-%d", mirror_host_count++)); 91 host->compositor()->SetBackgroundColor(SK_ColorBLACK); 92 // No need to remove the observer because the DisplayController outlives the 93 // host. 94 host->AddObserver(Shell::GetInstance()->display_controller()); 95 host->AddObserver(this); 96 // TODO(oshima): TouchHUD is using idkey. 97 InitRootWindowSettings(host->window())->display_id = display_info.id(); 98 host->InitHost(); 99#if defined(USE_X11) 100 DisableInput(host->GetAcceleratedWidget()); 101#endif 102 103 aura::client::SetCaptureClient(host->window(), new NoneCaptureClient()); 104 host->Show(); 105 106 // TODO(oshima): Start mirroring. 107 aura::Window* mirror_window = new aura::Window(NULL); 108 mirror_window->Init(aura::WINDOW_LAYER_TEXTURED); 109 host->window()->AddChild(mirror_window); 110 mirror_window->SetBounds(host->window()->bounds()); 111 mirror_window->Show(); 112 reflector_ = ui::ContextFactory::GetInstance()->CreateReflector( 113 Shell::GetPrimaryRootWindow()->GetHost()->compositor(), 114 mirror_window->layer()); 115 } else { 116 aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost(); 117 GetRootWindowSettings(host->window())->display_id = display_info.id(); 118 host->SetBounds(display_info.bounds_in_native()); 119 } 120 121 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 122 const DisplayInfo& source_display_info = display_manager->GetDisplayInfo( 123 Shell::GetScreen()->GetPrimaryDisplay().id()); 124 DCHECK(display_manager->IsMirrored()); 125 scoped_ptr<RootWindowTransformer> transformer( 126 CreateRootWindowTransformerForMirroredDisplay(source_display_info, 127 display_info)); 128 ash_host_->SetRootWindowTransformer(transformer.Pass()); 129} 130 131void MirrorWindowController::UpdateWindow() { 132 if (ash_host_.get()) { 133 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 134 const DisplayInfo& mirror_display_info = display_manager->GetDisplayInfo( 135 display_manager->mirrored_display_id()); 136 UpdateWindow(mirror_display_info); 137 } 138} 139 140void MirrorWindowController::Close() { 141 if (ash_host_.get()) { 142 aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost(); 143 ui::ContextFactory::GetInstance()->RemoveReflector(reflector_); 144 reflector_ = NULL; 145 NoneCaptureClient* capture_client = static_cast<NoneCaptureClient*>( 146 aura::client::GetCaptureClient(host->window())); 147 aura::client::SetCaptureClient(host->window(), NULL); 148 delete capture_client; 149 150 host->RemoveObserver(Shell::GetInstance()->display_controller()); 151 host->RemoveObserver(this); 152 ash_host_.reset(); 153 } 154} 155 156void MirrorWindowController::OnHostResized(const aura::WindowTreeHost* host) { 157 if (mirror_window_host_size_ == host->GetBounds().size()) 158 return; 159 mirror_window_host_size_ = host->GetBounds().size(); 160 reflector_->OnMirroringCompositorResized(); 161 ash_host_->SetRootWindowTransformer(CreateRootWindowTransformer().Pass()); 162 Shell::GetInstance()->display_controller()->cursor_window_controller()-> 163 UpdateLocation(); 164} 165 166aura::Window* MirrorWindowController::GetWindow() { 167 return ash_host_.get() ? ash_host_->AsWindowTreeHost()->window() : NULL; 168} 169 170scoped_ptr<RootWindowTransformer> 171MirrorWindowController::CreateRootWindowTransformer() const { 172 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 173 const DisplayInfo& mirror_display_info = display_manager->GetDisplayInfo( 174 display_manager->mirrored_display_id()); 175 const DisplayInfo& source_display_info = display_manager->GetDisplayInfo( 176 Shell::GetScreen()->GetPrimaryDisplay().id()); 177 DCHECK(display_manager->IsMirrored()); 178 return scoped_ptr<RootWindowTransformer>( 179 CreateRootWindowTransformerForMirroredDisplay(source_display_info, 180 mirror_display_info)); 181} 182 183} // namespace ash 184