Scaling scroll/fling events in multi-monitor setup

The CL adds an event filter that transforms input event properties
in the extended desktop environment. It currently scales scroll/fling
events' offset values based on the following logic:

1. Linear scaling w.r.t. the device scale factor, which is 2x for
   highDPI displays.
2. 1.2x scaling for external displays, since they are usually larger
   than internal ones.

Both scalings can stack on each other, i.e. you can get as high as
a 2.4x boost if you have a high DPI external display.

Contributed by sheckylin@chromium.org

BUG=chromium:166392
TEST=Tested on link w/o external display.

Change-Id: Ie29e03fcf9f6e5ae1dd6231990103237c3129fd6


Review URL: https://chromiumcodereview.appspot.com/11743013

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@176038 0039d316-1c4b-4281-b951-d872f2087c98
parent 002de2f6
......@@ -81,6 +81,8 @@
'display/display_error_dialog.h',
'display/display_manager.cc',
'display/display_manager.h',
'display/event_transformation_handler.cc',
'display/event_transformation_handler.h',
'display/mouse_cursor_event_filter.cc',
'display/mouse_cursor_event_filter.h',
'display/output_configurator_animation.cc',
......
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/display/event_transformation_handler.h"
#include "ash/display/display_manager.h"
#include "ash/screen_ash.h"
#include "ash/shell.h"
#include "ash/wm/coordinate_conversion.h"
#include "ash/wm/window_util.h"
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
#include "ui/base/events/event.h"
#include "ui/compositor/dip_util.h"
#include "ui/gfx/display.h"
#include "ui/gfx/screen.h"
namespace ash {
namespace internal {
namespace {
// Boost factor for non-integrated displays.
const float kBoostForNonIntegrated = 1.20f;
}
EventTransformationHandler::EventTransformationHandler()
: transformation_mode_(TRANSFORM_AUTO) {
}
EventTransformationHandler::~EventTransformationHandler() {
}
void EventTransformationHandler::OnScrollEvent(ui::ScrollEvent* event) {
if (transformation_mode_ == TRANSFORM_NONE)
return;
// Get the device scale factor and stack it on the final scale factor.
gfx::Point point_in_screen(event->location());
aura::Window* target = static_cast<aura::Window*>(event->target());
const float scale_at_target = ui::GetDeviceScaleFactor(target->layer());
float scale = scale_at_target;
// Apply some additional scaling if the display is non-integrated.
wm::ConvertPointToScreen(target, &point_in_screen);
const gfx::Display& display =
Shell::GetScreen()->GetDisplayNearestPoint(point_in_screen);
DisplayManager* display_manager = Shell::GetInstance()->display_manager();
if (!display_manager->IsInternalDisplayId(display.id()))
scale *= kBoostForNonIntegrated;
event->Scale(scale);
}
} // namespace internal
} // namespace ash
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_DISPLAY_EVENT_TRANSFORMATION_HANDLER_H_
#define ASH_DISPLAY_EVENT_TRANSFORMATION_HANDLER_H_
#include "ash/ash_export.h"
#include "base/compiler_specific.h"
#include "ui/base/events/event_handler.h"
namespace ash {
namespace internal {
// An event filter that transforms input event properties in extended desktop
// environment. It currently handles only ScrollEvents.
class ASH_EXPORT EventTransformationHandler : public ui::EventHandler {
public:
enum TransformationMode {
TRANSFORM_AUTO, // Transform events by the default amount.
// 1. Linear scaling w.r.t. the device scale factor.
// 2. Add 20% more for non-integrated displays.
TRANSFORM_NONE, // No transformation.
};
EventTransformationHandler();
virtual ~EventTransformationHandler();
void set_transformation_mode(TransformationMode transformation_mode) {
transformation_mode_ = transformation_mode;
}
// Overridden from ui::EventHandler.
virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE;
private:
TransformationMode transformation_mode_;
DISALLOW_COPY_AND_ASSIGN(EventTransformationHandler);
};
} // namespace internal
} // namespace ash
#endif // ASH_DISPLAY_EVENT_TRANSFORMATION_HANDLER_H_
......@@ -15,6 +15,7 @@
#include "ash/desktop_background/user_wallpaper_delegate.h"
#include "ash/display/display_controller.h"
#include "ash/display/display_manager.h"
#include "ash/display/event_transformation_handler.h"
#include "ash/display/mouse_cursor_event_filter.h"
#include "ash/display/screen_position_controller.h"
#include "ash/drag_drop/drag_drop_controller.h"
......@@ -469,6 +470,9 @@ void Shell::Init() {
AddPreTargetHandler(accelerator_filter_.get());
#endif
event_transformation_handler_.reset(new internal::EventTransformationHandler);
AddPreTargetHandler(event_transformation_handler_.get());
system_gesture_filter_.reset(new internal::SystemGestureEventFilter);
AddPreTargetHandler(system_gesture_filter_.get());
......
......@@ -102,6 +102,7 @@ class DisplayManager;
class DragDropController;
class EventClientImpl;
class EventRewriterEventFilter;
class EventTransformationHandler;
class FocusCycler;
class MouseCursorEventFilter;
class OutputConfiguratorAnimation;
......@@ -317,6 +318,9 @@ class ASH_EXPORT Shell
internal::MouseCursorEventFilter* mouse_cursor_filter() {
return mouse_cursor_filter_.get();
}
internal::EventTransformationHandler* event_transformation_handler() {
return event_transformation_handler_.get();
}
CursorManager* cursor_manager() { return &cursor_manager_; }
ShellDelegate* delegate() { return delegate_.get(); }
......@@ -535,6 +539,8 @@ class ASH_EXPORT Shell
scoped_ptr<internal::ScreenPositionController> screen_position_controller_;
scoped_ptr<internal::SystemModalContainerEventFilter> modality_filter_;
scoped_ptr<internal::EventClientImpl> event_client_;
scoped_ptr<internal::EventTransformationHandler>
event_transformation_handler_;
scoped_ptr<RootWindowHostFactory> root_window_host_factory_;
// An event filter that rewrites or drops an event.
......
......@@ -639,6 +639,11 @@ ScrollEvent::ScrollEvent(EventType type,
CHECK(IsScrollEvent());
}
void ScrollEvent::Scale(const float factor) {
x_offset_ *= factor;
y_offset_ *= factor;
}
////////////////////////////////////////////////////////////////////////////////
// GestureEvent
......
......@@ -631,6 +631,11 @@ class UI_EXPORT ScrollEvent : public MouseEvent {
float x_offset,
float y_offset);
// Scale the scroll event's offset value.
// This is useful in the multi-monitor setup where it needs to be scaled
// to provide a consistent user experience.
void Scale(const float factor);
float x_offset() const { return x_offset_; }
float y_offset() const { return y_offset_; }
int finger_count() const { return finger_count_; }
......
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