| // 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 |