blob: 6daa728fe518257e5559d24c28475bc9c8dfd136 [file] [log] [blame]
// Copyright 2016 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/platform_display_default.h"
#include <utility>
#include "build/build_config.h"
#include "gpu/ipc/client/gpu_channel_host.h"
#include "services/ui/display/screen_manager.h"
#include "services/ui/public/interfaces/cursor/cursor_struct_traits.h"
#include "services/ui/ws/server_window.h"
#include "services/ui/ws/threaded_image_cursors.h"
#include "services/viz/privileged/interfaces/compositing/display_private.mojom.h"
#include "ui/display/display.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/platform_window/platform_ime_controller.h"
#include "ui/platform_window/platform_window.h"
#include "ui/platform_window/stub/stub_window.h"
#if defined(USE_OZONE)
#include "ui/events/ozone/chromeos/cursor_controller.h"
#endif
namespace ui {
namespace ws {
PlatformDisplayDefault::PlatformDisplayDefault(
ServerWindow* root_window,
const display::ViewportMetrics& metrics,
std::unique_ptr<ThreadedImageCursors> image_cursors)
: root_window_(root_window),
image_cursors_(std::move(image_cursors)),
metrics_(metrics),
widget_(gfx::kNullAcceleratedWidget) {}
PlatformDisplayDefault::~PlatformDisplayDefault() {
#if defined(OS_CHROMEOS)
ui::CursorController::GetInstance()->ClearCursorConfigForWindow(
GetAcceleratedWidget());
#endif
// Don't notify the delegate from the destructor.
delegate_ = nullptr;
frame_generator_.reset();
image_cursors_.reset();
// Destroy the PlatformWindow early on as it may call us back during
// destruction and we want to be in a known state. But destroy the surface
// and ThreadedImageCursors first because they can still be using the platform
// window.
platform_window_.reset();
}
EventSink* PlatformDisplayDefault::GetEventSink() {
return delegate_->GetEventSink();
}
void PlatformDisplayDefault::Init(PlatformDisplayDelegate* delegate) {
DCHECK(delegate);
delegate_ = delegate;
const gfx::Rect& bounds = metrics_.bounds_in_pixels;
DCHECK(!bounds.size().IsEmpty());
if (delegate_->GetDisplay().id() == display::kUnifiedDisplayId) {
// Virtual unified displays use a StubWindow; see AshWindowTreeHostUnified.
platform_window_ = std::make_unique<ui::StubWindow>(this, true, bounds);
} else if (delegate_->GetDisplay().id() == display::kInvalidDisplayId) {
// Unit tests may use kInvalidDisplayId to request a StubWindow for testing.
platform_window_ = std::make_unique<ui::StubWindow>(this, false);
} else {
platform_window_ = CreatePlatformWindow(this, metrics_.bounds_in_pixels);
}
platform_window_->Show();
if (image_cursors_) {
image_cursors_->SetDisplay(delegate_->GetDisplay(),
metrics_.device_scale_factor);
}
}
void PlatformDisplayDefault::SetViewportSize(const gfx::Size& size) {
platform_window_->SetBounds(gfx::Rect(size));
}
void PlatformDisplayDefault::SetTitle(const base::string16& title) {
platform_window_->SetTitle(title);
}
void PlatformDisplayDefault::SetCapture() {
platform_window_->SetCapture();
}
void PlatformDisplayDefault::ReleaseCapture() {
platform_window_->ReleaseCapture();
}
void PlatformDisplayDefault::SetCursor(const ui::CursorData& cursor_data) {
if (!image_cursors_)
return;
image_cursors_->SetCursor(cursor_data, platform_window_.get());
}
void PlatformDisplayDefault::MoveCursorTo(
const gfx::Point& window_pixel_location) {
platform_window_->MoveCursorTo(window_pixel_location);
}
void PlatformDisplayDefault::SetCursorSize(const ui::CursorSize& cursor_size) {
image_cursors_->SetCursorSize(cursor_size);
}
void PlatformDisplayDefault::ConfineCursorToBounds(
const gfx::Rect& pixel_bounds) {
platform_window_->ConfineCursorToBounds(pixel_bounds);
}
void PlatformDisplayDefault::UpdateTextInputState(
const ui::TextInputState& state) {
ui::PlatformImeController* ime = platform_window_->GetPlatformImeController();
if (ime)
ime->UpdateTextInputState(state);
}
void PlatformDisplayDefault::SetImeVisibility(bool visible) {
ui::PlatformImeController* ime = platform_window_->GetPlatformImeController();
if (ime)
ime->SetImeVisibility(visible);
}
FrameGenerator* PlatformDisplayDefault::GetFrameGenerator() {
return frame_generator_.get();
}
void PlatformDisplayDefault::UpdateViewportMetrics(
const display::ViewportMetrics& metrics) {
if (metrics_ == metrics)
return;
gfx::Rect bounds = platform_window_->GetBounds();
if (bounds.size() != metrics.bounds_in_pixels.size()) {
bounds.set_size(metrics.bounds_in_pixels.size());
platform_window_->SetBounds(bounds);
}
metrics_ = metrics;
if (frame_generator_) {
frame_generator_->SetDeviceScaleFactor(metrics_.device_scale_factor);
frame_generator_->OnWindowSizeChanged(metrics_.bounds_in_pixels.size());
}
}
const display::ViewportMetrics& PlatformDisplayDefault::GetViewportMetrics() {
return metrics_;
}
gfx::AcceleratedWidget PlatformDisplayDefault::GetAcceleratedWidget() const {
return widget_;
}
void PlatformDisplayDefault::SetCursorConfig(
display::Display::Rotation rotation,
float scale) {
#if defined(OS_CHROMEOS)
ui::CursorController::GetInstance()->SetCursorConfigForWindow(
GetAcceleratedWidget(), rotation, scale);
#endif
}
void PlatformDisplayDefault::OnBoundsChanged(const gfx::Rect& new_bounds) {
// We only care if the window size has changed.
if (new_bounds.size() == metrics_.bounds_in_pixels.size())
return;
// TODO(tonikitoo): Handle the bounds changing in external window mode. The
// window should be resized by the WS and it shouldn't involve ScreenManager.
}
void PlatformDisplayDefault::OnDamageRect(const gfx::Rect& damaged_region) {
if (frame_generator_)
frame_generator_->OnWindowDamaged();
}
void PlatformDisplayDefault::DispatchEvent(ui::Event* event) {
// Mojo requires conversion of mouse and touch events to pointer events.
if (event->IsMouseEvent()) {
ui::PointerEvent pointer_event(*event->AsMouseEvent());
SendEventToSink(&pointer_event);
} else if (event->IsTouchEvent()) {
ui::PointerEvent pointer_event(*event->AsTouchEvent());
SendEventToSink(&pointer_event);
} else {
SendEventToSink(event);
}
}
void PlatformDisplayDefault::OnCloseRequest() {
// TODO(tonikitoo): Handle a close request in external window mode. The window
// should be closed by the WS and it shouldn't involve ScreenManager.
const int64_t display_id = delegate_->GetDisplay().id();
display::ScreenManager::GetInstance()->RequestCloseDisplay(display_id);
}
void PlatformDisplayDefault::OnClosed() {}
void PlatformDisplayDefault::OnWindowStateChanged(
ui::PlatformWindowState new_state) {}
void PlatformDisplayDefault::OnLostCapture() {
delegate_->OnNativeCaptureLost();
}
void PlatformDisplayDefault::OnAcceleratedWidgetAvailable(
gfx::AcceleratedWidget widget,
float device_scale_factor) {
// This will get called after Init() is called, either synchronously as part
// of the Init() callstack or async after Init() has returned, depending on
// the platform.
DCHECK_EQ(gfx::kNullAcceleratedWidget, widget_);
widget_ = widget;
delegate_->OnAcceleratedWidgetAvailable();
if (!delegate_->IsHostingViz())
return;
viz::mojom::CompositorFrameSinkAssociatedPtr compositor_frame_sink;
viz::mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client;
viz::mojom::CompositorFrameSinkClientRequest
compositor_frame_sink_client_request =
mojo::MakeRequest(&compositor_frame_sink_client);
// TODO(ccameron): |display_client| is not bound. This will need to
// change to support macOS.
viz::mojom::DisplayPrivateAssociatedPtr display_private;
viz::mojom::DisplayClientPtr display_client;
viz::mojom::DisplayClientRequest display_client_request =
mojo::MakeRequest(&display_client);
root_window_->CreateRootCompositorFrameSink(
widget_, mojo::MakeRequest(&compositor_frame_sink),
std::move(compositor_frame_sink_client),
mojo::MakeRequest(&display_private), std::move(display_client));
display_private->SetDisplayVisible(true);
frame_generator_ = std::make_unique<FrameGenerator>();
auto frame_sink_client_binding =
std::make_unique<CompositorFrameSinkClientBinding>(
frame_generator_.get(),
std::move(compositor_frame_sink_client_request),
std::move(compositor_frame_sink), std::move(display_private));
frame_generator_->Bind(std::move(frame_sink_client_binding));
frame_generator_->OnWindowSizeChanged(root_window_->bounds().size());
frame_generator_->SetDeviceScaleFactor(metrics_.device_scale_factor);
}
void PlatformDisplayDefault::OnAcceleratedWidgetDestroying() {}
void PlatformDisplayDefault::OnAcceleratedWidgetDestroyed() {
}
void PlatformDisplayDefault::OnActivationChanged(bool active) {}
} // namespace ws
} // namespace ui