• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
10 // Xlib.h defines RootWindow.
11 #undef RootWindow
12 #endif
13 
14 #include "ash/display/cursor_window_controller.h"
15 #include "ash/display/display_controller.h"
16 #include "ash/display/display_info.h"
17 #include "ash/display/display_manager.h"
18 #include "ash/display/root_window_transformers.h"
19 #include "ash/host/ash_window_tree_host.h"
20 #include "ash/host/ash_window_tree_host_init_params.h"
21 #include "ash/host/root_window_transformer.h"
22 #include "ash/root_window_settings.h"
23 #include "ash/shell.h"
24 #include "base/strings/stringprintf.h"
25 #include "ui/aura/client/capture_client.h"
26 #include "ui/aura/env.h"
27 #include "ui/aura/window_delegate.h"
28 #include "ui/aura/window_event_dispatcher.h"
29 #include "ui/aura/window_tree_host.h"
30 #include "ui/base/layout.h"
31 #include "ui/compositor/reflector.h"
32 #include "ui/gfx/canvas.h"
33 #include "ui/gfx/native_widget_types.h"
34 
35 #if defined(USE_X11)
36 #include "ui/gfx/x/x11_types.h"
37 #endif
38 
39 namespace ash {
40 namespace {
41 
42 #if defined(USE_X11)
43 // Mirror window shouldn't handle input events.
DisableInput(XID window)44 void DisableInput(XID window) {
45   long event_mask = ExposureMask | VisibilityChangeMask |
46       StructureNotifyMask | PropertyChangeMask;
47   XSelectInput(gfx::GetXDisplay(), window, event_mask);
48 }
49 #endif
50 
51 class NoneCaptureClient : public aura::client::CaptureClient {
52  public:
NoneCaptureClient()53   NoneCaptureClient() {}
~NoneCaptureClient()54   virtual ~NoneCaptureClient() {}
55 
56  private:
57   // Does a capture on the |window|.
SetCapture(aura::Window * window)58   virtual void SetCapture(aura::Window* window) OVERRIDE {}
59 
60   // Releases a capture from the |window|.
ReleaseCapture(aura::Window * window)61   virtual void ReleaseCapture(aura::Window* window) OVERRIDE {}
62 
63   // Returns the current capture window.
GetCaptureWindow()64   virtual aura::Window* GetCaptureWindow() OVERRIDE {
65     return NULL;
66   }
GetGlobalCaptureWindow()67   virtual aura::Window* GetGlobalCaptureWindow() OVERRIDE {
68     return NULL;
69   }
70 
71   DISALLOW_COPY_AND_ASSIGN(NoneCaptureClient);
72 };
73 
74 }  // namespace
75 
MirrorWindowController()76 MirrorWindowController::MirrorWindowController() {}
77 
~MirrorWindowController()78 MirrorWindowController::~MirrorWindowController() {
79   // Make sure the root window gets deleted before cursor_window_delegate.
80   Close();
81 }
82 
UpdateWindow(const DisplayInfo & display_info)83 void MirrorWindowController::UpdateWindow(const DisplayInfo& display_info) {
84   static int mirror_host_count = 0;
85   if (!ash_host_.get()) {
86     AshWindowTreeHostInitParams init_params;
87     init_params.initial_bounds = display_info.bounds_in_native();
88     ash_host_.reset(AshWindowTreeHost::Create(init_params));
89     aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost();
90     host->window()->SetName(
91         base::StringPrintf("MirrorRootWindow-%d", mirror_host_count++));
92     host->compositor()->SetBackgroundColor(SK_ColorBLACK);
93     // No need to remove the observer because the DisplayController outlives the
94     // host.
95     host->AddObserver(Shell::GetInstance()->display_controller());
96     host->AddObserver(this);
97     // TODO(oshima): TouchHUD is using idkey.
98     InitRootWindowSettings(host->window())->display_id = display_info.id();
99     host->InitHost();
100 #if defined(USE_X11)
101     DisableInput(host->GetAcceleratedWidget());
102 #endif
103 
104     aura::client::SetCaptureClient(host->window(), new NoneCaptureClient());
105     host->Show();
106 
107     // TODO(oshima): Start mirroring.
108     aura::Window* mirror_window = new aura::Window(NULL);
109     mirror_window->Init(aura::WINDOW_LAYER_TEXTURED);
110     host->window()->AddChild(mirror_window);
111     mirror_window->SetBounds(host->window()->bounds());
112     mirror_window->Show();
113     reflector_ = aura::Env::GetInstance()->context_factory()->CreateReflector(
114         Shell::GetPrimaryRootWindow()->GetHost()->compositor(),
115         mirror_window->layer());
116   } else {
117     aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost();
118     GetRootWindowSettings(host->window())->display_id = display_info.id();
119     host->SetBounds(display_info.bounds_in_native());
120   }
121 
122   DisplayManager* display_manager = Shell::GetInstance()->display_manager();
123   const DisplayInfo& source_display_info = display_manager->GetDisplayInfo(
124       Shell::GetScreen()->GetPrimaryDisplay().id());
125   DCHECK(display_manager->IsMirrored());
126   scoped_ptr<RootWindowTransformer> transformer(
127       CreateRootWindowTransformerForMirroredDisplay(source_display_info,
128                                                     display_info));
129   ash_host_->SetRootWindowTransformer(transformer.Pass());
130 }
131 
UpdateWindow()132 void MirrorWindowController::UpdateWindow() {
133   if (ash_host_.get()) {
134     DisplayManager* display_manager = Shell::GetInstance()->display_manager();
135     const DisplayInfo& mirror_display_info = display_manager->GetDisplayInfo(
136         display_manager->mirrored_display_id());
137     UpdateWindow(mirror_display_info);
138   }
139 }
140 
Close()141 void MirrorWindowController::Close() {
142   if (ash_host_.get()) {
143     aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost();
144     aura::Env::GetInstance()->context_factory()->RemoveReflector(reflector_);
145     reflector_ = NULL;
146     NoneCaptureClient* capture_client = static_cast<NoneCaptureClient*>(
147         aura::client::GetCaptureClient(host->window()));
148     aura::client::SetCaptureClient(host->window(), NULL);
149     delete capture_client;
150 
151     host->RemoveObserver(Shell::GetInstance()->display_controller());
152     host->RemoveObserver(this);
153     ash_host_.reset();
154   }
155 }
156 
OnHostResized(const aura::WindowTreeHost * host)157 void MirrorWindowController::OnHostResized(const aura::WindowTreeHost* host) {
158   if (mirror_window_host_size_ == host->GetBounds().size())
159     return;
160   mirror_window_host_size_ = host->GetBounds().size();
161   reflector_->OnMirroringCompositorResized();
162   ash_host_->SetRootWindowTransformer(CreateRootWindowTransformer().Pass());
163   Shell::GetInstance()->display_controller()->cursor_window_controller()->
164       UpdateLocation();
165 }
166 
GetWindow()167 aura::Window* MirrorWindowController::GetWindow() {
168   return ash_host_.get() ? ash_host_->AsWindowTreeHost()->window() : NULL;
169 }
170 
171 scoped_ptr<RootWindowTransformer>
CreateRootWindowTransformer() const172 MirrorWindowController::CreateRootWindowTransformer() const {
173   DisplayManager* display_manager = Shell::GetInstance()->display_manager();
174   const DisplayInfo& mirror_display_info = display_manager->GetDisplayInfo(
175       display_manager->mirrored_display_id());
176   const DisplayInfo& source_display_info = display_manager->GetDisplayInfo(
177       Shell::GetScreen()->GetPrimaryDisplay().id());
178   DCHECK(display_manager->IsMirrored());
179   return scoped_ptr<RootWindowTransformer>(
180       CreateRootWindowTransformerForMirroredDisplay(source_display_info,
181                                                     mirror_display_info));
182 }
183 
184 }  // namespace ash
185