mirror_window_controller.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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 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_host_count = 0; 83 84 if (!host_.get()) { 85 const gfx::Rect& bounds_in_native = display_info.bounds_in_native(); 86 host_.reset(Shell::GetInstance()->window_tree_host_factory()-> 87 CreateWindowTreeHost(bounds_in_native)); 88 host_->window()->SetName( 89 base::StringPrintf("MirrorRootWindow-%d", mirror_host_count++)); 90 host_->compositor()->SetBackgroundColor(SK_ColorBLACK); 91 // No need to remove the observer because the DisplayController outlives the 92 // host. 93 host_->AddObserver(Shell::GetInstance()->display_controller()); 94 host_->AddObserver(this); 95 // TODO(oshima): TouchHUD is using idkey. 96 InitRootWindowSettings(host_->window())->display_id = display_info.id(); 97 host_->InitHost(); 98#if defined(USE_X11) 99 DisableInput(host_->GetAcceleratedWidget()); 100#endif 101 102 aura::client::SetCaptureClient(host_->window(), new NoneCaptureClient()); 103 host_->Show(); 104 105 // TODO(oshima): Start mirroring. 106 aura::Window* mirror_window = new aura::Window(NULL); 107 mirror_window->Init(aura::WINDOW_LAYER_TEXTURED); 108 host_->window()->AddChild(mirror_window); 109 mirror_window->SetBounds(host_->window()->bounds()); 110 mirror_window->Show(); 111 reflector_ = ui::ContextFactory::GetInstance()->CreateReflector( 112 Shell::GetPrimaryRootWindow()->GetHost()->compositor(), 113 mirror_window->layer()); 114 } else { 115 GetRootWindowSettings(host_->window())->display_id = display_info.id(); 116 host_->SetBounds(display_info.bounds_in_native()); 117 } 118 119 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 120 const DisplayInfo& source_display_info = display_manager->GetDisplayInfo( 121 Shell::GetScreen()->GetPrimaryDisplay().id()); 122 DCHECK(display_manager->IsMirrored()); 123 scoped_ptr<aura::RootWindowTransformer> transformer( 124 internal::CreateRootWindowTransformerForMirroredDisplay( 125 source_display_info, 126 display_info)); 127 host_->SetRootWindowTransformer(transformer.Pass()); 128} 129 130void MirrorWindowController::UpdateWindow() { 131 if (host_.get()) { 132 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 133 const DisplayInfo& mirror_display_info = display_manager->GetDisplayInfo( 134 display_manager->mirrored_display_id()); 135 UpdateWindow(mirror_display_info); 136 } 137} 138 139void MirrorWindowController::Close() { 140 if (host_.get()) { 141 ui::ContextFactory::GetInstance()->RemoveReflector(reflector_); 142 reflector_ = NULL; 143 NoneCaptureClient* capture_client = static_cast<NoneCaptureClient*>( 144 aura::client::GetCaptureClient(host_->window())); 145 aura::client::SetCaptureClient(host_->window(), NULL); 146 delete capture_client; 147 148 host_->RemoveObserver(Shell::GetInstance()->display_controller()); 149 host_->RemoveObserver(this); 150 host_.reset(); 151 } 152} 153 154void MirrorWindowController::OnHostResized(const aura::WindowTreeHost* host) { 155 if (mirror_window_host_size_ == host->GetBounds().size()) 156 return; 157 mirror_window_host_size_ = host->GetBounds().size(); 158 reflector_->OnMirroringCompositorResized(); 159 host_->SetRootWindowTransformer(CreateRootWindowTransformer().Pass()); 160 Shell::GetInstance()->display_controller()->cursor_window_controller()-> 161 UpdateLocation(); 162} 163 164 165scoped_ptr<aura::RootWindowTransformer> 166MirrorWindowController::CreateRootWindowTransformer() const { 167 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 168 const DisplayInfo& mirror_display_info = display_manager->GetDisplayInfo( 169 display_manager->mirrored_display_id()); 170 const DisplayInfo& source_display_info = display_manager->GetDisplayInfo( 171 Shell::GetScreen()->GetPrimaryDisplay().id()); 172 DCHECK(display_manager->IsMirrored()); 173 return scoped_ptr<aura::RootWindowTransformer>( 174 internal::CreateRootWindowTransformerForMirroredDisplay( 175 source_display_info, 176 mirror_display_info)); 177} 178 179} // namespace internal 180} // namespace ash 181