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