Commit fa9facbf authored by Sammie Quon's avatar Sammie Quon Committed by Commit Bot

overview: Make scrolling more performant.

- Do not update scroll if the delta is too small, this matches what
  drags on overview items do.
- Pause occlusion tracker on scroll.
- When scrolling, do not call SetBounds unless the item is leaving or
  entering the view of the grid.

Tested locally with OverviewScrollTest.Basic. Not the greatest gains
when only 12 windows, but scales much better with larger number of
windows.

Presentation time:
Before 12 windows: 55ms
Before 42 windows: 180ms
After 12 windows: 53ms
After 42 windows: 88ms

Also renamed a overview_grid_pre_event_handler ->
overview_grid_event_handler as it handles regular events now.

Test: manual
Bug: 978112, 993615
Change-Id: I28bcbb8ce3291f975df9f1033961fbe176052fc0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1784349
Commit-Queue: Sammie Quon <sammiequon@chromium.org>
Reviewed-by: default avatarXiaoqian Dai <xdai@chromium.org>
Cr-Commit-Position: refs/heads/master@{#693921}
parent fb518331
...@@ -1161,8 +1161,8 @@ component("ash") { ...@@ -1161,8 +1161,8 @@ component("ash") {
"wm/overview/overview_delegate.h", "wm/overview/overview_delegate.h",
"wm/overview/overview_grid.cc", "wm/overview/overview_grid.cc",
"wm/overview/overview_grid.h", "wm/overview/overview_grid.h",
"wm/overview/overview_grid_pre_event_handler.cc", "wm/overview/overview_grid_event_handler.cc",
"wm/overview/overview_grid_pre_event_handler.h", "wm/overview/overview_grid_event_handler.h",
"wm/overview/overview_highlight_controller.cc", "wm/overview/overview_highlight_controller.cc",
"wm/overview/overview_highlight_controller.h", "wm/overview/overview_highlight_controller.h",
"wm/overview/overview_item.cc", "wm/overview/overview_item.cc",
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#include "ash/wm/overview/overview_constants.h" #include "ash/wm/overview/overview_constants.h"
#include "ash/wm/overview/overview_controller.h" #include "ash/wm/overview/overview_controller.h"
#include "ash/wm/overview/overview_delegate.h" #include "ash/wm/overview/overview_delegate.h"
#include "ash/wm/overview/overview_grid_pre_event_handler.h" #include "ash/wm/overview/overview_grid_event_handler.h"
#include "ash/wm/overview/overview_highlight_controller.h" #include "ash/wm/overview/overview_highlight_controller.h"
#include "ash/wm/overview/overview_item.h" #include "ash/wm/overview/overview_item.h"
#include "ash/wm/overview/overview_session.h" #include "ash/wm/overview/overview_session.h"
...@@ -76,6 +76,13 @@ constexpr int kTabletLayoutRow = 2; ...@@ -76,6 +76,13 @@ constexpr int kTabletLayoutRow = 2;
constexpr int kMinimumItemsForNewLayout = 6; constexpr int kMinimumItemsForNewLayout = 6;
// The minimum distance that is needed to process a scroll event.
constexpr float kMinimumScrollDistanceDp = 5.f;
// Wait a while before unpausing the occlusion tracker after a scroll has
// completed as the user may start another scroll.
constexpr int kOcclusionUnpauseDurationForScrollMs = 500;
// Histogram names for overview enter/exit smoothness in clamshell, // Histogram names for overview enter/exit smoothness in clamshell,
// tablet mode and splitview. // tablet mode and splitview.
constexpr char kOverviewEnterClamshellHistogram[] = constexpr char kOverviewEnterClamshellHistogram[] =
...@@ -402,7 +409,7 @@ OverviewGrid::~OverviewGrid() = default; ...@@ -402,7 +409,7 @@ OverviewGrid::~OverviewGrid() = default;
void OverviewGrid::Shutdown() { void OverviewGrid::Shutdown() {
ScreenRotationAnimator::GetForRootWindow(root_window_)->RemoveObserver(this); ScreenRotationAnimator::GetForRootWindow(root_window_)->RemoveObserver(this);
Shell::Get()->wallpaper_controller()->RemoveObserver(this); Shell::Get()->wallpaper_controller()->RemoveObserver(this);
grid_pre_event_handler_.reset(); grid_event_handler_.reset();
bool has_non_cover_animating = false; bool has_non_cover_animating = false;
int animate_count = 0; int animate_count = 0;
...@@ -445,7 +452,7 @@ void OverviewGrid::PrepareForOverview() { ...@@ -445,7 +452,7 @@ void OverviewGrid::PrepareForOverview() {
ScreenRotationAnimator::GetForRootWindow(root_window_)->AddObserver(this); ScreenRotationAnimator::GetForRootWindow(root_window_)->AddObserver(this);
} }
grid_pre_event_handler_ = std::make_unique<OverviewGridPreEventHandler>(this); grid_event_handler_ = std::make_unique<OverviewGridEventHandler>(this);
Shell::Get()->wallpaper_controller()->AddObserver(this); Shell::Get()->wallpaper_controller()->AddObserver(this);
} }
...@@ -922,11 +929,11 @@ void OverviewGrid::OnScreenRotationAnimationFinished( ...@@ -922,11 +929,11 @@ void OverviewGrid::OnScreenRotationAnimationFinished(
} }
void OverviewGrid::OnWallpaperChanging() { void OverviewGrid::OnWallpaperChanging() {
grid_pre_event_handler_.reset(); grid_event_handler_.reset();
} }
void OverviewGrid::OnWallpaperChanged() { void OverviewGrid::OnWallpaperChanged() {
grid_pre_event_handler_ = std::make_unique<OverviewGridPreEventHandler>(this); grid_event_handler_ = std::make_unique<OverviewGridEventHandler>(this);
} }
void OverviewGrid::OnStartingAnimationComplete(bool canceled) { void OverviewGrid::OnStartingAnimationComplete(bool canceled) {
...@@ -1344,17 +1351,25 @@ bool OverviewGrid::MaybeDropItemOnDeskMiniView( ...@@ -1344,17 +1351,25 @@ bool OverviewGrid::MaybeDropItemOnDeskMiniView(
} }
void OverviewGrid::StartScroll() { void OverviewGrid::StartScroll() {
Shell::Get()->overview_controller()->PauseOcclusionTracker();
// Users are not allowed to scroll past the leftmost or rightmost bounds of // Users are not allowed to scroll past the leftmost or rightmost bounds of
// the items on screen in the grid. |scroll_offset_min_| is the amount needed // the items on screen in the grid. |scroll_offset_min_| is the amount needed
// to fit the rightmost window into |total_bounds|. The max is zero which is // to fit the rightmost window into |total_bounds|. The max is zero which is
// default because windows are aligned to the left from the beginning. // default because windows are aligned to the left from the beginning.
gfx::Rect total_bounds = GetGridEffectiveBounds(); gfx::Rect total_bounds = GetGridEffectiveBounds();
total_bounds.Inset(GetGridInsets(total_bounds)); total_bounds.Inset(GetGridInsets(total_bounds));
float rightmost_window_right = 0; float rightmost_window_right = 0;
for (const auto& window : window_list_) { items_scrolling_bounds_.resize(window_list_.size());
if (rightmost_window_right < window->target_bounds().right()) for (size_t i = 0; i < items_scrolling_bounds_.size(); ++i) {
rightmost_window_right = window->target_bounds().right(); const gfx::RectF bounds = window_list_[i]->target_bounds();
if (rightmost_window_right < bounds.right())
rightmost_window_right = bounds.right();
items_scrolling_bounds_[i] = bounds;
} }
// |rightmost_window_right| may have been modified by an earlier scroll. // |rightmost_window_right| may have been modified by an earlier scroll.
// |scroll_offset_| is added to adjust for that. // |scroll_offset_| is added to adjust for that.
rightmost_window_right -= scroll_offset_; rightmost_window_right -= scroll_offset_;
...@@ -1366,13 +1381,33 @@ void OverviewGrid::StartScroll() { ...@@ -1366,13 +1381,33 @@ void OverviewGrid::StartScroll() {
} }
bool OverviewGrid::UpdateScrollOffset(float delta) { bool OverviewGrid::UpdateScrollOffset(float delta) {
const float previous_scroll_offset = scroll_offset_; float new_scroll_offset = scroll_offset_;
scroll_offset_ += delta; new_scroll_offset += delta;
scroll_offset_ = base::ClampToRange(scroll_offset_, scroll_offset_min_, 0.f); new_scroll_offset =
if (scroll_offset_ == previous_scroll_offset) base::ClampToRange(new_scroll_offset, scroll_offset_min_, 0.f);
if (new_scroll_offset == scroll_offset_)
return false; return false;
PositionWindows(/*animate=*/false); // Do not process scrolls that haven't moved much, unless we are at the
// edges.
if (std::abs(scroll_offset_ - new_scroll_offset) < kMinimumScrollDistanceDp &&
scroll_offset_ > scroll_offset_min_ && scroll_offset_ < 0) {
return false;
}
// Update the bounds of the items which are currently visible on screen.
DCHECK_EQ(items_scrolling_bounds_.size(), window_list_.size());
for (size_t i = 0; i < items_scrolling_bounds_.size(); ++i) {
const gfx::RectF previous_bounds = items_scrolling_bounds_[i];
items_scrolling_bounds_[i].Offset(new_scroll_offset - scroll_offset_, 0.f);
const gfx::RectF new_bounds = items_scrolling_bounds_[i];
if (gfx::RectF(GetGridEffectiveBounds()).Intersects(new_bounds) ||
gfx::RectF(GetGridEffectiveBounds()).Intersects(previous_bounds)) {
window_list_[i]->SetBounds(new_bounds, OVERVIEW_ANIMATION_NONE);
}
}
scroll_offset_ = new_scroll_offset;
DCHECK(presentation_time_recorder_); DCHECK(presentation_time_recorder_);
presentation_time_recorder_->RequestNext(); presentation_time_recorder_->RequestNext();
...@@ -1380,7 +1415,12 @@ bool OverviewGrid::UpdateScrollOffset(float delta) { ...@@ -1380,7 +1415,12 @@ bool OverviewGrid::UpdateScrollOffset(float delta) {
} }
void OverviewGrid::EndScroll() { void OverviewGrid::EndScroll() {
Shell::Get()->overview_controller()->UnpauseOcclusionTracker(
kOcclusionUnpauseDurationForScrollMs);
items_scrolling_bounds_.clear();
presentation_time_recorder_.reset(); presentation_time_recorder_.reset();
PositionWindows(/*animate=*/false);
} }
void OverviewGrid::MaybeInitDesksWidget() { void OverviewGrid::MaybeInitDesksWidget() {
......
...@@ -32,7 +32,7 @@ namespace ash { ...@@ -32,7 +32,7 @@ namespace ash {
class DesksBarView; class DesksBarView;
class FpsCounter; class FpsCounter;
class OverviewGridPreEventHandler; class OverviewGridEventHandler;
class OverviewItem; class OverviewItem;
class PresentationTimeRecorder; class PresentationTimeRecorder;
...@@ -316,8 +316,8 @@ class ASH_EXPORT OverviewGrid : public aura::WindowObserver, ...@@ -316,8 +316,8 @@ class ASH_EXPORT OverviewGrid : public aura::WindowObserver,
views::Widget* drop_target_widget() { return drop_target_widget_.get(); } views::Widget* drop_target_widget() { return drop_target_widget_.get(); }
OverviewGridPreEventHandler* grid_pre_event_handler() { OverviewGridEventHandler* grid_event_handler() {
return grid_pre_event_handler_.get(); return grid_event_handler_.get();
} }
private: private:
...@@ -439,8 +439,8 @@ class ASH_EXPORT OverviewGrid : public aura::WindowObserver, ...@@ -439,8 +439,8 @@ class ASH_EXPORT OverviewGrid : public aura::WindowObserver,
// Measures the animation smoothness of overview animation. // Measures the animation smoothness of overview animation.
std::unique_ptr<FpsCounter> fps_counter_; std::unique_ptr<FpsCounter> fps_counter_;
// True to skip |PositionWindows()|. Used to avoid O(n^2) layout // True to skip |PositionWindows()|. Used to avoid O(n^2) layout when
// when reposition windows in tablet overview mode. // reposition windows in tablet overview mode.
bool suspend_reposition_ = false; bool suspend_reposition_ = false;
// Used by |GetWindowRectsForTabletModeLayout| to shift the x position of the // Used by |GetWindowRectsForTabletModeLayout| to shift the x position of the
...@@ -451,8 +451,12 @@ class ASH_EXPORT OverviewGrid : public aura::WindowObserver, ...@@ -451,8 +451,12 @@ class ASH_EXPORT OverviewGrid : public aura::WindowObserver,
// are visible in tablet overview mode. // are visible in tablet overview mode.
float scroll_offset_min_ = 0; float scroll_offset_min_ = 0;
// Cached values of the item bounds so that they do not have to be calculated
// on each scroll update.
std::vector<gfx::RectF> items_scrolling_bounds_;
// Handles events that are not handled by the OverviewItems. // Handles events that are not handled by the OverviewItems.
std::unique_ptr<OverviewGridPreEventHandler> grid_pre_event_handler_; std::unique_ptr<OverviewGridEventHandler> grid_event_handler_;
// Records the presentation time of scrolling the grid in overview mode. // Records the presentation time of scrolling the grid in overview mode.
std::unique_ptr<PresentationTimeRecorder> presentation_time_recorder_; std::unique_ptr<PresentationTimeRecorder> presentation_time_recorder_;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "ash/wm/overview/overview_grid_pre_event_handler.h" #include "ash/wm/overview/overview_grid_event_handler.h"
#include "ash/root_window_controller.h" #include "ash/root_window_controller.h"
#include "ash/shell.h" #include "ash/shell.h"
...@@ -30,14 +30,14 @@ WallpaperView* GetWallpaperViewForRoot(const aura::Window* root_window) { ...@@ -30,14 +30,14 @@ WallpaperView* GetWallpaperViewForRoot(const aura::Window* root_window) {
} // namespace } // namespace
OverviewGridPreEventHandler::OverviewGridPreEventHandler(OverviewGrid* grid) OverviewGridEventHandler::OverviewGridEventHandler(OverviewGrid* grid)
: grid_(grid) { : grid_(grid) {
auto* wallpaper_view = GetWallpaperViewForRoot(grid_->root_window()); auto* wallpaper_view = GetWallpaperViewForRoot(grid_->root_window());
if (wallpaper_view) if (wallpaper_view)
wallpaper_view->AddPreTargetHandler(this); wallpaper_view->AddPreTargetHandler(this);
} }
OverviewGridPreEventHandler::~OverviewGridPreEventHandler() { OverviewGridEventHandler::~OverviewGridEventHandler() {
EndFling(); EndFling();
grid_->EndScroll(); grid_->EndScroll();
...@@ -46,12 +46,12 @@ OverviewGridPreEventHandler::~OverviewGridPreEventHandler() { ...@@ -46,12 +46,12 @@ OverviewGridPreEventHandler::~OverviewGridPreEventHandler() {
wallpaper_view->RemovePreTargetHandler(this); wallpaper_view->RemovePreTargetHandler(this);
} }
void OverviewGridPreEventHandler::OnMouseEvent(ui::MouseEvent* event) { void OverviewGridEventHandler::OnMouseEvent(ui::MouseEvent* event) {
if (event->type() == ui::ET_MOUSE_RELEASED) if (event->type() == ui::ET_MOUSE_RELEASED)
HandleClickOrTap(event); HandleClickOrTap(event);
} }
void OverviewGridPreEventHandler::OnGestureEvent(ui::GestureEvent* event) { void OverviewGridEventHandler::OnGestureEvent(ui::GestureEvent* event) {
switch (event->type()) { switch (event->type()) {
case ui::ET_GESTURE_TAP: { case ui::ET_GESTURE_TAP: {
HandleClickOrTap(event); HandleClickOrTap(event);
...@@ -91,7 +91,7 @@ void OverviewGridPreEventHandler::OnGestureEvent(ui::GestureEvent* event) { ...@@ -91,7 +91,7 @@ void OverviewGridPreEventHandler::OnGestureEvent(ui::GestureEvent* event) {
} }
} }
void OverviewGridPreEventHandler::OnAnimationStep(base::TimeTicks timestamp) { void OverviewGridEventHandler::OnAnimationStep(base::TimeTicks timestamp) {
// Updates |grid_| based on |offset| when |observed_compositor_| begins a new // Updates |grid_| based on |offset| when |observed_compositor_| begins a new
// frame. // frame.
DCHECK(observed_compositor_); DCHECK(observed_compositor_);
...@@ -113,13 +113,13 @@ void OverviewGridPreEventHandler::OnAnimationStep(base::TimeTicks timestamp) { ...@@ -113,13 +113,13 @@ void OverviewGridPreEventHandler::OnAnimationStep(base::TimeTicks timestamp) {
EndFling(); EndFling();
} }
void OverviewGridPreEventHandler::OnCompositingShuttingDown( void OverviewGridEventHandler::OnCompositingShuttingDown(
ui::Compositor* compositor) { ui::Compositor* compositor) {
DCHECK_EQ(compositor, observed_compositor_); DCHECK_EQ(compositor, observed_compositor_);
EndFling(); EndFling();
} }
void OverviewGridPreEventHandler::HandleClickOrTap(ui::Event* event) { void OverviewGridEventHandler::HandleClickOrTap(ui::Event* event) {
CHECK_EQ(ui::EP_PRETARGET, event->phase()); CHECK_EQ(ui::EP_PRETARGET, event->phase());
// Events that happen while app list is sliding out during overview should // Events that happen while app list is sliding out during overview should
// be ignored to prevent overview from disappearing out from under the user. // be ignored to prevent overview from disappearing out from under the user.
...@@ -128,7 +128,7 @@ void OverviewGridPreEventHandler::HandleClickOrTap(ui::Event* event) { ...@@ -128,7 +128,7 @@ void OverviewGridPreEventHandler::HandleClickOrTap(ui::Event* event) {
event->StopPropagation(); event->StopPropagation();
} }
void OverviewGridPreEventHandler::HandleFlingScroll(ui::GestureEvent* event) { void OverviewGridEventHandler::HandleFlingScroll(ui::GestureEvent* event) {
fling_velocity_ = gfx::Vector2dF(event->details().velocity_x(), fling_velocity_ = gfx::Vector2dF(event->details().velocity_x(),
event->details().velocity_y()); event->details().velocity_y());
fling_curve_ = fling_curve_ =
...@@ -138,7 +138,7 @@ void OverviewGridPreEventHandler::HandleFlingScroll(ui::GestureEvent* event) { ...@@ -138,7 +138,7 @@ void OverviewGridPreEventHandler::HandleFlingScroll(ui::GestureEvent* event) {
observed_compositor_->AddAnimationObserver(this); observed_compositor_->AddAnimationObserver(this);
} }
void OverviewGridPreEventHandler::EndFling() { void OverviewGridEventHandler::EndFling() {
if (!observed_compositor_) if (!observed_compositor_)
return; return;
observed_compositor_->RemoveAnimationObserver(this); observed_compositor_->RemoveAnimationObserver(this);
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef ASH_WM_OVERVIEW_OVERVIEW_GRID_PRE_EVENT_HANDLER_H_ #ifndef ASH_WM_OVERVIEW_OVERVIEW_GRID_EVENT_HANDLER_H_
#define ASH_WM_OVERVIEW_OVERVIEW_GRID_PRE_EVENT_HANDLER_H_ #define ASH_WM_OVERVIEW_OVERVIEW_GRID_EVENT_HANDLER_H_
#include "base/macros.h" #include "base/macros.h"
#include "base/optional.h" #include "base/optional.h"
...@@ -28,11 +28,11 @@ class OverviewGrid; ...@@ -28,11 +28,11 @@ class OverviewGrid;
// - Disabling overview mode on mouse release. // - Disabling overview mode on mouse release.
// - Scrolling through tablet overview mode on scrolling. // - Scrolling through tablet overview mode on scrolling.
// - Scrolling through tablet overview mode on flinging. // - Scrolling through tablet overview mode on flinging.
class OverviewGridPreEventHandler : public ui::EventHandler, class OverviewGridEventHandler : public ui::EventHandler,
public ui::CompositorAnimationObserver { public ui::CompositorAnimationObserver {
public: public:
explicit OverviewGridPreEventHandler(OverviewGrid* grid); explicit OverviewGridEventHandler(OverviewGrid* grid);
~OverviewGridPreEventHandler() override; ~OverviewGridEventHandler() override;
// ui::EventHandler: // ui::EventHandler:
void OnMouseEvent(ui::MouseEvent* event) override; void OnMouseEvent(ui::MouseEvent* event) override;
...@@ -67,9 +67,9 @@ class OverviewGridPreEventHandler : public ui::EventHandler, ...@@ -67,9 +67,9 @@ class OverviewGridPreEventHandler : public ui::EventHandler,
// The compositor we are observing when a fling is underway. // The compositor we are observing when a fling is underway.
ui::Compositor* observed_compositor_ = nullptr; ui::Compositor* observed_compositor_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(OverviewGridPreEventHandler); DISALLOW_COPY_AND_ASSIGN(OverviewGridEventHandler);
}; };
} // namespace ash } // namespace ash
#endif // ASH_WM_OVERVIEW_OVERVIEW_GRID_PRE_EVENT_HANDLER_H_ #endif // ASH_WM_OVERVIEW_OVERVIEW_GRID_EVENT_HANDLER_H_
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#include "ash/wm/overview/overview_constants.h" #include "ash/wm/overview/overview_constants.h"
#include "ash/wm/overview/overview_controller.h" #include "ash/wm/overview/overview_controller.h"
#include "ash/wm/overview/overview_grid.h" #include "ash/wm/overview/overview_grid.h"
#include "ash/wm/overview/overview_grid_pre_event_handler.h" #include "ash/wm/overview/overview_grid_event_handler.h"
#include "ash/wm/overview/overview_highlight_controller.h" #include "ash/wm/overview/overview_highlight_controller.h"
#include "ash/wm/overview/overview_utils.h" #include "ash/wm/overview/overview_utils.h"
#include "ash/wm/overview/overview_window_drag_controller.h" #include "ash/wm/overview/overview_window_drag_controller.h"
...@@ -818,21 +818,21 @@ void OverviewItem::HandleGestureEventForTabletModeLayout( ...@@ -818,21 +818,21 @@ void OverviewItem::HandleGestureEventForTabletModeLayout(
if (IsDragItem()) if (IsDragItem())
HandleDragEvent(location); HandleDragEvent(location);
else else
overview_grid()->grid_pre_event_handler()->OnGestureEvent(event); overview_grid()->grid_event_handler()->OnGestureEvent(event);
break; break;
case ui::ET_SCROLL_FLING_START: case ui::ET_SCROLL_FLING_START:
if (IsDragItem()) { if (IsDragItem()) {
HandleFlingStartEvent(location, event->details().velocity_x(), HandleFlingStartEvent(location, event->details().velocity_x(),
event->details().velocity_y()); event->details().velocity_y());
} else { } else {
overview_grid()->grid_pre_event_handler()->OnGestureEvent(event); overview_grid()->grid_event_handler()->OnGestureEvent(event);
} }
break; break;
case ui::ET_GESTURE_SCROLL_END: case ui::ET_GESTURE_SCROLL_END:
if (IsDragItem()) if (IsDragItem())
HandleReleaseEvent(location); HandleReleaseEvent(location);
else else
overview_grid()->grid_pre_event_handler()->OnGestureEvent(event); overview_grid()->grid_event_handler()->OnGestureEvent(event);
break; break;
case ui::ET_GESTURE_LONG_PRESS: case ui::ET_GESTURE_LONG_PRESS:
HandlePressEvent(location, /*from_touch_gesture=*/true); HandlePressEvent(location, /*from_touch_gesture=*/true);
...@@ -844,7 +844,7 @@ void OverviewItem::HandleGestureEventForTabletModeLayout( ...@@ -844,7 +844,7 @@ void OverviewItem::HandleGestureEventForTabletModeLayout(
HandleGestureEndEvent(); HandleGestureEndEvent();
break; break;
default: default:
overview_grid()->grid_pre_event_handler()->OnGestureEvent(event); overview_grid()->grid_event_handler()->OnGestureEvent(event);
break; break;
} }
} }
......
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