Commit 49361034 authored by Evan Stade's avatar Evan Stade Committed by Commit Bot

Mash: Handle events on browser frame.

This re-implements functionality Ash would normally provide via
WorkspaceEventHandler (double click/tap on frame for maximize) and
WmToplevelWindowEventHandler (drag).

Dragging by gesture is a TODO, and may be more complicated. (It doesn't
work for tab-initiated drags either.)

Change-Id: Ie9eff39915dd6ea68dcc69ac9b46d6edda78f23f
Reviewed-on: https://chromium-review.googlesource.com/1246417Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Commit-Queue: Evan Stade <estade@chromium.org>
Cr-Commit-Position: refs/heads/master@{#595828}
parent a0b0fe61
......@@ -4,6 +4,8 @@
module ash.mojom;
import "ui/events/mojo/event_constants.mojom";
// The previewed snap state for a window, corresponding to the use of a
// PhantomWindowController.
enum SnapDirection {
......@@ -21,4 +23,8 @@ interface AshWindowManager {
ShowSnapPreview(uint64 window_id, SnapDirection snap);
CommitSnap(uint64 window_id, SnapDirection snap);
// Maximizes the window in response to a double click or tap on the HTCAPTION
// area.
MaximizeWindowByCaptionClick(uint64 window_id, ui.mojom.PointerKind pointer);
};
......@@ -6,7 +6,10 @@
#include "ash/shell.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "ash/wm/window_state.h"
#include "ash/wm/wm_event.h"
#include "base/logging.h"
#include "base/metrics/user_metrics.h"
#include "services/ws/window_tree.h"
namespace ash {
......@@ -49,4 +52,28 @@ void AshWindowManager::CommitSnap(ws::Id window_id, mojom::SnapDirection snap) {
}
}
void AshWindowManager::MaximizeWindowByCaptionClick(
ws::Id window_id,
ui::mojom::PointerKind pointer) {
aura::Window* window = window_tree_->GetWindowByTransportId(window_id);
if (!window || !window_tree_->IsTopLevel(window)) {
DVLOG(1) << "MaximizeWindowByCaptionClick passed invalid window, id="
<< window_id;
return;
}
if (pointer == ui::mojom::PointerKind::MOUSE) {
base::RecordAction(base::UserMetricsAction("Caption_ClickTogglesMaximize"));
} else if (pointer == ui::mojom::PointerKind::TOUCH) {
base::RecordAction(
base::UserMetricsAction("Caption_GestureTogglesMaximize"));
} else {
DVLOG(1) << "MaximizeWindowByCaptionClick passed invalid event";
return;
}
const wm::WMEvent wm_event(wm::WM_EVENT_TOGGLE_MAXIMIZE_CAPTION);
wm::GetWindowState(window)->OnWMEvent(&wm_event);
}
} // namespace ash
......@@ -33,6 +33,8 @@ class AshWindowManager : public mojom::AshWindowManager,
void AddWindowToTabletMode(ws::Id window_id) override;
void ShowSnapPreview(ws::Id window_id, mojom::SnapDirection snap) override;
void CommitSnap(ws::Id window_id, mojom::SnapDirection snap) override;
void MaximizeWindowByCaptionClick(ws::Id window_id,
ui::mojom::PointerKind pointer) override;
private:
ws::WindowTree* window_tree_;
......
......@@ -55,6 +55,7 @@
#include "ui/base/layout.h"
#include "ui/base/material_design/material_design_controller.h"
#include "ui/base/ui_base_features.h"
#include "ui/display/screen.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/scoped_canvas.h"
......@@ -471,6 +472,80 @@ void BrowserNonClientFrameViewAsh::ChildPreferredSizeChanged(
}
}
bool BrowserNonClientFrameViewAsh::OnMousePressed(const ui::MouseEvent& event) {
if (!features::IsUsingWindowService())
return false;
if (event.IsOnlyLeftMouseButton()) {
if (event.flags() & ui::EF_IS_DOUBLE_CLICK) {
ash_window_manager_->MaximizeWindowByCaptionClick(
GetServerWindowId(), ui::mojom::PointerKind::MOUSE);
}
// Return true for single clicks to receive subsequent drag events.
return true;
}
return false;
}
bool BrowserNonClientFrameViewAsh::OnMouseDragged(const ui::MouseEvent& event) {
if (!features::IsUsingWindowService())
return false;
// The client may receive multiple drag events before Ash has taken over the
// window move. In this case, ignore the extras.
if (performing_window_move_)
return true;
aura::WindowTreeHostMus* window_tree_host_mus =
static_cast<aura::WindowTreeHostMus*>(
GetWidget()->GetNativeWindow()->GetHost());
performing_window_move_ = true;
window_tree_host_mus->PerformWindowMove(
ws::mojom::MoveLoopSource::MOUSE,
display::Screen::GetScreen()->GetCursorScreenPoint(),
base::BindRepeating(&BrowserNonClientFrameViewAsh::OnWindowMoveDone,
weak_ptr_factory_.GetWeakPtr()));
return true;
}
void BrowserNonClientFrameViewAsh::OnMouseReleased(
const ui::MouseEvent& event) {
// If a window move has already been triggered and OnMouseReleased() is
// called, it means the mouse was released before the Ash asserted mouse
// capture, and the move should be cancelled. Note that if something else
// grabs mouse capture right after PerformWindowMove(), Ash may re-assert that
// capture instead of cancelling the move.
if (performing_window_move_) {
aura::WindowTreeHostMus* window_tree_host_mus =
static_cast<aura::WindowTreeHostMus*>(
GetWidget()->GetNativeWindow()->GetHost());
window_tree_host_mus->CancelWindowMove();
}
}
void BrowserNonClientFrameViewAsh::OnGestureEvent(ui::GestureEvent* event) {
if (!features::IsUsingWindowService())
return;
switch (event->type()) {
case ui::ET_GESTURE_TAP:
if (event->details().tap_count() == 2) {
// TODO(estade): need to log TouchUMA for GESTURE_MAXIMIZE_DOUBLETAP and
// GESTURE_FRAMEVIEW_TAP, as in WorkspaceEventHandler.
ash_window_manager_->MaximizeWindowByCaptionClick(
GetServerWindowId(), ui::mojom::PointerKind::TOUCH);
event->StopPropagation();
}
break;
// TODO(estade): handle gestures that trigger drags.
default:
break;
}
}
///////////////////////////////////////////////////////////////////////////////
// ash::BrowserFrameHeaderAsh::AppearanceProvider:
......@@ -877,6 +952,10 @@ bool BrowserNonClientFrameViewAsh::IsInOverviewMode() const {
return GetFrameWindow()->GetProperty(ash::kIsShowingInOverviewKey);
}
void BrowserNonClientFrameViewAsh::OnWindowMoveDone(bool success) {
performing_window_move_ = false;
}
const aura::Window* BrowserNonClientFrameViewAsh::GetFrameWindow() const {
return const_cast<BrowserNonClientFrameViewAsh*>(this)->GetFrameWindow();
}
......
......@@ -11,6 +11,7 @@
#include "ash/public/interfaces/split_view.mojom.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observer.h"
#include "chrome/browser/command_observer.h"
#include "chrome/browser/ui/ash/tablet_mode_client_observer.h"
......@@ -87,6 +88,10 @@ class BrowserNonClientFrameViewAsh
gfx::Size GetMinimumSize() const override;
void OnThemeChanged() override;
void ChildPreferredSizeChanged(views::View* child) override;
bool OnMousePressed(const ui::MouseEvent& event) override;
bool OnMouseDragged(const ui::MouseEvent& event) override;
void OnMouseReleased(const ui::MouseEvent& event) override;
void OnGestureEvent(ui::GestureEvent* event) override;
// BrowserFrameHeaderAsh::AppearanceProvider:
SkColor GetTitleColor() override;
......@@ -216,6 +221,8 @@ class BrowserNonClientFrameViewAsh
// Returns whether this window is currently in the overview list.
bool IsInOverviewMode() const;
void OnWindowMoveDone(bool success);
// Returns the top level aura::Window for this browser window.
const aura::Window* GetFrameWindow() const;
aura::Window* GetFrameWindow();
......@@ -254,6 +261,8 @@ class BrowserNonClientFrameViewAsh
ScopedObserver<aura::Window, aura::WindowObserver> window_observer_{this};
bool performing_window_move_ = false;
// Maintains the current split view state.
ash::mojom::SplitViewState split_view_state_ =
ash::mojom::SplitViewState::NO_SNAP;
......@@ -261,6 +270,8 @@ class BrowserNonClientFrameViewAsh
// Only used in mash.
ash::mojom::AshWindowManagerAssociatedPtr ash_window_manager_;
base::WeakPtrFactory<BrowserNonClientFrameViewAsh> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(BrowserNonClientFrameViewAsh);
};
......
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