blob: 05225f23bdd04c2d468bc61708e03cc4ec3d994b [file] [log] [blame]
// Copyright (c) 2017 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/app_list/app_list_util.h"
#include "ash/app_list/views/app_list_main_view.h"
#include "ash/app_list/views/app_list_view.h"
#include "ash/app_list/views/contents_view.h"
#include "ui/aura/window.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/focus/focus_manager.h"
#include "ui/wm/public/activation_client.h"
namespace ash {
bool IsUnhandledUnmodifiedEvent(const ui::KeyEvent& event) {
if (event.handled() || event.type() != ui::ET_KEY_PRESSED)
return false;
if (event.IsShiftDown() || event.IsControlDown() || event.IsAltDown())
return false;
return true;
}
bool IsUnhandledLeftRightKeyEvent(const ui::KeyEvent& event) {
if (!IsUnhandledUnmodifiedEvent(event))
return false;
return event.key_code() == ui::VKEY_LEFT ||
event.key_code() == ui::VKEY_RIGHT;
}
bool IsUnhandledUpDownKeyEvent(const ui::KeyEvent& event) {
if (!IsUnhandledUnmodifiedEvent(event))
return false;
return event.key_code() == ui::VKEY_UP || event.key_code() == ui::VKEY_DOWN;
}
bool IsUnhandledArrowKeyEvent(const ui::KeyEvent& event) {
if (!IsUnhandledUnmodifiedEvent(event))
return false;
return IsArrowKeyEvent(event);
}
bool IsArrowKeyEvent(const ui::KeyEvent& event) {
return IsArrowKey(event.key_code());
}
bool IsArrowKey(const ui::KeyboardCode& key_code) {
return key_code == ui::VKEY_DOWN || key_code == ui::VKEY_RIGHT ||
key_code == ui::VKEY_LEFT || key_code == ui::VKEY_UP;
}
bool LeftRightKeyEventShouldExitText(views::Textfield* textfield,
const ui::KeyEvent& key_event) {
DCHECK(IsUnhandledLeftRightKeyEvent(key_event));
if (textfield->GetText().empty())
return true;
if (textfield->HasSelection())
return false;
if (textfield->GetCursorPosition() != 0 &&
textfield->GetCursorPosition() != textfield->GetText().length()) {
return false;
}
// For RTL language, the beginning position of the cursor will be at the right
// side and it grows towards left as we are typing.
const bool text_rtl =
textfield->GetTextDirection() == base::i18n::RIGHT_TO_LEFT;
const bool cursor_at_beginning = textfield->GetCursorPosition() == 0;
const bool move_cursor_reverse =
(text_rtl && key_event.key_code() == ui::VKEY_RIGHT) ||
(!text_rtl && key_event.key_code() == ui::VKEY_LEFT);
if ((cursor_at_beginning && !move_cursor_reverse) ||
(!cursor_at_beginning && move_cursor_reverse)) {
// Cursor is at either the beginning or the end of the textfield, and it
// will move inward.
return false;
}
return true;
}
bool ProcessLeftRightKeyTraversalForTextfield(views::Textfield* textfield,
const ui::KeyEvent& key_event) {
DCHECK(IsUnhandledLeftRightKeyEvent(key_event));
if (!LeftRightKeyEventShouldExitText(textfield, key_event))
return false;
const bool move_focus_reverse = base::i18n::IsRTL()
? key_event.key_code() == ui::VKEY_RIGHT
: key_event.key_code() == ui::VKEY_LEFT;
// Move focus outside the textfield.
textfield->GetFocusManager()->AdvanceFocus(move_focus_reverse);
return true;
}
void UpdateActivationForAppListView(AppListView* app_list_view,
bool is_tablet_mode) {
views::Widget* widget = app_list_view->GetWidget();
const aura::Window* active_window =
wm::GetActivationClient(widget->GetNativeWindow()->GetRootWindow())
->GetActiveWindow();
// After switching to tablet mode, other app windows may be active. Show the
// app list without activating it to avoid breaking other windows' state.
if (is_tablet_mode && active_window)
return;
widget->Show();
// Refocus the embedded assistant page after widget activation.
auto* contents_view = app_list_view->app_list_main_view()->contents_view();
if (contents_view->IsShowingEmbeddedAssistantUI())
contents_view->FocusEmbeddedAssistantPage();
}
} // namespace ash