chromium/ash/public/cpp/accelerator_configuration.h

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

#ifndef ASH_PUBLIC_CPP_ACCELERATOR_CONFIGURATION_H_
#define ASH_PUBLIC_CPP_ACCELERATOR_CONFIGURATION_H_

#include <map>
#include <vector>

#include "ash/public/cpp/ash_public_export.h"
#include "ash/public/mojom/accelerator_configuration.mojom.h"
#include "ash/public/mojom/accelerator_info.mojom.h"
#include "base/functional/callback.h"
#include "base/types/optional_ref.h"
#include "ui/base/accelerators/accelerator.h"

namespace ash {

using AcceleratorActionId = uint32_t;
using ActionIdToAcceleratorsMap =
    std::map<AcceleratorActionId, std::vector<ui::Accelerator>>;

// The public-facing interface for shortcut providers, this should be
// implemented by sources, e.g. Browser, Ash, that want their shortcuts to be
// exposed to separate clients.
class ASH_PUBLIC_EXPORT AcceleratorConfiguration {
 public:
  using AcceleratorsUpdatedCallback =
      base::RepeatingCallback<void(ash::mojom::AcceleratorSource,
                                   const ActionIdToAcceleratorsMap&)>;

  explicit AcceleratorConfiguration(ash::mojom::AcceleratorSource source);
  virtual ~AcceleratorConfiguration();

  // Callback will fire immediately once after updating.
  void AddAcceleratorsUpdatedCallback(AcceleratorsUpdatedCallback callback);

  void RemoveAcceleratorsUpdatedCallback(AcceleratorsUpdatedCallback callback);

  // Get the accelerators for a single action.
  virtual base::optional_ref<const std::vector<ui::Accelerator>>
  GetAcceleratorsForAction(AcceleratorActionId action_id) = 0;

  // Whether this source of shortcuts can be modified. If this returns false
  // then any of the Add/Remove/Replace class will DCHECK. The two Restore
  // methods will be no-ops.
  virtual bool IsMutable() const = 0;

  // Return true if the accelerator is deprecated.
  virtual bool IsDeprecated(const ui::Accelerator& accelerator) const = 0;

  // Return true if the accelerator data does not allow users to modify.
  virtual bool IsAcceleratorLocked(
      const ui::Accelerator& accelerator) const = 0;

  // Add a new user defined accelerator.
  virtual mojom::AcceleratorConfigResult AddUserAccelerator(
      AcceleratorActionId action_id,
      const ui::Accelerator& accelerator) = 0;

  // Remove a shortcut. This will delete a user-defined shortcut, or
  // mark a default one disabled.
  virtual mojom::AcceleratorConfigResult RemoveAccelerator(
      AcceleratorActionId action_id,
      const ui::Accelerator& accelerator) = 0;

  // Atomic version of Remove then Add.
  virtual mojom::AcceleratorConfigResult ReplaceAccelerator(
      AcceleratorActionId action_id,
      const ui::Accelerator& old_acc,
      const ui::Accelerator& new_acc) = 0;

  // Restore the defaults for the given action.
  virtual mojom::AcceleratorConfigResult RestoreDefault(
      AcceleratorActionId action_id) = 0;

  // Restore all defaults.
  virtual mojom::AcceleratorConfigResult RestoreAllDefaults() = 0;

 protected:
  // Updates the local cache and notifies observers of the updated accelerators.
  void UpdateAccelerators(const ActionIdToAcceleratorsMap& accelerators);

 private:
  void NotifyAcceleratorsUpdated();

  // The source of the accelerators. Derived classes are responsible for only
  // one source.
  const ash::mojom::AcceleratorSource source_;

  // Container of all invoked callbacks when the accelerators are updated. Call
  // AddAcceleratorsUpdatedCallback or RemoveAcceleratorsUpdatedCallback to
  // add/remove callbacks to the container.
  std::vector<AcceleratorsUpdatedCallback> callbacks_;

  // Keep a cache of the accelerator map, it's possible that adding a new
  // observer is done after initializing the accelerator mapping. This lets
  // new observers to get the immediate cached mapping.
  ActionIdToAcceleratorsMap accelerator_mapping_cache_;
};

}  // namespace ash

#endif  // ASH_PUBLIC_CPP_ACCELERATOR_CONFIGURATION_H_