| // Copyright 2024 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ash/wm/system_panel_view.h" |
| |
| #include "base/debug/dump_without_crashing.h" |
| #include "ui/base/metadata/metadata_impl_macros.h" |
| #include "ui/display/screen.h" |
| #include "ui/events/event.h" |
| #include "ui/events/types/event_type.h" |
| #include "ui/gfx/geometry/point.h" |
| #include "ui/gfx/geometry/rect.h" |
| #include "ui/views/widget/widget.h" |
| |
| namespace ash { |
| |
| namespace { |
| |
| // The percentage of the panel which will be used as the buffer zone around the |
| // screen edges. |
| constexpr float kBufferRatio = 2.0 / 3.0; |
| |
| } // namespace |
| |
| // ----------------------------------------------------------------------------- |
| // SystemPanelView::DragController: |
| void SystemPanelView::DragController::OnLocatedPanelEvent( |
| views::Widget* const widget, |
| ui::LocatedEvent* event) { |
| if (!widget) { |
| is_dragging_ = false; |
| base::debug::DumpWithoutCrashing(); |
| return; |
| } |
| |
| switch (event->type()) { |
| case ui::EventType::kMousePressed: |
| case ui::EventType::kGestureScrollBegin: |
| is_dragging_ = true; |
| panel_widget_initial_bounds_ = widget->GetWindowBoundsInScreen(); |
| start_dragging_event_location_ = |
| event->target()->GetScreenLocation(*event); |
| event->SetHandled(); |
| break; |
| case ui::EventType::kMouseDragged: |
| case ui::EventType::kGestureScrollUpdate: { |
| if (!is_dragging_) { |
| break; |
| } |
| |
| gfx::Point event_location = event->target()->GetScreenLocation(*event); |
| gfx::Rect panel_widget_bounds = panel_widget_initial_bounds_; |
| panel_widget_bounds.Offset(event_location - |
| start_dragging_event_location_); |
| |
| // Establishes a buffer zone around the screen edges equal to |
| // `kBufferRatio` of the height or width of the panel. This will prevent |
| // the panel from being dragged too far that less than 1-`kBufferRatio` of |
| // it remains visible on the screen. |
| auto buff_width = panel_widget_bounds.width() * kBufferRatio; |
| auto buff_height = panel_widget_bounds.height() * kBufferRatio; |
| auto screen_bounds = display::Screen::GetScreen() |
| ->GetDisplayNearestPoint(event_location) |
| .bounds(); |
| screen_bounds.SetByBounds( |
| screen_bounds.x() - buff_width, screen_bounds.y() - buff_height, |
| screen_bounds.width() + screen_bounds.x() + buff_width, |
| screen_bounds.y() + screen_bounds.height() + buff_height); |
| panel_widget_bounds.AdjustToFit(screen_bounds); |
| |
| widget->SetBounds(panel_widget_bounds); |
| event->SetHandled(); |
| break; |
| } |
| case ui::EventType::kMouseReleased: |
| case ui::EventType::kGestureScrollEnd: |
| case ui::EventType::kGestureEnd: |
| if (!is_dragging_) { |
| break; |
| } |
| is_dragging_ = false; |
| event->SetHandled(); |
| break; |
| default: |
| break; |
| } |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // SystemPanelView: |
| |
| SystemPanelView::SystemPanelView() = default; |
| |
| SystemPanelView::~SystemPanelView() = default; |
| |
| bool SystemPanelView::IsDragging() const { |
| return drag_controller_.is_dragging_; |
| } |
| |
| void SystemPanelView::OnMouseEvent(ui::MouseEvent* event) { |
| HandleDragEventIfNeeded(event); |
| } |
| |
| void SystemPanelView::OnGestureEvent(ui::GestureEvent* event) { |
| HandleDragEventIfNeeded(event); |
| } |
| |
| void SystemPanelView::HandleDragEventIfNeeded(ui::LocatedEvent* event) { |
| // Checks whether the event is part of a drag sequence and handles it if |
| // needed. Note that we only handle drag events for repositioning the panel |
| // here. Other drag behavior, e.g. for text selection, is handled by the |
| // panel's child views. |
| drag_controller_.OnLocatedPanelEvent(GetWidget(), event); |
| } |
| |
| BEGIN_METADATA(SystemPanelView) |
| END_METADATA |
| |
| } // namespace ash |