blob: 472bc732819429f681d017c0e68f546f5350b1f8 [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_GLIC_WIDGET_LOCAL_HOTKEY_MANAGER_H_
#define CHROME_BROWSER_GLIC_WIDGET_LOCAL_HOTKEY_MANAGER_H_
#include "base/containers/flat_map.h"
#include "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_list_observer.h"
#include "components/prefs/pref_change_registrar.h"
#include "ui/base/accelerators/accelerator.h"
namespace glic {
class GlicWindowController;
// Manages hotkeys that are active within a specific local scope, such as the
// Glic window itself or the broader Chrome application when Glic is relevant.
// This class handles retrieving accelerator definitions (potentially from user
// preferences), registering them within the appropriate scope via a Delegate,
// and dispatching pressed accelerators back to the Delegate for handling.
class LocalHotkeyManager : public ui::AcceleratorTarget {
public:
// Enum representing the different hotkeys managed by this class.
enum class Hotkey {
// Close the Glic window. Only works when the Glic window has focus.
kClose,
// Toggle focus between the Glic window and the last active
// browser window.
kFocusToggle,
#if BUILDFLAG(IS_WIN)
// Show the title bar context menu
kTitleBarContextMenu,
#endif
};
constexpr static const char* HotkeyToString(Hotkey hotkey) {
switch (hotkey) {
case Hotkey::kClose:
return "kClose";
case Hotkey::kFocusToggle:
return "kFocusToggle";
#if BUILDFLAG(IS_WIN)
case Hotkey::kTitleBarContextMenu:
return "kTitleBarContextMenu";
#endif
}
}
// Interface for managing the lifetime of a registered hotkey.
// Implementations handle the specific registration/unregistration logic
// for their scope (e.g., adding/removing from a views::View or
// views::FocusManager).
class ScopedHotkeyRegistration {
public:
virtual ~ScopedHotkeyRegistration() = default;
};
// Delegate interface responsible for the actual registration and handling
// of hotkeys within a specific scope (e.g., Glic window, application-wide).
class Delegate {
public:
virtual ~Delegate() = default;
virtual const base::span<const Hotkey> GetSupportedHotkeys() const = 0;
// Creates a ScopedHotkeyRegistration for the given accelerator.
// The implementation should register the hotkey within its specific scope
// and return an object that unregisters it upon destruction.
virtual std::unique_ptr<ScopedHotkeyRegistration>
CreateScopedHotkeyRegistration(
ui::Accelerator accelerator,
base::WeakPtr<ui::AcceleratorTarget> target) = 0;
// Called when a registered hotkey associated with this manager is pressed.
// Returns true if the accelerator was handled, false otherwise.
virtual bool AcceleratorPressed(Hotkey) = 0;
};
explicit LocalHotkeyManager(
base::WeakPtr<GlicWindowController> window_controller,
std::unique_ptr<Delegate> delegate);
~LocalHotkeyManager() override;
// Returns the default accelerator for a given hotkey.
static ui::Accelerator GetDefaultAccelerator(Hotkey hotkey_enum);
// Returns the hardcoded, non-configurable accelerators for a given hotkey.
// CHECKs if the hotkey is not defined as static (i.e., not in
// kHotkeyToStaticAcceleratorsMap).
static base::span<const ui::Accelerator> GetStaticAccelerators(
LocalHotkeyManager::Hotkey hotkey);
// Returns the current configurable accelerator for a given hotkey,
// potentially reading from user preferences. Falls back to the default if
// no preference is set or the preference is invalid. CHECKs if the passed
// hotkey_enum is not defined as configurable.
static ui::Accelerator GetConfigurableAccelerator(Hotkey hotkey_enum);
// Returns the Hotkey enum value corresponding to the given accelerator.
// CHECKs if the accelerator is not supported by this manager.
Hotkey GetHotkeyEnum(ui::Accelerator accelerator);
void InitializeAccelerators();
// ui::AcceleratorTarget:
bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
bool CanHandleAccelerators() const override;
base::WeakPtr<LocalHotkeyManager> GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
private:
std::vector<ui::Accelerator> GetAccelerators(Hotkey hotkey);
void RegisterHotkey(Hotkey hotkey_enum);
base::WeakPtr<GlicWindowController> window_controller_;
std::unique_ptr<Delegate> delegate_;
PrefChangeRegistrar pref_registrar_;
base::flat_map<Hotkey, std::vector<std::unique_ptr<ScopedHotkeyRegistration>>>
hotkey_registrations_;
base::WeakPtrFactory<LocalHotkeyManager> weak_ptr_factory_{this};
};
} // namespace glic
#endif // CHROME_BROWSER_GLIC_WIDGET_LOCAL_HOTKEY_MANAGER_H_