blob: 2a0271641be745214df7a753a711e622b25ae88e [file] [log] [blame]
// Copyright 2021 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 "ash/capture_mode/folder_selection_dialog_controller.h"
#include <memory>
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/ash_color_provider.h"
#include "base/files/file_path.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window_observer.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/events/event.h"
#include "ui/shell_dialogs/select_file_dialog.h"
#include "ui/shell_dialogs/select_file_policy.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/wm/core/transient_window_manager.h"
namespace ash {
namespace {
class NullSelectFolderPolicy : public ui::SelectFilePolicy {
public:
NullSelectFolderPolicy() = default;
~NullSelectFolderPolicy() override = default;
// ui::SelectFileDialog:
bool CanOpenSelectFileDialog() override { return true; }
void SelectFileDenied() override {}
};
// Returns true if |event| is targeting a window in the subtree rooted at
// |window|.
bool IsEventTargetingWindowInSubtree(const ui::Event* event,
const aura::Window* window) {
DCHECK(window);
auto* target = static_cast<aura::Window*>(event->target());
return window->Contains(target);
}
} // namespace
FolderSelectionDialogController::FolderSelectionDialogController(
Delegate* delegate,
aura::Window* root)
: delegate_(delegate),
dialog_background_dimmer_(
root->GetChildById(kShellWindowId_OverlayContainer)),
select_folder_dialog_(ui::SelectFileDialog::Create(
/*listener=*/this,
std::make_unique<NullSelectFolderPolicy>())) {
DCHECK(delegate_);
DCHECK(root);
DCHECK(root->IsRootWindow());
window_observation_.Observe(wm::TransientWindowManager::GetOrCreate(
dialog_background_dimmer_.window()));
dialog_background_dimmer_.SetDimColor(
AshColorProvider::Get()->GetShieldLayerColor(
AshColorProvider::ShieldLayerType::kShield40));
dialog_background_dimmer_.window()->Show();
select_folder_dialog_->SelectFile(
ui::SelectFileDialog::SELECT_FOLDER,
l10n_util::GetStringUTF16(IDS_ASH_SCREEN_CAPTURE_SAVE_TO_DIALOG_TITLE),
/*default_path=*/base::FilePath(),
/*file_types=*/nullptr,
/*file_type_index=*/0,
/*default_extension=*/base::FilePath::StringType(),
/*owning_window=*/dialog_background_dimmer_.window(),
/*params=*/nullptr);
}
FolderSelectionDialogController::~FolderSelectionDialogController() {
if (select_folder_dialog_)
select_folder_dialog_->ListenerDestroyed();
}
bool FolderSelectionDialogController::ShouldConsumeEvent(
const ui::Event* event) const {
if (!dialog_window_)
return true;
return !IsEventTargetingWindowInSubtree(event, dialog_window_);
}
void FolderSelectionDialogController::FileSelected(const base::FilePath& path,
int index,
void* params) {
delegate_->OnFolderSelected(path);
}
void FolderSelectionDialogController::OnTransientChildAdded(
aura::Window* window,
aura::Window* transient) {
DCHECK_EQ(window, dialog_background_dimmer_.window());
DCHECK(!dialog_window_);
dialog_window_ = transient;
dialog_window_->SetId(kShellWindowId_CaptureModeFolderSelectionDialog);
// The dialog should never resize, minimize or maximize.
auto* widget = views::Widget::GetWidgetForNativeWindow(dialog_window_);
DCHECK(widget);
views::WidgetDelegate* widget_delegate = widget->widget_delegate();
DCHECK(widget_delegate);
widget_delegate->SetCanResize(false);
widget_delegate->SetCanMinimize(false);
widget_delegate->SetCanMaximize(false);
}
void FolderSelectionDialogController::OnTransientChildRemoved(
aura::Window* window,
aura::Window* transient) {
DCHECK_EQ(window, dialog_background_dimmer_.window());
DCHECK(dialog_window_);
DCHECK_EQ(transient, dialog_window_);
dialog_window_ = nullptr;
delegate_->OnSelectionWindowClosed();
// |this| will be deleted after the above call.
}
} // namespace ash