blob: 14f1e81a9f7283e8bec0e469c473602c073fc1a0 [file] [log] [blame]
// Copyright 2018 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 "ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h"
#include "ui/aura/client/drag_drop_client.h"
#include "ui/aura/client/transient_window_client.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/platform_window/platform_window.h"
#include "ui/views/corewm/tooltip_aura.h"
#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
#include "ui/views/window/native_frame_view.h"
#include "ui/wm/core/window_util.h"
namespace views {
////////////////////////////////////////////////////////////////////////////////
// DesktopWindowTreeHostPlatform:
DesktopWindowTreeHostPlatform::DesktopWindowTreeHostPlatform(
internal::NativeWidgetDelegate* native_widget_delegate,
DesktopNativeWidgetAura* desktop_native_widget_aura)
: native_widget_delegate_(native_widget_delegate),
desktop_native_widget_aura_(desktop_native_widget_aura) {}
DesktopWindowTreeHostPlatform::~DesktopWindowTreeHostPlatform() {
DCHECK(got_on_closed_);
desktop_native_widget_aura_->OnDesktopWindowTreeHostDestroyed(this);
DestroyDispatcher();
}
void DesktopWindowTreeHostPlatform::SetBoundsInDIP(
const gfx::Rect& bounds_in_dip) {
DCHECK_NE(0, device_scale_factor());
SetBoundsInPixels(
gfx::ConvertRectToPixel(device_scale_factor(), bounds_in_dip),
viz::LocalSurfaceId());
}
void DesktopWindowTreeHostPlatform::Init(const Widget::InitParams& params) {
CreateAndSetDefaultPlatformWindow();
// TODO(sky): this should be |params.force_software_compositing|, figure out
// why it has to be true now.
const bool use_software_compositing = true;
CreateCompositor(viz::FrameSinkId(), use_software_compositing);
aura::WindowTreeHost::OnAcceleratedWidgetAvailable();
InitHost();
if (!params.bounds.IsEmpty())
SetBoundsInDIP(params.bounds);
window()->Show();
}
void DesktopWindowTreeHostPlatform::OnNativeWidgetCreated(
const Widget::InitParams& params) {
native_widget_delegate_->OnNativeWidgetCreated(true);
}
void DesktopWindowTreeHostPlatform::OnWidgetInitDone() {}
void DesktopWindowTreeHostPlatform::OnActiveWindowChanged(bool active) {}
std::unique_ptr<corewm::Tooltip>
DesktopWindowTreeHostPlatform::CreateTooltip() {
return std::make_unique<corewm::TooltipAura>();
}
std::unique_ptr<aura::client::DragDropClient>
DesktopWindowTreeHostPlatform::CreateDragDropClient(
DesktopNativeCursorManager* cursor_manager) {
// TODO: needs PlatformWindow support.
NOTIMPLEMENTED_LOG_ONCE();
return nullptr;
}
void DesktopWindowTreeHostPlatform::Close() {
if (waiting_for_close_now_)
return;
// Hide while waiting for the close.
platform_window()->Hide();
waiting_for_close_now_ = true;
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&DesktopWindowTreeHostPlatform::CloseNow,
weak_factory_.GetWeakPtr()));
}
void DesktopWindowTreeHostPlatform::CloseNow() {
auto weak_ref = weak_factory_.GetWeakPtr();
// Deleting the PlatformWindow may not result in OnClosed() being called, if
// not behave as though it was.
SetPlatformWindow(nullptr);
if (!weak_ref || got_on_closed_)
return;
got_on_closed_ = true;
desktop_native_widget_aura_->OnHostClosed();
}
aura::WindowTreeHost* DesktopWindowTreeHostPlatform::AsWindowTreeHost() {
return this;
}
void DesktopWindowTreeHostPlatform::ShowWindowWithState(
ui::WindowShowState show_state) {
if (compositor()) {
platform_window()->Show();
compositor()->SetVisible(true);
}
switch (show_state) {
case ui::SHOW_STATE_MAXIMIZED:
platform_window()->Maximize();
break;
case ui::SHOW_STATE_MINIMIZED:
platform_window()->Minimize();
break;
case ui::SHOW_STATE_FULLSCREEN:
// TODO(sky): this isn't necessarily the same as explicitly setting
// fullscreen.
platform_window()->ToggleFullscreen();
break;
default:
break;
}
if (native_widget_delegate_->CanActivate()) {
if (show_state != ui::SHOW_STATE_INACTIVE)
Activate();
// SetInitialFocus() should be always be called, even for
// SHOW_STATE_INACTIVE. If the window has to stay inactive, the method will
// do the right thing.
// Activate() might fail if the window is non-activatable. In this case, we
// should pass SHOW_STATE_INACTIVE to SetInitialFocus() to stop the initial
// focused view from getting focused. See https://crbug.com/515594 for
// example.
native_widget_delegate_->SetInitialFocus(
IsActive() ? show_state : ui::SHOW_STATE_INACTIVE);
}
}
void DesktopWindowTreeHostPlatform::ShowMaximizedWithBounds(
const gfx::Rect& restored_bounds) {
// TODO: support |restored_bounds|.
ShowWindowWithState(ui::SHOW_STATE_MAXIMIZED);
}
bool DesktopWindowTreeHostPlatform::IsVisible() const {
// TODO: needs PlatformWindow support.
NOTIMPLEMENTED_LOG_ONCE();
return true;
}
void DesktopWindowTreeHostPlatform::SetSize(const gfx::Size& size) {
gfx::Rect screen_bounds =
gfx::ConvertRectToDIP(device_scale_factor(), GetBoundsInPixels());
screen_bounds.set_size(size);
SetBoundsInDIP(screen_bounds);
}
void DesktopWindowTreeHostPlatform::StackAbove(aura::Window* window) {
NOTIMPLEMENTED_LOG_ONCE();
}
void DesktopWindowTreeHostPlatform::StackAtTop() {
NOTIMPLEMENTED_LOG_ONCE();
}
void DesktopWindowTreeHostPlatform::CenterWindow(const gfx::Size& size) {
gfx::Rect bounds_to_center_in = GetWorkAreaBoundsInScreen();
// If there is a transient parent and it fits |size|, then center over it.
aura::Window* content_window = desktop_native_widget_aura_->content_window();
if (wm::GetTransientParent(content_window)) {
gfx::Rect transient_parent_bounds =
wm::GetTransientParent(content_window)->GetBoundsInScreen();
if (transient_parent_bounds.height() >= size.height() &&
transient_parent_bounds.width() >= size.width()) {
bounds_to_center_in = transient_parent_bounds;
}
}
gfx::Rect resulting_bounds(bounds_to_center_in);
resulting_bounds.ClampToCenteredSize(size);
SetBoundsInDIP(resulting_bounds);
}
void DesktopWindowTreeHostPlatform::GetWindowPlacement(
gfx::Rect* bounds,
ui::WindowShowState* show_state) const {
NOTIMPLEMENTED_LOG_ONCE();
*bounds = gfx::Rect(0, 0, 640, 840);
*show_state = ui::SHOW_STATE_NORMAL;
}
gfx::Rect DesktopWindowTreeHostPlatform::GetWindowBoundsInScreen() const {
gfx::Rect bounds =
gfx::ConvertRectToDIP(device_scale_factor(), GetBoundsInPixels());
bounds += display::Screen::GetScreen()
->GetDisplayNearestWindow(const_cast<aura::Window*>(window()))
.bounds()
.OffsetFromOrigin();
return bounds;
}
gfx::Rect DesktopWindowTreeHostPlatform::GetClientAreaBoundsInScreen() const {
// View-to-screen coordinate system transformations depend on this returning
// the full window bounds, for example View::ConvertPointToScreen().
return GetWindowBoundsInScreen();
}
gfx::Rect DesktopWindowTreeHostPlatform::GetRestoredBounds() const {
NOTIMPLEMENTED_LOG_ONCE();
return gfx::Rect(0, 0, 640, 840);
}
std::string DesktopWindowTreeHostPlatform::GetWorkspace() const {
return std::string();
}
gfx::Rect DesktopWindowTreeHostPlatform::GetWorkAreaBoundsInScreen() const {
// TODO(sky): GetDisplayNearestWindow() should take a const aura::Window*.
return display::Screen::GetScreen()
->GetDisplayNearestWindow(const_cast<aura::Window*>(window()))
.work_area();
}
void DesktopWindowTreeHostPlatform::SetShape(
std::unique_ptr<Widget::ShapeRects> native_shape) {
NOTIMPLEMENTED_LOG_ONCE();
}
void DesktopWindowTreeHostPlatform::Activate() {
// TODO: needs PlatformWindow support.
NOTIMPLEMENTED_LOG_ONCE();
}
void DesktopWindowTreeHostPlatform::Deactivate() {
// TODO: needs PlatformWindow support.
NOTIMPLEMENTED_LOG_ONCE();
}
bool DesktopWindowTreeHostPlatform::IsActive() const {
return is_active_;
}
void DesktopWindowTreeHostPlatform::Maximize() {
platform_window()->Maximize();
}
void DesktopWindowTreeHostPlatform::Minimize() {
platform_window()->Minimize();
}
void DesktopWindowTreeHostPlatform::Restore() {
platform_window()->Restore();
}
bool DesktopWindowTreeHostPlatform::IsMaximized() const {
// TODO: needs PlatformWindow support.
NOTIMPLEMENTED_LOG_ONCE();
return false;
}
bool DesktopWindowTreeHostPlatform::IsMinimized() const {
// TODO: needs PlatformWindow support.
NOTIMPLEMENTED_LOG_ONCE();
return false;
}
bool DesktopWindowTreeHostPlatform::HasCapture() const {
return platform_window()->HasCapture();
}
void DesktopWindowTreeHostPlatform::SetAlwaysOnTop(bool always_on_top) {
// TODO: needs PlatformWindow support.
NOTIMPLEMENTED_LOG_ONCE();
}
bool DesktopWindowTreeHostPlatform::IsAlwaysOnTop() const {
// TODO: needs PlatformWindow support.
return false;
}
void DesktopWindowTreeHostPlatform::SetVisibleOnAllWorkspaces(
bool always_visible) {
// TODO: needs PlatformWindow support.
NOTIMPLEMENTED_LOG_ONCE();
}
bool DesktopWindowTreeHostPlatform::IsVisibleOnAllWorkspaces() const {
// TODO: needs PlatformWindow support.
return false;
}
bool DesktopWindowTreeHostPlatform::SetWindowTitle(
const base::string16& title) {
// TODO: needs PlatformWindow support.
NOTIMPLEMENTED_LOG_ONCE();
return false;
}
void DesktopWindowTreeHostPlatform::ClearNativeFocus() {
// TODO: needs PlatformWindow support.
NOTIMPLEMENTED_LOG_ONCE();
}
Widget::MoveLoopResult DesktopWindowTreeHostPlatform::RunMoveLoop(
const gfx::Vector2d& drag_offset,
Widget::MoveLoopSource source,
Widget::MoveLoopEscapeBehavior escape_behavior) {
// TODO: needs PlatformWindow support.
NOTIMPLEMENTED_LOG_ONCE();
return Widget::MOVE_LOOP_CANCELED;
}
void DesktopWindowTreeHostPlatform::EndMoveLoop() {
// TODO: needs PlatformWindow support.
NOTIMPLEMENTED_LOG_ONCE();
}
void DesktopWindowTreeHostPlatform::SetVisibilityChangedAnimationsEnabled(
bool value) {
// TODO: needs PlatformWindow support.
NOTIMPLEMENTED_LOG_ONCE();
}
NonClientFrameView* DesktopWindowTreeHostPlatform::CreateNonClientFrameView() {
return ShouldUseNativeFrame() ? new NativeFrameView(GetWidget()) : nullptr;
}
bool DesktopWindowTreeHostPlatform::ShouldUseNativeFrame() const {
return false;
}
bool DesktopWindowTreeHostPlatform::ShouldWindowContentsBeTransparent() const {
return false;
}
void DesktopWindowTreeHostPlatform::FrameTypeChanged() {}
void DesktopWindowTreeHostPlatform::SetFullscreen(bool fullscreen) {
// TODO: needs PlatformWindow support.
NOTIMPLEMENTED_LOG_ONCE();
}
bool DesktopWindowTreeHostPlatform::IsFullscreen() const {
// TODO: needs PlatformWindow support.
NOTIMPLEMENTED_LOG_ONCE();
return false;
}
void DesktopWindowTreeHostPlatform::SetOpacity(float opacity) {
// TODO: needs PlatformWindow support.
NOTIMPLEMENTED_LOG_ONCE();
}
void DesktopWindowTreeHostPlatform::SetWindowIcons(
const gfx::ImageSkia& window_icon,
const gfx::ImageSkia& app_icon) {
// TODO: needs PlatformWindow support.
NOTIMPLEMENTED_LOG_ONCE();
}
void DesktopWindowTreeHostPlatform::InitModalType(ui::ModalType modal_type) {
// TODO: needs PlatformWindow support (alternatively, remove as
// DesktopWindowTreeHostX11 doesn't support at all).
NOTIMPLEMENTED_LOG_ONCE();
}
void DesktopWindowTreeHostPlatform::FlashFrame(bool flash_frame) {
// TODO: needs PlatformWindow support.
NOTIMPLEMENTED_LOG_ONCE();
}
bool DesktopWindowTreeHostPlatform::IsAnimatingClosed() const {
// TODO: needs PlatformWindow support.
NOTIMPLEMENTED_LOG_ONCE();
return false;
}
bool DesktopWindowTreeHostPlatform::IsTranslucentWindowOpacitySupported()
const {
// TODO: needs PlatformWindow support.
NOTIMPLEMENTED_LOG_ONCE();
return false;
}
void DesktopWindowTreeHostPlatform::SizeConstraintsChanged() {
// TODO: needs PlatformWindow support.
NOTIMPLEMENTED_LOG_ONCE();
}
bool DesktopWindowTreeHostPlatform::ShouldUpdateWindowTransparency() const {
return false;
}
bool DesktopWindowTreeHostPlatform::ShouldUseDesktopNativeCursorManager()
const {
return true;
}
bool DesktopWindowTreeHostPlatform::ShouldCreateVisibilityController() const {
return true;
}
void DesktopWindowTreeHostPlatform::OnClosed() {
got_on_closed_ = true;
desktop_native_widget_aura_->OnHostClosed();
}
void DesktopWindowTreeHostPlatform::OnCloseRequest() {
GetWidget()->Close();
}
void DesktopWindowTreeHostPlatform::OnActivationChanged(bool active) {
is_active_ = active;
aura::WindowTreeHostPlatform::OnActivationChanged(active);
desktop_native_widget_aura_->HandleActivationChanged(active);
}
Widget* DesktopWindowTreeHostPlatform::GetWidget() {
return native_widget_delegate_->AsWidget();
}
////////////////////////////////////////////////////////////////////////////////
// DesktopWindowTreeHost:
// static
DesktopWindowTreeHost* DesktopWindowTreeHost::Create(
internal::NativeWidgetDelegate* native_widget_delegate,
DesktopNativeWidgetAura* desktop_native_widget_aura) {
return new DesktopWindowTreeHostPlatform(native_widget_delegate,
desktop_native_widget_aura);
}
} // namespace views