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