190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file.
490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ash/display/mirror_window_controller.h"
690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(USE_X11)
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <X11/Xlib.h>
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <X11/extensions/XInput2.h>
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Xlib.h defines RootWindow.
1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#undef RootWindow
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/display/cursor_window_controller.h"
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ash/display/display_controller.h"
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ash/display/display_info.h"
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ash/display/display_manager.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ash/display/root_window_transformers.h"
20a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ash/host/ash_window_tree_host.h"
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ash/host/ash_window_tree_host_init_params.h"
22a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ash/host/root_window_transformer.h"
2358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ash/root_window_settings.h"
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ash/shell.h"
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/aura/client/capture_client.h"
2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ui/aura/env.h"
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/aura/window_delegate.h"
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h"
30a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ui/aura/window_tree_host.h"
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/base/layout.h"
32558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "ui/compositor/reflector.h"
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/gfx/canvas.h"
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/gfx/native_widget_types.h"
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#if defined(USE_X11)
3768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/gfx/x/x11_types.h"
38d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif
39d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace ash {
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace {
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(USE_X11)
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Mirror window shouldn't handle input events.
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void DisableInput(XID window) {
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  long event_mask = ExposureMask | VisibilityChangeMask |
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      StructureNotifyMask | PropertyChangeMask;
4868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  XSelectInput(gfx::GetXDisplay(), window, event_mask);
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  unsigned char mask[XIMaskLen(XI_LASTEVENT)] = {0};
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  XIEventMask evmask;
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  evmask.deviceid = XIAllDevices;
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  evmask.mask_len = sizeof(mask);
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  evmask.mask = mask;
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  XISelectEvents(gfx::GetXDisplay(), window, &evmask, 1);
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class NoneCaptureClient : public aura::client::CaptureClient {
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public:
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  NoneCaptureClient() {}
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual ~NoneCaptureClient() {}
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private:
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Does a capture on the |window|.
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void SetCapture(aura::Window* window) OVERRIDE {}
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Releases a capture from the |window|.
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void ReleaseCapture(aura::Window* window) OVERRIDE {}
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Returns the current capture window.
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual aura::Window* GetCaptureWindow() OVERRIDE {
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return NULL;
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual aura::Window* GetGlobalCaptureWindow() OVERRIDE {
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return NULL;
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(NoneCaptureClient);
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)};
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)MirrorWindowController::MirrorWindowController() {}
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)MirrorWindowController::~MirrorWindowController() {
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Make sure the root window gets deleted before cursor_window_delegate.
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Close();
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void MirrorWindowController::UpdateWindow(const DisplayInfo& display_info) {
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  static int mirror_host_count = 0;
92a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!ash_host_.get()) {
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    AshWindowTreeHostInitParams init_params;
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    init_params.initial_bounds = display_info.bounds_in_native();
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ash_host_.reset(AshWindowTreeHost::Create(init_params));
96a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost();
97a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    host->window()->SetName(
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        base::StringPrintf("MirrorRootWindow-%d", mirror_host_count++));
99a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    host->compositor()->SetBackgroundColor(SK_ColorBLACK);
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // No need to remove the observer because the DisplayController outlives the
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // host.
102a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    host->AddObserver(Shell::GetInstance()->display_controller());
103a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    host->AddObserver(this);
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // TODO(oshima): TouchHUD is using idkey.
105a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    InitRootWindowSettings(host->window())->display_id = display_info.id();
106a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    host->InitHost();
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(USE_X11)
108a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    DisableInput(host->GetAcceleratedWidget());
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
111a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    aura::client::SetCaptureClient(host->window(), new NoneCaptureClient());
112a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    host->Show();
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // TODO(oshima): Start mirroring.
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    aura::Window* mirror_window = new aura::Window(NULL);
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    mirror_window->Init(aura::WINDOW_LAYER_TEXTURED);
117a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    host->window()->AddChild(mirror_window);
118a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    mirror_window->SetBounds(host->window()->bounds());
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    mirror_window->Show();
12046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    reflector_ = aura::Env::GetInstance()->context_factory()->CreateReflector(
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        Shell::GetPrimaryRootWindow()->GetHost()->compositor(),
1221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        mirror_window->layer());
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
124a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost();
125a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    GetRootWindowSettings(host->window())->display_id = display_info.id();
126a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    host->SetBounds(display_info.bounds_in_native());
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DisplayManager* display_manager = Shell::GetInstance()->display_manager();
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const DisplayInfo& source_display_info = display_manager->GetDisplayInfo(
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      Shell::GetScreen()->GetPrimaryDisplay().id());
1321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(display_manager->IsMirrored());
133a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  scoped_ptr<RootWindowTransformer> transformer(
134c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      CreateRootWindowTransformerForMirroredDisplay(source_display_info,
135c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                                    display_info));
136a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  ash_host_->SetRootWindowTransformer(transformer.Pass());
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void MirrorWindowController::UpdateWindow() {
140a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (ash_host_.get()) {
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DisplayManager* display_manager = Shell::GetInstance()->display_manager();
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const DisplayInfo& mirror_display_info = display_manager->GetDisplayInfo(
1431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        display_manager->mirrored_display_id());
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    UpdateWindow(mirror_display_info);
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void MirrorWindowController::Close() {
149a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (ash_host_.get()) {
150a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost();
15146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    aura::Env::GetInstance()->context_factory()->RemoveReflector(reflector_);
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    reflector_ = NULL;
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    NoneCaptureClient* capture_client = static_cast<NoneCaptureClient*>(
154a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        aura::client::GetCaptureClient(host->window()));
155a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    aura::client::SetCaptureClient(host->window(), NULL);
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    delete capture_client;
157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
158a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    host->RemoveObserver(Shell::GetInstance()->display_controller());
159a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    host->RemoveObserver(this);
160a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    ash_host_.reset();
16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void MirrorWindowController::OnHostResized(const aura::WindowTreeHost* host) {
165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (mirror_window_host_size_ == host->GetBounds().size())
166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  mirror_window_host_size_ = host->GetBounds().size();
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  reflector_->OnMirroringCompositorResized();
169a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  ash_host_->SetRootWindowTransformer(CreateRootWindowTransformer().Pass());
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Shell::GetInstance()->display_controller()->cursor_window_controller()->
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      UpdateLocation();
1727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
174a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochaura::Window* MirrorWindowController::GetWindow() {
175a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return ash_host_.get() ? ash_host_->AsWindowTreeHost()->window() : NULL;
176a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
178a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochscoped_ptr<RootWindowTransformer>
1797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)MirrorWindowController::CreateRootWindowTransformer() const {
180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DisplayManager* display_manager = Shell::GetInstance()->display_manager();
181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const DisplayInfo& mirror_display_info = display_manager->GetDisplayInfo(
1821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      display_manager->mirrored_display_id());
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const DisplayInfo& source_display_info = display_manager->GetDisplayInfo(
184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      Shell::GetScreen()->GetPrimaryDisplay().id());
1851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(display_manager->IsMirrored());
186a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return scoped_ptr<RootWindowTransformer>(
187c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      CreateRootWindowTransformerForMirroredDisplay(source_display_info,
188c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                                    mirror_display_info));
189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace ash
192