Upstream version 10.38.220.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 #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