mirror_window_controller.cc revision a02191e04bc25c4935f804f2c080ae28663d096d
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/display/mirror_window_controller.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_X11) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/Xlib.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Xlib.h defines RootWindow. 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef RootWindow 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/display/cursor_window_controller.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/display/display_controller.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/display/display_info.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/display/display_manager.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/display/root_window_transformers.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/host/ash_window_tree_host.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/host/root_window_transformer.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/root_window_settings.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/strings/stringprintf.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/client/capture_client.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window_delegate.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window_tree_host.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/layout.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/reflector.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/native_widget_types.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_X11) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/x/x11_types.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ash { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_X11) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Mirror window shouldn't handle input events. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisableInput(XID window) { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) long event_mask = ExposureMask | VisibilityChangeMask | 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StructureNotifyMask | PropertyChangeMask; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XSelectInput(gfx::GetXDisplay(), window, event_mask); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NoneCaptureClient : public aura::client::CaptureClient { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NoneCaptureClient() {} 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~NoneCaptureClient() {} 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Does a capture on the |window|. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetCapture(aura::Window* window) OVERRIDE {} 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Releases a capture from the |window|. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void ReleaseCapture(aura::Window* window) OVERRIDE {} 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the current capture window. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual aura::Window* GetCaptureWindow() OVERRIDE { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual aura::Window* GetGlobalCaptureWindow() OVERRIDE { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(NoneCaptureClient); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MirrorWindowController::MirrorWindowController() {} 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MirrorWindowController::~MirrorWindowController() { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure the root window gets deleted before cursor_window_delegate. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Close(); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MirrorWindowController::UpdateWindow(const DisplayInfo& display_info) { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int mirror_host_count = 0; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ash_host_.get()) { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& bounds_in_native = display_info.bounds_in_native(); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ash_host_.reset(AshWindowTreeHost::Create(bounds_in_native)); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost(); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host->window()->SetName( 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPrintf("MirrorRootWindow-%d", mirror_host_count++)); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host->compositor()->SetBackgroundColor(SK_ColorBLACK); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No need to remove the observer because the DisplayController outlives the 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // host. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host->AddObserver(Shell::GetInstance()->display_controller()); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host->AddObserver(this); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(oshima): TouchHUD is using idkey. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitRootWindowSettings(host->window())->display_id = display_info.id(); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host->InitHost(); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_X11) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DisableInput(host->GetAcceleratedWidget()); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aura::client::SetCaptureClient(host->window(), new NoneCaptureClient()); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host->Show(); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(oshima): Start mirroring. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aura::Window* mirror_window = new aura::Window(NULL); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mirror_window->Init(aura::WINDOW_LAYER_TEXTURED); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 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 aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost(); 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<RootWindowTransformer> transformer( 124 CreateRootWindowTransformerForMirroredDisplay(source_display_info, 125 display_info)); 126 ash_host_->SetRootWindowTransformer(transformer.Pass()); 127} 128 129void MirrorWindowController::UpdateWindow() { 130 if (ash_host_.get()) { 131 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 132 const DisplayInfo& mirror_display_info = display_manager->GetDisplayInfo( 133 display_manager->mirrored_display_id()); 134 UpdateWindow(mirror_display_info); 135 } 136} 137 138void MirrorWindowController::Close() { 139 if (ash_host_.get()) { 140 aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost(); 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 ash_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 ash_host_->SetRootWindowTransformer(CreateRootWindowTransformer().Pass()); 160 Shell::GetInstance()->display_controller()->cursor_window_controller()-> 161 UpdateLocation(); 162} 163 164aura::Window* MirrorWindowController::GetWindow() { 165 return ash_host_.get() ? ash_host_->AsWindowTreeHost()->window() : NULL; 166} 167 168scoped_ptr<RootWindowTransformer> 169MirrorWindowController::CreateRootWindowTransformer() const { 170 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 171 const DisplayInfo& mirror_display_info = display_manager->GetDisplayInfo( 172 display_manager->mirrored_display_id()); 173 const DisplayInfo& source_display_info = display_manager->GetDisplayInfo( 174 Shell::GetScreen()->GetPrimaryDisplay().id()); 175 DCHECK(display_manager->IsMirrored()); 176 return scoped_ptr<RootWindowTransformer>( 177 CreateRootWindowTransformerForMirroredDisplay(source_display_info, 178 mirror_display_info)); 179} 180 181} // namespace ash 182