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