Commit 0ab13293 authored by Antonio Gomes's avatar Antonio Gomes Committed by Santosh Mahto

c++ / mojo changes for 'external window mode'

This CL is the first step towards having 'external window mode' support
in Mus. The existing MusDemo is adapted to test the functionality,
and its respective unit test (mus_demo_unittests) is changed to
exercise  multiple external windows creation in a follow up CL [2].

[2] https://codereview.chromium.org/2715533005/

New code flow:

* MusDemoExternal creates and holds a WindowTreeClient instance.

Note: In Chrome, it also happens in
c/b/ui/views/chrome_browser_main_extra_parts_views.cc,
::ServiceManagerConnectionStarted, when MusClient is created.

* MusDemoExternal calls WindowTreeClient::ConnectViaWindowTreeHostFactory.
This "enters" WindowTreeClient in 'external window mode', and
creates a WindowTreeHostFactoryRegistrar instance.
Through this object, WindowTreeHostFactoryRegistrar::Register is
called, creating WindowTree and WindowTreeHostFactory instances on
the server side, and acquiring WindowTree and
WindowTreeHostFactory mojo handles on the client side.

Note: In external window mode, the WindowTree and WindowTreeHostFactory
are unique instances, serving 0 or 'n' WindowTreeHostMus instances.

* Yet from MusDemoExternal, WindowTreeHostMus instance(s) are
created, in accordance to the value passed to command line
parameter --external-window-count, or 1 by default.

Note: In Chrome, this happens in
c/b/ui/views/frame/browser_frame_mus.cc, ::GetWidgetParams when
DesktopWindowTreeHostMus is created for each outer platform window.

WindowTreeHostMus ctor takes a WindowTreeClient instance which
works as a "window tree host delegate".

* During the creation chain of WindowTreeHostMus, WindowTreeClient::CreateWindowPortForTopLevel
is called, and this is what calls the newly added method
WindowTreeHostFactory::CreatePlatformWindow, when in 'external
window mode'. That is the entry point of of ws::Display instance
creation.

* In the existing creation flow of ws::Display, the server
actually calls back to the client via WindowTreeClient::OnEmbed
when it is done. In 'external window mode' this callback is kept,
but it passes a 'null' WindowTree object as parameter.
Why? Because in ::ConnectViaWindowTreeHostFactory (above) the
unique WindowTree instance was already created.

* services/ui/ws/window_tree_host_factory_registrar.cc|h:

  This class implements WindowTreeHostFactoryRegistrar class.
  It exposes a ::Register method, that:

    (a) Binds the mojom::WindowTreeHostFactoryRequest
    (b) Binds the mojom::WindowTreeRequest
    (c) Stores the mojom::WindowTreeClientPtr to call out
        WindowTreeClient later on.
    (d) A ws::WindowTree instance is also created here. It ensures
        single WindowTree and WindowTreeClient instances serving
        various WindowTreeHost instances.

  The goal of the WindowTreeHostFactoryRegistrar interface is
  to ensure a WindowTreeHostFactory::CreatePlatformWindow can not
  be called before WindowTreeHostFactory being properly set up.

* services/ui/ws/window_tree_host_factory.cc|h:

  Adds ::CreatePlatformWindow method so that it triggers the
  creation of per-outer-window ws::Display instances in external
  window mode.

TODO (in follow up CLs):

  1) Factor non-specific WindowManager specific bits out of
  ws::WindowManagerState, so that event dispatching code can be
  shared between internal and external window modes.

  2) Rename WindowManagerDisplayRoot since it is used in non-WindowManager
  path.

  3) Clean up mus_demo_external (launch instances in parallel?).

  4) Clean up WindowTreeClient::OnEmbed flow.

  5) Experiment with launching Chrome in external window mode.

BUG=666958

