blob: 2f709b2c55ad0b030e637097baee1b3a7a1b96bd [file] [log] [blame]
// Copyright 2015 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 UI_WIN_DIRECT_MANIPULATION_H_
#define UI_WIN_DIRECT_MANIPULATION_H_
#include <windows.h>
#include <directmanipulation.h>
#include <wrl.h>
#include <memory>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "ui/base/ui_base_export.h"
#include "ui/base/win/window_event_target.h"
#include "ui/gfx/geometry/size.h"
namespace content {
class DirectManipulationBrowserTest;
} // namespace content
namespace ui {
namespace win {
class DirectManipulationUnitTest;
class DirectManipulationHelper;
// DirectManipulationHandler receives status update and gesture events from
// Direct Manipulation API.
class DirectManipulationHandler
: public Microsoft::WRL::RuntimeClass<
Microsoft::WRL::RuntimeClassFlags<
Microsoft::WRL::RuntimeClassType::ClassicCom>,
Microsoft::WRL::Implements<
Microsoft::WRL::RuntimeClassFlags<
Microsoft::WRL::RuntimeClassType::ClassicCom>,
Microsoft::WRL::FtmBase,
IDirectManipulationViewportEventHandler>> {
public:
explicit DirectManipulationHandler(DirectManipulationHelper* helper,
WindowEventTarget* event_target);
// WindowEventTarget updates for every DM_POINTERHITTEST in case window
// hierarchy changed.
void SetWindowEventTarget(WindowEventTarget* event_target);
void SetDeviceScaleFactor(float device_scale_factor);
private:
friend DirectManipulationUnitTest;
DirectManipulationHandler();
~DirectManipulationHandler() override;
enum class Gesture { kNone, kScroll, kFling, kPinch };
void TransitionToState(Gesture gesture);
HRESULT STDMETHODCALLTYPE
OnViewportStatusChanged(_In_ IDirectManipulationViewport* viewport,
_In_ DIRECTMANIPULATION_STATUS current,
_In_ DIRECTMANIPULATION_STATUS previous) override;
HRESULT STDMETHODCALLTYPE
OnViewportUpdated(_In_ IDirectManipulationViewport* viewport) override;
HRESULT STDMETHODCALLTYPE
OnContentUpdated(_In_ IDirectManipulationViewport* viewport,
_In_ IDirectManipulationContent* content) override;
DirectManipulationHelper* helper_ = nullptr;
WindowEventTarget* event_target_ = nullptr;
float device_scale_factor_ = 1.0f;
float last_scale_ = 1.0f;
int last_x_offset_ = 0;
int last_y_offset_ = 0;
bool first_ready_ = false;
bool should_send_scroll_begin_ = false;
// Current recognized gesture from Direct Manipulation.
Gesture gesture_state_ = Gesture::kNone;
DISALLOW_COPY_AND_ASSIGN(DirectManipulationHandler);
};
// Windows 10 provides a new API called Direct Manipulation which generates
// smooth scroll and scale factor via IDirectManipulationViewportEventHandler
// on precision touchpad.
// 1. The foreground window is checked to see if it is a Direct Manipulation
// consumer.
// 2. Call SetContact in Direct Manipulation takes over the following scrolling
// when DM_POINTERHITTEST.
// 3. OnViewportStatusChanged will be called when the gesture phase change.
// OnContentUpdated will be called when the gesture update.
class UI_BASE_EXPORT DirectManipulationHelper {
public:
// Creates and initializes an instance of this class if Direct Manipulation is
// enabled on the platform. Returns nullptr if it disabled or failed on
// initialization.
static std::unique_ptr<DirectManipulationHelper> CreateInstance(
HWND window,
WindowEventTarget* event_target);
// Creates and initializes an instance for testing.
static std::unique_ptr<DirectManipulationHelper> CreateInstanceForTesting(
WindowEventTarget* event_target,
Microsoft::WRL::ComPtr<IDirectManipulationViewport> viewport);
~DirectManipulationHelper();
// Registers and activates the passed in |window| as a Direct Manipulation
// consumer.
void Activate();
// Deactivates Direct Manipulation processing on the passed in |window|.
void Deactivate();
// Updates viewport size. Call it when window bounds updated.
void SetSize(const gfx::Size& size_in_pixels);
// Reset the fake viewport for gesture end.
HRESULT ResetViewport(bool need_animtation);
// Pass the pointer hit test to Direct Manipulation. Return true indicated we
// need poll for new events every frame from here.
bool OnPointerHitTest(WPARAM w_param, WindowEventTarget* event_target);
// On each frame poll new Direct Manipulation events. Return true if we still
// need poll for new events on next frame, otherwise stop request need begin
// frame.
bool PollForNextEvent();
private:
friend class content::DirectManipulationBrowserTest;
friend class DirectManipulationUnitTest;
DirectManipulationHelper();
// This function instantiates Direct Manipulation and creates a viewport for
// the passed in |window|. Return false if initialize failed.
bool Initialize(WindowEventTarget* event_target);
void SetDeviceScaleFactorForTesting(float factor);
Microsoft::WRL::ComPtr<IDirectManipulationManager> manager_;
Microsoft::WRL::ComPtr<IDirectManipulationUpdateManager> update_manager_;
Microsoft::WRL::ComPtr<IDirectManipulationViewport> viewport_;
Microsoft::WRL::ComPtr<DirectManipulationHandler> event_handler_;
HWND window_;
DWORD view_port_handler_cookie_;
bool need_poll_events_ = false;
gfx::Size viewport_size_;
DISALLOW_COPY_AND_ASSIGN(DirectManipulationHelper);
};
} // namespace win
} // namespace ui
#endif // UI_WIN_DIRECT_MANIPULATION_H_