1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115

ash / webui / common / backend / accelerator_fetcher.cc [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.

#include "ash/webui/common/backend/accelerator_fetcher.h"

#include <algorithm>
#include <utility>
#include <vector>

#include "ash/accelerators/accelerator_controller_impl.h"
#include "ash/accelerators/accelerator_lookup.h"
#include "ash/accelerators/ash_accelerator_configuration.h"
#include "ash/public/cpp/accelerator_actions.h"
#include "ash/public/mojom/accelerator_actions.mojom.h"
#include "ash/public/mojom/accelerator_info.mojom.h"
#include "ash/shell.h"
#include "ui/base/accelerators/accelerator.h"
#include "ui/base/ui_base_features.h"
#include "ui/events/ash/keyboard_capability.h"

namespace ash {

namespace {

std::vector<mojom::StandardAcceleratorPropertiesPtr> GetAcceleratorsForActionId(
    AcceleratorAction action) {
  CHECK(Shell::HasInstance());
  const std::vector<AcceleratorLookup::AcceleratorDetails>&
      available_accelerators =
          Shell::Get()->accelerator_lookup()->GetAvailableAcceleratorsForAction(
              action);

  std::vector<mojom::StandardAcceleratorPropertiesPtr> accelerator_properties;
  accelerator_properties.reserve(available_accelerators.size());
  for (const auto& available_accelerator : available_accelerators) {
    accelerator_properties.push_back(mojom::StandardAcceleratorProperties::New(
        available_accelerator.accelerator, available_accelerator.key_display,
        /*original_accelerator=*/std::nullopt));
  }

  return accelerator_properties;
}

}  // namespace

AcceleratorFetcher::AcceleratorFetcher() {
  if (Shell::HasInstance()) {
    Shell::Get()
        ->accelerator_controller()
        ->accelerator_configuration()
        ->AddObserver(this);
  }
  accelerator_observers_.set_disconnect_handler(
      base::BindRepeating(&AcceleratorFetcher::OnObserverDisconnect,
                          weak_ptr_factory_.GetWeakPtr()));
}

AcceleratorFetcher::~AcceleratorFetcher() {
  if (Shell::HasInstance()) {
    Shell::Get()
        ->accelerator_controller()
        ->accelerator_configuration()
        ->RemoveObserver(this);
  }
}

void AcceleratorFetcher::BindInterface(
    mojo::PendingReceiver<common::mojom::AcceleratorFetcher> receiver) {
  if (accelerator_fetcher_receiver_.is_bound()) {
    accelerator_fetcher_receiver_.reset();
  }
  accelerator_fetcher_receiver_.Bind(std::move(receiver));
}

void AcceleratorFetcher::ObserveAcceleratorChanges(
    const std::vector<AcceleratorAction>& action_ids,
    mojo::PendingRemote<common::mojom::AcceleratorFetcherObserver> observer) {
  mojo::RemoteSetElementId id = accelerator_observers_.Add(std::move(observer));
  actions_for_receivers_[id] = action_ids;

  common::mojom::AcceleratorFetcherObserver* receiver =
      accelerator_observers_.Get(id);
  // Notify the observer immediately after adding it.
  for (const AcceleratorAction& action_id : action_ids) {
    receiver->OnAcceleratorsUpdated(action_id,
                                    GetAcceleratorsForActionId(action_id));
  }
}

void AcceleratorFetcher::OnAcceleratorsUpdated() {
  for (const auto& [receiver_id, action_ids] : actions_for_receivers_) {
    for (const auto& action_id : action_ids) {
      accelerator_observers_.Get(receiver_id)
          ->OnAcceleratorsUpdated(action_id,
                                  GetAcceleratorsForActionId(action_id));
    }
  }
}

void AcceleratorFetcher::GetMetaKeyToDisplay(
    GetMetaKeyToDisplayCallback callback) {
  std::move(callback).Run(
      Shell::Get()->keyboard_capability()->GetMetaKeyToDisplay());
}

void AcceleratorFetcher::OnObserverDisconnect(mojo::RemoteSetElementId id) {
  actions_for_receivers_.erase(id);
}

void AcceleratorFetcher::FlushMojoForTesting() {
  accelerator_observers_.FlushForTesting();  // IN-TEST
}

}  // namespace ash