blob: 72b5daa03c46b027c7de60ab1da1b93302d1eb63 [file] [log] [blame]
// 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.
#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_STYLUS_HANDWRITING_CONTROLLER_WIN_H_
#define CONTENT_BROWSER_RENDERER_HOST_INPUT_STYLUS_HANDWRITING_CONTROLLER_WIN_H_
#include <ShellHandwriting.h>
#include <msctf.h>
#include <winerror.h>
#include <wrl/client.h>
#include <wrl/implements.h>
#include "base/functional/callback_forward.h"
#include "base/memory/weak_ptr.h"
#include "base/no_destructor.h"
#include "content/common/content_export.h"
namespace base {
class ScopedClosureRunner;
}
namespace gfx {
class Rect;
class Size;
} // namespace gfx
namespace ui {
struct StylusHandwritingPropertiesWin;
} // namespace ui
namespace content {
class StylusHandwritingCallbackSinkWin;
// Encapsulates the Shell Handwriting API. Receives signals from the application
// to notify the Shell Handwriting API of relevant interactions, and forwards
// information back to the renderer process to perform hit testing and focus
// events.
class CONTENT_EXPORT StylusHandwritingControllerWin {
public:
// Callback invoked in response to the Shell Handwriting API
// ITfHandwritingSink::FocusHandwritingTarget method.
using OnFocusHandwritingTargetCallback =
base::RepeatingCallback<void(const gfx::Rect& /*rect_in_screen*/,
const gfx::Size& /*distance_threshold*/)>;
// Sets `g_thread_manager_instance_for_testing` using the provided mocked
// thread manager instance, initializes the controller instance. Resets the
// state upon exiting the scope (e.g., on the test fixture tear down).
[[nodiscard]] static base::ScopedClosureRunner InitializeForTesting(
ITfThreadMgr* thread_manager);
// Returns true if Shell Handwriting API is available and the bindings
// have been successfully set up.
static bool IsHandwritingAPIAvailable();
// Checks if we're on a build which supports handwriting. Needed to work
// around crbug.com/372506009.
static bool StylusHandwritingSupportedOnBuild();
// Initializes the controller singleton instance.
static void Initialize();
// Gets the controller instance if it was successfully initialized.
// Nullptr otherwise.
static StylusHandwritingControllerWin* GetInstance();
static Microsoft::WRL::ComPtr<ITfThreadMgr> GetThreadManager();
StylusHandwritingControllerWin(const StylusHandwritingControllerWin&) =
delete;
StylusHandwritingControllerWin& operator=(
const StylusHandwritingControllerWin&) = delete;
virtual ~StylusHandwritingControllerWin();
// Returns the Handwriting Callback Sink Com pointer for testing.
Microsoft::WRL::ComPtr<StylusHandwritingCallbackSinkWin>
GetCallbackSinkForTesting() const;
// Used for testing instance initialization on builds that support handwriting
// without having to deal with the hassel of mocking handwriting APIs or the
// ThreadManager.
static bool BindInterfacesCalledForTesting();
// Notify the Shell Handwriting API about the intent to write. At this point,
// we delegate the input processing to the API which starts inking. After
// intent is confirmed, the API will request that focus is updated by calling
// ITfHandwritingSink::FocusHandwritingTarget.
void OnStartStylusWriting(
OnFocusHandwritingTargetCallback callback,
const ui::StylusHandwritingPropertiesWin& properties);
// Signal the Handwriting API whether focus has been updated successfully and
// may begin committing edits or collect character bounds for evaluating
// gesture recognition using TSF/IME APIs.
void OnFocusHandled();
// Signal the Handwriting API that focus was not updated successfully and must
// cancel the inking session.
void OnFocusFailed();
private:
friend class base::NoDestructor<StylusHandwritingControllerWin>;
// Binds interfaces and sets the global g_instance if the initialization is
// successful.
StylusHandwritingControllerWin();
// Binds required API interfaces if available.
void BindInterfaces();
Microsoft::WRL::ComPtr<StylusHandwritingCallbackSinkWin>
handwriting_callback_sink_;
Microsoft::WRL::ComPtr<::ITfHandwriting> handwriting_;
};
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_STYLUS_HANDWRITING_CONTROLLER_WIN_H_