chromium/ui/views/widget/desktop_aura/desktop_native_cursor_manager_win.cc

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/views/widget/desktop_aura/desktop_native_cursor_manager_win.h"

#include <utility>

#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/numerics/safe_conversions.h"
#include "base/win/windows_types.h"
#include "ui/wm/core/native_cursor_manager_delegate.h"

namespace views {

namespace {

constexpr int kDefaultCursorSize = 32;

}  // namespace

DesktopNativeCursorManagerWin::DesktopNativeCursorManagerWin() = default;

DesktopNativeCursorManagerWin::~DesktopNativeCursorManagerWin() = default;

void DesktopNativeCursorManagerWin::SetSystemCursorSize(
    wm::NativeCursorManagerDelegate* delegate) {
  DWORD cursor_base_size = 0;
  if (hkcu_cursor_regkey_.Valid() &&
      hkcu_cursor_regkey_.ReadValueDW(L"CursorBaseSize", &cursor_base_size) ==
          ERROR_SUCCESS) {
    int size = base::checked_cast<int>(cursor_base_size);
    system_cursor_size_ = gfx::Size(size, size);
  }

  // Report cursor size.
  delegate->CommitSystemCursorSize(system_cursor_size_);
}

void DesktopNativeCursorManagerWin::RegisterCursorRegkeyObserver(
    wm::NativeCursorManagerDelegate* delegate) {
  if (!hkcu_cursor_regkey_.Valid())
    return;

  hkcu_cursor_regkey_.StartWatching(base::BindOnce(
      [](DesktopNativeCursorManagerWin* manager,
         wm::NativeCursorManagerDelegate* delegate) {
        manager->SetSystemCursorSize(delegate);
        // RegKey::StartWatching only provides one notification.
        // Reregistration is required to get future notifications.
        manager->RegisterCursorRegkeyObserver(delegate);
      },
      // It's safe to use |base::Unretained(this)| here, because |this| owns
      // the |hkcu_cursor_regkey_|, and the callback will be cancelled if
      // |hkcu_cursor_regkey_| is destroyed.
      base::Unretained(this), delegate));
}

void DesktopNativeCursorManagerWin::InitCursorSizeObserver(
    wm::NativeCursorManagerDelegate* delegate) {
  // Validity of this key is checked at time-of-use.
  (void)hkcu_cursor_regkey_.Open(HKEY_CURRENT_USER, L"Control Panel\\Cursors",
                                 KEY_READ | KEY_NOTIFY);
  system_cursor_size_ = gfx::Size(kDefaultCursorSize, kDefaultCursorSize);
  RegisterCursorRegkeyObserver(delegate);
  SetSystemCursorSize(delegate);
}

}  // namespace views