Commit 5a98d611 authored by Jun Mukai's avatar Jun Mukai Committed by Commit Bot

Allow dragging for NonClientArea (i.e. DraggableRegions)

The non-client area in ProxyWindow is set through "DraggableRegions",
and this section is used for draggability of the window (see
https://cs.chromium.org/chromium/src/apps/ui/views/app_window_frame_view.cc?sq=package:chromium&g=0&l=196).

The same logic should be introduced on Mash, otherwise frameless
app window can't be dragged.

Bug: 920469
Test: ash_unittests
Change-Id: If249d58dbf0a84aa3b333799f44f122dca04c4e6
Reviewed-on: https://chromium-review.googlesource.com/c/1405458Reviewed-by: default avatarScott Violet <sky@chromium.org>
Commit-Queue: Jun Mukai <mukai@chromium.org>
Cr-Commit-Position: refs/heads/master@{#622061}
parent 36665607
......@@ -26,6 +26,7 @@
#include "services/ws/public/mojom/window_manager.mojom.h"
#include "services/ws/window_properties.h"
#include "services/ws/window_service.h"
#include "services/ws/window_utils.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/ax_tree_id.h"
#include "ui/accessibility/platform/aura_window_properties.h"
......@@ -66,6 +67,11 @@ class EmptyDraggableNonClientFrameView : public views::NonClientFrameView {
return bounds();
}
int NonClientHitTest(const gfx::Point& point) override {
// For non-standard frame window, the located event in the non-client area
// should be used for window dragging to allow dragging frameless app
// windows. See https://crbug.com/920469
if (ws::IsLocationInNonClientArea(GetWidget()->GetNativeWindow(), point))
return HTCAPTION;
return FrameBorderNonClientHitTest(this, point);
}
void GetWindowMask(const gfx::Size& size, SkPath* window_mask) override {}
......
......@@ -23,6 +23,7 @@
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
#include "ui/base/hit_test.h"
#include "ui/base/ui_base_features.h"
#include "ui/views/widget/widget.h"
......@@ -103,4 +104,27 @@ TEST_F(NonClientFrameControllerTest, HonorsMinimumSizeWithoutFrame) {
EXPECT_EQ(min_size, window->delegate()->GetMinimumSize());
}
TEST_F(NonClientFrameControllerTest, NonClientAreaShouldBeDraggable) {
using TransportType = std::vector<uint8_t>;
auto properties = CreatePropertiesForProxyWindow();
properties[ws::mojom::WindowManager::kRemoveStandardFrame_InitProperty] =
mojo::ConvertTo<TransportType>(true);
std::unique_ptr<aura::Window> window(
GetWindowTreeTestHelper()->NewTopLevelWindow(
mojo::MapToFlatMap(properties)));
const gfx::Point point(10, 10);
EXPECT_EQ(HTCLIENT, window->delegate()->GetNonClientComponent(point));
std::vector<gfx::Rect> additional_areas = {
gfx::Rect(window->bounds().width() - 20, 0, 20, 20)};
GetWindowTreeTestHelper()->SetClientArea(
window.get(), gfx::Insets(20, 20, 20, 20), additional_areas);
EXPECT_EQ(HTCAPTION, window->delegate()->GetNonClientComponent(point));
EXPECT_EQ(HTCLIENT,
window->delegate()->GetNonClientComponent(gfx::Point(30, 30)));
EXPECT_EQ(HTCLIENT, window->delegate()->GetNonClientComponent(
gfx::Point(window->bounds().width() - 10, 10)));
}
} // namespace ash
......@@ -28,6 +28,7 @@ component("lib") {
"window_tree.h",
"window_tree_binding.h",
"window_tree_factory.h",
"window_utils.h",
]
sources = [
"client_change.cc",
......@@ -70,6 +71,7 @@ component("lib") {
"window_tree.cc",
"window_tree_binding.cc",
"window_tree_factory.cc",
"window_utils.cc",
]
configs += [ "//build/config/compiler:wexit_time_destructors" ]
......
......@@ -11,9 +11,8 @@
#include "services/ws/client_root.h"
#include "services/ws/drag_drop_delegate.h"
#include "services/ws/embedding.h"
#include "services/ws/public/mojom/window_tree_constants.mojom.h"
#include "services/ws/window_tree.h"
#include "ui/aura/client/aura_constants.h"
#include "services/ws/window_utils.h"
#include "ui/aura/client/capture_client_observer.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
......@@ -30,44 +29,6 @@ namespace ws {
namespace {
DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(ProxyWindow, kProxyWindowKey, nullptr);
// Returns true if |location| is in the non-client area (or outside the bounds
// of the window). A return value of false means the location is in the client
// area.
bool IsLocationInNonClientArea(const aura::Window* window,
const gfx::Point& location) {
const ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(window);
if (!proxy_window || !proxy_window->IsTopLevel())
return false;
// Locations inside bounds but within the resize insets count as non-client
// area. Locations outside the bounds, assume it's in extended hit test area,
// which is non-client area.
ui::WindowShowState window_state =
window->GetProperty(aura::client::kShowStateKey);
if ((window->GetProperty(aura::client::kResizeBehaviorKey) &
ws::mojom::kResizeBehaviorCanResize) &&
(window_state != ui::WindowShowState::SHOW_STATE_MAXIMIZED) &&
(window_state != ui::WindowShowState::SHOW_STATE_FULLSCREEN)) {
int resize_handle_size =
window->GetProperty(aura::client::kResizeHandleInset);
gfx::Rect non_handle_area(window->bounds().size());
non_handle_area.Inset(gfx::Insets(resize_handle_size));
if (!non_handle_area.Contains(location))
return true;
}
gfx::Rect client_area(window->bounds().size());
client_area.Inset(proxy_window->client_area());
if (client_area.Contains(location))
return false;
for (const auto& rect : proxy_window->additional_client_areas()) {
if (rect.Contains(location))
return false;
}
return true;
}
bool IsPointerPressedEvent(const ui::Event& event) {
return event.type() == ui::ET_MOUSE_PRESSED ||
event.type() == ui::ET_TOUCH_PRESSED;
......
// Copyright 2019 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/ws/window_utils.h"
#include "services/ws/proxy_window.h"
#include "services/ws/public/mojom/window_tree_constants.mojom.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
namespace ws {
bool IsLocationInNonClientArea(const aura::Window* window,
const gfx::Point& location) {
const ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(window);
if (!proxy_window || !proxy_window->IsTopLevel())
return false;
// Locations inside bounds but within the resize insets count as non-client
// area. Locations outside the bounds, assume it's in extended hit test area,
// which is non-client area.
ui::WindowShowState window_state =
window->GetProperty(aura::client::kShowStateKey);
if ((window->GetProperty(aura::client::kResizeBehaviorKey) &
ws::mojom::kResizeBehaviorCanResize) &&
(window_state != ui::WindowShowState::SHOW_STATE_MAXIMIZED) &&
(window_state != ui::WindowShowState::SHOW_STATE_FULLSCREEN)) {
int resize_handle_size =
window->GetProperty(aura::client::kResizeHandleInset);
gfx::Rect non_handle_area(window->bounds().size());
non_handle_area.Inset(gfx::Insets(resize_handle_size));
if (!non_handle_area.Contains(location))
return true;
}
gfx::Rect client_area(window->bounds().size());
client_area.Inset(proxy_window->client_area());
if (client_area.Contains(location))
return false;
for (const auto& rect : proxy_window->additional_client_areas()) {
if (rect.Contains(location))
return false;
}
return true;
}
} // namespace ws
// Copyright 2019 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_WS_WINDOW_UTILS_H_
#define SERVICES_WS_WINDOW_UTILS_H_
#include "base/component_export.h"
namespace aura {
class Window;
}
namespace gfx {
class Point;
}
namespace ws {
// Returns true if |location| is in the non-client area (or outside the bounds
// of the window). A return value of false means the location is in the client
// area.
COMPONENT_EXPORT(WINDOW_SERVICE)
bool IsLocationInNonClientArea(const aura::Window* window,
const gfx::Point& location);
} // namespace ws
#endif // SERVICES_WS_WINDOW_PROPERTIES_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment