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