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> 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <X11/extensions/XInput2.h> 1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Xlib.h defines RootWindow. 1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#undef RootWindow 1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/display/cursor_window_controller.h" 16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ash/display/display_controller.h" 1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ash/display/display_info.h" 1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ash/display/display_manager.h" 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ash/display/root_window_transformers.h" 20a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ash/host/ash_window_tree_host.h" 21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ash/host/ash_window_tree_host_init_params.h" 22a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ash/host/root_window_transformer.h" 2358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ash/root_window_settings.h" 2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ash/shell.h" 25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/aura/client/capture_client.h" 2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ui/aura/env.h" 2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/aura/window_delegate.h" 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h" 30a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ui/aura/window_tree_host.h" 3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/base/layout.h" 32558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "ui/compositor/reflector.h" 3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/gfx/canvas.h" 3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/gfx/native_widget_types.h" 3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#if defined(USE_X11) 3768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/gfx/x/x11_types.h" 38d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif 39d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace ash { 4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace { 4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(USE_X11) 4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Mirror window shouldn't handle input events. 4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void DisableInput(XID window) { 4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) long event_mask = ExposureMask | VisibilityChangeMask | 4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) StructureNotifyMask | PropertyChangeMask; 4868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XSelectInput(gfx::GetXDisplay(), window, event_mask); 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci unsigned char mask[XIMaskLen(XI_LASTEVENT)] = {0}; 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci XIEventMask evmask; 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci evmask.deviceid = XIAllDevices; 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci evmask.mask_len = sizeof(mask); 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci evmask.mask = mask; 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci XISelectEvents(gfx::GetXDisplay(), window, &evmask, 1); 5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class NoneCaptureClient : public aura::client::CaptureClient { 5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public: 6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) NoneCaptureClient() {} 6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual ~NoneCaptureClient() {} 6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private: 6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Does a capture on the |window|. 6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual void SetCapture(aura::Window* window) OVERRIDE {} 6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Releases a capture from the |window|. 6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual void ReleaseCapture(aura::Window* window) OVERRIDE {} 6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Returns the current capture window. 7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual aura::Window* GetCaptureWindow() OVERRIDE { 7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return NULL; 7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) virtual aura::Window* GetGlobalCaptureWindow() OVERRIDE { 75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return NULL; 76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(NoneCaptureClient); 7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}; 8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace 8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)MirrorWindowController::MirrorWindowController() {} 8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)MirrorWindowController::~MirrorWindowController() { 8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Make sure the root window gets deleted before cursor_window_delegate. 87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Close(); 8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void MirrorWindowController::UpdateWindow(const DisplayInfo& display_info) { 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static int mirror_host_count = 0; 92a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (!ash_host_.get()) { 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) AshWindowTreeHostInitParams init_params; 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) init_params.initial_bounds = display_info.bounds_in_native(); 95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ash_host_.reset(AshWindowTreeHost::Create(init_params)); 96a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost(); 97a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch host->window()->SetName( 98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::StringPrintf("MirrorRootWindow-%d", mirror_host_count++)); 99a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch host->compositor()->SetBackgroundColor(SK_ColorBLACK); 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // No need to remove the observer because the DisplayController outlives the 101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // host. 102a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch host->AddObserver(Shell::GetInstance()->display_controller()); 103a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch host->AddObserver(this); 104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // TODO(oshima): TouchHUD is using idkey. 105a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch InitRootWindowSettings(host->window())->display_id = display_info.id(); 106a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch host->InitHost(); 10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(USE_X11) 108a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch DisableInput(host->GetAcceleratedWidget()); 10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 111a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch aura::client::SetCaptureClient(host->window(), new NoneCaptureClient()); 112a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch host->Show(); 113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // TODO(oshima): Start mirroring. 115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) aura::Window* mirror_window = new aura::Window(NULL); 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mirror_window->Init(aura::WINDOW_LAYER_TEXTURED); 117a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch host->window()->AddChild(mirror_window); 118a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch mirror_window->SetBounds(host->window()->bounds()); 119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) mirror_window->Show(); 12046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) reflector_ = aura::Env::GetInstance()->context_factory()->CreateReflector( 121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Shell::GetPrimaryRootWindow()->GetHost()->compositor(), 1221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) mirror_window->layer()); 123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else { 124a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost(); 125a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch GetRootWindowSettings(host->window())->display_id = display_info.id(); 126a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch host->SetBounds(display_info.bounds_in_native()); 127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const DisplayInfo& source_display_info = display_manager->GetDisplayInfo( 131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Shell::GetScreen()->GetPrimaryDisplay().id()); 1321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DCHECK(display_manager->IsMirrored()); 133a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch scoped_ptr<RootWindowTransformer> transformer( 134c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch CreateRootWindowTransformerForMirroredDisplay(source_display_info, 135c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch display_info)); 136a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch ash_host_->SetRootWindowTransformer(transformer.Pass()); 137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void MirrorWindowController::UpdateWindow() { 140a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (ash_host_.get()) { 141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const DisplayInfo& mirror_display_info = display_manager->GetDisplayInfo( 1431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) display_manager->mirrored_display_id()); 144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) UpdateWindow(mirror_display_info); 145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void MirrorWindowController::Close() { 149a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (ash_host_.get()) { 150a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost(); 15146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) aura::Env::GetInstance()->context_factory()->RemoveReflector(reflector_); 152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) reflector_ = NULL; 15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) NoneCaptureClient* capture_client = static_cast<NoneCaptureClient*>( 154a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch aura::client::GetCaptureClient(host->window())); 155a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch aura::client::SetCaptureClient(host->window(), NULL); 15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) delete capture_client; 157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 158a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch host->RemoveObserver(Shell::GetInstance()->display_controller()); 159a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch host->RemoveObserver(this); 160a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch ash_host_.reset(); 16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void MirrorWindowController::OnHostResized(const aura::WindowTreeHost* host) { 165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (mirror_window_host_size_ == host->GetBounds().size()) 166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) mirror_window_host_size_ = host->GetBounds().size(); 168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) reflector_->OnMirroringCompositorResized(); 169a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch ash_host_->SetRootWindowTransformer(CreateRootWindowTransformer().Pass()); 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Shell::GetInstance()->display_controller()->cursor_window_controller()-> 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UpdateLocation(); 1727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 1737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 174a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochaura::Window* MirrorWindowController::GetWindow() { 175a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return ash_host_.get() ? ash_host_->AsWindowTreeHost()->window() : NULL; 176a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 178a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochscoped_ptr<RootWindowTransformer> 1797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)MirrorWindowController::CreateRootWindowTransformer() const { 180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const DisplayInfo& mirror_display_info = display_manager->GetDisplayInfo( 1821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) display_manager->mirrored_display_id()); 183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const DisplayInfo& source_display_info = display_manager->GetDisplayInfo( 184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Shell::GetScreen()->GetPrimaryDisplay().id()); 1851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DCHECK(display_manager->IsMirrored()); 186a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return scoped_ptr<RootWindowTransformer>( 187c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch CreateRootWindowTransformerForMirroredDisplay(source_display_info, 188c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch mirror_display_info)); 189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace ash 192