mirror_window_controller.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file. 490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ash/display/mirror_window_controller.h" 690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(USE_X11) 890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <X11/Xlib.h> 990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Xlib.h defines RootWindow. 1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#undef RootWindow 1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/display/cursor_window_controller.h" 15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ash/display/display_controller.h" 1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ash/display/display_info.h" 1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ash/display/display_manager.h" 18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ash/display/root_window_transformers.h" 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/host/window_tree_host_factory.h" 2058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ash/root_window_settings.h" 2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ash/shell.h" 22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/aura/client/capture_client.h" 2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/aura/root_window.h" 25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/aura/root_window_transformer.h" 2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/aura/window_delegate.h" 2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/base/layout.h" 28558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "ui/compositor/reflector.h" 2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/gfx/canvas.h" 3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/gfx/native_widget_types.h" 3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 32d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#if defined(USE_X11) 3368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/gfx/x/x11_types.h" 34d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif 35d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace ash { 3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace internal { 3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace { 3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(USE_X11) 4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Mirror window shouldn't handle input events. 4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void DisableInput(XID window) { 4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) long event_mask = ExposureMask | VisibilityChangeMask | 4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) StructureNotifyMask | PropertyChangeMask; 4568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XSelectInput(gfx::GetXDisplay(), window, event_mask); 4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class NoneCaptureClient : public aura::client::CaptureClient { 5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public: 5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) NoneCaptureClient() {} 5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual ~NoneCaptureClient() {} 5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private: 5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Does a capture on the |window|. 5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual void SetCapture(aura::Window* window) OVERRIDE {} 5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Releases a capture from the |window|. 5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual void ReleaseCapture(aura::Window* window) OVERRIDE {} 6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Returns the current capture window. 6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual aura::Window* GetCaptureWindow() OVERRIDE { 6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return NULL; 6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) virtual aura::Window* GetGlobalCaptureWindow() OVERRIDE { 66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return NULL; 67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(NoneCaptureClient); 7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}; 7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace 7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)MirrorWindowController::MirrorWindowController() {} 7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)MirrorWindowController::~MirrorWindowController() { 7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Make sure the root window gets deleted before cursor_window_delegate. 78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Close(); 7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void MirrorWindowController::UpdateWindow(const DisplayInfo& display_info) { 8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) static int mirror_root_window_count = 0; 83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!root_window_.get()) { 8568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const gfx::Rect& bounds_in_native = display_info.bounds_in_native(); 8668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) aura::RootWindow::CreateParams params(bounds_in_native); 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) params.host = Shell::GetInstance()->window_tree_host_factory()-> 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateWindowTreeHost(bounds_in_native); 89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) root_window_.reset(new aura::RootWindow(params)); 90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) root_window_->window()->SetName( 91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::StringPrintf("MirrorRootWindow-%d", mirror_root_window_count++)); 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) root_window_->host()->compositor()->SetBackgroundColor(SK_ColorBLACK); 93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // No need to remove RootWindowObserver because 947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // the DisplayController object outlives RootWindow objects. 957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch root_window_->AddRootWindowObserver( 967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Shell::GetInstance()->display_controller()); 97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) root_window_->AddRootWindowObserver(this); 98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // TODO(oshima): TouchHUD is using idkey. 99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) InitRootWindowSettings(root_window_->window())->display_id = 100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) display_info.id(); 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) root_window_->host()->InitHost(); 10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(USE_X11) 103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DisableInput(root_window_->host()->GetAcceleratedWidget()); 10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) aura::client::SetCaptureClient(root_window_->window(), 107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) new NoneCaptureClient()); 108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) root_window_->host()->Show(); 109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // TODO(oshima): Start mirroring. 111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) aura::Window* mirror_window = new aura::Window(NULL); 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mirror_window->Init(aura::WINDOW_LAYER_TEXTURED); 113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) root_window_->window()->AddChild(mirror_window); 114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mirror_window->SetBounds(root_window_->window()->bounds()); 115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) mirror_window->Show(); 1161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) reflector_ = ui::ContextFactory::GetInstance()->CreateReflector( 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Shell::GetPrimaryRootWindow()->GetDispatcher()->host()->compositor(), 1181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) mirror_window->layer()); 119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else { 120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) GetRootWindowSettings(root_window_->window())->display_id = 121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) display_info.id(); 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) root_window_->host()->SetBounds(display_info.bounds_in_native()); 123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const DisplayInfo& source_display_info = display_manager->GetDisplayInfo( 127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Shell::GetScreen()->GetPrimaryDisplay().id()); 1281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DCHECK(display_manager->IsMirrored()); 129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<aura::RootWindowTransformer> transformer( 130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) internal::CreateRootWindowTransformerForMirroredDisplay( 131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) source_display_info, 132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) display_info)); 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) root_window_->host()->SetRootWindowTransformer(transformer.Pass()); 134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void MirrorWindowController::UpdateWindow() { 137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (root_window_.get()) { 138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const DisplayInfo& mirror_display_info = display_manager->GetDisplayInfo( 1401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) display_manager->mirrored_display_id()); 141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) UpdateWindow(mirror_display_info); 142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void MirrorWindowController::Close() { 14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (root_window_.get()) { 147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ui::ContextFactory::GetInstance()->RemoveReflector(reflector_); 148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) reflector_ = NULL; 14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) NoneCaptureClient* capture_client = static_cast<NoneCaptureClient*>( 150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) aura::client::GetCaptureClient(root_window_->window())); 151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) aura::client::SetCaptureClient(root_window_->window(), NULL); 15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) delete capture_client; 153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) root_window_->RemoveRootWindowObserver( 1557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Shell::GetInstance()->display_controller()); 156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) root_window_->RemoveRootWindowObserver(this); 15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) root_window_.reset(); 15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MirrorWindowController::OnWindowTreeHostResized( 1627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const aura::RootWindow* root) { 163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Do not use |old_size| as it contains RootWindow's (but not host's) size, 164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // and this parameter wil be removed soon. 165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (mirror_window_host_size_ == root->host()->GetBounds().size()) 166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mirror_window_host_size_ = root->host()->GetBounds().size(); 168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) reflector_->OnMirroringCompositorResized(); 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) root_window_->host()->SetRootWindowTransformer( 1707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) CreateRootWindowTransformer().Pass()); 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Shell::GetInstance()->display_controller()->cursor_window_controller()-> 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UpdateLocation(); 1737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 1747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)scoped_ptr<aura::RootWindowTransformer> 1777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)MirrorWindowController::CreateRootWindowTransformer() const { 178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const DisplayInfo& mirror_display_info = display_manager->GetDisplayInfo( 1801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) display_manager->mirrored_display_id()); 181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const DisplayInfo& source_display_info = display_manager->GetDisplayInfo( 182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Shell::GetScreen()->GetPrimaryDisplay().id()); 1831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DCHECK(display_manager->IsMirrored()); 1847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return scoped_ptr<aura::RootWindowTransformer>( 185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) internal::CreateRootWindowTransformerForMirroredDisplay( 186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) source_display_info, 187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) mirror_display_info)); 188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace internal 19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace ash 192