chromium/ui/views/widget/desktop_aura/window_event_filter_lacros.cc

// Copyright 2022 The Chromium Authors
// 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/window_event_filter_lacros.h"

#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/hit_test.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/platform_window/wm/wm_move_resize_handler.h"
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h"
#include "ui/views/widget/widget.h"

namespace views {

WindowEventFilterLacros::WindowEventFilterLacros(
    DesktopWindowTreeHostPlatform* desktop_window_tree_host,
    ui::WmMoveResizeHandler* handler)
    : desktop_window_tree_host_(desktop_window_tree_host), handler_(handler) {
  desktop_window_tree_host_->window()->AddPreTargetHandler(this);
}

WindowEventFilterLacros::~WindowEventFilterLacros() {
  desktop_window_tree_host_->window()->RemovePreTargetHandler(this);
}

void WindowEventFilterLacros::OnMouseEvent(ui::MouseEvent* event) {
  if (event->type() != ui::EventType::kMousePressed ||
      !event->IsOnlyLeftMouseButton()) {
    return;
  }

  auto* window = static_cast<aura::Window*>(event->target());
  int component =
      window->delegate()
          ? window->delegate()->GetNonClientComponent(event->location())
          : HTNOWHERE;

  if (event->flags() & ui::EF_IS_DOUBLE_CLICK) {
    if (previous_pressed_component_ == HTCAPTION && component == HTCAPTION) {
      MaybeToggleMaximizedState(window);
      previous_pressed_component_ = HTNOWHERE;
      event->SetHandled();
    }
    return;
  }
  previous_pressed_component_ = component;
  MaybeDispatchHostWindowDragMovement(component, event);
}

void WindowEventFilterLacros::OnGestureEvent(ui::GestureEvent* event) {
  auto* window = static_cast<aura::Window*>(event->target());
  int component =
      window->delegate()
          ? window->delegate()->GetNonClientComponent(event->location())
          : HTNOWHERE;

  // Double tap to maximize.
  if (event->type() == ui::EventType::kGestureTap) {
    int previous_pressed_component = previous_pressed_component_;
    previous_pressed_component_ = component;

    if (previous_pressed_component_ == HTCAPTION &&
        previous_pressed_component == HTCAPTION &&
        event->details().tap_count() == 2) {
      MaybeToggleMaximizedState(window);
      previous_pressed_component_ = HTNOWHERE;
      event->SetHandled();
    }
    return;
  }

  // Interactive window move.
  if (event->type() == ui::EventType::kGestureScrollBegin) {
    MaybeDispatchHostWindowDragMovement(component, event);
  }
}

void WindowEventFilterLacros::MaybeToggleMaximizedState(aura::Window* window) {
  if (!(window->GetProperty(aura::client::kResizeBehaviorKey) &
        aura::client::kResizeBehaviorCanMaximize)) {
    return;
  }

  // TODO(crbug.com/40215883): send toggle event to ash-chrome.
  if (desktop_window_tree_host_->IsMaximized())
    desktop_window_tree_host_->Restore();
  else
    desktop_window_tree_host_->Maximize();
}

void WindowEventFilterLacros::MaybeDispatchHostWindowDragMovement(
    int component,
    ui::LocatedEvent* event) {
  if (!handler_ || !ui::CanPerformDragOrResize(component))
    return;

  // The location argument is not used in lacros as the drag and resize
  // are handled by the compositor (ash-chrome).
  handler_->DispatchHostWindowDragMovement(component, gfx::Point());

  // Stop the event propagation for mouse events only (not touch), given that
  // it'd prevent the Gesture{Provider,Detector} machirery to get triggered,
  // breaking gestures including tapping, double tapping, show press and
  // long press.
  if (event->IsMouseEvent())
    event->StopPropagation();
}

}  // namespace views