mirror_window_controller.cc revision a02191e04bc25c4935f804f2c080ae28663d096d
10ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Copyright (c) 2013 The Chromium Authors. All rights reserved. 20ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Use of this source code is governed by a BSD-style license that can be 30ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// found in the LICENSE file. 40ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 50ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ash/display/mirror_window_controller.h" 60ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 70ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#if defined(USE_X11) 80ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include <X11/Xlib.h> 90ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 100ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Xlib.h defines RootWindow. 110ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#undef RootWindow 120ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#endif 130ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 140ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ash/display/cursor_window_controller.h" 150ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ash/display/display_controller.h" 160ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ash/display/display_info.h" 170ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ash/display/display_manager.h" 180ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ash/display/root_window_transformers.h" 190ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ash/host/ash_window_tree_host.h" 200ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ash/host/root_window_transformer.h" 210ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ash/root_window_settings.h" 220ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ash/shell.h" 230ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "base/strings/stringprintf.h" 240ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ui/aura/client/capture_client.h" 250ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ui/aura/window_delegate.h" 260ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ui/aura/window_event_dispatcher.h" 270ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ui/aura/window_tree_host.h" 280ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ui/base/layout.h" 290ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ui/compositor/reflector.h" 300ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ui/gfx/canvas.h" 310ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ui/gfx/native_widget_types.h" 320ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 330ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#if defined(USE_X11) 340ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ui/gfx/x/x11_types.h" 350ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#endif 360ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 370ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongnamespace ash { 380ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongnamespace { 390ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 400ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#if defined(USE_X11) 410ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Mirror window shouldn't handle input events. 420ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongvoid DisableInput(XID window) { 430ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong long event_mask = ExposureMask | VisibilityChangeMask | 440ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong StructureNotifyMask | PropertyChangeMask; 450ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong XSelectInput(gfx::GetXDisplay(), window, event_mask); 460ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong} 470ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#endif 480ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 490ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongclass NoneCaptureClient : public aura::client::CaptureClient { 500ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong public: 510ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong NoneCaptureClient() {} 520ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong virtual ~NoneCaptureClient() {} 530ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 540ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong private: 550ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Does a capture on the |window|. 560ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong virtual void SetCapture(aura::Window* window) OVERRIDE {} 570ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 580ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Releases a capture from the |window|. 590ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong virtual void ReleaseCapture(aura::Window* window) OVERRIDE {} 600ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 610ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Returns the current capture window. 620ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong virtual aura::Window* GetCaptureWindow() OVERRIDE { 630ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong return NULL; 640ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 650ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong virtual aura::Window* GetGlobalCaptureWindow() OVERRIDE { 660ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong return NULL; 670ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 680ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 690ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong DISALLOW_COPY_AND_ASSIGN(NoneCaptureClient); 700ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}; 710ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 720ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong} // namespace 730ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 740ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus KongMirrorWindowController::MirrorWindowController() {} 750ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 760ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus KongMirrorWindowController::~MirrorWindowController() { 770ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Make sure the root window gets deleted before cursor_window_delegate. 780ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong Close(); 790ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong} 800ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 810ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongvoid MirrorWindowController::UpdateWindow(const DisplayInfo& display_info) { 820ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong static int mirror_host_count = 0; 830ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong if (!ash_host_.get()) { 840ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong const gfx::Rect& bounds_in_native = display_info.bounds_in_native(); 850ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong ash_host_.reset(AshWindowTreeHost::Create(bounds_in_native)); 860ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost(); 870ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong host->window()->SetName( 880ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong base::StringPrintf("MirrorRootWindow-%d", mirror_host_count++)); 890ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong host->compositor()->SetBackgroundColor(SK_ColorBLACK); 900ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // No need to remove the observer because the DisplayController outlives the 910ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // host. 920ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong host->AddObserver(Shell::GetInstance()->display_controller()); 930ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong host->AddObserver(this); 940ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // TODO(oshima): TouchHUD is using idkey. 950ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong InitRootWindowSettings(host->window())->display_id = display_info.id(); 960ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong host->InitHost(); 970ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#if defined(USE_X11) 980ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong DisableInput(host->GetAcceleratedWidget()); 990ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#endif 1000ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1010ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong aura::client::SetCaptureClient(host->window(), new NoneCaptureClient()); 1020ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong host->Show(); 1030ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1040ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // TODO(oshima): Start mirroring. 1050ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong aura::Window* mirror_window = new aura::Window(NULL); 1060ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong mirror_window->Init(aura::WINDOW_LAYER_TEXTURED); 1070ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong host->window()->AddChild(mirror_window); 1080ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong mirror_window->SetBounds(host->window()->bounds()); 1090ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong mirror_window->Show(); 1100ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong reflector_ = ui::ContextFactory::GetInstance()->CreateReflector( 1110ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong Shell::GetPrimaryRootWindow()->GetHost()->compositor(), 1120ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong mirror_window->layer()); 1130ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } else { 1140ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost(); 1150ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong GetRootWindowSettings(host->window())->display_id = display_info.id(); 1160ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong host->SetBounds(display_info.bounds_in_native()); 1170ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 1180ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1190ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 1200ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong const DisplayInfo& source_display_info = display_manager->GetDisplayInfo( 1210ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong Shell::GetScreen()->GetPrimaryDisplay().id()); 1220ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong DCHECK(display_manager->IsMirrored()); 1230ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong scoped_ptr<RootWindowTransformer> transformer( 1240ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CreateRootWindowTransformerForMirroredDisplay(source_display_info, 1250ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong display_info)); 1260ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong ash_host_->SetRootWindowTransformer(transformer.Pass()); 1270ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong} 1280ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1290ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongvoid MirrorWindowController::UpdateWindow() { 1300ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong if (ash_host_.get()) { 1310ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 1320ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong const DisplayInfo& mirror_display_info = display_manager->GetDisplayInfo( 1330ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong display_manager->mirrored_display_id()); 1340ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong UpdateWindow(mirror_display_info); 1350ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 1360ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong} 1370ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1380ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongvoid MirrorWindowController::Close() { 1390ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong if (ash_host_.get()) { 1400ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost(); 1410ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong ui::ContextFactory::GetInstance()->RemoveReflector(reflector_); 1420ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong reflector_ = NULL; 1430ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong NoneCaptureClient* capture_client = static_cast<NoneCaptureClient*>( 1440ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong aura::client::GetCaptureClient(host->window())); 1450ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong aura::client::SetCaptureClient(host->window(), NULL); 1460ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong delete capture_client; 1470ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1480ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong host->RemoveObserver(Shell::GetInstance()->display_controller()); 1490ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong host->RemoveObserver(this); 1500ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong ash_host_.reset(); 1510ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 1520ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong} 1530ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1540ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongvoid MirrorWindowController::OnHostResized(const aura::WindowTreeHost* host) { 1550ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong if (mirror_window_host_size_ == host->GetBounds().size()) 1560ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong return; 1570ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong mirror_window_host_size_ = host->GetBounds().size(); 1580ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong reflector_->OnMirroringCompositorResized(); 1590ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong ash_host_->SetRootWindowTransformer(CreateRootWindowTransformer().Pass()); 1600ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong Shell::GetInstance()->display_controller()->cursor_window_controller()-> 1610ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong UpdateLocation(); 1620ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong} 1630ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1640ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongaura::Window* MirrorWindowController::GetWindow() { 1650ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong return ash_host_.get() ? ash_host_->AsWindowTreeHost()->window() : NULL; 1660ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong} 1670ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1680ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongscoped_ptr<RootWindowTransformer> 1690ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus KongMirrorWindowController::CreateRootWindowTransformer() const { 1700ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 1710ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong const DisplayInfo& mirror_display_info = display_manager->GetDisplayInfo( 1720ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong display_manager->mirrored_display_id()); 1730ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong const DisplayInfo& source_display_info = display_manager->GetDisplayInfo( 1740ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong Shell::GetScreen()->GetPrimaryDisplay().id()); 1750ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong DCHECK(display_manager->IsMirrored()); 1760ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong return scoped_ptr<RootWindowTransformer>( 1770ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CreateRootWindowTransformerForMirroredDisplay(source_display_info, 1780ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong mirror_display_info)); 1790ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong} 1800ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1810ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong} // namespace ash 1820ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong