Commit f5eb8533 authored by Mitsuru Oshima's avatar Mitsuru Oshima Committed by Commit Bot

Client initiated resize

* Start resizing upon resize request from client.
* Client can start drag only if
  1) mouse is pressed on the shell surface.
  2) gesture is on progress.

This CL includes a fix for potential issue when
the drag to resize/move was requested when the mouse/touch
drag wasn't in progress.

BUG: b/72918846
TEST: covered by unit test
Change-Id: Id32f9da7a2c718fdaef1cb0e4a4adb3b99cbd7f8
Reviewed-on: https://chromium-review.googlesource.com/938498
Commit-Queue: Mitsuru Oshima <oshima@chromium.org>
Reviewed-by: default avatarDavid Reveman <reveman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#539962}
parent 75c9fe22
......@@ -50,6 +50,10 @@ class ASH_EXPORT ToplevelWindowEventHandler : public ui::EventHandler,
::wm::WindowMoveSource move_source) override;
void EndMoveLoop() override;
aura::Window* gesture_target() {
return wm_toplevel_window_event_handler_.gesture_target();
}
private:
// Callback from WmToplevelWindowEventHandler once the drag completes.
void OnDragCompleted(
......
......@@ -26,6 +26,8 @@
#include "components/exo/wm_helper.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/class_property.h"
#include "ui/compositor/compositor_lock.h"
#include "ui/display/display.h"
......@@ -361,13 +363,13 @@ void ClientControlledShellSurface::OnWindowStateChangeEvent(
state_changed_callback_.Run(current_state, next_state);
}
void ClientControlledShellSurface::StartResize_DEPRECATED() {
TRACE_EVENT0("exo", "ClientControlledShellSurface::StartResize");
void ClientControlledShellSurface::StartResize(int component) {
TRACE_EVENT1("exo", "ClientControlledShellSurface::StartResize", "component",
component);
if (!widget_ || !client_controlled_move_resize_)
if (!widget_ || client_controlled_move_resize_)
return;
AttemptToStartDrag(HTBORDER);
AttemptToStartDrag(component, GetMouseLocation());
}
void ClientControlledShellSurface::StartMove(const gfx::Point& location) {
......@@ -375,15 +377,29 @@ void ClientControlledShellSurface::StartMove(const gfx::Point& location) {
if (!widget_)
return;
AttemptToStartDrag(HTCAPTION, location);
}
gfx::Point point_in_root(location);
wm::ConvertPointFromScreen(widget_->GetNativeWindow()->GetRootWindow(),
&point_in_root);
void ClientControlledShellSurface::AttemptToStartDrag(
int component,
const gfx::Point& location) {
aura::Window* target = widget_->GetNativeWindow();
ash::Shell::Get()->toplevel_window_event_handler()->AttemptToStartDrag(
target, point_in_root, HTCAPTION,
ash::ToplevelWindowEventHandler* toplevel_handler =
ash::Shell::Get()->toplevel_window_event_handler();
aura::Window* mouse_pressed_handler =
target->GetHost()->dispatcher()->mouse_pressed_handler();
// Start dragging only if ...
// 1) touch guesture is in progres.
// 2) mouse was pressed on the target or its subsurfaces.
if (toplevel_handler->gesture_target() ||
(mouse_pressed_handler && target->Contains(mouse_pressed_handler))) {
gfx::Point point_in_root(location);
wm::ConvertPointFromScreen(target->GetRootWindow(), &point_in_root);
toplevel_handler->AttemptToStartDrag(
target, point_in_root, component,
ash::wm::WmToplevelWindowEventHandler::EndClosure());
}
}
void ClientControlledShellSurface::SetCanMaximize(bool can_maximize) {
......
......@@ -150,7 +150,7 @@ class ClientControlledShellSurface
void OnDragStarted(int component);
void OnDragFinished(bool cancel, const gfx::Point& location);
void StartResize_DEPRECATED();
void StartResize(int component);
// Starts the move-by-drag operation.
void StartMove(const gfx::Point& location);
......@@ -219,6 +219,8 @@ class ClientControlledShellSurface
void UpdateBackdrop();
void AttemptToStartDrag(int component, const gfx::Point& location);
// Lock the compositor if it's not already locked, or extends the
// lock timeout if it's already locked.
// TODO(reveman): Remove this when using configure callbacks for orientation.
......
......@@ -860,4 +860,45 @@ TEST_F(ClientControlledShellSurfaceTest, SnapWindowInSplitViewModeTest) {
EXPECT_TRUE(HasBackdrop());
}
// The shell surface in SystemModal container should not become target
// at the edge.
TEST_F(ClientControlledShellSurfaceTest, ClientIniatedResize) {
std::unique_ptr<Surface> surface(new Surface);
auto shell_surface =
exo_test_helper()->CreateClientControlledShellSurface(surface.get());
shell_surface->set_client_controlled_move_resize(false);
display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
gfx::Size window_size(100, 100);
std::unique_ptr<Buffer> desktop_buffer(
new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(window_size)));
surface->Attach(desktop_buffer.get());
shell_surface->SetGeometry(gfx::Rect(window_size));
surface->Commit();
EXPECT_TRUE(shell_surface->GetWidget()->widget_delegate()->CanResize());
shell_surface->StartResize(HTTOP);
aura::Window* window = shell_surface->GetWidget()->GetNativeWindow();
// Client cannot start drag if mouse isn't pressed.
ash::wm::WindowState* window_state = ash::wm::GetWindowState(window);
ASSERT_FALSE(window_state->is_dragged());
// Client can start drag only when the mouse is pressed on the widget.
ui::test::EventGenerator& event_generator = GetEventGenerator();
event_generator.MoveMouseToCenterOf(window);
event_generator.PressLeftButton();
shell_surface->StartResize(HTTOP);
ASSERT_TRUE(window_state->is_dragged());
event_generator.ReleaseLeftButton();
ASSERT_FALSE(window_state->is_dragged());
// Press pressed outside of the window.
event_generator.MoveMouseTo(gfx::Point(200, 50));
event_generator.PressLeftButton();
shell_surface->StartResize(HTTOP);
ASSERT_FALSE(window_state->is_dragged());
}
} // namespace exo
......@@ -281,6 +281,61 @@ base::flat_set<DndAction> DataDeviceManagerDndActions(uint32_t value) {
return actions;
}
uint32_t ResizeDirection(int component) {
switch (component) {
case HTCAPTION:
return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_NONE;
case HTTOP:
return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOP;
case HTTOPRIGHT:
return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPRIGHT;
case HTRIGHT:
return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_RIGHT;
case HTBOTTOMRIGHT:
return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMRIGHT;
case HTBOTTOM:
return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOM;
case HTBOTTOMLEFT:
return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMLEFT;
case HTLEFT:
return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_LEFT;
case HTTOPLEFT:
return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPLEFT;
default:
LOG(ERROR) << "Unknown component:" << component;
break;
}
NOTREACHED();
return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_NONE;
}
int Component(uint32_t direction) {
switch (direction) {
case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_NONE:
return HTNOWHERE;
case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOP:
return HTTOP;
case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPRIGHT:
return HTTOPRIGHT;
case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_RIGHT:
return HTRIGHT;
case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMRIGHT:
return HTBOTTOMRIGHT;
case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOM:
return HTBOTTOM;
case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMLEFT:
return HTBOTTOMLEFT;
case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_LEFT:
return HTLEFT;
case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPLEFT:
return HTTOPLEFT;
default:
VLOG(2) << "Unknown direction:" << direction;
break;
}
return HTNOWHERE;
}
// A property key containing the surface resource that is associated with
// window. If unset, no surface resource is associated with surface object.
DEFINE_UI_CLASS_PROPERTY_KEY(wl_resource*, kSurfaceResourceKey, nullptr);
......@@ -2071,9 +2126,10 @@ void remote_surface_set_window_type(wl_client* client,
}
}
void remote_surface_resize(wl_client* client, wl_resource* resource) {
GetUserDataAs<ClientControlledShellSurface>(resource)
->StartResize_DEPRECATED();
void remote_surface_resize(wl_client* client,
wl_resource* resource,
uint32_t direction) {
// DEPRECATED
}
void remote_surface_set_resize_outset(wl_client* client,
......@@ -2126,6 +2182,13 @@ void remote_surface_set_snapped_to_right(wl_client* client,
GetUserDataAs<ClientControlledShellSurface>(resource)->SetSnappedToRight();
}
void remote_surface_start_resize(wl_client* client,
wl_resource* resource,
uint32_t direction) {
GetUserDataAs<ClientControlledShellSurface>(resource)->StartResize(
Component(direction));
}
const struct zcr_remote_surface_v1_interface remote_surface_implementation = {
remote_surface_destroy,
remote_surface_set_app_id,
......@@ -2161,7 +2224,8 @@ const struct zcr_remote_surface_v1_interface remote_surface_implementation = {
remote_surface_set_min_size,
remote_surface_set_max_size,
remote_surface_set_snapped_to_left,
remote_surface_set_snapped_to_right};
remote_surface_set_snapped_to_right,
remote_surface_start_resize};
////////////////////////////////////////////////////////////////////////////////
// notification_surface_interface:
......@@ -2457,34 +2521,6 @@ void HandleRemoteSurfaceBoundsChangedCallback(
wl_client_flush(wl_resource_get_client(resource));
}
uint32_t ResizeDirection(int component) {
switch (component) {
case HTCAPTION:
return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_NONE;
case HTTOP:
return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOP;
case HTTOPRIGHT:
return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPRIGHT;
case HTRIGHT:
return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_RIGHT;
case HTBOTTOMRIGHT:
return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMRIGHT;
case HTBOTTOM:
return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOM;
case HTBOTTOMLEFT:
return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMLEFT;
case HTLEFT:
return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_LEFT;
case HTTOPLEFT:
return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPLEFT;
default:
LOG(ERROR) << "Unknown component:" << component;
break;
}
NOTREACHED();
return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_NONE;
}
void HandleRemoteSurfaceDragStartedCallback(wl_resource* resource,
int component) {
zcr_remote_surface_v1_send_drag_started(resource, ResizeDirection(component));
......@@ -2616,7 +2652,7 @@ const struct zcr_remote_shell_v1_interface remote_shell_implementation = {
remote_shell_destroy, remote_shell_get_remote_surface,
remote_shell_get_notification_surface};
const uint32_t remote_shell_version = 11;
const uint32_t remote_shell_version = 12;
void bind_remote_shell(wl_client* client,
void* data,
......
/* Generated by wayland-scanner 1.13.0 */
/* Generated by wayland-scanner 1.14.0 */
#ifndef REMOTE_SHELL_UNSTABLE_V1_CLIENT_PROTOCOL_H
#define REMOTE_SHELL_UNSTABLE_V1_CLIENT_PROTOCOL_H
......@@ -774,6 +774,7 @@ zcr_remote_surface_v1_add_listener(struct zcr_remote_surface_v1 *zcr_remote_surf
#define ZCR_REMOTE_SURFACE_V1_SET_MAX_SIZE 32
#define ZCR_REMOTE_SURFACE_V1_SET_SNAPPED_TO_LEFT 33
#define ZCR_REMOTE_SURFACE_V1_SET_SNAPPED_TO_RIGHT 34
#define ZCR_REMOTE_SURFACE_V1_START_RESIZE 35
/**
* @ingroup iface_zcr_remote_surface_v1
......@@ -944,6 +945,10 @@ zcr_remote_surface_v1_add_listener(struct zcr_remote_surface_v1 *zcr_remote_surf
* @ingroup iface_zcr_remote_surface_v1
*/
#define ZCR_REMOTE_SURFACE_V1_SET_SNAPPED_TO_RIGHT_SINCE_VERSION 11
/**
* @ingroup iface_zcr_remote_surface_v1
*/
#define ZCR_REMOTE_SURFACE_V1_START_RESIZE_SINCE_VERSION 12
/** @ingroup iface_zcr_remote_surface_v1 */
static inline void
......@@ -1399,7 +1404,7 @@ zcr_remote_surface_v1_set_window_type(struct zcr_remote_surface_v1 *zcr_remote_s
/**
* @ingroup iface_zcr_remote_surface_v1
*
* Start an interactive, user-driven resize of the surface.
* [Deprecated] Start an interactive, user-driven resize of the surface.
*
* The compositor responds to this request with a configure event that
* transitions to the "resizing" state. The client must only initiate
......@@ -1411,10 +1416,10 @@ zcr_remote_surface_v1_set_window_type(struct zcr_remote_surface_v1 *zcr_remote_s
* surface, e.g. fullscreen or maximized.
*/
static inline void
zcr_remote_surface_v1_resize(struct zcr_remote_surface_v1 *zcr_remote_surface_v1)
zcr_remote_surface_v1_resize(struct zcr_remote_surface_v1 *zcr_remote_surface_v1, uint32_t direction)
{
wl_proxy_marshal((struct wl_proxy *) zcr_remote_surface_v1,
ZCR_REMOTE_SURFACE_V1_RESIZE);
ZCR_REMOTE_SURFACE_V1_RESIZE, direction);
}
/**
......@@ -1536,6 +1541,27 @@ zcr_remote_surface_v1_set_snapped_to_right(struct zcr_remote_surface_v1 *zcr_rem
ZCR_REMOTE_SURFACE_V1_SET_SNAPPED_TO_RIGHT);
}
/**
* @ingroup iface_zcr_remote_surface_v1
*
* Request to start an interactive, user-driven resize of the surface.
*
* The compositor responds to this request with a "drag_started"
* event, followed by "bounds_changed" events, and ends the
* resize operation with a "drag_finhsed" event. The compositor
* determines the new bounds using the resize_direction and the
* pointer event location.
*
* The compositor may ignore resize requests depending on the state of the
* surface, e.g. fullscreen or maximized, or no drag event is in pregress.
*/
static inline void
zcr_remote_surface_v1_start_resize(struct zcr_remote_surface_v1 *zcr_remote_surface_v1, uint32_t resize_direction)
{
wl_proxy_marshal((struct wl_proxy *) zcr_remote_surface_v1,
ZCR_REMOTE_SURFACE_V1_START_RESIZE, resize_direction);
}
#define ZCR_NOTIFICATION_SURFACE_V1_DESTROY 0
......
/* Generated by wayland-scanner 1.13.0 */
/* Generated by wayland-scanner 1.14.0 */
#ifndef REMOTE_SHELL_UNSTABLE_V1_SERVER_PROTOCOL_H
#define REMOTE_SHELL_UNSTABLE_V1_SERVER_PROTOCOL_H
......@@ -888,7 +888,8 @@ struct zcr_remote_surface_v1_interface {
/**
* start an interactive resize
*
* Start an interactive, user-driven resize of the surface.
* [Deprecated] Start an interactive, user-driven resize of the
* surface.
*
* The compositor responds to this request with a configure event
* that transitions to the "resizing" state. The client must only
......@@ -899,10 +900,12 @@ struct zcr_remote_surface_v1_interface {
*
* The compositor may ignore resize requests depending on the state
* of the surface, e.g. fullscreen or maximized.
* @param direction the direction of resize
* @since 9
*/
void (*resize)(struct wl_client *client,
struct wl_resource *resource);
struct wl_resource *resource,
uint32_t direction);
/**
* expand input region for resizing
*
......@@ -998,6 +1001,27 @@ struct zcr_remote_surface_v1_interface {
*/
void (*set_snapped_to_right)(struct wl_client *client,
struct wl_resource *resource);
/**
* start an interactive resize
*
* Request to start an interactive, user-driven resize of the
* surface.
*
* The compositor responds to this request with a "drag_started"
* event, followed by "bounds_changed" events, and ends the resize
* operation with a "drag_finhsed" event. The compositor determines
* the new bounds using the resize_direction and the pointer event
* location.
*
* The compositor may ignore resize requests depending on the state
* of the surface, e.g. fullscreen or maximized, or no drag event
* is in pregress.
* @param resize_direction the direction of resize
* @since 12
*/
void (*start_resize)(struct wl_client *client,
struct wl_resource *resource,
uint32_t resize_direction);
};
#define ZCR_REMOTE_SURFACE_V1_CLOSE 0
......@@ -1177,6 +1201,10 @@ struct zcr_remote_surface_v1_interface {
* @ingroup iface_zcr_remote_surface_v1
*/
#define ZCR_REMOTE_SURFACE_V1_SET_SNAPPED_TO_RIGHT_SINCE_VERSION 11
/**
* @ingroup iface_zcr_remote_surface_v1
*/
#define ZCR_REMOTE_SURFACE_V1_START_RESIZE_SINCE_VERSION 12
/**
* @ingroup iface_zcr_remote_surface_v1
......
/* Generated by wayland-scanner 1.13.0 */
/* Generated by wayland-scanner 1.14.0 */
/*
* Copyright 2016 The Chromium Authors.
......@@ -70,7 +70,7 @@ static const struct wl_message zcr_remote_shell_v1_events[] = {
};
WL_EXPORT const struct wl_interface zcr_remote_shell_v1_interface = {
"zcr_remote_shell_v1", 11,
"zcr_remote_shell_v1", 12,
3, zcr_remote_shell_v1_requests,
5, zcr_remote_shell_v1_events,
};
......@@ -102,7 +102,7 @@ static const struct wl_message zcr_remote_surface_v1_requests[] = {
{ "move", "5", types + 0 },
{ "set_orientation", "6i", types + 0 },
{ "set_window_type", "7u", types + 0 },
{ "resize", "9", types + 0 },
{ "resize", "9u", types + 0 },
{ "set_resize_outset", "9i", types + 0 },
{ "start_move", "10ii", types + 0 },
{ "set_can_maximize", "10", types + 0 },
......@@ -111,6 +111,7 @@ static const struct wl_message zcr_remote_surface_v1_requests[] = {
{ "set_max_size", "10ii", types + 0 },
{ "set_snapped_to_left", "11", types + 0 },
{ "set_snapped_to_right", "11", types + 0 },
{ "start_resize", "12u", types + 0 },
};
static const struct wl_message zcr_remote_surface_v1_events[] = {
......@@ -124,8 +125,8 @@ static const struct wl_message zcr_remote_surface_v1_events[] = {
};
WL_EXPORT const struct wl_interface zcr_remote_surface_v1_interface = {
"zcr_remote_surface_v1", 11,
35, zcr_remote_surface_v1_requests,
"zcr_remote_surface_v1", 12,
36, zcr_remote_surface_v1_requests,
7, zcr_remote_surface_v1_events,
};
......
......@@ -38,7 +38,7 @@
reset.
</description>
<interface name="zcr_remote_shell_v1" version="11">
<interface name="zcr_remote_shell_v1" version="12">
<description summary="remote_shell">
The global interface that allows clients to turn a wl_surface into a
"real window" which is remotely managed but can be stacked, activated
......@@ -183,7 +183,7 @@
</event>
</interface>
<interface name="zcr_remote_surface_v1" version="11">
<interface name="zcr_remote_surface_v1" version="12">
<description summary="A desktop window">
An interface that may be implemented by a wl_surface, for
implementations that provide a desktop-style user interface
......@@ -584,7 +584,7 @@
<request name="resize" since="9">
<description summary="start an interactive resize">
Start an interactive, user-driven resize of the surface.
[Deprecated] Start an interactive, user-driven resize of the surface.
The compositor responds to this request with a configure event that
transitions to the "resizing" state. The client must only initiate
......@@ -773,6 +773,24 @@
</description>
</request>
<!-- Version 12 additions -->
<request name="start_resize" since="12">
<description summary="start an interactive resize">
Request to start an interactive, user-driven resize of the surface.
The compositor responds to this request with a "drag_started"
event, followed by "bounds_changed" events, and ends the
resize operation with a "drag_finhsed" event. The compositor
determines the new bounds using the resize_direction and the
pointer event location.
The compositor may ignore resize requests depending on the state of the
surface, e.g. fullscreen or maximized, or no drag event is in pregress.
</description>
<arg name="resize_direction" type="uint" summary="the direction of resize"/>
</request>
</interface>
<interface name="zcr_notification_surface_v1" version="1">
......
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