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