Home | History | Annotate | Download | only in display
      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