patch from issue 2712203002 at patchset 240001 (http://crrev.com/2712203002#ps240001)

Conflicts:
	services/ui/service.cc
	services/ui/service.h
	ui/aura/mus/window_tree_client.cc

fixup! c++ / mojo changes for 'external window mode'

In external window mode, it makes no sense to call
DisplayManager::OnDisplayUpdate when a ws::Display is
initialized.

First because ws::Display has not information about
display::Display instances. Second because ws::Display::display_
is solely to be used in internal window mode, as per the comment
in the header.

Conflicts:
	services/ui/ws/mus_ws_unittests_app_manifest.json
	services/ui/ws/window_server.h
	ui/aura/mus/window_tree_client.h

fixup! c++ / mojo changes for 'external window mode'

This CL makes the WindowTreeClient awaits on the WindowTree
connection to establish before it continues.

Before this, there was a mismatch between the values of
WindowTreeClient::client_id_ and the WindowTree::id_. The
reason was because the former was only updated when
WindowTreeClient::OnEmbed was called.

With the patch, we behave similarly to (m)ash, where it awaits for
the WindowTreeClient::OnConnect call, where the WTC::client_id_ is
set.

This fixes one of the blockers on using WindowManagerAccessPolicy
for both chrome/mus_demo and unittests.

fixup! c++ / mojo changes for 'external window mode'

This fixes a crash in touch handling.

Issue #100

fixup! c++ / mojo changes for 'external window mode'

Patch makes WindowTreeHostFactory an associated interface of WindowTree,
in external window mode.
This allows both interfaces to share the same mojo pipe, ensuring
ordering of messages.

This is important because during the creation of windows/ws::Display's,
WindowTreeHostFactory::CreatePlatformWindow messages concurs with
subsequent WindowTree method calls, causing non-deterministic crashes
in chrome/mus.

In summary, the patch:

- renames WindowTreeHostFactoryRegistrar to ExternalWindowTreeFactory.
- removes the use/logic of the WindowTreeHostFactoryRequest from the
  ::Registrar method.
- adds a WindowTree::GetWindowTreeHostFactory method that takes an
  associated interface request.
- adapts call sites accordingly.

In the end the new ExternalWindowTreeFactory flow works more similarly
to WindowTreeFactory's and WindowManagerWindowTreeFactory's.

Issue #161.

fixup! c++ / mojo changes for 'external window mode'

Avoid double initialization of WindowTreeHost: after
https://chromium-review.googlesource.com/c/606933 commit, the
chromium browser on Linux build with ozone has stopped to
start. It has always been observing a crash due to a DCHECK
in WindowTreeHost::InitCompositor(), which checked that
the compositor must not have a root_layer() set.

The reason of hitting the DCHECK is that the very first initialization
is always done during the browser start up:

6 0x7f4ff06c0981 views::DesktopNativeWidgetAura::InitNativeWidget()
7 0x7f4ff0682405 views::Widget::Init()
8 0x55e62a03742c BrowserFrame::InitBrowserFrame()
9 0x55e629d227e9 BrowserWindow::CreateBrowserWindow()
10 0x55e629b3d4e5 (anonymous namespace)::CreateBrowserWindow()
11 0x55e629b3cb79 Browser::Browser()
12 0x55e629b9b1b2 StartupBrowserCreatorImpl::OpenTabsInBrowser()
13 0x55e629b9cffa StartupBrowserCreatorImpl::RestoreOrCreateBrowser()
14 0x55e629b9a6a6 StartupBrowserCreatorImpl::ProcessLaunchUrlsUsingConsolidatedFlow()
15 0x55e629b99742 StartupBrowserCreatorImpl::Launch()
16 0x55e629b93a72 StartupBrowserCreator::LaunchBrowser()
17 0x55e629b929d4 StartupBrowserCreator::ProcessCmdLineImpl()
18 0x55e629b91102 StartupBrowserCreator::Start()
19 0x55e626f60fc7 ChromeBrowserMainParts::PreMainMessageLoopRunImpl()
20 0x55e626f5f8bc ChromeBrowserMainParts::PreMainMessageLoopRun()
21 0x7f4ff563c574 content::BrowserMainLoop::PreMainMessageLoopRun()

After this when WindowTreeClient::OnEmbed() is called,
we used to call window_tree_host->InitHost() second time and then
crash.

What is more, in order to mimic standart browser creation,
make WindowTreeDataExternal to call InitHost() before allowing
to calling to create an actual window.

fixup!  c++ / mojo changes for 'external window mode'

Adapt to https://chromium-review.googlesource.com/c/chromium/src/+/617378.

fixup! c++ / mojo changes for 'external window mode'

Remove this secondary blocking Wait call [1], since it was
causing Mus to hang undeterministically.

Valid displays will be awaited in ScreenMus.

[1] https://github.com/Igalia/chromium/pull/129/

Issue #212
parent 015f3ed1
......@@ -48,7 +48,8 @@
"pdf_to_pwg_raster_converter": [ "converter" ],
"preferences": [ "pref_client", "pref_control" ],
"ui": [
"display_dev",
"display_controller",
"external_window_tree_factory",
"ime_registrar",
"input_device_controller",
"window_manager"
......
......@@ -4,7 +4,7 @@
"interface_provider_specs": {
"service_manager:connector": {
"requires": {
"ui": [ "window_manager", "window_tree_host_factory" ]
"ui": [ "external_window_tree_factory", "window_manager" ]
}
}
}
......
......@@ -22,19 +22,16 @@ namespace {
class WindowTreeDataExternal : public WindowTreeData {
public:
// Creates a new window tree host associated to the WindowTreeData.
WindowTreeDataExternal(mojom::WindowTreeHostFactory* factory,
mojom::WindowTreeClientPtr tree_client,
WindowTreeDataExternal(aura::WindowTreeClient* window_tree_client,
int square_size)
: WindowTreeData(square_size) {
// TODO(tonikitoo,fwang): Extend the API to allow creating WindowTreeHost
// using the WindowTreeClient.
factory->CreateWindowTreeHost(MakeRequest(&host_), std::move(tree_client));
std::unique_ptr<aura::WindowTreeHostMus> tree_host =
base::MakeUnique<aura::WindowTreeHostMus>(window_tree_client));
tree_host->InitHost();
SetWindowTreeHost(std::move(tree_host));
}
private:
// Holds the Mojo pointer to the window tree host.
mojom::WindowTreeHostPtr host_;
DISALLOW_COPY_AND_ASSIGN(WindowTreeDataExternal);
};
......@@ -50,9 +47,7 @@ MusDemoExternal::~MusDemoExternal() {}
std::unique_ptr<aura::WindowTreeClient>
MusDemoExternal::CreateWindowTreeClient() {
return base::MakeUnique<aura::WindowTreeClient>(
context()->connector(), this, nullptr,
MakeRequest(&window_tree_client_mojo_));
return base::MakeUnique<aura::WindowTreeClient>(context()->connector(), this);
}
void MusDemoExternal::OnStartImpl() {
......@@ -67,38 +62,31 @@ void MusDemoExternal::OnStartImpl() {
}
}
// TODO(tonikitoo,fwang): Extend the WindowTreeClient API to allow connection
// to the window tree host factory using window_tree_client().
context()->connector()->BindInterface(ui::mojom::kServiceName,
&window_tree_host_factory_);
window_tree_client()->ConnectViaWindowTreeHostFactory();
// TODO(tonikitoo,fwang): Implement management of displays in external mode.
// For now, a fake display is created in order to work around an assertion in
// aura::GetDeviceScaleFactorFromDisplay().
AddPrimaryDisplay(display::Display(0));
// The number of windows to open is specified by number_of_windows_. The
// windows are opened sequentially (the first one here and the others after
// each call to OnEmbed) to ensure that the WindowTreeHostMus passed to
// OnEmbed corresponds to the WindowTreeDataExternal::host_ created in
// OpenNewWindow.
// TODO(tonikitoo,fwang): New windows can be launched without need to wait
// the respective ::OnEmbed call of the previous instance.
OpenNewWindow();
}
void MusDemoExternal::OpenNewWindow() {
// TODO(tonikitoo,fwang): Extend the WindowTreeClient API to allow creation
// of window tree host. Then pass window_tree_client() here and remove
// window_tree_host_factory_ and window_tree_client_mojo_. Currently
// window_tree_client_mojo_ is only initialized once so this is incorrect when
// kNumberOfWindows > 1.
AppendWindowTreeData(base::MakeUnique<WindowTreeDataExternal>(
window_tree_host_factory_.get(), std::move(window_tree_client_mojo_),
window_tree_client(),
GetSquareSizeForWindow(initialized_windows_count_)));
}
void MusDemoExternal::OnEmbed(
std::unique_ptr<aura::WindowTreeHostMus> window_tree_host) {
InitWindowTreeData(std::move(window_tree_host));
DCHECK(!window_tree_host);
// TODO: Clean up WindowTreeClientDelegate::OnEmbed API so that it passes
// no ownership of WindowTreeHostMus instance.
InitWindowTreeData(nullptr);
initialized_windows_count_++;
// Open the next window until the requested number of windows is reached.
......
......@@ -9,7 +9,6 @@
#include <vector>
#include "services/ui/demo/mus_demo.h"
#include "services/ui/public/interfaces/window_tree_host.mojom.h"
namespace ui {
namespace demo {
......@@ -32,8 +31,6 @@ class MusDemoExternal : public MusDemo {
void OnEmbed(std::unique_ptr<aura::WindowTreeHostMus> window_tree_host) final;
void OnEmbedRootDestroyed(aura::WindowTreeHostMus* window_tree_host) final;
mojom::WindowTreeHostFactoryPtr window_tree_host_factory_;
mojom::WindowTreeClientPtr window_tree_client_mojo_;
size_t initialized_windows_count_ = 0;
size_t number_of_windows_ = 1;
......
......@@ -68,9 +68,10 @@ aura::Window* WindowTreeData::bitmap_window() {
void WindowTreeData::Init(
std::unique_ptr<aura::WindowTreeHostMus> window_tree_host) {
window_tree_host->Show();
// Take ownership of the WTH.
window_tree_host_ = std::move(window_tree_host);
if (window_tree_host) {
window_tree_host->Show();
SetWindowTreeHost(std::move(window_tree_host));
}
// Initialize the window for the bitmap.
window_delegate_ = new aura_extra::ImageWindowDelegate();
......
......@@ -27,12 +27,18 @@ class WindowTreeData {
// Initializes the window tree host and start drawing frames.
void Init(std::unique_ptr<aura::WindowTreeHostMus> window_tree_host);
bool IsInitialized() const { return !!window_tree_host_; }
bool IsInitialized() const { return window_delegate_; }
const aura::WindowTreeHostMus* WindowTreeHost() const {
return window_tree_host_.get();
}
protected:
void SetWindowTreeHost(
std::unique_ptr<aura::WindowTreeHostMus> window_tree_host) {
window_tree_host_ = std::move(window_tree_host);
}
private:
// Draws one frame, incrementing the rotation angle.
void DrawFrame();
......
......@@ -72,6 +72,9 @@
],
"window_tree_host_factory": [
"ui::mojom::WindowTreeHostFactory"
],
"external_window_tree_factory": [
"ui::mojom::ExternalWindowTreeFactory"
]
},
"requires": {
......
......@@ -11,6 +11,7 @@ mojom("interfaces") {
"clipboard.mojom",
"display_manager.mojom",
"event_matcher.mojom",
"external_window_tree_factory.mojom",
"gpu.mojom",
"mus_constants.mojom",
"remote_event_dispatcher.mojom",
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
module ui.mojom;
import "services/ui/public/interfaces/window_tree.mojom";
import "services/ui/public/interfaces/window_tree_host.mojom";
// ExternalWindowTreeFactory is the entry point to obtain a
// WindowTree instance in 'external window mode'.
// Callers obtain a mojo handle to the unique ws::WindowTree instance,
// on the server-side.
//
// NOTE: WindowTreeHostFactoryRegistrar::Register and
// WindowTreeHostFactory::CreatePlatformWindow are put on separate interfaces,
// so that the interface containing ::CreatePlatformWindow is obtained by
// calling ::Register. That eliminates the possibility of ::CreatePlatformWindow
// being called before ::Register.
interface ExternalWindowTreeFactory {
Register(WindowTree& tree_request,
WindowTreeClient client);
};
......@@ -11,6 +11,7 @@ import "services/ui/public/interfaces/mus_constants.mojom";
import "services/ui/public/interfaces/window_manager.mojom";
import "services/ui/public/interfaces/window_manager_constants.mojom";
import "services/ui/public/interfaces/window_tree_constants.mojom";
import "services/ui/public/interfaces/window_tree_host.mojom";
import "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom";
import "services/viz/public/interfaces/compositing/frame_sink_id.mojom";
import "services/viz/public/interfaces/compositing/local_surface_id.mojom";
......@@ -308,6 +309,10 @@ interface WindowTree {
// Tells the window manager to perform |string_action| for |window_id|.
PerformWmAction(uint32 window_id, string action);
// Gets the (singleton) instance of WindowTreeHostFactory, as an associated
// interface of WindowTree. This allows them to share the same mojo message
// pipe, ensuring ordering of messages.
GetWindowTreeHostFactory(associated WindowTreeHostFactory& request);
// See description of WindowManager for details.
GetWindowManagerClient(associated WindowManagerClient& internal);
......
......@@ -4,7 +4,6 @@
module ui.mojom;
import "services/ui/public/interfaces/window_tree.mojom";
import "ui/gfx/geometry/mojo/geometry.mojom";
// WindowTreeHost encapsulates a unique underlying platform window, with a tree
......@@ -17,9 +16,10 @@ interface WindowTreeHost {
SetTitle(string title);
};
// WindowTreeHostFactory triggers the creation of WindowTreeHost instances.
interface WindowTreeHostFactory {
// Creates a new WindowTreeHost. |tree_client| is queried for the
// WindowManager.
CreateWindowTreeHost(WindowTreeHost& window_tree_host,
WindowTreeClient tree_client);
// Creates a new WindowTreeHost in 'external window mode'.
// One WindowTree/WindowTreeClient pair can serve one or more WindowTreeHost
// instances.
CreatePlatformWindow(WindowTreeHost& window_tree_host, uint32 client_id);
};
......@@ -30,6 +30,7 @@
#include "services/ui/ws/display_binding.h"
#include "services/ui/ws/display_creation_config.h"
#include "services/ui/ws/display_manager.h"
#include "services/ui/ws/external_window_tree_factory.h"
#include "services/ui/ws/gpu_host.h"
#include "services/ui/ws/remote_event_dispatcher.h"
#include "services/ui/ws/threaded_image_cursors.h"
......@@ -41,7 +42,6 @@
#include "services/ui/ws/window_tree.h"
#include "services/ui/ws/window_tree_binding.h"
#include "services/ui/ws/window_tree_factory.h"
#include "services/ui/ws/window_tree_host_factory.h"
#include "ui/base/cursor/image_cursors.h"
#include "ui/base/platform_window_defaults.h"
#include "ui/base/resource/resource_bundle.h"
......@@ -68,7 +68,6 @@
using mojo::InterfaceRequest;
using ui::mojom::WindowServerTest;
using ui::mojom::WindowTreeHostFactory;
namespace ui {
......@@ -132,7 +131,6 @@ struct Service::PendingRequest {
struct Service::UserState {
std::unique_ptr<clipboard::ClipboardImpl> clipboard;
std::unique_ptr<ws::AccessibilityManager> accessibility;
std::unique_ptr<ws::WindowTreeHostFactory> window_tree_host_factory;
};
Service::InProcessConfig::InProcessConfig() = default;
......@@ -307,8 +305,9 @@ void Service::OnStart() {
registry_with_source_info_.AddInterface<mojom::UserActivityMonitor>(
base::Bind(&Service::BindUserActivityMonitorRequest,
base::Unretained(this)));
registry_with_source_info_.AddInterface<WindowTreeHostFactory>(base::Bind(
&Service::BindWindowTreeHostFactoryRequest, base::Unretained(this)));
registry_with_source_info_.AddInterface<mojom::ExternalWindowTreeFactory>(
base::Bind(&Service::BindExternalWindowTreeFactoryRequest,
base::Unretained(this)));
registry_with_source_info_
.AddInterface<mojom::WindowManagerWindowTreeFactory>(
base::Bind(&Service::BindWindowManagerWindowTreeFactoryRequest,
......@@ -513,15 +512,15 @@ void Service::BindWindowTreeFactoryRequest(
std::move(request));
}
void Service::BindWindowTreeHostFactoryRequest(
mojom::WindowTreeHostFactoryRequest request,
void Service::BindExternalWindowTreeFactoryRequest(
mojom::ExternalWindowTreeFactoryRequest request,
const service_manager::BindSourceInfo& source_info) {
UserState* user_state = GetUserState(source_info.identity);
if (!user_state->window_tree_host_factory) {
user_state->window_tree_host_factory.reset(new ws::WindowTreeHostFactory(
window_server_.get(), source_info.identity.user_id()));
}
user_state->window_tree_host_factory->AddBinding(std::move(request));
AddUserIfNecessary(source_info.identity);
mojo::MakeStrongBinding(
base::MakeUnique<ws::ExternalWindowTreeFactory>(
window_server_.get(), source_info.identity.user_id()),
std::move(request));
window_server_->SetInExternalWindowMode();
}
void Service::BindDiscardableSharedMemoryManagerRequest(
......
......@@ -26,6 +26,7 @@
#include "services/ui/public/interfaces/accessibility_manager.mojom.h"
#include "services/ui/public/interfaces/clipboard.mojom.h"
#include "services/ui/public/interfaces/display_manager.mojom.h"
#include "services/ui/public/interfaces/external_window_tree_factory.mojom.h"
#include "services/ui/public/interfaces/gpu.mojom.h"
#include "services/ui/public/interfaces/ime/ime.mojom.h"
#include "services/ui/public/interfaces/remote_event_dispatcher.mojom.h"
......@@ -35,7 +36,6 @@
#include "services/ui/public/interfaces/window_manager_window_tree_factory.mojom.h"
#include "services/ui/public/interfaces/window_server_test.mojom.h"
#include "services/ui/public/interfaces/window_tree.mojom.h"
#include "services/ui/public/interfaces/window_tree_host.mojom.h"
#include "services/ui/ws/user_id.h"
#include "services/ui/ws/window_server_delegate.h"
......@@ -166,8 +166,8 @@ class Service : public service_manager::Service,
mojom::WindowTreeFactoryRequest request,
const service_manager::BindSourceInfo& source_info);
void BindWindowTreeHostFactoryRequest(
mojom::WindowTreeHostFactoryRequest request,
void BindExternalWindowTreeFactoryRequest(
mojom::ExternalWindowTreeFactoryRequest request,
const service_manager::BindSourceInfo& source_info);
void BindDiscardableSharedMemoryManagerRequest(
......
......@@ -53,6 +53,8 @@ static_library("lib") {
"event_targeter.cc",
"event_targeter.h",
"event_targeter_delegate.h",
"external_window_tree_factory.cc",
"external_window_tree_factory.h",
"focus_controller.cc",
"focus_controller.h",
"focus_controller_observer.h",
......
......@@ -59,9 +59,11 @@ Display::~Display() {
} else if (!window_manager_display_root_map_.empty()) {
// If there is a |binding_| then the tree was created specifically for this
// display (which corresponds to a WindowTreeHost).
window_server_->DestroyTree(window_manager_display_root_map_.begin()
->second->window_manager_state()
->window_tree());
WindowManagerDisplayRoot* display_root =
window_manager_display_root_map_.begin()->second;
if (display_root->window_manager_state())
window_server_->DestroyTree(
display_root->window_manager_state()->window_tree());
}
}
......@@ -209,7 +211,27 @@ void Display::SetTitle(const std::string& title) {
platform_display_->SetTitle(base::UTF8ToUTF16(title));
}
void Display::InitDisplayRoot() {
DCHECK(window_server_->IsInExternalWindowMode());
DCHECK(binding_);
external_mode_root_ = base::MakeUnique<WindowManagerDisplayRoot>(this);
// TODO(tonikitoo): Code still has assumptions that even in external window
// mode make 'window_manager_display_root_map_' needed.
window_manager_display_root_map_[service_manager::mojom::kRootUserID] =
external_mode_root_.get();
ServerWindow* server_window = external_mode_root_->root();
WindowTree* window_tree = window_server_->GetTreeForExternalWindowMode();
window_tree->AddRoot(server_window);
window_tree->DoOnEmbed(nullptr /*mojom::WindowTreePtr*/, server_window);
}
void Display::InitWindowManagerDisplayRoots() {
// Tests can create ws::Display instances directly, by-passing
// WindowTreeHostFactory.
// TODO(tonikitoo): Check if with the introduction of 'external window mode'
// this path is still needed.
if (binding_) {
std::unique_ptr<WindowManagerDisplayRoot> display_root_ptr(
new WindowManagerDisplayRoot(this));
......@@ -290,7 +312,11 @@ EventSink* Display::GetEventSink() {
void Display::OnAcceleratedWidgetAvailable() {
display_manager()->OnDisplayAcceleratedWidgetAvailable(this);
InitWindowManagerDisplayRoots();
if (window_server_->IsInExternalWindowMode())
InitDisplayRoot();
else
InitWindowManagerDisplayRoots();
}
void Display::OnNativeCaptureLost() {
......@@ -414,6 +440,12 @@ void Display::OnWindowManagerWindowTreeFactoryReady(
}
EventDispatchDetails Display::OnEventFromSource(Event* event) {
// TODO(tonikitoo): Current WindowManagerDisplayRoot class is misnamed, since
// in external window mode a non-WindowManager specific 'DisplayRoot' is also
// needed.
// Bits of WindowManagerState also should be factored out and made available
// in external window mode, so that event handling is functional.
// htts://crbug.com/701129
WindowManagerDisplayRoot* display_root = GetActiveWindowManagerDisplayRoot();
if (display_root) {
WindowManagerState* wm_state = display_root->window_manager_state();
......
......@@ -171,6 +171,10 @@ class Display : public PlatformDisplayDelegate,
// Inits the necessary state once the display is ready.
void InitWindowManagerDisplayRoots();
// Inits the display root once the display is ready in
// 'external window mode'.
void InitDisplayRoot();
// Creates the set of WindowManagerDisplayRoots from the
// WindowManagerWindowTreeFactorySet.
void CreateWindowManagerDisplayRootsFromFactories();
......@@ -223,6 +227,8 @@ class Display : public PlatformDisplayDelegate,
WindowManagerDisplayRootMap window_manager_display_root_map_;
std::unique_ptr<WindowManagerDisplayRoot> external_mode_root_;
DISALLOW_COPY_AND_ASSIGN(Display);
};
......
......@@ -9,7 +9,7 @@
#include "base/macros.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/ui/public/interfaces/window_tree_host.mojom.h"
#include "services/ui/public/interfaces/window_tree.mojom.h"
#include "services/ui/ws/user_id.h"
namespace ui {
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/ui/ws/external_window_tree_factory.h"
#include "services/ui/ws/window_manager_access_policy.h"
#include "services/ui/ws/window_server.h"
#include "services/ui/ws/window_server_delegate.h"
#include "services/ui/ws/window_tree.h"
namespace ui {
namespace ws {
ExternalWindowTreeFactory::ExternalWindowTreeFactory(
WindowServer* window_server,
const UserId& user_id)
: window_server_(window_server), user_id_(user_id) {}
ExternalWindowTreeFactory::~ExternalWindowTreeFactory() {}
void ExternalWindowTreeFactory::Register(
mojom::WindowTreeRequest tree_request,
mojom::WindowTreeClientPtr tree_client) {
// NOTE: The code below is analogous to WS::CreateTreeForWindowManager,
// but for the sake of an easier rebase, we are concentrating additions
// like this here.
bool automatically_create_display_roots = true;
// TODO(tonikitoo,msisov): Maybe remove the "window manager" suffix
// if the method name?
window_server_->delegate()->OnWillCreateTreeForWindowManager(
automatically_create_display_roots);
// FIXME(tonikitoo,msisov,fwang): Do we need our own AccessPolicy?
std::unique_ptr<ws::WindowTree> tree(
new ws::WindowTree(window_server_, user_id_, nullptr /*ServerWindow*/,
base::WrapUnique(new WindowManagerAccessPolicy)));
std::unique_ptr<ws::DefaultWindowTreeBinding> tree_binding(
new ws::DefaultWindowTreeBinding(tree.get(), window_server_,
std::move(tree_request),
std::move(tree_client)));
// Pass nullptr as mojom::WindowTreePtr (3rd parameter), because in external
// window mode, the WindowTreePtr is created on the aura/WindowTreeClient
// side.
//
// NOTE: This call to ::AddTree calls ::Init. However, it will not trigger a
// ::OnEmbed call because the WindowTree instance was created above passing
// 'nullptr' as the ServerWindow, hence there is no 'root' yet.
WindowTree* tree_ptr = tree.get();
window_server_->AddTree(std::move(tree), std::move(tree_binding),
nullptr /*mojom::WindowTreePtr*/);
tree_ptr->ConfigureRootWindowTreeClient(automatically_create_display_roots);
}
} // namespace ws
} // namespace ui
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SERVICES_UI_WS_EXTERNAL_WINDOW_TREE_FACTORY_H_
#define SERVICES_UI_WS_EXTERNAL_WINDOW_TREE_FACTORY_H_
#include "services/ui/public/interfaces/external_window_tree_factory.mojom.h"
#include "services/ui/ws/user_id.h"
namespace ui {
namespace ws {
class WindowServer;
class ExternalWindowTreeFactory : public mojom::ExternalWindowTreeFactory {
public:
ExternalWindowTreeFactory(WindowServer* window_server, const UserId& user_id);
~ExternalWindowTreeFactory() override;
const UserId& user_id() const { return user_id_; }
private:
void Register(mojom::WindowTreeRequest tree_request,
mojom::WindowTreeClientPtr tree_client) override;
WindowServer* window_server_;
const UserId user_id_;
DISALLOW_COPY_AND_ASSIGN(ExternalWindowTreeFactory);
};
} // namespace ws
} // namespace ui
#endif // SERVICES_UI_WS_EXTERNAL_WINDOW_TREE_FACTORY_H_
......@@ -12,6 +12,7 @@
"*": [ "app" ],
"ui_service_unittests": [ "ui:window_tree_client" ],
"ui": [
"external_window_tree_factory",
"window_manager",
"window_tree_host_factory"
],
......
......@@ -233,6 +233,12 @@ WindowTree* WindowServer::GetTreeWithClientName(
return nullptr;
}
WindowTree* WindowServer::GetTreeForExternalWindowMode() {
DCHECK_LE(1u, tree_map_.size());
DCHECK(IsInExternalWindowMode());
return tree_map_.begin()->second.get();
}
ServerWindow* WindowServer::GetWindow(const WindowId& id) {
// kWindowServerClientId is used for Display and WindowManager nodes.
if (id.client_id == kWindowServerClientId) {
......
......@@ -116,6 +116,8 @@ class WindowServer : public ServerWindowDelegate,
WindowTree* GetTreeWithClientName(const std::string& client_name);
WindowTree* GetTreeForExternalWindowMode();
size_t num_trees() const { return tree_map_.size(); }
// Returns the Window identified by |id|.
......@@ -158,6 +160,9 @@ class WindowServer : public ServerWindowDelegate,
bool SetFocusedWindow(ServerWindow* window);
ServerWindow* GetFocusedWindow();
void SetInExternalWindowMode() { in_external_window_mode_ = true; }
bool IsInExternalWindowMode() const { return in_external_window_mode_; }
void SetHighContrastMode(const UserId& user, bool enabled);
// Returns a change id for the window manager that is associated with
......@@ -419,6 +424,8 @@ class WindowServer : public ServerWindowDelegate,
// attached to a display they are removed.
ServerWindowTracker pending_system_modal_windows_;
bool in_external_window_mode_ = false;
DisplayCreationConfig display_creation_config_;
DISALLOW_COPY_AND_ASSIGN(WindowServer);
......
......@@ -159,7 +159,35 @@ void WindowTree::Init(std::unique_ptr<WindowTreeBinding> binding,
if (roots_.empty())
return;
DoOnEmbed(std::move(tree), nullptr /*ServerWindow*/);
}
void WindowTree::DoOnEmbed(mojom::WindowTreePtr tree,
ServerWindow* root_window) {
bool in_external_window_mode = !!root_window;
if (in_external_window_mode) {
DCHECK(!tree);
CHECK_LE(1u, roots_.size());
Display* display = GetDisplay(root_window);
int64_t display_id =
display ? display->GetId() : display::kInvalidDisplayId;
ClientWindowId window_id;
IsWindowKnown(root_window, &window_id);
const bool drawn =
root_window->parent() && root_window->parent()->IsDrawn();
client()->OnEmbed(WindowToWindowData(root_window),
nullptr /*mojom::WindowTreePtr*/, display_id,
ClientWindowIdToTransportId(window_id), drawn,
root_window->current_local_surface_id());
return;
}
std::vector<const ServerWindow*> to_send;
DCHECK(!root_window);
CHECK_EQ(1u, roots_.size());
const ServerWindow* root = *roots_.begin();
GetUnknownWindowsFrom(root, &to_send);
......@@ -195,6 +223,17 @@ void WindowTree::ConfigureWindowManager(
window_manager_state_ = base::MakeUnique<WindowManagerState>(this);
}
void WindowTree::ConfigureRootWindowTreeClient(
bool automatically_create_display_roots) {
DCHECK(window_server_->IsInExternalWindowMode());
automatically_create_display_roots_ = automatically_create_display_roots;
window_manager_internal_ = binding_->GetWindowManager();
window_manager_internal_->OnConnect();
window_tree_host_factory_.reset(
new WindowTreeHostFactory(window_server_, user_id_));
}
const ServerWindow* WindowTree::GetWindow(const WindowId& id) const {
if (id_ == id.client_id) {
auto iter = created_window_map_.find(id);
......@@ -251,6 +290,24 @@ void WindowTree::PrepareForWindowServerShutdown() {
window_manager_internal_ = binding_->GetWindowManager();
}
void WindowTree::AddRoot(const ServerWindow* root) {
DCHECK(pending_client_window_id_ != kInvalidClientId);
const ClientWindowId client_window_id(
MakeClientWindowId(pending_client_window_id_));
DCHECK_EQ(0u, client_id_to_window_id_map_.count(client_window_id));
client_id_to_window_id_map_[client_window_id] = root->id();
window_id_to_client_id_map_[root->id()] = client_window_id;
pending_client_window_id_ = kInvalidClientId;
roots_.insert(root);
Display* display = GetDisplay(root);
DCHECK(display);
}
void WindowTree::AddRootForWindowManager(const ServerWindow* root) {
if (!automatically_create_display_roots_)
return;
......@@ -437,6 +494,8 @@ bool WindowTree::ProcessSetBlockingContainers(
bool WindowTree::SetCapture(const ClientWindowId& client_window_id) {
ServerWindow* window = GetWindowByClientId(client_window_id);
WindowManagerDisplayRoot* display_root = GetWindowManagerDisplayRoot(window);
if (display_root && !display_root->window_manager_state())
return false;
ServerWindow* current_capture_window =
display_root ? display_root->window_manager_state()->capture_window()
: nullptr;
......@@ -454,6 +513,8 @@ bool WindowTree::SetCapture(const ClientWindowId& client_window_id) {
bool WindowTree::ReleaseCapture(const ClientWindowId& client_window_id) {
ServerWindow* window = GetWindowByClientId(client_window_id);
WindowManagerDisplayRoot* display_root = GetWindowManagerDisplayRoot(window);
if (display_root && !display_root->window_manager_state())
return false;
ServerWindow* current_capture_window =
display_root ? display_root->window_manager_state()->capture_window()
: nullptr;
......@@ -2233,6 +2294,17 @@ void WindowTree::GetWindowManagerClient(
this, std::move(internal)));
}
void WindowTree::GetWindowTreeHostFactory(
mojo::AssociatedInterfaceRequest<mojom::WindowTreeHostFactory> request) {
if (!window_server_->IsInExternalWindowMode() || !window_tree_host_factory_ ||
window_tree_host_factory_binding_) {
return;
}
window_tree_host_factory_binding_.reset(
new mojo::AssociatedBinding<mojom::WindowTreeHostFactory>(
window_tree_host_factory_.get(), std::move(request)));
}
void WindowTree::GetCursorLocationMemory(
const GetCursorLocationMemoryCallback& callback) {
callback.Run(display_manager()
......
......@@ -21,12 +21,14 @@
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "services/ui/public/interfaces/window_tree.mojom.h"
#include "services/ui/public/interfaces/window_tree_host.mojom.h"
#include "services/ui/ws/access_policy_delegate.h"
#include "services/ui/ws/drag_source.h"
#include "services/ui/ws/drag_target_connection.h"
#include "services/ui/ws/ids.h"
#include "services/ui/ws/user_id.h"