blob: 79517fbd4bdc6dcd0fd29e4df490941d5aba3c88 [file] [log] [blame]
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/views/focus/widget_focus_manager.h"
#include "base/supports_user_data.h"
#if defined(USE_AURA)
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#endif
namespace views {
#if defined(USE_AURA)
namespace {
const char kWidgetFocusManagerKey[] = "WidgetFocusManager";
} // namespace
class WidgetFocusManager::Owner : public base::SupportsUserData::Data {
public:
explicit Owner(std::unique_ptr<WidgetFocusManager> focus_manager)
: focus_manager_(std::move(focus_manager)) {}
~Owner() override = default;
WidgetFocusManager* focus_manager() { return focus_manager_.get(); }
private:
std::unique_ptr<WidgetFocusManager> focus_manager_;
DISALLOW_COPY_AND_ASSIGN(Owner);
};
#endif
// WidgetFocusManager ----------------------------------------------------------
// static
WidgetFocusManager* WidgetFocusManager::GetInstance(gfx::NativeWindow context) {
#if defined(USE_AURA)
// With aura there may be multiple Envs, in such a situation the
// WidgetFocusManager needs to be per Env.
aura::Env* env = context ? context->env() : aura::Env::GetInstance();
DCHECK(env);
Owner* owner = static_cast<Owner*>(env->GetUserData(kWidgetFocusManagerKey));
if (!owner) {
std::unique_ptr<Owner> owner_ptr =
std::make_unique<Owner>(base::WrapUnique(new WidgetFocusManager()));
owner = owner_ptr.get();
env->SetUserData(kWidgetFocusManagerKey, std::move(owner_ptr));
}
return owner->focus_manager();
#else
static base::NoDestructor<WidgetFocusManager> instance;
return instance.get();
#endif
}
WidgetFocusManager::~WidgetFocusManager() = default;
void WidgetFocusManager::AddFocusChangeListener(
WidgetFocusChangeListener* listener) {
focus_change_listeners_.AddObserver(listener);
}
void WidgetFocusManager::RemoveFocusChangeListener(
WidgetFocusChangeListener* listener) {
focus_change_listeners_.RemoveObserver(listener);
}
void WidgetFocusManager::OnNativeFocusChanged(gfx::NativeView focused_now) {
if (enabled_) {
for (WidgetFocusChangeListener& observer : focus_change_listeners_)
observer.OnNativeFocusChanged(focused_now);
}
}
WidgetFocusManager::WidgetFocusManager() : enabled_(true) {}
// AutoNativeNotificationDisabler ----------------------------------------------
AutoNativeNotificationDisabler::AutoNativeNotificationDisabler() {
WidgetFocusManager::GetInstance()->DisableNotifications();
}
AutoNativeNotificationDisabler::~AutoNativeNotificationDisabler() {
WidgetFocusManager::GetInstance()->EnableNotifications();
}
} // namespace views