123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- // 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/keyboard/ui/keyboard_ui_controller.h"
- #include "ash/public/cpp/shell_window_ids.h"
- #include "ash/strings/grit/ash_strings.h"
- #include "ash/style/ash_color_id.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),
- // The SettingBubbleContainer was chosen since it's below the virtual
- // keyboard container, and therefore users can use the VK to interact with
- // this dialog e.g. to rename a folder.
- dialog_background_dimmer_(
- root->GetChildById(kShellWindowId_SettingBubbleContainer)),
- select_folder_dialog_(ui::SelectFileDialog::Create(
- /*listener=*/this,
- std::make_unique<NullSelectFolderPolicy>())) {
- DCHECK(delegate_);
- DCHECK(root);
- DCHECK(root->IsRootWindow());
- auto* owner = dialog_background_dimmer_.window();
- owner->SetId(kShellWindowId_CaptureModeFolderSelectionDialogOwner);
- window_observation_.Observe(wm::TransientWindowManager::GetOrCreate(owner));
- dialog_background_dimmer_.SetDimColor(kColorAshShieldAndBase40);
- owner->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=*/owner,
- /*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;
- if (IsEventTargetingWindowInSubtree(event, dialog_window_))
- return false;
- // The event maybe targeting a virtual keyboard window that is being used to
- // interact with the dialog. In this case the event should not be consumed.
- auto* keyboard_ui_controller = keyboard::KeyboardUIController::Get();
- DCHECK(keyboard_ui_controller);
- if (!keyboard_ui_controller->IsKeyboardVisible())
- return true;
- auto* keyboard_window = keyboard_ui_controller->GetKeyboardWindow();
- if (!keyboard_window ||
- keyboard_window->GetRootWindow() != dialog_window_->GetRootWindow()) {
- return true;
- }
- return !IsEventTargetingWindowInSubtree(event, keyboard_window);
- }
- void FolderSelectionDialogController::FileSelected(const base::FilePath& path,
- int index,
- void* params) {
- did_user_select_a_folder_ = true;
- 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;
- // 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);
- delegate_->OnSelectionWindowAdded();
- if (on_dialog_window_added_callback_for_test_)
- std::move(on_dialog_window_added_callback_for_test_).Run();
- }
- 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
|