Port Android relocation packer to chromium build
[chromium-blink-merge.git] / ash / display / mirror_window_controller.cc
blob604cb895fe0c2cba4fc193580266fc34e83a474e
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.
5 #include "ash/display/mirror_window_controller.h"
7 #if defined(USE_X11)
8 #include <X11/Xlib.h>
9 #include <X11/extensions/XInput2.h>
11 // Xlib.h defines RootWindow.
12 #undef RootWindow
13 #endif
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"
36 #if defined(USE_X11)
37 #include "ui/gfx/x/x11_types.h"
38 #endif
40 namespace ash {
41 namespace {
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);
56 #endif
58 class NoneCaptureClient : public aura::client::CaptureClient {
59 public:
60 NoneCaptureClient() {}
61 ~NoneCaptureClient() override {}
63 private:
64 // Does a capture on the |window|.
65 void SetCapture(aura::Window* window) override {}
67 // Releases a capture from the |window|.
68 void ReleaseCapture(aura::Window* window) override {}
70 // Returns the current capture window.
71 aura::Window* GetCaptureWindow() override { return NULL; }
72 aura::Window* GetGlobalCaptureWindow() override { return NULL; }
74 DISALLOW_COPY_AND_ASSIGN(NoneCaptureClient);
77 } // namespace
79 MirrorWindowController::MirrorWindowController() {}
81 MirrorWindowController::~MirrorWindowController() {
82 // Make sure the root window gets deleted before cursor_window_delegate.
83 Close();
86 void MirrorWindowController::UpdateWindow(const DisplayInfo& display_info) {
87 static int mirror_host_count = 0;
88 if (!ash_host_.get()) {
89 AshWindowTreeHostInitParams init_params;
90 init_params.initial_bounds = display_info.bounds_in_native();
91 ash_host_.reset(AshWindowTreeHost::Create(init_params));
92 aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost();
93 host->window()->SetName(
94 base::StringPrintf("MirrorRootWindow-%d", mirror_host_count++));
95 host->compositor()->SetBackgroundColor(SK_ColorBLACK);
96 // No need to remove the observer because the DisplayController outlives the
97 // host.
98 host->AddObserver(Shell::GetInstance()->display_controller());
99 host->AddObserver(this);
100 // TODO(oshima): TouchHUD is using idkey.
101 InitRootWindowSettings(host->window())->display_id = display_info.id();
102 host->InitHost();
103 #if defined(USE_X11)
104 DisableInput(host->GetAcceleratedWidget());
105 #endif
107 aura::client::SetCaptureClient(host->window(), new NoneCaptureClient());
108 host->Show();
110 // TODO(oshima): Start mirroring.
111 aura::Window* mirror_window = new aura::Window(NULL);
112 mirror_window->Init(aura::WINDOW_LAYER_SOLID_COLOR);
113 host->window()->AddChild(mirror_window);
114 mirror_window->SetBounds(host->window()->bounds());
115 mirror_window->Show();
116 reflector_ = aura::Env::GetInstance()->context_factory()->CreateReflector(
117 Shell::GetPrimaryRootWindow()->GetHost()->compositor(),
118 mirror_window->layer());
119 } else {
120 aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost();
121 GetRootWindowSettings(host->window())->display_id = display_info.id();
122 host->SetBounds(display_info.bounds_in_native());
125 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
126 const DisplayInfo& source_display_info = display_manager->GetDisplayInfo(
127 Shell::GetScreen()->GetPrimaryDisplay().id());
128 DCHECK(display_manager->IsMirrored());
129 scoped_ptr<RootWindowTransformer> transformer(
130 CreateRootWindowTransformerForMirroredDisplay(source_display_info,
131 display_info));
132 ash_host_->SetRootWindowTransformer(transformer.Pass());
135 void MirrorWindowController::UpdateWindow() {
136 if (ash_host_.get()) {
137 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
138 const DisplayInfo& mirror_display_info = display_manager->GetDisplayInfo(
139 display_manager->mirrored_display_id());
140 UpdateWindow(mirror_display_info);
144 void MirrorWindowController::Close() {
145 if (ash_host_.get()) {
146 aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost();
147 aura::Env::GetInstance()->context_factory()->RemoveReflector(
148 reflector_.get());
149 reflector_ = nullptr;
150 NoneCaptureClient* capture_client = static_cast<NoneCaptureClient*>(
151 aura::client::GetCaptureClient(host->window()));
152 aura::client::SetCaptureClient(host->window(), NULL);
153 delete capture_client;
155 host->RemoveObserver(Shell::GetInstance()->display_controller());
156 host->RemoveObserver(this);
157 ash_host_.reset();
161 void MirrorWindowController::OnHostResized(const aura::WindowTreeHost* host) {
162 if (mirror_window_host_size_ == host->GetBounds().size())
163 return;
164 mirror_window_host_size_ = host->GetBounds().size();
165 reflector_->OnMirroringCompositorResized();
166 ash_host_->SetRootWindowTransformer(CreateRootWindowTransformer().Pass());
167 Shell::GetInstance()->display_controller()->cursor_window_controller()->
168 UpdateLocation();
171 aura::Window* MirrorWindowController::GetWindow() {
172 return ash_host_.get() ? ash_host_->AsWindowTreeHost()->window() : NULL;
175 scoped_ptr<RootWindowTransformer>
176 MirrorWindowController::CreateRootWindowTransformer() const {
177 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
178 const DisplayInfo& mirror_display_info = display_manager->GetDisplayInfo(
179 display_manager->mirrored_display_id());
180 const DisplayInfo& source_display_info = display_manager->GetDisplayInfo(
181 Shell::GetScreen()->GetPrimaryDisplay().id());
182 DCHECK(display_manager->IsMirrored());
183 return scoped_ptr<RootWindowTransformer>(
184 CreateRootWindowTransformerForMirroredDisplay(source_display_info,
185 mirror_display_info));
188 } // namespace ash